import { o as __toESM } from "./rolldown-runtime-B2q5OVn9.es.js";
import { t as require_jszip_min } from "./jszip-ChlR43oI.es.js";
import { t as require_lib } from "./xml-js-40FWvL78.es.js";
import { _ as getContentTypesFromXml, p as detectImageType, s as base64ToUint8Array, t as COMMENT_FILE_BASENAMES } from "./constants-CIF8yzNk.es.js";
import { t as Buffer } from "./dist-DGse2t39.es.js";
const DOCX = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
const PDF = "application/pdf";
const HTML = "text/html";
const documentTypes = {
	docx: DOCX,
	pdf: PDF,
	html: HTML
};
const isXmlLike = (name) => /\.xml$|\.rels$/i.test(name);
function sniffEncoding(u8) {
	if (u8.length >= 2) {
		const b0 = u8[0], b1 = u8[1];
		if (b0 === 255 && b1 === 254) return "utf-16le";
		if (b0 === 254 && b1 === 255) return "utf-16be";
	}
	let nul = 0;
	for (let i = 0; i < Math.min(64, u8.length); i++) if (u8[i] === 0) nul++;
	if (nul > 16) return "utf-16le";
	return "utf-8";
}
function stripBOM(str) {
	return str && str.charCodeAt(0) === 65279 ? str.slice(1) : str;
}
function ensureXmlString(content) {
	if (typeof content === "string") return stripBOM(content);
	let u8 = null;
	if (content && typeof content === "object") {
		if (content instanceof Uint8Array) u8 = content;
		else if (typeof Buffer !== "undefined" && Buffer.isBuffer && Buffer.isBuffer(content)) u8 = new Uint8Array(content.buffer, content.byteOffset, content.byteLength);
		else if (ArrayBuffer.isView && ArrayBuffer.isView(content)) u8 = new Uint8Array(content.buffer, content.byteOffset, content.byteLength);
		else if (content.constructor && (content instanceof ArrayBuffer || content.constructor.name === "ArrayBuffer")) u8 = new Uint8Array(content);
	}
	if (!u8) throw new Error("Unsupported content type for XML");
	const enc = sniffEncoding(u8);
	let xml = new TextDecoder(enc).decode(u8);
	xml = stripBOM(xml);
	if (enc !== "utf-8") xml = xml.replace(/(<\?xml\b[^?]*?)\bencoding\s*=\s*["'][^"']*["']/i, "$1encoding=\"UTF-8\"");
	return xml;
}
const MANAGED_PACKAGE_PARTS = [
	{
		zipPath: "word/document.xml",
		contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml",
		relationshipType: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
	},
	{
		zipPath: "docProps/core.xml",
		contentType: "application/vnd.openxmlformats-package.core-properties+xml",
		relationshipType: "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"
	},
	{
		zipPath: "docProps/app.xml",
		contentType: "application/vnd.openxmlformats-officedocument.extended-properties+xml",
		relationshipType: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"
	},
	{
		zipPath: "docProps/custom.xml",
		contentType: "application/vnd.openxmlformats-officedocument.custom-properties+xml",
		relationshipType: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties"
	}
];
var import_lib$2 = /* @__PURE__ */ __toESM(require_lib(), 1);
var RELATIONSHIPS_NS = "http://schemas.openxmlformats.org/package/2006/relationships";
function readEntry(path, baseFiles, updatedDocs) {
	if (updatedDocs && Object.prototype.hasOwnProperty.call(updatedDocs, path)) return updatedDocs[path];
	if (!baseFiles) return void 0;
	if (Array.isArray(baseFiles)) return baseFiles.find((f) => f.name === path)?.content;
	return baseFiles[path];
}
function partExistsInPackage(zipPath, baseFiles, updatedDocs) {
	return readEntry(zipPath, baseFiles, updatedDocs) != null;
}
function parseXml(xmlString) {
	try {
		return import_lib$2.xml2js(xmlString, { compact: false });
	} catch {
		return null;
	}
}
function serializeXml(jsObject) {
	return import_lib$2.js2xml(jsObject, { spaces: 0 });
}
function findRootElement(parsed, tagName) {
	return parsed?.elements?.find((el) => {
		if (!el.name) return false;
		return (el.name.includes(":") ? el.name.split(":").pop() : el.name) === tagName;
	});
}
function createEmptyRels() {
	return {
		declaration: { attributes: {
			version: "1.0",
			encoding: "UTF-8",
			standalone: "yes"
		} },
		elements: [{
			type: "element",
			name: "Relationships",
			attributes: { xmlns: RELATIONSHIPS_NS },
			elements: []
		}]
	};
}
function findMaxRId$1(relsRoot) {
	let max = 0;
	for (const el of relsRoot.elements || []) {
		const id = el.attributes?.Id;
		if (!id) continue;
		const match = id.match(/^rId(\d+)$/);
		if (match) max = Math.max(max, parseInt(match[1], 10));
	}
	return max;
}
function reconcileContentTypes(typesRoot, presentParts) {
	if (!typesRoot.elements) typesRoot.elements = [];
	const managedByPartName = /* @__PURE__ */ new Map();
	for (const entry of MANAGED_PACKAGE_PARTS) managedByPartName.set(`/${entry.zipPath}`, entry);
	const existingOverrides = /* @__PURE__ */ new Map();
	for (let i = 0; i < typesRoot.elements.length; i++) {
		const el = typesRoot.elements[i];
		if (el.name !== "Override") continue;
		const partName = el.attributes?.PartName;
		if (!partName || !managedByPartName.has(partName)) continue;
		if (!existingOverrides.has(partName)) existingOverrides.set(partName, []);
		existingOverrides.get(partName).push(i);
	}
	const indicesToRemove = /* @__PURE__ */ new Set();
	for (const [partName, entry] of managedByPartName) {
		const isPresent = presentParts.has(entry.zipPath);
		const indices = existingOverrides.get(partName) || [];
		if (!isPresent) {
			for (const idx of indices) indicesToRemove.add(idx);
			continue;
		}
		if (indices.length === 0) typesRoot.elements.push({
			type: "element",
			name: "Override",
			attributes: {
				PartName: partName,
				ContentType: entry.contentType
			}
		});
		else {
			typesRoot.elements[indices[0]].attributes.ContentType = entry.contentType;
			for (let i = 1; i < indices.length; i++) indicesToRemove.add(indices[i]);
		}
	}
	if (indicesToRemove.size > 0) {
		const sorted = [...indicesToRemove].sort((a, b) => b - a);
		for (const idx of sorted) typesRoot.elements.splice(idx, 1);
	}
}
function reconcileRootRels(relsRoot, presentParts) {
	if (!relsRoot.elements) relsRoot.elements = [];
	const managedByType = /* @__PURE__ */ new Map();
	for (const entry of MANAGED_PACKAGE_PARTS) managedByType.set(entry.relationshipType, entry);
	const existingRels = /* @__PURE__ */ new Map();
	for (let i = 0; i < relsRoot.elements.length; i++) {
		const el = relsRoot.elements[i];
		if (el.name !== "Relationship") continue;
		const type = el.attributes?.Type;
		if (!type || !managedByType.has(type)) continue;
		if (!existingRels.has(type)) existingRels.set(type, []);
		existingRels.get(type).push({
			index: i,
			element: el
		});
	}
	const indicesToRemove = /* @__PURE__ */ new Set();
	let maxRId = findMaxRId$1(relsRoot);
	for (const [relType, entry] of managedByType) {
		const isPresent = presentParts.has(entry.zipPath);
		const existing = existingRels.get(relType) || [];
		if (!isPresent) {
			for (const { index } of existing) indicesToRemove.add(index);
			continue;
		}
		if (existing.length === 0) {
			maxRId++;
			relsRoot.elements.push({
				type: "element",
				name: "Relationship",
				attributes: {
					Id: `rId${maxRId}`,
					Type: relType,
					Target: entry.zipPath
				}
			});
		} else {
			existing[0].element.attributes.Target = entry.zipPath;
			for (let i = 1; i < existing.length; i++) indicesToRemove.add(existing[i].index);
		}
	}
	if (indicesToRemove.size > 0) {
		const sorted = [...indicesToRemove].sort((a, b) => b - a);
		for (const idx of sorted) relsRoot.elements.splice(idx, 1);
	}
}
function syncPackageMetadata({ baseFiles, updatedDocs }) {
	const presentParts = /* @__PURE__ */ new Set();
	for (const entry of MANAGED_PACKAGE_PARTS) if (partExistsInPackage(entry.zipPath, baseFiles, updatedDocs)) presentParts.add(entry.zipPath);
	const rawContentTypes = readEntry("[Content_Types].xml", baseFiles, updatedDocs);
	if (rawContentTypes == null) throw new Error("syncPackageMetadata: [Content_Types].xml is missing from the package. Cannot safely reconcile package metadata without an existing content types file.");
	const contentTypesParsed = parseXml(rawContentTypes);
	if (!contentTypesParsed) throw new Error("syncPackageMetadata: [Content_Types].xml could not be parsed as valid XML. Cannot safely reconcile package metadata from a malformed content types file.");
	const typesRoot = findRootElement(contentTypesParsed, "Types");
	if (!typesRoot) throw new Error("syncPackageMetadata: [Content_Types].xml does not contain a <Types> root element.");
	reconcileContentTypes(typesRoot, presentParts);
	const rawRels = readEntry("_rels/.rels", baseFiles, updatedDocs);
	let relsParsed;
	if (rawRels == null) relsParsed = createEmptyRels();
	else {
		relsParsed = parseXml(rawRels);
		if (!relsParsed) throw new Error("syncPackageMetadata: _rels/.rels could not be parsed as valid XML. Cannot safely reconcile root relationships from a malformed rels file.");
	}
	let relsRoot = findRootElement(relsParsed, "Relationships");
	if (!relsRoot) {
		relsParsed = createEmptyRels();
		relsRoot = relsParsed.elements[0];
	}
	reconcileRootRels(relsRoot, presentParts);
	return {
		contentTypesXml: serializeXml(contentTypesParsed),
		relsXml: serializeXml(relsParsed)
	};
}
var import_lib$1 = /* @__PURE__ */ __toESM(require_lib(), 1);
const MANAGED_DOCUMENT_PARTS = [{
	zipPath: "word/numbering.xml",
	contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml",
	relationshipType: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",
	relTarget: "numbering.xml"
}];
function findMaxRId(elements) {
	let max = 0;
	for (const el of elements) {
		const match = el.attributes?.Id?.match(/^rId(\d+)$/);
		if (match) max = Math.max(max, Number(match[1]));
	}
	return max;
}
function reconcileDocumentRelationships(relsXml, fileExists) {
	if (!relsXml) return relsXml;
	let parsed;
	try {
		parsed = import_lib$1.xml2js(relsXml, { compact: false });
	} catch {
		return relsXml;
	}
	const relsTag = parsed?.elements?.find((el) => el.name === "Relationships");
	if (!relsTag) return relsXml;
	if (!relsTag.elements) relsTag.elements = [];
	let changed = false;
	let maxId = findMaxRId(relsTag.elements);
	for (const entry of MANAGED_DOCUMENT_PARTS) {
		if (!fileExists(entry.zipPath)) continue;
		if (relsTag.elements.some((el) => el.attributes?.Type === entry.relationshipType)) continue;
		maxId++;
		relsTag.elements.push({
			type: "element",
			name: "Relationship",
			attributes: {
				Id: `rId${maxId}`,
				Type: entry.relationshipType,
				Target: entry.relTarget
			}
		});
		changed = true;
	}
	if (!changed) return relsXml;
	return import_lib$1.js2xml(parsed, { spaces: 0 });
}
var import_lib = /* @__PURE__ */ __toESM(require_lib(), 1);
var import_jszip_min = /* @__PURE__ */ __toESM(require_jszip_min(), 1);
var IMAGE_EXTS = new Set([
	"png",
	"jpg",
	"jpeg",
	"gif",
	"bmp",
	"tiff",
	"tif",
	"emf",
	"wmf",
	"svg",
	"webp"
]);
var MIME_TYPE_FOR_EXT = {
	tif: "tiff",
	jpg: "jpeg"
};
var CUSTOM_XML_ITEM_PROPS_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.customXmlProperties+xml";
var FONT_CONTENT_TYPES = {
	odttf: "application/vnd.openxmlformats-officedocument.obfuscatedFont",
	ttf: "application/x-font-ttf",
	otf: "application/vnd.ms-opentype"
};
var DocxZipper = class {
	constructor(params = {}) {
		this.debug = params.debug || false;
		this.zip = new import_jszip_min.default();
		this.files = [];
		this.media = {};
		this.mediaFiles = {};
		this.fonts = {};
		this.decryptedFileData = null;
	}
	async #peekBytes(file, n) {
		if (file instanceof Uint8Array || typeof Buffer !== "undefined" && Buffer.isBuffer(file)) return new Uint8Array(file.buffer, file.byteOffset, Math.min(n, file.byteLength));
		if (file instanceof ArrayBuffer) return new Uint8Array(file, 0, Math.min(n, file.byteLength));
		if (typeof Blob !== "undefined" && file instanceof Blob) try {
			if (typeof file.arrayBuffer === "function") {
				const buf = await file.arrayBuffer();
				return new Uint8Array(buf, 0, Math.min(n, buf.byteLength));
			}
		} catch {}
		return new Uint8Array(0);
	}
	async getDocxData(file, isNode = false, options = {}) {
		const { detectContainerType } = await import("./detect-container-Mk-wjDRB.es.js");
		const containerType = detectContainerType(await this.#peekBytes(file, 8));
		let fileData = file;
		if (containerType === "cfb") {
			const { decryptDocxIfNeeded } = await import("./decrypt-docx-DRUoMq6X.es.js");
			const result = await decryptDocxIfNeeded(file instanceof Uint8Array ? file : file instanceof ArrayBuffer ? new Uint8Array(file) : new Uint8Array(await file.arrayBuffer()), { password: options.password });
			fileData = result.data;
			this.decryptedFileData = result.data;
		}
		const extractedFiles = await this.unzip(fileData);
		const files = Object.entries(extractedFiles.files);
		for (const [, zipEntry] of files) {
			const name = zipEntry.name;
			if (isXmlLike(name)) {
				const content = ensureXmlString(await zipEntry.async("uint8array"));
				this.files.push({
					name,
					content
				});
			} else if (name.startsWith("word/media") && name !== "word/media/" || zipEntry.name.startsWith("media") && zipEntry.name !== "media/" || name.startsWith("media") && name !== "media/" || name.startsWith("word/embeddings") && name !== "word/embeddings/") if (isNode) {
				const fileBase64 = (await zipEntry.async("nodebuffer")).toString("base64");
				this.mediaFiles[name] = fileBase64;
			} else {
				const fileBase64 = await zipEntry.async("base64");
				let extension = this.getFileExtension(name)?.toLowerCase();
				let detectedType = null;
				if (!IMAGE_EXTS.has(extension) || extension === "tmp") {
					detectedType = detectImageType(fileBase64);
					if (detectedType) extension = detectedType;
				}
				if (IMAGE_EXTS.has(extension)) {
					const mimeSubtype = MIME_TYPE_FOR_EXT[extension] || extension;
					this.mediaFiles[name] = `data:image/${mimeSubtype};base64,${fileBase64}`;
					const blob = await zipEntry.async("blob");
					const fileObj = new File([blob], name, { type: blob.type });
					const imageUrl = URL.createObjectURL(fileObj);
					this.media[name] = imageUrl;
				} else this.mediaFiles[name] = fileBase64;
			}
			else if (name.startsWith("word/fonts") && name !== "word/fonts/") {
				const uint8array = await zipEntry.async("uint8array");
				this.fonts[name] = uint8array;
			}
		}
		return this.files;
	}
	getFileExtension(fileName) {
		const fileSplit = fileName.split(".");
		if (fileSplit.length < 2) return null;
		return fileSplit[fileSplit.length - 1];
	}
	async updateContentTypes(docx, media, fromJson, updatedDocs = {}, fonts = {}) {
		const additionalPartNames = Object.keys(updatedDocs || {});
		const newMediaTypes = Object.keys(media).map((name) => this.getFileExtension(name)).filter((ext) => ext && IMAGE_EXTS.has(ext));
		const extensionlessMediaOverrides = Object.entries(media).filter(([name]) => !this.getFileExtension(name)).map(([name, value]) => ({
			name,
			contentType: this.#detectImageContentType(value)
		})).filter((entry) => entry.contentType);
		const contentTypesPath = "[Content_Types].xml";
		let contentTypesXml;
		if (fromJson) if (Array.isArray(docx.files)) contentTypesXml = docx.files.find((file) => file.name === contentTypesPath)?.content || "";
		else contentTypesXml = docx.files?.[contentTypesPath] || "";
		else contentTypesXml = await docx.file(contentTypesPath).async("string");
		let typesString = "";
		const defaultMediaTypes = getContentTypesFromXml(contentTypesXml);
		const seenTypes = /* @__PURE__ */ new Set();
		for (let type of newMediaTypes) {
			if (defaultMediaTypes.includes(type)) continue;
			if (seenTypes.has(type)) continue;
			const newContentType = `<Default Extension="${type}" ContentType="image/${MIME_TYPE_FOR_EXT[type] || type}"/>`;
			typesString += newContentType;
			seenTypes.add(type);
		}
		if (fonts) {
			const fontExts = new Set(Object.keys(fonts).map((name) => this.getFileExtension(name)).filter((ext) => ext && FONT_CONTENT_TYPES[ext]));
			for (const ext of fontExts) {
				if (defaultMediaTypes.includes(ext)) continue;
				if (seenTypes.has(ext)) continue;
				typesString += `<Default Extension="${ext}" ContentType="${FONT_CONTENT_TYPES[ext]}"/>`;
				seenTypes.add(ext);
			}
		}
		const types = JSON.parse(import_lib.xml2json(contentTypesXml, null, 2)).elements?.find((el) => el.name === "Types") || {};
		const hasPartOverride = (partName) => types.elements?.some((el) => el.name === "Override" && el.attributes.PartName === partName);
		for (const { name, contentType } of extensionlessMediaOverrides) {
			const partName = `/${name}`;
			if (hasPartOverride(partName)) continue;
			typesString += `<Override PartName="${partName}" ContentType="${contentType}" />`;
		}
		const hasComments = types.elements?.some((el) => el.name === "Override" && el.attributes.PartName === "/word/comments.xml");
		const hasCommentsExtended = types.elements?.some((el) => el.name === "Override" && el.attributes.PartName === "/word/commentsExtended.xml");
		const hasCommentsIds = types.elements?.some((el) => el.name === "Override" && el.attributes.PartName === "/word/commentsIds.xml");
		const hasCommentsExtensible = types.elements?.some((el) => el.name === "Override" && el.attributes.PartName === "/word/commentsExtensible.xml");
		const hasFile = (filename) => {
			if (updatedDocs && Object.prototype.hasOwnProperty.call(updatedDocs, filename)) return updatedDocs[filename] !== null;
			if (!docx?.files) return false;
			if (!fromJson) return Boolean(docx.files[filename]);
			if (Array.isArray(docx.files)) return docx.files.some((file) => file.name === filename);
			return Boolean(docx.files[filename]);
		};
		if (hasFile("word/comments.xml")) {
			const commentsDef = `<Override PartName="/word/comments.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml" />`;
			if (!hasComments) typesString += commentsDef;
		}
		if (hasFile("word/commentsExtended.xml")) {
			const commentsExtendedDef = `<Override PartName="/word/commentsExtended.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml" />`;
			if (!hasCommentsExtended) typesString += commentsExtendedDef;
		}
		if (hasFile("word/commentsIds.xml")) {
			const commentsIdsDef = `<Override PartName="/word/commentsIds.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.commentsIds+xml" />`;
			if (!hasCommentsIds) typesString += commentsIdsDef;
		}
		if (hasFile("word/commentsExtensible.xml")) {
			const commentsExtendedDef = `<Override PartName="/word/commentsExtensible.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtensible+xml" />`;
			if (!hasCommentsExtensible) typesString += commentsExtendedDef;
		}
		const hasFootnotes = types.elements?.some((el) => el.name === "Override" && el.attributes.PartName === "/word/footnotes.xml");
		if (hasFile("word/footnotes.xml")) {
			const footnotesDef = `<Override PartName="/word/footnotes.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml" />`;
			if (!hasFootnotes) typesString += footnotesDef;
		}
		for (const entry of MANAGED_DOCUMENT_PARTS) if (hasFile(entry.zipPath) && !hasPartOverride(`/${entry.zipPath}`)) typesString += `<Override PartName="/${entry.zipPath}" ContentType="${entry.contentType}" />`;
		const partNames = new Set(additionalPartNames);
		if (docx?.files) if (fromJson && Array.isArray(docx.files)) docx.files.forEach((file) => partNames.add(file.name));
		else Object.keys(docx.files).forEach((key) => partNames.add(key));
		partNames.forEach((name) => {
			if (!/^customXml\/itemProps\d+\.xml$/i.test(name)) return;
			if (!hasFile(name)) return;
			const partName = `/${name}`;
			if (hasPartOverride(partName)) return;
			typesString += `<Override PartName="${partName}" ContentType="${CUSTOM_XML_ITEM_PROPS_CONTENT_TYPE}" />`;
		});
		partNames.forEach((name) => {
			if (name.includes(".rels")) return;
			if (!name.includes("header") && !name.includes("footer")) return;
			const hasExtensible = types.elements?.some((el) => el.name === "Override" && el.attributes.PartName === `/${name}`);
			const extendedDef = `<Override PartName="/${name}" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.${name.includes("header") ? "header" : "footer"}+xml"/>`;
			if (!hasExtensible) typesString += extendedDef;
		});
		const staleOverridePartNames = COMMENT_FILE_BASENAMES.map((name) => `/word/${name}`).filter((partName) => {
			return !hasFile(partName.slice(1));
		});
		const beginningString = "<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">";
		let updatedContentTypesXml = contentTypesXml.replace(beginningString, `${beginningString}${typesString}`);
		for (const partName of staleOverridePartNames) {
			const escapedPartName = partName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
			const overrideRegex = new RegExp(`\\s*<Override[^>]*PartName="${escapedPartName}"[^>]*/>`, "g");
			updatedContentTypesXml = updatedContentTypesXml.replace(overrideRegex, "");
		}
		let relationshipsXml = updatedDocs["word/_rels/document.xml.rels"];
		if (!relationshipsXml) if (fromJson) if (Array.isArray(docx.files)) relationshipsXml = docx.files.find((file) => file.name === "word/_rels/document.xml.rels")?.content;
		else relationshipsXml = docx.files?.["word/_rels/document.xml.rels"];
		else relationshipsXml = await docx.file("word/_rels/document.xml.rels")?.async("string");
		if (relationshipsXml) try {
			(import_lib.xml2js(relationshipsXml, { compact: false }).elements?.find((el) => el.name === "Relationships"))?.elements?.forEach((rel) => {
				const type = rel.attributes?.Type;
				const target = rel.attributes?.Target;
				if (!type || !target) return;
				const isHeader = type.includes("/header");
				const isFooter = type.includes("/footer");
				if (!isHeader && !isFooter) return;
				let sanitizedTarget = target.replace(/^\.\//, "");
				if (sanitizedTarget.startsWith("../")) sanitizedTarget = sanitizedTarget.slice(3);
				if (sanitizedTarget.startsWith("/")) sanitizedTarget = sanitizedTarget.slice(1);
				const partName = sanitizedTarget.startsWith("word/") ? sanitizedTarget : `word/${sanitizedTarget}`;
				partNames.add(partName);
			});
		} catch (error) {
			console.warn("Failed to parse document relationships while updating content types", error);
		}
		partNames.forEach((name) => {
			if (name.includes(".rels")) return;
			if (!name.includes("header") && !name.includes("footer")) return;
			if (updatedContentTypesXml.includes(`PartName="/${name}"`)) return;
			const extendedDef = `<Override PartName="/${name}" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.${name.includes("header") ? "header" : "footer"}+xml"/>`;
			updatedContentTypesXml = updatedContentTypesXml.replace("</Types>", `${extendedDef}</Types>`);
		});
		if (relationshipsXml) {
			const reconciledRels = reconcileDocumentRelationships(relationshipsXml, hasFile);
			if (reconciledRels !== relationshipsXml) if (fromJson) updatedDocs["word/_rels/document.xml.rels"] = reconciledRels;
			else docx.file("word/_rels/document.xml.rels", reconciledRels);
		}
		if (fromJson) return updatedContentTypesXml;
		docx.file(contentTypesPath, updatedContentTypesXml);
	}
	async #syncPackageMetadataInZip(zip) {
		const baseForSync = {};
		zip.forEach((path) => {
			baseForSync[path] = "";
		});
		const ctEntry = zip.file("[Content_Types].xml");
		if (ctEntry) baseForSync["[Content_Types].xml"] = await ctEntry.async("string");
		const rlEntry = zip.file("_rels/.rels");
		if (rlEntry) baseForSync["_rels/.rels"] = await rlEntry.async("string");
		const { contentTypesXml, relsXml } = syncPackageMetadata({
			baseFiles: baseForSync,
			updatedDocs: {}
		});
		zip.file("[Content_Types].xml", contentTypesXml);
		zip.file("_rels/.rels", relsXml);
	}
	async unzip(file) {
		return await this.zip.loadAsync(file);
	}
	async updateZip({ docx, updatedDocs, originalDocxFile, media, fonts, isHeadless, compression = "DEFLATE" }) {
		let zip;
		if (originalDocxFile) zip = await this.exportFromOriginalFile(originalDocxFile, updatedDocs, media, fonts);
		else zip = await this.exportFromCollaborativeDocx(docx, updatedDocs, media, fonts);
		const exportType = isHeadless ? "nodebuffer" : "blob";
		return await zip.generateAsync({
			type: exportType,
			mimeType: DOCX,
			compression,
			compressionOptions: compression === "DEFLATE" ? { level: 6 } : void 0
		});
	}
	async exportFromCollaborativeDocx(docx, updatedDocs, media, fonts) {
		if (!Array.isArray(docx)) throw new Error("Collaborative DOCX export requires base package entries");
		const zip = new import_jszip_min.default();
		for (const file of docx) {
			const content = file.content;
			zip.file(file.name, content);
		}
		Object.keys(updatedDocs).forEach((key) => {
			if (updatedDocs[key] === null) zip.remove(key);
			else zip.file(key, updatedDocs[key]);
		});
		Object.keys(media).forEach((path) => {
			const value = media[path];
			const binaryData = typeof value === "string" ? base64ToUint8Array(value) : value;
			zip.file(path, binaryData);
		});
		for (const [fontName, fontUintArray] of Object.entries(fonts)) zip.file(fontName, fontUintArray);
		await this.updateContentTypes(zip, media, false, updatedDocs, fonts);
		await this.#syncPackageMetadataInZip(zip);
		return zip;
	}
	async exportFromOriginalFile(originalDocxFile, updatedDocs, media, fonts) {
		const unzippedOriginalDocx = await this.unzip(originalDocxFile);
		const filePromises = [];
		unzippedOriginalDocx.forEach((relativePath, zipEntry) => {
			const promise = zipEntry.async("uint8array").then((u8) => {
				unzippedOriginalDocx.file(zipEntry.name, isXmlLike(zipEntry.name) ? ensureXmlString(u8) : u8);
			});
			filePromises.push(promise);
		});
		await Promise.all(filePromises);
		Object.keys(updatedDocs).forEach((key) => {
			if (updatedDocs[key] === null) unzippedOriginalDocx.remove(key);
			else unzippedOriginalDocx.file(key, updatedDocs[key]);
		});
		Object.keys(media).forEach((path) => {
			unzippedOriginalDocx.file(path, media[path]);
		});
		if (fonts) for (const [fontName, fontUintArray] of Object.entries(fonts)) unzippedOriginalDocx.file(fontName, fontUintArray);
		await this.updateContentTypes(unzippedOriginalDocx, media, false, updatedDocs, fonts);
		await this.#syncPackageMetadataInZip(unzippedOriginalDocx);
		return unzippedOriginalDocx;
	}
	#detectImageContentType(value) {
		if (value == null) return null;
		if (typeof value === "string" && value.startsWith("data:image/")) return value.match(/^data:(image\/[a-zA-Z0-9.+-]+);/i)?.[1]?.toLowerCase() || null;
		let detectedType = null;
		if (value instanceof ArrayBuffer) detectedType = detectImageType(new Uint8Array(value));
		else if (ArrayBuffer.isView(value)) detectedType = detectImageType(new Uint8Array(value.buffer, value.byteOffset, value.byteLength));
		else if (typeof value === "string") detectedType = detectImageType(value.startsWith("data:") ? value.split(",", 2)[1] : value);
		if (!detectedType) return null;
		return `image/${MIME_TYPE_FOR_EXT[detectedType] || detectedType}`;
	}
};
var DocxZipper_default = DocxZipper;
export { PDF as a, HTML as i, syncPackageMetadata as n, documentTypes as o, DOCX as r, DocxZipper_default as t };
