@bendyline/squisq-formats 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -10
- package/dist/{chunk-MQHCXI56.js → chunk-6OVREALI.js} +31 -13
- package/dist/chunk-6OVREALI.js.map +1 -0
- package/dist/{chunk-ULLIPBEJ.js → chunk-743COJWQ.js} +6 -2
- package/dist/chunk-743COJWQ.js.map +1 -0
- package/dist/{chunk-KAK4V57E.js → chunk-BHHEDPRB.js} +16 -112
- package/dist/chunk-BHHEDPRB.js.map +1 -0
- package/dist/chunk-FIFCQN3W.js +630 -0
- package/dist/chunk-FIFCQN3W.js.map +1 -0
- package/dist/chunk-KJ4NS4DX.js +120 -0
- package/dist/chunk-KJ4NS4DX.js.map +1 -0
- package/dist/{chunk-TBPD5PCU.js → chunk-PP5N46YD.js} +33 -11
- package/dist/chunk-PP5N46YD.js.map +1 -0
- package/dist/docx/export.d.ts +6 -0
- package/dist/docx/export.d.ts.map +1 -1
- package/dist/docx/export.js +24 -7
- package/dist/docx/export.js.map +1 -1
- package/dist/html/htmlTemplate.d.ts +6 -0
- package/dist/html/htmlTemplate.d.ts.map +1 -1
- package/dist/html/htmlTemplate.js +5 -1
- package/dist/html/htmlTemplate.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/ooxml/index.d.ts +1 -1
- package/dist/ooxml/index.d.ts.map +1 -1
- package/dist/ooxml/index.js +1 -1
- package/dist/ooxml/index.js.map +1 -1
- package/dist/ooxml/namespaces.d.ts +10 -0
- package/dist/ooxml/namespaces.d.ts.map +1 -1
- package/dist/ooxml/namespaces.js +10 -0
- package/dist/ooxml/namespaces.js.map +1 -1
- package/dist/pdf/export.d.ts +6 -0
- package/dist/pdf/export.d.ts.map +1 -1
- package/dist/pdf/export.js +37 -9
- package/dist/pdf/export.js.map +1 -1
- package/dist/pptx/export.d.ts +75 -0
- package/dist/pptx/export.d.ts.map +1 -0
- package/dist/pptx/export.js +722 -0
- package/dist/pptx/export.js.map +1 -0
- package/dist/pptx/index.d.ts +12 -27
- package/dist/pptx/index.d.ts.map +1 -1
- package/dist/pptx/index.js +12 -22
- package/dist/pptx/index.js.map +1 -1
- package/dist/pptx/styles.d.ts +54 -0
- package/dist/pptx/styles.d.ts.map +1 -0
- package/dist/pptx/styles.js +73 -0
- package/dist/pptx/styles.js.map +1 -0
- package/dist/pptx/templates.d.ts +24 -0
- package/dist/pptx/templates.d.ts.map +1 -0
- package/dist/pptx/templates.js +158 -0
- package/dist/pptx/templates.js.map +1 -0
- package/package.json +2 -2
- package/src/docx/export.ts +36 -8
- package/src/html/htmlTemplate.ts +13 -0
- package/src/index.ts +2 -2
- package/src/ooxml/index.ts +7 -0
- package/src/ooxml/namespaces.ts +23 -0
- package/src/pdf/export.ts +57 -9
- package/src/pptx/export.ts +1041 -0
- package/src/pptx/index.ts +15 -37
- package/src/pptx/styles.ts +96 -0
- package/src/pptx/templates.ts +187 -0
- package/dist/chunk-532L4D5D.js +0 -21
- package/dist/chunk-532L4D5D.js.map +0 -1
- package/dist/chunk-KAK4V57E.js.map +0 -1
- package/dist/chunk-MQHCXI56.js.map +0 -1
- package/dist/chunk-TBPD5PCU.js.map +0 -1
- package/dist/chunk-ULLIPBEJ.js.map +0 -1
|
@@ -33,6 +33,13 @@ var CONTENT_TYPE_DOCX_SETTINGS = "application/vnd.openxmlformats-officedocument.
|
|
|
33
33
|
var CONTENT_TYPE_DOCX_FONT_TABLE = "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml";
|
|
34
34
|
var CONTENT_TYPE_DOCX_FOOTNOTES = "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml";
|
|
35
35
|
var CONTENT_TYPE_PPTX_PRESENTATION = "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml";
|
|
36
|
+
var CONTENT_TYPE_PPTX_SLIDE = "application/vnd.openxmlformats-officedocument.presentationml.slide+xml";
|
|
37
|
+
var CONTENT_TYPE_PPTX_SLIDE_LAYOUT = "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml";
|
|
38
|
+
var CONTENT_TYPE_PPTX_SLIDE_MASTER = "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml";
|
|
39
|
+
var CONTENT_TYPE_PPTX_THEME = "application/vnd.openxmlformats-officedocument.theme+xml";
|
|
40
|
+
var REL_SLIDE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide";
|
|
41
|
+
var REL_SLIDE_LAYOUT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout";
|
|
42
|
+
var REL_SLIDE_MASTER = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster";
|
|
36
43
|
var CONTENT_TYPE_XLSX_WORKBOOK = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml";
|
|
37
44
|
|
|
38
45
|
// src/ooxml/xmlUtils.ts
|
|
@@ -230,111 +237,6 @@ function groupRelationshipsBySource(pending) {
|
|
|
230
237
|
return grouped;
|
|
231
238
|
}
|
|
232
239
|
|
|
233
|
-
// src/ooxml/reader.ts
|
|
234
|
-
import JSZip2 from "jszip";
|
|
235
|
-
async function openPackage(data) {
|
|
236
|
-
const zip = await JSZip2.loadAsync(data);
|
|
237
|
-
const contentTypes = await parseContentTypes(zip);
|
|
238
|
-
const rootRelationships = await parseRelationships(zip, "");
|
|
239
|
-
return { zip, contentTypes, rootRelationships };
|
|
240
|
-
}
|
|
241
|
-
async function parseContentTypes(zip) {
|
|
242
|
-
const overrides = /* @__PURE__ */ new Map();
|
|
243
|
-
const defaults = /* @__PURE__ */ new Map();
|
|
244
|
-
const file = zip.file("[Content_Types].xml");
|
|
245
|
-
if (!file) return { overrides, defaults };
|
|
246
|
-
const text = await file.async("text");
|
|
247
|
-
const doc = new DOMParser().parseFromString(text, "application/xml");
|
|
248
|
-
const defaultEls = doc.getElementsByTagName("Default");
|
|
249
|
-
for (let i = 0; i < defaultEls.length; i++) {
|
|
250
|
-
const el = defaultEls[i];
|
|
251
|
-
const ext = el.getAttribute("Extension");
|
|
252
|
-
const ct = el.getAttribute("ContentType");
|
|
253
|
-
if (ext && ct) defaults.set(ext, ct);
|
|
254
|
-
}
|
|
255
|
-
const overrideEls = doc.getElementsByTagName("Override");
|
|
256
|
-
for (let i = 0; i < overrideEls.length; i++) {
|
|
257
|
-
const el = overrideEls[i];
|
|
258
|
-
const partName = el.getAttribute("PartName");
|
|
259
|
-
const ct = el.getAttribute("ContentType");
|
|
260
|
-
if (partName && ct) {
|
|
261
|
-
overrides.set(partName.replace(/^\//, ""), ct);
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
return { overrides, defaults };
|
|
265
|
-
}
|
|
266
|
-
async function getPartRelationships(pkg, partPath) {
|
|
267
|
-
return parseRelationships(pkg.zip, partPath);
|
|
268
|
-
}
|
|
269
|
-
async function parseRelationships(zip, partPath) {
|
|
270
|
-
const relsPath = partPath === "" ? "_rels/.rels" : buildRelsPath2(partPath);
|
|
271
|
-
const file = zip.file(relsPath);
|
|
272
|
-
if (!file) return [];
|
|
273
|
-
const text = await file.async("text");
|
|
274
|
-
const doc = new DOMParser().parseFromString(text, "application/xml");
|
|
275
|
-
const result = [];
|
|
276
|
-
const els = doc.getElementsByTagNameNS(NS_RELATIONSHIPS, "Relationship");
|
|
277
|
-
const fallbackEls = els.length > 0 ? els : doc.getElementsByTagName("Relationship");
|
|
278
|
-
for (let i = 0; i < fallbackEls.length; i++) {
|
|
279
|
-
const el = fallbackEls[i];
|
|
280
|
-
const id = el.getAttribute("Id");
|
|
281
|
-
const type = el.getAttribute("Type");
|
|
282
|
-
const target = el.getAttribute("Target");
|
|
283
|
-
if (id && type && target) {
|
|
284
|
-
const targetMode = el.getAttribute("TargetMode");
|
|
285
|
-
result.push({
|
|
286
|
-
id,
|
|
287
|
-
type,
|
|
288
|
-
target,
|
|
289
|
-
...targetMode ? { targetMode } : {}
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
return result;
|
|
294
|
-
}
|
|
295
|
-
function buildRelsPath2(partPath) {
|
|
296
|
-
const lastSlash = partPath.lastIndexOf("/");
|
|
297
|
-
if (lastSlash === -1) {
|
|
298
|
-
return `_rels/${partPath}.rels`;
|
|
299
|
-
}
|
|
300
|
-
const dir = partPath.substring(0, lastSlash);
|
|
301
|
-
const file = partPath.substring(lastSlash + 1);
|
|
302
|
-
return `${dir}/_rels/${file}.rels`;
|
|
303
|
-
}
|
|
304
|
-
async function getPartXml(pkg, partPath) {
|
|
305
|
-
const file = pkg.zip.file(partPath);
|
|
306
|
-
if (!file) return null;
|
|
307
|
-
const text = await file.async("text");
|
|
308
|
-
return new DOMParser().parseFromString(text, "application/xml");
|
|
309
|
-
}
|
|
310
|
-
async function getPartBinary(pkg, partPath) {
|
|
311
|
-
const file = pkg.zip.file(partPath);
|
|
312
|
-
if (!file) return null;
|
|
313
|
-
return file.async("arraybuffer");
|
|
314
|
-
}
|
|
315
|
-
async function getCoreProperties(pkg) {
|
|
316
|
-
const doc = await getPartXml(pkg, "docProps/core.xml");
|
|
317
|
-
if (!doc) return {};
|
|
318
|
-
function getText(ns, localName) {
|
|
319
|
-
const els = doc.getElementsByTagNameNS(ns, localName);
|
|
320
|
-
if (els.length > 0 && els[0].textContent) {
|
|
321
|
-
return els[0].textContent;
|
|
322
|
-
}
|
|
323
|
-
return void 0;
|
|
324
|
-
}
|
|
325
|
-
return {
|
|
326
|
-
title: getText(NS_DC, "title"),
|
|
327
|
-
subject: getText(NS_DC, "subject"),
|
|
328
|
-
creator: getText(NS_DC, "creator"),
|
|
329
|
-
description: getText(NS_DC, "description"),
|
|
330
|
-
keywords: getText(NS_CORE_PROPERTIES, "keywords"),
|
|
331
|
-
lastModifiedBy: getText(NS_CORE_PROPERTIES, "lastModifiedBy"),
|
|
332
|
-
revision: getText(NS_CORE_PROPERTIES, "revision"),
|
|
333
|
-
created: getText(NS_DCTERMS, "created"),
|
|
334
|
-
modified: getText(NS_DCTERMS, "modified")
|
|
335
|
-
};
|
|
336
|
-
}
|
|
337
|
-
|
|
338
240
|
export {
|
|
339
241
|
NS_RELATIONSHIPS,
|
|
340
242
|
NS_CONTENT_TYPES,
|
|
@@ -370,6 +272,13 @@ export {
|
|
|
370
272
|
CONTENT_TYPE_DOCX_FONT_TABLE,
|
|
371
273
|
CONTENT_TYPE_DOCX_FOOTNOTES,
|
|
372
274
|
CONTENT_TYPE_PPTX_PRESENTATION,
|
|
275
|
+
CONTENT_TYPE_PPTX_SLIDE,
|
|
276
|
+
CONTENT_TYPE_PPTX_SLIDE_LAYOUT,
|
|
277
|
+
CONTENT_TYPE_PPTX_SLIDE_MASTER,
|
|
278
|
+
CONTENT_TYPE_PPTX_THEME,
|
|
279
|
+
REL_SLIDE,
|
|
280
|
+
REL_SLIDE_LAYOUT,
|
|
281
|
+
REL_SLIDE_MASTER,
|
|
373
282
|
CONTENT_TYPE_XLSX_WORKBOOK,
|
|
374
283
|
xmlDeclaration,
|
|
375
284
|
escapeXml,
|
|
@@ -377,11 +286,6 @@ export {
|
|
|
377
286
|
selfClosingElement,
|
|
378
287
|
xmlElement,
|
|
379
288
|
textElement,
|
|
380
|
-
createPackage
|
|
381
|
-
openPackage,
|
|
382
|
-
getPartRelationships,
|
|
383
|
-
getPartXml,
|
|
384
|
-
getPartBinary,
|
|
385
|
-
getCoreProperties
|
|
289
|
+
createPackage
|
|
386
290
|
};
|
|
387
|
-
//# sourceMappingURL=chunk-
|
|
291
|
+
//# sourceMappingURL=chunk-BHHEDPRB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ooxml/namespaces.ts","../src/ooxml/xmlUtils.ts","../src/ooxml/writer.ts"],"sourcesContent":["/**\n * OOXML Namespace Constants\n *\n * All Office Open XML namespace URIs used across DOCX, PPTX, and XLSX.\n * Organized by category for easy reference.\n */\n\n// ============================================\n// Package-level namespaces (shared by all formats)\n// ============================================\n\n/** Relationships namespace (used in _rels/*.rels files) */\nexport const NS_RELATIONSHIPS = 'http://schemas.openxmlformats.org/package/2006/relationships';\n\n/** Content Types namespace ([Content_Types].xml) */\nexport const NS_CONTENT_TYPES = 'http://schemas.openxmlformats.org/package/2006/content-types';\n\n// ============================================\n// Relationship type URIs\n// ============================================\n\n/** Relationship type: Office document (main part) */\nexport const REL_OFFICE_DOCUMENT =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument';\n\n/** Relationship type: Core properties */\nexport const REL_CORE_PROPERTIES =\n 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties';\n\n/** Relationship type: Extended properties (app.xml) */\nexport const REL_EXTENDED_PROPERTIES =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties';\n\n/** Relationship type: Styles */\nexport const REL_STYLES =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles';\n\n/** Relationship type: Numbering */\nexport const REL_NUMBERING =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering';\n\n/** Relationship type: Font table */\nexport const REL_FONT_TABLE =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable';\n\n/** Relationship type: Settings */\nexport const REL_SETTINGS =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings';\n\n/** Relationship type: Hyperlink */\nexport const REL_HYPERLINK =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink';\n\n/** Relationship type: Image */\nexport const REL_IMAGE =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image';\n\n/** Relationship type: Footnotes */\nexport const REL_FOOTNOTES =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes';\n\n/** Relationship type: Theme */\nexport const REL_THEME =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme';\n\n// ============================================\n// WordprocessingML (DOCX)\n// ============================================\n\n/** WordprocessingML main namespace (w:) */\nexport const NS_WML = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';\n\n// ============================================\n// PresentationML (PPTX)\n// ============================================\n\n/** PresentationML main namespace (p:) */\nexport const NS_PML = 'http://schemas.openxmlformats.org/presentationml/2006/main';\n\n// ============================================\n// SpreadsheetML (XLSX)\n// ============================================\n\n/** SpreadsheetML main namespace */\nexport const NS_SML = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main';\n\n// ============================================\n// DrawingML (shared across formats)\n// ============================================\n\n/** DrawingML main namespace (a:) */\nexport const NS_DRAWINGML = 'http://schemas.openxmlformats.org/drawingml/2006/main';\n\n/** DrawingML WordprocessingML drawing namespace (wp:) */\nexport const NS_WP_DRAWING =\n 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing';\n\n/** DrawingML picture namespace (pic:) */\nexport const NS_PICTURE = 'http://schemas.openxmlformats.org/drawingml/2006/picture';\n\n// ============================================\n// Dublin Core / Core Properties\n// ============================================\n\n/** Dublin Core elements namespace */\nexport const NS_DC = 'http://purl.org/dc/elements/1.1/';\n\n/** Dublin Core terms namespace */\nexport const NS_DCTERMS = 'http://purl.org/dc/terms/';\n\n/** Core properties namespace */\nexport const NS_CORE_PROPERTIES =\n 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties';\n\n/** XML Schema Instance namespace */\nexport const NS_XSI = 'http://www.w3.org/2001/XMLSchema-instance';\n\n// ============================================\n// Markup Compatibility\n// ============================================\n\n/** Markup Compatibility namespace (mc:) */\nexport const NS_MC = 'http://schemas.openxmlformats.org/markup-compatibility/2006';\n\n/** Office relationships namespace (r:) */\nexport const NS_R = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships';\n\n// ============================================\n// Content type strings\n// ============================================\n\nexport const CONTENT_TYPE_RELATIONSHIPS =\n 'application/vnd.openxmlformats-package.relationships+xml';\n\nexport const CONTENT_TYPE_CORE_PROPERTIES =\n 'application/vnd.openxmlformats-package.core-properties+xml';\n\nexport const CONTENT_TYPE_DOCX_DOCUMENT =\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml';\n\nexport const CONTENT_TYPE_DOCX_STYLES =\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml';\n\nexport const CONTENT_TYPE_DOCX_NUMBERING =\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml';\n\nexport const CONTENT_TYPE_DOCX_SETTINGS =\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml';\n\nexport const CONTENT_TYPE_DOCX_FONT_TABLE =\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml';\n\nexport const CONTENT_TYPE_DOCX_FOOTNOTES =\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml';\n\nexport const CONTENT_TYPE_PPTX_PRESENTATION =\n 'application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml';\n\nexport const CONTENT_TYPE_PPTX_SLIDE =\n 'application/vnd.openxmlformats-officedocument.presentationml.slide+xml';\n\nexport const CONTENT_TYPE_PPTX_SLIDE_LAYOUT =\n 'application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml';\n\nexport const CONTENT_TYPE_PPTX_SLIDE_MASTER =\n 'application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml';\n\nexport const CONTENT_TYPE_PPTX_THEME = 'application/vnd.openxmlformats-officedocument.theme+xml';\n\n/** Relationship type: Slide */\nexport const REL_SLIDE =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide';\n\n/** Relationship type: Slide layout */\nexport const REL_SLIDE_LAYOUT =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout';\n\n/** Relationship type: Slide master */\nexport const REL_SLIDE_MASTER =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster';\n\nexport const CONTENT_TYPE_XLSX_WORKBOOK =\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml';\n","/**\n * XML Utility Functions\n *\n * Lightweight helpers for generating well-formed XML strings.\n * Used by all OOXML writers (DOCX, PPTX, XLSX) to construct\n * part content without a heavy DOM library.\n */\n\n/**\n * XML declaration for the start of every OOXML part.\n */\nexport function xmlDeclaration(): string {\n return '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>';\n}\n\n/**\n * Escape a string for safe inclusion in XML text content or attribute values.\n *\n * Handles the five predefined XML entities:\n * - & → &\n * - < → <\n * - > → >\n * - \" → "\n * - ' → '\n */\nexport function escapeXml(text: string): string {\n return text\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\n/**\n * Build an XML attribute string from a key-value record.\n * Only includes entries where the value is defined and non-empty.\n *\n * @example\n * ```ts\n * attrString({ 'w:val': 'Heading1', 'w:eastAsia': undefined })\n * // ' w:val=\"Heading1\"'\n * ```\n */\nexport function attrString(attrs?: Record<string, string | undefined>): string {\n if (!attrs) return '';\n const parts: string[] = [];\n for (const [key, value] of Object.entries(attrs)) {\n if (value !== undefined && value !== '') {\n parts.push(` ${key}=\"${escapeXml(value)}\"`);\n }\n }\n return parts.join('');\n}\n\n/**\n * Build a self-closing XML element: `<tag attr=\"val\"/>`.\n *\n * @example\n * ```ts\n * selfClosingElement('w:b')\n * // '<w:b/>'\n *\n * selfClosingElement('w:pStyle', { 'w:val': 'Heading1' })\n * // '<w:pStyle w:val=\"Heading1\"/>'\n * ```\n */\nexport function selfClosingElement(\n tag: string,\n attrs?: Record<string, string | undefined>,\n): string {\n return `<${tag}${attrString(attrs)}/>`;\n}\n\n/**\n * Build an XML element with children: `<tag attr=\"val\">...children...</tag>`.\n * Children are concatenated directly (no extra whitespace).\n *\n * @example\n * ```ts\n * xmlElement('w:p', {},\n * xmlElement('w:r', {},\n * xmlElement('w:t', {}, 'Hello')\n * )\n * )\n * // '<w:p><w:r><w:t>Hello</w:t></w:r></w:p>'\n * ```\n */\nexport function xmlElement(\n tag: string,\n attrs?: Record<string, string | undefined>,\n ...children: string[]\n): string {\n const content = children.join('');\n if (content === '') {\n return selfClosingElement(tag, attrs);\n }\n return `<${tag}${attrString(attrs)}>${content}</${tag}>`;\n}\n\n/**\n * Build an XML text element: `<tag attr=\"val\">escaped text</tag>`.\n * The text value is XML-escaped automatically.\n *\n * This is a convenience for the common pattern of wrapping text in an element,\n * where you want automatic escaping (unlike `xmlElement` which takes raw children).\n *\n * @example\n * ```ts\n * textElement('w:t', { 'xml:space': 'preserve' }, 'Hello & world')\n * // '<w:t xml:space=\"preserve\">Hello & world</w:t>'\n * ```\n */\nexport function textElement(\n tag: string,\n attrs?: Record<string, string | undefined>,\n text?: string,\n): string {\n if (text === undefined || text === '') {\n return selfClosingElement(tag, attrs);\n }\n return `<${tag}${attrString(attrs)}>${escapeXml(text)}</${tag}>`;\n}\n","/**\n * OOXML Package Writer\n *\n * Builds OOXML archives (.docx, .pptx, .xlsx) from parts.\n * Handles automatic generation of [Content_Types].xml and\n * _rels/*.rels files from the registered parts and relationships.\n */\n\nimport JSZip from 'jszip';\nimport type { CoreProperties, PackagePart, PendingRelationship, Relationship } from './types.js';\nimport {\n NS_CONTENT_TYPES,\n NS_RELATIONSHIPS,\n NS_CORE_PROPERTIES,\n NS_DC,\n NS_DCTERMS,\n NS_XSI,\n CONTENT_TYPE_RELATIONSHIPS,\n CONTENT_TYPE_CORE_PROPERTIES,\n REL_CORE_PROPERTIES,\n} from './namespaces.js';\nimport { xmlDeclaration, escapeXml } from './xmlUtils.js';\n\n// ============================================\n// Package Builder\n// ============================================\n\n/**\n * Mutable builder for constructing an OOXML package.\n *\n * Add parts, relationships, and core properties, then call `toBlob()`\n * or `toArrayBuffer()` to produce the final ZIP archive.\n *\n * @example\n * ```ts\n * const builder = createPackage();\n * builder.addPart('word/document.xml', documentXml, CONTENT_TYPE_DOCX_DOCUMENT);\n * builder.addRelationship('', {\n * id: 'rId1',\n * type: REL_OFFICE_DOCUMENT,\n * target: 'word/document.xml',\n * });\n * const blob = await builder.toBlob();\n * ```\n */\nexport interface OoxmlPackageBuilder {\n /**\n * Add an XML or text part to the package.\n *\n * @param path - Path within the archive (e.g., \"word/document.xml\")\n * @param content - XML string content\n * @param contentType - MIME content type for [Content_Types].xml\n */\n addPart(path: string, content: string, contentType: string): void;\n\n /**\n * Add a binary part to the package (e.g., an image).\n *\n * @param path - Path within the archive (e.g., \"word/media/image1.png\")\n * @param data - Binary content\n * @param contentType - MIME content type (e.g., \"image/png\")\n */\n addBinaryPart(path: string, data: ArrayBuffer | Uint8Array, contentType: string): void;\n\n /**\n * Register a relationship.\n *\n * @param sourcePart - The part this relationship belongs to (e.g., \"word/document.xml\").\n * Use \"\" (empty string) for root-level relationships (_rels/.rels).\n * @param rel - The relationship entry\n */\n addRelationship(sourcePart: string, rel: Relationship): void;\n\n /**\n * Set core document properties (docProps/core.xml).\n * Calling this multiple times overwrites previous values.\n */\n setCoreProperties(props: CoreProperties): void;\n\n /**\n * Assemble the final OOXML package as a Blob.\n * Generates [Content_Types].xml and all _rels/*.rels files automatically.\n */\n toBlob(): Promise<Blob>;\n\n /**\n * Assemble the final OOXML package as an ArrayBuffer.\n */\n toArrayBuffer(): Promise<ArrayBuffer>;\n}\n\n/**\n * Create a new OOXML package builder.\n */\nexport function createPackage(): OoxmlPackageBuilder {\n const parts: PackagePart[] = [];\n const relationships: PendingRelationship[] = [];\n let coreProps: CoreProperties | undefined;\n\n return {\n addPart(path, content, contentType) {\n parts.push({ path, content, contentType });\n },\n\n addBinaryPart(path, data, contentType) {\n parts.push({ path, binaryContent: data, contentType });\n },\n\n addRelationship(sourcePart, rel) {\n relationships.push({ sourcePart, relationship: rel });\n },\n\n setCoreProperties(props) {\n coreProps = props;\n },\n\n async toBlob() {\n const zip = assemble(parts, relationships, coreProps);\n return zip.generateAsync({ type: 'blob' });\n },\n\n async toArrayBuffer() {\n const zip = assemble(parts, relationships, coreProps);\n return zip.generateAsync({ type: 'arraybuffer' });\n },\n };\n}\n\n// ============================================\n// Assembly\n// ============================================\n\n/**\n * Assemble a JSZip archive from parts, relationships, and core properties.\n */\nfunction assemble(\n parts: PackagePart[],\n relationships: PendingRelationship[],\n coreProps?: CoreProperties,\n): JSZip {\n const zip = new JSZip();\n\n // Write content parts\n for (const part of parts) {\n if (part.content !== undefined) {\n zip.file(part.path, part.content);\n } else if (part.binaryContent !== undefined) {\n zip.file(part.path, part.binaryContent);\n }\n }\n\n // Add core properties if set\n if (coreProps) {\n const coreXml = buildCorePropertiesXml(coreProps);\n zip.file('docProps/core.xml', coreXml);\n\n // Add relationship to core properties\n relationships.push({\n sourcePart: '',\n relationship: {\n id: `rId${relationships.length + 100}`,\n type: REL_CORE_PROPERTIES,\n target: 'docProps/core.xml',\n },\n });\n }\n\n // Build and write [Content_Types].xml\n zip.file('[Content_Types].xml', buildContentTypesXml(parts, coreProps));\n\n // Build and write _rels/*.rels files\n const relsBySource = groupRelationshipsBySource(relationships);\n for (const [sourcePart, rels] of relsBySource) {\n const relsPath = sourcePart === '' ? '_rels/.rels' : buildRelsPath(sourcePart);\n zip.file(relsPath, buildRelationshipsXml(rels));\n }\n\n return zip;\n}\n\n// ============================================\n// [Content_Types].xml\n// ============================================\n\nfunction buildContentTypesXml(parts: PackagePart[], coreProps?: CoreProperties): string {\n const lines: string[] = [xmlDeclaration()];\n lines.push(`<Types xmlns=\"${NS_CONTENT_TYPES}\">`);\n\n // Default extension types\n const extensionTypes = new Map<string, string>();\n extensionTypes.set('rels', CONTENT_TYPE_RELATIONSHIPS);\n extensionTypes.set('xml', 'application/xml');\n\n // Collect extensions from binary parts (e.g., png, jpeg)\n for (const part of parts) {\n if (part.binaryContent !== undefined) {\n const ext = getExtension(part.path);\n if (ext && !extensionTypes.has(ext)) {\n extensionTypes.set(ext, part.contentType);\n }\n }\n }\n\n for (const [ext, ct] of extensionTypes) {\n lines.push(` <Default Extension=\"${escapeXml(ext)}\" ContentType=\"${escapeXml(ct)}\"/>`);\n }\n\n // Override entries for each XML part\n for (const part of parts) {\n if (part.content !== undefined) {\n lines.push(\n ` <Override PartName=\"/${escapeXml(part.path)}\" ContentType=\"${escapeXml(part.contentType)}\"/>`,\n );\n }\n }\n\n // Core properties override\n if (coreProps) {\n lines.push(\n ` <Override PartName=\"/docProps/core.xml\" ContentType=\"${CONTENT_TYPE_CORE_PROPERTIES}\"/>`,\n );\n }\n\n lines.push('</Types>');\n return lines.join('\\n');\n}\n\n// ============================================\n// Relationships XML\n// ============================================\n\nfunction buildRelationshipsXml(rels: Relationship[]): string {\n const lines: string[] = [xmlDeclaration()];\n lines.push(`<Relationships xmlns=\"${NS_RELATIONSHIPS}\">`);\n\n for (const rel of rels) {\n const attrs: string[] = [\n `Id=\"${escapeXml(rel.id)}\"`,\n `Type=\"${escapeXml(rel.type)}\"`,\n `Target=\"${escapeXml(rel.target)}\"`,\n ];\n if (rel.targetMode) {\n attrs.push(`TargetMode=\"${escapeXml(rel.targetMode)}\"`);\n }\n lines.push(` <Relationship ${attrs.join(' ')}/>`);\n }\n\n lines.push('</Relationships>');\n return lines.join('\\n');\n}\n\n// ============================================\n// Core Properties XML\n// ============================================\n\nfunction buildCorePropertiesXml(props: CoreProperties): string {\n const lines: string[] = [xmlDeclaration()];\n lines.push(\n `<cp:coreProperties` +\n ` xmlns:cp=\"${NS_CORE_PROPERTIES}\"` +\n ` xmlns:dc=\"${NS_DC}\"` +\n ` xmlns:dcterms=\"${NS_DCTERMS}\"` +\n ` xmlns:xsi=\"${NS_XSI}\">`,\n );\n\n if (props.title) lines.push(` <dc:title>${escapeXml(props.title)}</dc:title>`);\n if (props.subject) lines.push(` <dc:subject>${escapeXml(props.subject)}</dc:subject>`);\n if (props.creator) lines.push(` <dc:creator>${escapeXml(props.creator)}</dc:creator>`);\n if (props.description)\n lines.push(` <dc:description>${escapeXml(props.description)}</dc:description>`);\n if (props.keywords) lines.push(` <cp:keywords>${escapeXml(props.keywords)}</cp:keywords>`);\n if (props.lastModifiedBy)\n lines.push(` <cp:lastModifiedBy>${escapeXml(props.lastModifiedBy)}</cp:lastModifiedBy>`);\n if (props.revision) lines.push(` <cp:revision>${escapeXml(props.revision)}</cp:revision>`);\n if (props.created) {\n lines.push(\n ` <dcterms:created xsi:type=\"dcterms:W3CDTF\">${escapeXml(props.created)}</dcterms:created>`,\n );\n }\n if (props.modified) {\n lines.push(\n ` <dcterms:modified xsi:type=\"dcterms:W3CDTF\">${escapeXml(props.modified)}</dcterms:modified>`,\n );\n }\n\n lines.push('</cp:coreProperties>');\n return lines.join('\\n');\n}\n\n// ============================================\n// Helpers\n// ============================================\n\nfunction getExtension(path: string): string | undefined {\n const dot = path.lastIndexOf('.');\n if (dot === -1) return undefined;\n return path.substring(dot + 1).toLowerCase();\n}\n\nfunction buildRelsPath(partPath: string): string {\n const lastSlash = partPath.lastIndexOf('/');\n if (lastSlash === -1) {\n return `_rels/${partPath}.rels`;\n }\n const dir = partPath.substring(0, lastSlash);\n const file = partPath.substring(lastSlash + 1);\n return `${dir}/_rels/${file}.rels`;\n}\n\nfunction groupRelationshipsBySource(pending: PendingRelationship[]): Map<string, Relationship[]> {\n const grouped = new Map<string, Relationship[]>();\n for (const { sourcePart, relationship } of pending) {\n let list = grouped.get(sourcePart);\n if (!list) {\n list = [];\n grouped.set(sourcePart, list);\n }\n list.push(relationship);\n }\n return grouped;\n}\n"],"mappings":"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","names":[]}
|