@bendyline/squisq-formats 0.1.0

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.
Files changed (61) hide show
  1. package/dist/chunk-532L4D5D.js +21 -0
  2. package/dist/chunk-532L4D5D.js.map +1 -0
  3. package/dist/chunk-67KIJHV2.js +21 -0
  4. package/dist/chunk-67KIJHV2.js.map +1 -0
  5. package/dist/chunk-KAK4V57E.js +387 -0
  6. package/dist/chunk-KAK4V57E.js.map +1 -0
  7. package/dist/chunk-MQHCXI56.js +1035 -0
  8. package/dist/chunk-MQHCXI56.js.map +1 -0
  9. package/dist/chunk-TBPD5PCU.js +1136 -0
  10. package/dist/chunk-TBPD5PCU.js.map +1 -0
  11. package/dist/chunk-ULLIPBEJ.js +271 -0
  12. package/dist/chunk-ULLIPBEJ.js.map +1 -0
  13. package/dist/docx/index.d.ts +108 -0
  14. package/dist/docx/index.js +14 -0
  15. package/dist/docx/index.js.map +1 -0
  16. package/dist/html/index.d.ts +166 -0
  17. package/dist/html/index.js +17 -0
  18. package/dist/html/index.js.map +1 -0
  19. package/dist/index.d.ts +7 -0
  20. package/dist/index.js +54 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/ooxml/index.d.ts +351 -0
  23. package/dist/ooxml/index.js +99 -0
  24. package/dist/ooxml/index.js.map +1 -0
  25. package/dist/pdf/index.d.ts +130 -0
  26. package/dist/pdf/index.js +15 -0
  27. package/dist/pdf/index.js.map +1 -0
  28. package/dist/pptx/index.d.ts +58 -0
  29. package/dist/pptx/index.js +13 -0
  30. package/dist/pptx/index.js.map +1 -0
  31. package/dist/xlsx/index.d.ts +58 -0
  32. package/dist/xlsx/index.js +13 -0
  33. package/dist/xlsx/index.js.map +1 -0
  34. package/package.json +85 -0
  35. package/src/__tests__/docxExport.test.ts +457 -0
  36. package/src/__tests__/docxImport.test.ts +410 -0
  37. package/src/__tests__/html.test.ts +295 -0
  38. package/src/__tests__/ooxml.test.ts +197 -0
  39. package/src/__tests__/pdfExport.test.ts +322 -0
  40. package/src/__tests__/pdfImport.test.ts +290 -0
  41. package/src/__tests__/roundTrip.test.ts +201 -0
  42. package/src/docx/export.ts +978 -0
  43. package/src/docx/import.ts +909 -0
  44. package/src/docx/index.ts +26 -0
  45. package/src/docx/styles.ts +145 -0
  46. package/src/html/htmlTemplate.ts +307 -0
  47. package/src/html/imageUtils.ts +66 -0
  48. package/src/html/index.ts +168 -0
  49. package/src/index.ts +51 -0
  50. package/src/ooxml/index.ts +87 -0
  51. package/src/ooxml/namespaces.ts +160 -0
  52. package/src/ooxml/reader.ts +218 -0
  53. package/src/ooxml/types.ts +104 -0
  54. package/src/ooxml/writer.ts +321 -0
  55. package/src/ooxml/xmlUtils.ts +123 -0
  56. package/src/pdf/export.ts +1029 -0
  57. package/src/pdf/import.ts +835 -0
  58. package/src/pdf/index.ts +29 -0
  59. package/src/pdf/styles.ts +180 -0
  60. package/src/pptx/index.ts +78 -0
  61. package/src/xlsx/index.ts +78 -0
@@ -0,0 +1,1035 @@
1
+ import {
2
+ CONTENT_TYPE_DOCX_DOCUMENT,
3
+ CONTENT_TYPE_DOCX_FONT_TABLE,
4
+ CONTENT_TYPE_DOCX_FOOTNOTES,
5
+ CONTENT_TYPE_DOCX_NUMBERING,
6
+ CONTENT_TYPE_DOCX_SETTINGS,
7
+ CONTENT_TYPE_DOCX_STYLES,
8
+ NS_MC,
9
+ NS_R,
10
+ NS_WML,
11
+ REL_FONT_TABLE,
12
+ REL_FOOTNOTES,
13
+ REL_HYPERLINK,
14
+ REL_NUMBERING,
15
+ REL_OFFICE_DOCUMENT,
16
+ REL_SETTINGS,
17
+ REL_STYLES,
18
+ createPackage,
19
+ escapeXml,
20
+ getPartRelationships,
21
+ getPartXml,
22
+ openPackage,
23
+ xmlDeclaration
24
+ } from "./chunk-KAK4V57E.js";
25
+
26
+ // src/docx/export.ts
27
+ import { docToMarkdown } from "@bendyline/squisq/doc";
28
+
29
+ // src/docx/styles.ts
30
+ var HEADING_STYLE_MAP = {
31
+ Heading1: 1,
32
+ Heading2: 2,
33
+ Heading3: 3,
34
+ Heading4: 4,
35
+ Heading5: 5,
36
+ Heading6: 6,
37
+ heading1: 1,
38
+ heading2: 2,
39
+ heading3: 3,
40
+ heading4: 4,
41
+ heading5: 5,
42
+ heading6: 6,
43
+ // Some localized/legacy variants
44
+ Title: 1,
45
+ Subtitle: 2
46
+ };
47
+ var DEPTH_TO_STYLE_ID = {
48
+ 1: "Heading1",
49
+ 2: "Heading2",
50
+ 3: "Heading3",
51
+ 4: "Heading4",
52
+ 5: "Heading5",
53
+ 6: "Heading6"
54
+ };
55
+ var QUOTE_STYLE_IDS = /* @__PURE__ */ new Set(["Quote", "IntenseQuote", "quote", "BlockQuote"]);
56
+ var CODE_STYLE_IDS = /* @__PURE__ */ new Set(["Code", "CodeBlock", "HTMLCode", "PlainText"]);
57
+ var INLINE_CODE_STYLE_IDS = /* @__PURE__ */ new Set(["CodeChar", "HTMLCodeChar", "VerbatimChar"]);
58
+ var BULLET_NUM_FORMATS = /* @__PURE__ */ new Set(["bullet", "none"]);
59
+ var DEFAULT_FONT = "Calibri";
60
+ var DEFAULT_HEADING_FONT = "Calibri Light";
61
+ var DEFAULT_FONT_SIZE_HALF_POINTS = 22;
62
+ var DEFAULT_CODE_FONT = "Consolas";
63
+ var DEFAULT_CODE_FONT_SIZE = 20;
64
+ var HEADING_FONT_SIZES = {
65
+ 1: 32,
66
+ // 16pt
67
+ 2: 26,
68
+ // 13pt
69
+ 3: 24,
70
+ // 12pt
71
+ 4: 22,
72
+ // 11pt
73
+ 5: 22,
74
+ // 11pt
75
+ 6: 22
76
+ // 11pt
77
+ };
78
+ var HYPERLINK_COLOR = "0563C1";
79
+ function pointsToTwips(points) {
80
+ return Math.round(points * 20);
81
+ }
82
+
83
+ // src/docx/export.ts
84
+ async function markdownDocToDocx(doc, options = {}) {
85
+ const ctx = new ExportContext(options);
86
+ const bodyXml = convertBlocks(doc.children, ctx);
87
+ return buildDocxPackage(bodyXml, ctx, options);
88
+ }
89
+ async function docToDocx(doc, options = {}) {
90
+ const markdownDoc = docToMarkdown(doc);
91
+ return markdownDocToDocx(markdownDoc, options);
92
+ }
93
+ var ExportContext = class {
94
+ constructor(options) {
95
+ this.nextRelId = 1;
96
+ this.nextNumId = 1;
97
+ this.nextFootnoteId = 1;
98
+ // 0 is separator, start user footnotes at 1
99
+ /** Relationships for word/_rels/document.xml.rels */
100
+ this.relationships = [];
101
+ /** Numbering definitions (abstract + num) */
102
+ this.numberingDefs = [];
103
+ /** Footnote XML bodies (keyed by footnote id) */
104
+ this.footnotes = /* @__PURE__ */ new Map();
105
+ /** Footnote identifier → numeric id mapping */
106
+ this.footnoteIdMap = /* @__PURE__ */ new Map();
107
+ /** Embedded images: rId → { path, data, contentType } */
108
+ this.images = [];
109
+ /** Whether we have any lists (determines if numbering.xml is needed) */
110
+ this.hasLists = false;
111
+ /** Whether we have any footnotes */
112
+ this.hasFootnotes = false;
113
+ this.font = options.defaultFont ?? DEFAULT_FONT;
114
+ this.fontSize = options.defaultFontSize ? options.defaultFontSize * 2 : DEFAULT_FONT_SIZE_HALF_POINTS;
115
+ }
116
+ /** Allocate a new relationship ID */
117
+ allocRelId() {
118
+ return `rId${this.nextRelId++}`;
119
+ }
120
+ /** Add a hyperlink relationship and return the rId */
121
+ addHyperlink(url) {
122
+ const id = this.allocRelId();
123
+ this.relationships.push({
124
+ id,
125
+ type: REL_HYPERLINK,
126
+ target: url,
127
+ targetMode: "External"
128
+ });
129
+ return id;
130
+ }
131
+ /** Allocate a numbering definition for a list */
132
+ allocNumbering(ordered) {
133
+ const numId = this.nextNumId++;
134
+ this.numberingDefs.push({ numId, ordered });
135
+ this.hasLists = true;
136
+ return numId;
137
+ }
138
+ /** Register or look up a footnote by its string identifier */
139
+ getFootnoteId(identifier) {
140
+ let id = this.footnoteIdMap.get(identifier);
141
+ if (id === void 0) {
142
+ id = this.nextFootnoteId++;
143
+ this.footnoteIdMap.set(identifier, id);
144
+ this.hasFootnotes = true;
145
+ }
146
+ return id;
147
+ }
148
+ };
149
+ function convertBlocks(nodes, ctx) {
150
+ const parts = [];
151
+ for (const node of nodes) {
152
+ parts.push(convertBlock(node, ctx, 0));
153
+ }
154
+ return parts.join("");
155
+ }
156
+ function convertBlock(node, ctx, listDepth) {
157
+ switch (node.type) {
158
+ case "heading":
159
+ return convertHeading(node, ctx);
160
+ case "paragraph":
161
+ return convertParagraph(node, ctx);
162
+ case "blockquote":
163
+ return convertBlockquote(node, ctx);
164
+ case "list":
165
+ return convertList(node, ctx, listDepth);
166
+ case "code":
167
+ return convertCodeBlock(node);
168
+ case "table":
169
+ return convertTable(node, ctx);
170
+ case "thematicBreak":
171
+ return convertThematicBreak();
172
+ case "htmlBlock":
173
+ return convertHtmlBlock(node);
174
+ case "math":
175
+ return convertMathBlock(node);
176
+ case "footnoteDefinition":
177
+ return convertFootnoteDefinition(node, ctx);
178
+ default:
179
+ return "";
180
+ }
181
+ }
182
+ function convertHeading(node, ctx) {
183
+ const styleId = DEPTH_TO_STYLE_ID[node.depth] ?? "Heading1";
184
+ const runs = convertInlines(node.children, ctx);
185
+ return `<w:p><w:pPr><w:pStyle w:val="${styleId}"/></w:pPr>` + runs + `</w:p>`;
186
+ }
187
+ function convertParagraph(node, ctx) {
188
+ const runs = convertInlines(node.children, ctx);
189
+ return `<w:p>${runs}</w:p>`;
190
+ }
191
+ function convertBlockquote(node, ctx) {
192
+ const parts = [];
193
+ for (const child of node.children) {
194
+ if (child.type === "paragraph") {
195
+ const runs = convertInlines(child.children, ctx);
196
+ parts.push(
197
+ `<w:p><w:pPr><w:pStyle w:val="Quote"/><w:ind w:left="${pointsToTwips(36)}"/><w:pBdr><w:left w:val="single" w:sz="12" w:space="4" w:color="CCCCCC"/></w:pBdr></w:pPr>` + runs + `</w:p>`
198
+ );
199
+ } else {
200
+ parts.push(convertBlock(child, ctx, 0));
201
+ }
202
+ }
203
+ return parts.join("");
204
+ }
205
+ function convertList(node, ctx, depth) {
206
+ const numId = ctx.allocNumbering(node.ordered ?? false);
207
+ const parts = [];
208
+ for (const item of node.children) {
209
+ parts.push(convertListItem(item, ctx, numId, depth));
210
+ }
211
+ return parts.join("");
212
+ }
213
+ function convertListItem(item, ctx, numId, depth) {
214
+ const parts = [];
215
+ for (const child of item.children) {
216
+ if (child.type === "paragraph") {
217
+ const runs = convertInlines(child.children, ctx);
218
+ parts.push(
219
+ `<w:p><w:pPr><w:pStyle w:val="ListParagraph"/><w:numPr><w:ilvl w:val="${depth}"/><w:numId w:val="${numId}"/></w:numPr></w:pPr>` + runs + `</w:p>`
220
+ );
221
+ } else if (child.type === "list") {
222
+ parts.push(convertList(child, ctx, depth + 1));
223
+ } else {
224
+ parts.push(convertBlock(child, ctx, depth));
225
+ }
226
+ }
227
+ return parts.join("");
228
+ }
229
+ function convertCodeBlock(node) {
230
+ const lines = node.value.split("\n");
231
+ const parts = [];
232
+ for (const line of lines) {
233
+ parts.push(
234
+ `<w:p><w:pPr><w:pStyle w:val="Code"/><w:pBdr><w:top w:val="single" w:sz="4" w:space="1" w:color="CCCCCC"/><w:left w:val="single" w:sz="4" w:space="4" w:color="CCCCCC"/><w:bottom w:val="single" w:sz="4" w:space="1" w:color="CCCCCC"/><w:right w:val="single" w:sz="4" w:space="4" w:color="CCCCCC"/></w:pBdr><w:shd w:val="clear" w:color="auto" w:fill="F5F5F5"/></w:pPr><w:r><w:rPr><w:rFonts w:ascii="${DEFAULT_CODE_FONT}" w:hAnsi="${DEFAULT_CODE_FONT}"/><w:sz w:val="${DEFAULT_CODE_FONT_SIZE}"/></w:rPr><w:t xml:space="preserve">${escapeXml(line)}</w:t></w:r></w:p>`
235
+ );
236
+ }
237
+ return parts.join("");
238
+ }
239
+ function convertTable(node, ctx) {
240
+ const rows = [];
241
+ for (let ri = 0; ri < node.children.length; ri++) {
242
+ const row = node.children[ri];
243
+ rows.push(convertTableRow(row, ctx, ri === 0, node.align));
244
+ }
245
+ return `<w:tbl><w:tblPr><w:tblStyle w:val="TableGrid"/><w:tblW w:w="0" w:type="auto"/><w:tblBorders><w:top w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:left w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:bottom w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:right w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:insideH w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:insideV w:val="single" w:sz="4" w:space="0" w:color="auto"/></w:tblBorders></w:tblPr><w:tblGrid/>` + rows.join("") + `</w:tbl>`;
246
+ }
247
+ function convertTableRow(row, ctx, isHeader, align) {
248
+ const cells = [];
249
+ for (let ci = 0; ci < row.children.length; ci++) {
250
+ const cell = row.children[ci];
251
+ const cellAlign = align?.[ci] ?? null;
252
+ cells.push(convertTableCell(cell, ctx, isHeader, cellAlign));
253
+ }
254
+ const trPr = isHeader ? "<w:trPr><w:tblHeader/></w:trPr>" : "";
255
+ return `<w:tr>${trPr}${cells.join("")}</w:tr>`;
256
+ }
257
+ function convertTableCell(cell, ctx, isHeader, align) {
258
+ const runs = convertInlines(cell.children, ctx);
259
+ const rPr = isHeader ? "<w:rPr><w:b/></w:rPr>" : "";
260
+ const jcMap = { left: "left", center: "center", right: "right" };
261
+ const jc = align ? `<w:jc w:val="${jcMap[align]}"/>` : "";
262
+ const pPr = rPr || jc ? `<w:pPr>${jc}</w:pPr>` : "";
263
+ return `<w:tc><w:p>${pPr}${runs}</w:p></w:tc>`;
264
+ }
265
+ function convertThematicBreak() {
266
+ return `<w:p><w:pPr><w:pBdr><w:bottom w:val="single" w:sz="6" w:space="1" w:color="auto"/></w:pBdr></w:pPr></w:p>`;
267
+ }
268
+ function convertHtmlBlock(node) {
269
+ const text = stripHtmlTags(node.rawHtml);
270
+ if (!text.trim()) return "";
271
+ return `<w:p><w:r><w:t xml:space="preserve">${escapeXml(text)}</w:t></w:r></w:p>`;
272
+ }
273
+ function convertMathBlock(node) {
274
+ return `<w:p><w:pPr><w:jc w:val="center"/></w:pPr><w:r><w:rPr><w:rFonts w:ascii="Cambria Math" w:hAnsi="Cambria Math"/><w:i/></w:rPr><w:t xml:space="preserve">${escapeXml(node.value)}</w:t></w:r></w:p>`;
275
+ }
276
+ function convertFootnoteDefinition(node, ctx) {
277
+ const fnId = ctx.getFootnoteId(node.identifier);
278
+ const bodyParts = [];
279
+ for (const child of node.children) {
280
+ if (child.type === "paragraph") {
281
+ const runs = convertInlines(child.children, ctx);
282
+ bodyParts.push(`<w:p>${runs}</w:p>`);
283
+ }
284
+ }
285
+ const footnoteXml = `<w:footnote w:id="${fnId}">` + (bodyParts.length > 0 ? bodyParts.join("") : `<w:p/>`) + `</w:footnote>`;
286
+ ctx.footnotes.set(fnId, footnoteXml);
287
+ return "";
288
+ }
289
+ function convertInlines(nodes, ctx, format = {}) {
290
+ const parts = [];
291
+ for (const node of nodes) {
292
+ parts.push(convertInline(node, ctx, format));
293
+ }
294
+ return parts.join("");
295
+ }
296
+ function convertInline(node, ctx, format) {
297
+ switch (node.type) {
298
+ case "text":
299
+ return makeRun(node.value, format);
300
+ case "strong":
301
+ return convertInlines(node.children, ctx, { ...format, bold: true });
302
+ case "emphasis":
303
+ return convertInlines(node.children, ctx, { ...format, italic: true });
304
+ case "delete":
305
+ return convertInlines(node.children, ctx, { ...format, strike: true });
306
+ case "inlineCode":
307
+ return makeRun(node.value, { ...format, code: true });
308
+ case "link":
309
+ return convertLink(node, ctx, format);
310
+ case "image":
311
+ return convertImage(node);
312
+ case "break":
313
+ return `<w:r><w:br/></w:r>`;
314
+ case "htmlInline":
315
+ return makeRun(stripHtmlTags(node.rawHtml), format);
316
+ case "inlineMath":
317
+ return makeRun(node.value, { ...format, code: true });
318
+ case "footnoteReference":
319
+ return convertFootnoteRef(node, ctx);
320
+ default:
321
+ return "";
322
+ }
323
+ }
324
+ function makeRun(text, format) {
325
+ if (!text) return "";
326
+ const rPrParts = [];
327
+ if (format.bold) rPrParts.push("<w:b/>");
328
+ if (format.italic) rPrParts.push("<w:i/>");
329
+ if (format.strike) rPrParts.push("<w:strike/>");
330
+ if (format.code) {
331
+ rPrParts.push(
332
+ `<w:rFonts w:ascii="${DEFAULT_CODE_FONT}" w:hAnsi="${DEFAULT_CODE_FONT}"/>`,
333
+ `<w:sz w:val="${DEFAULT_CODE_FONT_SIZE}"/>`
334
+ );
335
+ }
336
+ const rPr = rPrParts.length > 0 ? `<w:rPr>${rPrParts.join("")}</w:rPr>` : "";
337
+ return `<w:r>${rPr}<w:t xml:space="preserve">${escapeXml(text)}</w:t></w:r>`;
338
+ }
339
+ function convertLink(node, ctx, format) {
340
+ const rId = ctx.addHyperlink(node.url);
341
+ const _runs = convertInlines(node.children, ctx, { ...format });
342
+ const styledRuns = convertInlinesWithHyperlinkStyle(node.children, ctx, format);
343
+ return `<w:hyperlink r:id="${rId}">${styledRuns}</w:hyperlink>`;
344
+ }
345
+ function convertInlinesWithHyperlinkStyle(nodes, ctx, format) {
346
+ const parts = [];
347
+ for (const node of nodes) {
348
+ if (node.type === "text") {
349
+ parts.push(makeHyperlinkRun(node.value, format));
350
+ } else {
351
+ parts.push(convertInline(node, ctx, format));
352
+ }
353
+ }
354
+ return parts.join("");
355
+ }
356
+ function makeHyperlinkRun(text, format) {
357
+ if (!text) return "";
358
+ const rPrParts = [
359
+ '<w:rStyle w:val="Hyperlink"/>',
360
+ `<w:color w:val="${HYPERLINK_COLOR}"/>`,
361
+ '<w:u w:val="single"/>'
362
+ ];
363
+ if (format.bold) rPrParts.push("<w:b/>");
364
+ if (format.italic) rPrParts.push("<w:i/>");
365
+ return `<w:r><w:rPr>${rPrParts.join("")}</w:rPr><w:t xml:space="preserve">${escapeXml(text)}</w:t></w:r>`;
366
+ }
367
+ function convertImage(_node) {
368
+ const alt = _node.alt || _node.url;
369
+ return makeRun(`[Image: ${alt}]`, { italic: true });
370
+ }
371
+ function convertFootnoteRef(node, ctx) {
372
+ const fnId = ctx.getFootnoteId(node.identifier);
373
+ return `<w:r><w:rPr><w:rStyle w:val="FootnoteReference"/><w:vertAlign w:val="superscript"/></w:rPr><w:footnoteReference w:id="${fnId}"/></w:r>`;
374
+ }
375
+ async function buildDocxPackage(bodyXml, ctx, options) {
376
+ const pkg = createPackage();
377
+ let relCounter = 100;
378
+ const stylesRelId = `rId${relCounter++}`;
379
+ const numberingRelId = `rId${relCounter++}`;
380
+ const settingsRelId = `rId${relCounter++}`;
381
+ const fontTableRelId = `rId${relCounter++}`;
382
+ const footnotesRelId = `rId${relCounter++}`;
383
+ const documentXml = buildDocumentXml(bodyXml);
384
+ pkg.addPart("word/document.xml", documentXml, CONTENT_TYPE_DOCX_DOCUMENT);
385
+ const stylesXml = buildStylesXml(options);
386
+ pkg.addPart("word/styles.xml", stylesXml, CONTENT_TYPE_DOCX_STYLES);
387
+ const settingsXml = buildSettingsXml();
388
+ pkg.addPart("word/settings.xml", settingsXml, CONTENT_TYPE_DOCX_SETTINGS);
389
+ const fontTableXml = buildFontTableXml(options);
390
+ pkg.addPart("word/fontTable.xml", fontTableXml, CONTENT_TYPE_DOCX_FONT_TABLE);
391
+ if (ctx.hasLists) {
392
+ const numberingXml = buildNumberingXml(ctx);
393
+ pkg.addPart("word/numbering.xml", numberingXml, CONTENT_TYPE_DOCX_NUMBERING);
394
+ }
395
+ if (ctx.hasFootnotes) {
396
+ const footnotesXml = buildFootnotesXml(ctx);
397
+ pkg.addPart("word/footnotes.xml", footnotesXml, CONTENT_TYPE_DOCX_FOOTNOTES);
398
+ }
399
+ pkg.addRelationship("", {
400
+ id: "rId1",
401
+ type: REL_OFFICE_DOCUMENT,
402
+ target: "word/document.xml"
403
+ });
404
+ pkg.addRelationship("word/document.xml", {
405
+ id: stylesRelId,
406
+ type: REL_STYLES,
407
+ target: "styles.xml"
408
+ });
409
+ pkg.addRelationship("word/document.xml", {
410
+ id: settingsRelId,
411
+ type: REL_SETTINGS,
412
+ target: "settings.xml"
413
+ });
414
+ pkg.addRelationship("word/document.xml", {
415
+ id: fontTableRelId,
416
+ type: REL_FONT_TABLE,
417
+ target: "fontTable.xml"
418
+ });
419
+ if (ctx.hasLists) {
420
+ pkg.addRelationship("word/document.xml", {
421
+ id: numberingRelId,
422
+ type: REL_NUMBERING,
423
+ target: "numbering.xml"
424
+ });
425
+ }
426
+ if (ctx.hasFootnotes) {
427
+ pkg.addRelationship("word/document.xml", {
428
+ id: footnotesRelId,
429
+ type: REL_FOOTNOTES,
430
+ target: "footnotes.xml"
431
+ });
432
+ }
433
+ for (const rel of ctx.relationships) {
434
+ pkg.addRelationship("word/document.xml", {
435
+ id: rel.id,
436
+ type: rel.type,
437
+ target: rel.target,
438
+ ...rel.targetMode ? { targetMode: rel.targetMode } : {}
439
+ });
440
+ }
441
+ for (const img of ctx.images) {
442
+ pkg.addBinaryPart(img.path, img.data, img.contentType);
443
+ }
444
+ if (options.title || options.author || options.description) {
445
+ pkg.setCoreProperties({
446
+ title: options.title,
447
+ creator: options.author,
448
+ description: options.description,
449
+ created: (/* @__PURE__ */ new Date()).toISOString(),
450
+ modified: (/* @__PURE__ */ new Date()).toISOString()
451
+ });
452
+ }
453
+ return pkg.toArrayBuffer();
454
+ }
455
+ function buildDocumentXml(bodyXml) {
456
+ return xmlDeclaration() + `<w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:mc="${NS_MC}" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="${NS_R}" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="${NS_WML}" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml"><w:body>` + bodyXml + `<w:sectPr><w:pgSz w:w="12240" w:h="15840"/><w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="720" w:footer="720" w:gutter="0"/><w:cols w:space="720"/></w:sectPr></w:body></w:document>`;
457
+ }
458
+ function buildStylesXml(options) {
459
+ const font = options.defaultFont ?? DEFAULT_FONT;
460
+ const headingFont = DEFAULT_HEADING_FONT;
461
+ return xmlDeclaration() + `<w:styles xmlns:w="${NS_WML}"><w:docDefaults><w:rPrDefault><w:rPr><w:rFonts w:ascii="${escapeXml(font)}" w:hAnsi="${escapeXml(font)}" w:eastAsia="${escapeXml(font)}" w:cs="${escapeXml(font)}"/><w:sz w:val="${DEFAULT_FONT_SIZE_HALF_POINTS}"/><w:szCs w:val="${DEFAULT_FONT_SIZE_HALF_POINTS}"/></w:rPr></w:rPrDefault><w:pPrDefault/></w:docDefaults><w:style w:type="paragraph" w:default="1" w:styleId="Normal"><w:name w:val="Normal"/><w:qFormat/></w:style>` + // Heading styles
462
+ buildHeadingStyles(headingFont) + // Quote style
463
+ `<w:style w:type="paragraph" w:styleId="Quote"><w:name w:val="Quote"/><w:basedOn w:val="Normal"/><w:pPr><w:ind w:left="720"/></w:pPr><w:rPr><w:i/><w:color w:val="404040"/></w:rPr></w:style><w:style w:type="paragraph" w:styleId="Code"><w:name w:val="Code"/><w:basedOn w:val="Normal"/><w:rPr><w:rFonts w:ascii="${DEFAULT_CODE_FONT}" w:hAnsi="${DEFAULT_CODE_FONT}"/><w:sz w:val="${DEFAULT_CODE_FONT_SIZE}"/></w:rPr></w:style><w:style w:type="paragraph" w:styleId="ListParagraph"><w:name w:val="List Paragraph"/><w:basedOn w:val="Normal"/><w:pPr><w:ind w:left="720"/></w:pPr></w:style><w:style w:type="character" w:styleId="Hyperlink"><w:name w:val="Hyperlink"/><w:rPr><w:color w:val="${HYPERLINK_COLOR}"/><w:u w:val="single"/></w:rPr></w:style><w:style w:type="character" w:styleId="FootnoteReference"><w:name w:val="footnote reference"/><w:rPr><w:vertAlign w:val="superscript"/></w:rPr></w:style><w:style w:type="table" w:styleId="TableGrid"><w:name w:val="Table Grid"/><w:tblPr><w:tblBorders><w:top w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:left w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:bottom w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:right w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:insideH w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:insideV w:val="single" w:sz="4" w:space="0" w:color="auto"/></w:tblBorders></w:tblPr></w:style></w:styles>`;
464
+ }
465
+ function buildHeadingStyles(headingFont) {
466
+ let result = "";
467
+ for (let depth = 1; depth <= 6; depth++) {
468
+ const styleId = DEPTH_TO_STYLE_ID[depth];
469
+ const fontSize = HEADING_FONT_SIZES[depth] ?? 22;
470
+ result += `<w:style w:type="paragraph" w:styleId="${styleId}"><w:name w:val="heading ${depth}"/><w:basedOn w:val="Normal"/><w:next w:val="Normal"/><w:qFormat/><w:pPr><w:outlineLvl w:val="${depth - 1}"/><w:spacing w:before="240" w:after="60"/></w:pPr><w:rPr><w:rFonts w:ascii="${escapeXml(headingFont)}" w:hAnsi="${escapeXml(headingFont)}"/><w:b/><w:sz w:val="${fontSize}"/><w:szCs w:val="${fontSize}"/></w:rPr></w:style>`;
471
+ }
472
+ return result;
473
+ }
474
+ function buildSettingsXml() {
475
+ return xmlDeclaration() + `<w:settings xmlns:w="${NS_WML}"><w:defaultTabStop w:val="720"/><w:characterSpacingControl w:val="doNotCompress"/></w:settings>`;
476
+ }
477
+ function buildFontTableXml(options) {
478
+ const font = options.defaultFont ?? DEFAULT_FONT;
479
+ return xmlDeclaration() + `<w:fonts xmlns:w="${NS_WML}"><w:font w:name="${escapeXml(font)}"><w:panose1 w:val="020F0502020204030204"/><w:charset w:val="00"/><w:family w:val="swiss"/><w:pitch w:val="variable"/></w:font><w:font w:name="${DEFAULT_HEADING_FONT}"><w:panose1 w:val="020F0302020204030204"/><w:charset w:val="00"/><w:family w:val="swiss"/><w:pitch w:val="variable"/></w:font><w:font w:name="${DEFAULT_CODE_FONT}"><w:charset w:val="00"/><w:family w:val="modern"/><w:pitch w:val="fixed"/></w:font></w:fonts>`;
480
+ }
481
+ function buildNumberingXml(ctx) {
482
+ const abstract = [];
483
+ const concrete = [];
484
+ for (const def of ctx.numberingDefs) {
485
+ const absId = def.numId;
486
+ const levels = [];
487
+ for (let lvl = 0; lvl < 9; lvl++) {
488
+ if (def.ordered) {
489
+ levels.push(
490
+ `<w:lvl w:ilvl="${lvl}"><w:start w:val="1"/><w:numFmt w:val="decimal"/><w:lvlText w:val="%${lvl + 1}."/><w:lvlJc w:val="left"/><w:pPr><w:ind w:left="${720 * (lvl + 1)}" w:hanging="360"/></w:pPr></w:lvl>`
491
+ );
492
+ } else {
493
+ const bullets = ["\u2022", "\u25E6", "\u25AA"];
494
+ const bullet = bullets[lvl % bullets.length];
495
+ levels.push(
496
+ `<w:lvl w:ilvl="${lvl}"><w:start w:val="1"/><w:numFmt w:val="bullet"/><w:lvlText w:val="${bullet}"/><w:lvlJc w:val="left"/><w:pPr><w:ind w:left="${720 * (lvl + 1)}" w:hanging="360"/></w:pPr><w:rPr><w:rFonts w:ascii="Symbol" w:hAnsi="Symbol"/></w:rPr></w:lvl>`
497
+ );
498
+ }
499
+ }
500
+ abstract.push(
501
+ `<w:abstractNum w:abstractNumId="${absId}">` + levels.join("") + `</w:abstractNum>`
502
+ );
503
+ concrete.push(
504
+ `<w:num w:numId="${def.numId}"><w:abstractNumId w:val="${absId}"/></w:num>`
505
+ );
506
+ }
507
+ return xmlDeclaration() + `<w:numbering xmlns:w="${NS_WML}">` + abstract.join("") + concrete.join("") + `</w:numbering>`;
508
+ }
509
+ function buildFootnotesXml(ctx) {
510
+ const footnotes = [];
511
+ footnotes.push(
512
+ `<w:footnote w:type="separator" w:id="-1"><w:p><w:r><w:separator/></w:r></w:p></w:footnote>`
513
+ );
514
+ footnotes.push(
515
+ `<w:footnote w:type="continuationSeparator" w:id="0"><w:p><w:r><w:continuationSeparator/></w:r></w:p></w:footnote>`
516
+ );
517
+ for (const [_id, xml] of ctx.footnotes) {
518
+ footnotes.push(xml);
519
+ }
520
+ return xmlDeclaration() + `<w:footnotes xmlns:w="${NS_WML}" xmlns:r="${NS_R}">` + footnotes.join("") + `</w:footnotes>`;
521
+ }
522
+ function stripHtmlTags(html) {
523
+ return html.replace(/<[^>]*>/g, "");
524
+ }
525
+
526
+ // src/docx/import.ts
527
+ import { markdownToDoc } from "@bendyline/squisq/doc";
528
+ async function docxToMarkdownDoc(data, options = {}) {
529
+ const pkg = await openPackage(data);
530
+ const ctx = await buildImportContext(pkg, options);
531
+ const documentXml = await getPartXml(pkg, "word/document.xml");
532
+ if (!documentXml) {
533
+ return { type: "document", children: [] };
534
+ }
535
+ const body = getFirstElement(documentXml, "body");
536
+ if (!body) {
537
+ return { type: "document", children: [] };
538
+ }
539
+ const blocks = await convertBody(body, ctx);
540
+ return { type: "document", children: blocks };
541
+ }
542
+ async function docxToDoc(data, options = {}) {
543
+ const markdownDoc = await docxToMarkdownDoc(data, options);
544
+ return markdownToDoc(markdownDoc);
545
+ }
546
+ async function buildImportContext(pkg, options) {
547
+ const ctx = {
548
+ headingStyles: /* @__PURE__ */ new Map(),
549
+ quoteStyles: /* @__PURE__ */ new Set(),
550
+ codeStyles: /* @__PURE__ */ new Set(),
551
+ inlineCodeStyles: /* @__PURE__ */ new Set(),
552
+ documentRels: /* @__PURE__ */ new Map(),
553
+ numbering: /* @__PURE__ */ new Map(),
554
+ footnotes: /* @__PURE__ */ new Map(),
555
+ pkg,
556
+ options
557
+ };
558
+ for (const [id, depth] of Object.entries(HEADING_STYLE_MAP)) {
559
+ ctx.headingStyles.set(id, depth);
560
+ }
561
+ for (const id of QUOTE_STYLE_IDS) {
562
+ ctx.quoteStyles.add(id);
563
+ }
564
+ for (const id of CODE_STYLE_IDS) {
565
+ ctx.codeStyles.add(id);
566
+ }
567
+ for (const id of INLINE_CODE_STYLE_IDS) {
568
+ ctx.inlineCodeStyles.add(id);
569
+ }
570
+ await parseStyles(pkg, ctx);
571
+ const rels = await getPartRelationships(pkg, "word/document.xml");
572
+ for (const rel of rels) {
573
+ ctx.documentRels.set(rel.id, rel);
574
+ }
575
+ await parseNumbering(pkg, ctx);
576
+ await parseFootnotes(pkg, ctx);
577
+ return ctx;
578
+ }
579
+ async function parseStyles(pkg, ctx) {
580
+ const doc = await getPartXml(pkg, "word/styles.xml");
581
+ if (!doc) return;
582
+ const styles = doc.getElementsByTagNameNS(NS_WML, "style");
583
+ const stylesList = styles.length > 0 ? styles : doc.getElementsByTagName("style");
584
+ for (let i = 0; i < stylesList.length; i++) {
585
+ const style = stylesList[i];
586
+ const styleId = style.getAttributeNS(NS_WML, "styleId") ?? style.getAttribute("w:styleId");
587
+ if (!styleId) continue;
588
+ const nameEl = getFirstChildElement(style, "name");
589
+ const styleName = nameEl?.getAttributeNS(NS_WML, "val") ?? nameEl?.getAttribute("w:val") ?? "";
590
+ const headingMatch = styleName.match(/^heading\s+(\d+)$/i);
591
+ if (headingMatch) {
592
+ const depth = parseInt(headingMatch[1], 10);
593
+ if (depth >= 1 && depth <= 6) {
594
+ ctx.headingStyles.set(styleId, depth);
595
+ }
596
+ }
597
+ const pPr = getFirstChildElement(style, "pPr");
598
+ if (pPr) {
599
+ const outlineLvl = getFirstChildElement(pPr, "outlineLvl");
600
+ if (outlineLvl) {
601
+ const val = outlineLvl.getAttributeNS(NS_WML, "val") ?? outlineLvl.getAttribute("w:val");
602
+ if (val !== null) {
603
+ const depth = parseInt(val, 10) + 1;
604
+ if (depth >= 1 && depth <= 6) {
605
+ ctx.headingStyles.set(styleId, depth);
606
+ }
607
+ }
608
+ }
609
+ }
610
+ }
611
+ }
612
+ async function parseNumbering(pkg, ctx) {
613
+ const doc = await getPartXml(pkg, "word/numbering.xml");
614
+ if (!doc) return;
615
+ const abstractNums = /* @__PURE__ */ new Map();
616
+ const abstractNumEls = getAllElements(doc, "abstractNum");
617
+ for (const absNum of abstractNumEls) {
618
+ const absId = getAttr(absNum, "abstractNumId");
619
+ if (!absId) continue;
620
+ const levels = /* @__PURE__ */ new Map();
621
+ const lvlEls = getAllChildElements(absNum, "lvl");
622
+ for (const lvl of lvlEls) {
623
+ const ilvlStr = getAttr(lvl, "ilvl");
624
+ if (ilvlStr === null) continue;
625
+ const ilvl = parseInt(ilvlStr, 10);
626
+ const numFmtEl = getFirstChildElement(lvl, "numFmt");
627
+ const numFmt = numFmtEl ? getAttr(numFmtEl, "val") : null;
628
+ const isOrdered = numFmt !== null && !BULLET_NUM_FORMATS.has(numFmt);
629
+ levels.set(ilvl, isOrdered);
630
+ }
631
+ abstractNums.set(absId, levels);
632
+ }
633
+ const numEls = getAllElements(doc, "num");
634
+ for (const num of numEls) {
635
+ const numId = getAttr(num, "numId");
636
+ if (!numId) continue;
637
+ const abstractNumIdEl = getFirstChildElement(num, "abstractNumId");
638
+ const absId = abstractNumIdEl ? getAttr(abstractNumIdEl, "val") : null;
639
+ if (!absId) continue;
640
+ const levels = abstractNums.get(absId);
641
+ if (levels) {
642
+ ctx.numbering.set(numId, { levels });
643
+ }
644
+ }
645
+ }
646
+ async function parseFootnotes(pkg, ctx) {
647
+ const doc = await getPartXml(pkg, "word/footnotes.xml");
648
+ if (!doc) return;
649
+ const footnoteEls = getAllElements(doc, "footnote");
650
+ for (const fn of footnoteEls) {
651
+ const id = getAttr(fn, "id");
652
+ const type = getAttr(fn, "type");
653
+ if (!id || type === "separator" || type === "continuationSeparator") continue;
654
+ ctx.footnotes.set(id, fn);
655
+ }
656
+ }
657
+ async function convertBody(body, ctx) {
658
+ const result = [];
659
+ const children = Array.from(body.children);
660
+ let i = 0;
661
+ while (i < children.length) {
662
+ const el = children[i];
663
+ const localName = el.localName;
664
+ if (localName === "p") {
665
+ const numPr = getNumPr(el);
666
+ if (numPr) {
667
+ const { node, consumed } = await collectList(children, i, ctx);
668
+ result.push(node);
669
+ i += consumed;
670
+ continue;
671
+ }
672
+ const block = await convertParagraph2(el, ctx);
673
+ if (block) {
674
+ result.push(block);
675
+ }
676
+ i++;
677
+ } else if (localName === "tbl") {
678
+ const table = await convertTable2(el, ctx);
679
+ if (table) result.push(table);
680
+ i++;
681
+ } else {
682
+ i++;
683
+ }
684
+ }
685
+ const footnoteNodes = await convertFootnoteDefinitions(ctx);
686
+ result.push(...footnoteNodes);
687
+ return result;
688
+ }
689
+ async function convertParagraph2(el, ctx) {
690
+ const pPr = getFirstChildElement(el, "pPr");
691
+ const styleId = getParagraphStyleId(pPr);
692
+ if (styleId && ctx.headingStyles.has(styleId)) {
693
+ const depth = ctx.headingStyles.get(styleId);
694
+ const inlines2 = await convertRuns(el, ctx);
695
+ if (inlines2.length === 0) return null;
696
+ return {
697
+ type: "heading",
698
+ depth: Math.min(Math.max(depth, 1), 6),
699
+ children: inlines2
700
+ };
701
+ }
702
+ if (styleId && ctx.quoteStyles.has(styleId)) {
703
+ const inlines2 = await convertRuns(el, ctx);
704
+ if (inlines2.length === 0) return null;
705
+ const paragraph = { type: "paragraph", children: inlines2 };
706
+ return { type: "blockquote", children: [paragraph] };
707
+ }
708
+ if (styleId && ctx.codeStyles.has(styleId)) {
709
+ const text = getElementTextContent(el);
710
+ return { type: "code", value: text };
711
+ }
712
+ const inlines = await convertRuns(el, ctx);
713
+ if (inlines.length === 0) return null;
714
+ return { type: "paragraph", children: inlines };
715
+ }
716
+ async function convertRuns(paragraphEl, ctx) {
717
+ const result = [];
718
+ const children = Array.from(paragraphEl.children);
719
+ for (const child of children) {
720
+ const localName = child.localName;
721
+ if (localName === "r") {
722
+ const inlines = await convertRun(child, ctx);
723
+ result.push(...inlines);
724
+ } else if (localName === "hyperlink") {
725
+ const link = await convertHyperlink(child, ctx);
726
+ if (link) result.push(link);
727
+ }
728
+ }
729
+ return mergeAdjacentText(result);
730
+ }
731
+ async function convertRun(runEl, ctx) {
732
+ const result = [];
733
+ const rPr = getFirstChildElement(runEl, "rPr");
734
+ const format = parseRunFormat(rPr, ctx);
735
+ for (const child of Array.from(runEl.children)) {
736
+ const localName = child.localName;
737
+ if (localName === "t") {
738
+ const text = child.textContent ?? "";
739
+ if (!text) continue;
740
+ if (format.code) {
741
+ result.push({ type: "inlineCode", value: text });
742
+ } else {
743
+ let node = { type: "text", value: text };
744
+ if (format.strike) {
745
+ node = { type: "delete", children: [node] };
746
+ }
747
+ if (format.italic) {
748
+ node = { type: "emphasis", children: [node] };
749
+ }
750
+ if (format.bold) {
751
+ node = { type: "strong", children: [node] };
752
+ }
753
+ result.push(node);
754
+ }
755
+ } else if (localName === "br") {
756
+ result.push({ type: "break" });
757
+ } else if (localName === "footnoteReference") {
758
+ const fnId = getAttr(child, "id");
759
+ if (fnId && fnId !== "0" && fnId !== "-1") {
760
+ result.push({
761
+ type: "footnoteReference",
762
+ identifier: `fn${fnId}`
763
+ });
764
+ }
765
+ } else if (localName === "drawing" || localName === "pict") {
766
+ const img = await extractImage(child, ctx);
767
+ if (img) result.push(img);
768
+ }
769
+ }
770
+ return result;
771
+ }
772
+ function parseRunFormat(rPr, ctx) {
773
+ if (!rPr) return { bold: false, italic: false, strike: false, code: false };
774
+ const bold = hasChildElement(rPr, "b") && !isFalseToggle(getFirstChildElement(rPr, "b"));
775
+ const italic = hasChildElement(rPr, "i") && !isFalseToggle(getFirstChildElement(rPr, "i"));
776
+ const strike = hasChildElement(rPr, "strike") && !isFalseToggle(getFirstChildElement(rPr, "strike"));
777
+ const rStyle = getFirstChildElement(rPr, "rStyle");
778
+ const charStyleId = rStyle ? getAttr(rStyle, "val") : null;
779
+ const isCodeStyle = charStyleId ? ctx.inlineCodeStyles.has(charStyleId) : false;
780
+ const rFonts = getFirstChildElement(rPr, "rFonts");
781
+ const fontName = rFonts ? getAttr(rFonts, "ascii") ?? getAttr(rFonts, "hAnsi") ?? "" : "";
782
+ const isMonospace = /consolas|courier|mono/i.test(fontName);
783
+ return { bold, italic, strike, code: isCodeStyle || isMonospace };
784
+ }
785
+ function isFalseToggle(el) {
786
+ const val = getAttr(el, "val");
787
+ return val === "0" || val === "false";
788
+ }
789
+ async function convertHyperlink(el, ctx) {
790
+ const rId = el.getAttributeNS(NS_R, "id") ?? el.getAttribute("r:id");
791
+ let url = "";
792
+ if (rId) {
793
+ const rel = ctx.documentRels.get(rId);
794
+ if (rel) url = rel.target;
795
+ }
796
+ if (!url) {
797
+ const anchor = el.getAttributeNS(NS_WML, "anchor") ?? el.getAttribute("w:anchor");
798
+ if (anchor) url = `#${anchor}`;
799
+ }
800
+ const inlines = [];
801
+ for (const child of Array.from(el.children)) {
802
+ if (child.localName === "r") {
803
+ inlines.push(...await convertRun(child, ctx));
804
+ }
805
+ }
806
+ if (inlines.length === 0) return null;
807
+ return {
808
+ type: "link",
809
+ url,
810
+ children: mergeAdjacentText(inlines)
811
+ };
812
+ }
813
+ async function extractImage(_el, _ctx) {
814
+ return {
815
+ type: "image",
816
+ url: "",
817
+ alt: "Image"
818
+ };
819
+ }
820
+ async function collectList(elements, startIdx, ctx) {
821
+ const firstNumPr = getNumPr(elements[startIdx]);
822
+ const { numId } = firstNumPr;
823
+ const numInfo = ctx.numbering.get(numId);
824
+ const isOrdered = numInfo?.levels.get(0) ?? false;
825
+ const items = [];
826
+ let consumed = 0;
827
+ let i = startIdx;
828
+ while (i < elements.length) {
829
+ const el = elements[i];
830
+ if (el.localName !== "p") break;
831
+ const numPr = getNumPr(el);
832
+ if (!numPr || numPr.numId !== numId) break;
833
+ const inlines = await convertRuns(el, ctx);
834
+ if (inlines.length > 0) {
835
+ const paragraph = { type: "paragraph", children: inlines };
836
+ if (numPr.ilvl > firstNumPr.ilvl) {
837
+ const nested = await collectNestedList(elements, i, ctx, firstNumPr.ilvl);
838
+ if (items.length > 0) {
839
+ const lastItem = items[items.length - 1];
840
+ const nestedIsOrdered = numInfo?.levels.get(numPr.ilvl) ?? false;
841
+ const nestedList = {
842
+ type: "list",
843
+ ordered: nestedIsOrdered,
844
+ children: nested.items
845
+ };
846
+ lastItem.children.push(nestedList);
847
+ }
848
+ i += nested.consumed;
849
+ consumed += nested.consumed;
850
+ continue;
851
+ }
852
+ items.push({
853
+ type: "listItem",
854
+ children: [paragraph]
855
+ });
856
+ }
857
+ i++;
858
+ consumed++;
859
+ }
860
+ return {
861
+ node: {
862
+ type: "list",
863
+ ordered: isOrdered,
864
+ children: items
865
+ },
866
+ consumed
867
+ };
868
+ }
869
+ async function collectNestedList(elements, startIdx, ctx, parentIlvl) {
870
+ const items = [];
871
+ let consumed = 0;
872
+ let i = startIdx;
873
+ while (i < elements.length) {
874
+ const el = elements[i];
875
+ if (el.localName !== "p") break;
876
+ const numPr = getNumPr(el);
877
+ if (!numPr) break;
878
+ if (numPr.ilvl <= parentIlvl) break;
879
+ const inlines = await convertRuns(el, ctx);
880
+ if (inlines.length > 0) {
881
+ const paragraph = { type: "paragraph", children: inlines };
882
+ items.push({ type: "listItem", children: [paragraph] });
883
+ }
884
+ i++;
885
+ consumed++;
886
+ }
887
+ return { items, consumed };
888
+ }
889
+ function getNumPr(el) {
890
+ const pPr = getFirstChildElement(el, "pPr");
891
+ if (!pPr) return null;
892
+ const numPr = getFirstChildElement(pPr, "numPr");
893
+ if (!numPr) return null;
894
+ const ilvlEl = getFirstChildElement(numPr, "ilvl");
895
+ const numIdEl = getFirstChildElement(numPr, "numId");
896
+ const ilvlVal = ilvlEl ? getAttr(ilvlEl, "val") : null;
897
+ const numIdVal = numIdEl ? getAttr(numIdEl, "val") : null;
898
+ if (!numIdVal || numIdVal === "0") return null;
899
+ return {
900
+ numId: numIdVal,
901
+ ilvl: ilvlVal ? parseInt(ilvlVal, 10) : 0
902
+ };
903
+ }
904
+ async function convertTable2(tblEl, ctx) {
905
+ const rows = [];
906
+ const trEls = getAllChildElements(tblEl, "tr");
907
+ for (let ri = 0; ri < trEls.length; ri++) {
908
+ const row = await convertTableRow2(trEls[ri], ctx, ri === 0);
909
+ rows.push(row);
910
+ }
911
+ if (rows.length === 0) return null;
912
+ return {
913
+ type: "table",
914
+ children: rows
915
+ };
916
+ }
917
+ async function convertTableRow2(trEl, ctx, isHeader) {
918
+ const cells = [];
919
+ const tcEls = getAllChildElements(trEl, "tc");
920
+ for (const tc of tcEls) {
921
+ const cell = await convertTableCell2(tc, ctx, isHeader);
922
+ cells.push(cell);
923
+ }
924
+ return { type: "tableRow", children: cells };
925
+ }
926
+ async function convertTableCell2(tcEl, ctx, isHeader) {
927
+ const inlines = [];
928
+ const paragraphs = getAllChildElements(tcEl, "p");
929
+ for (let pi = 0; pi < paragraphs.length; pi++) {
930
+ if (pi > 0) {
931
+ inlines.push({ type: "break" });
932
+ }
933
+ const runs = await convertRuns(paragraphs[pi], ctx);
934
+ inlines.push(...runs);
935
+ }
936
+ return {
937
+ type: "tableCell",
938
+ isHeader,
939
+ children: mergeAdjacentText(inlines)
940
+ };
941
+ }
942
+ async function convertFootnoteDefinitions(ctx) {
943
+ const results = [];
944
+ for (const [id, el] of ctx.footnotes) {
945
+ const children = [];
946
+ const paragraphs = getAllChildElements(el, "p");
947
+ for (const p of paragraphs) {
948
+ const inlines = await convertRuns(p, ctx);
949
+ if (inlines.length > 0) {
950
+ children.push({
951
+ type: "paragraph",
952
+ children: inlines
953
+ });
954
+ }
955
+ }
956
+ if (children.length > 0) {
957
+ results.push({
958
+ type: "footnoteDefinition",
959
+ identifier: `fn${id}`,
960
+ children
961
+ });
962
+ }
963
+ }
964
+ return results;
965
+ }
966
+ function getFirstChildElement(parent, localName) {
967
+ for (const child of Array.from(parent.children ?? [])) {
968
+ if (child.localName === localName) return child;
969
+ }
970
+ return null;
971
+ }
972
+ function getAllChildElements(parent, localName) {
973
+ const result = [];
974
+ for (const child of Array.from(parent.children)) {
975
+ if (child.localName === localName) result.push(child);
976
+ }
977
+ return result;
978
+ }
979
+ function getAllElements(doc, localName) {
980
+ const nsEls = "getElementsByTagNameNS" in doc ? doc.getElementsByTagNameNS(NS_WML, localName) : null;
981
+ if (nsEls && nsEls.length > 0) return Array.from(nsEls);
982
+ const prefixed = doc.getElementsByTagName(`w:${localName}`);
983
+ if (prefixed.length > 0) return Array.from(prefixed);
984
+ return Array.from(doc.getElementsByTagName(localName));
985
+ }
986
+ function getFirstElement(doc, localName) {
987
+ const els = getAllElements(doc, localName);
988
+ return els.length > 0 ? els[0] : null;
989
+ }
990
+ function getAttr(el, localName) {
991
+ return el.getAttributeNS(NS_WML, localName) || el.getAttribute(`w:${localName}`) || null;
992
+ }
993
+ function hasChildElement(parent, localName) {
994
+ return getFirstChildElement(parent, localName) !== null;
995
+ }
996
+ function getParagraphStyleId(pPr) {
997
+ if (!pPr) return null;
998
+ const pStyle = getFirstChildElement(pPr, "pStyle");
999
+ if (!pStyle) return null;
1000
+ return getAttr(pStyle, "val");
1001
+ }
1002
+ function getElementTextContent(el) {
1003
+ const parts = [];
1004
+ function walk(node) {
1005
+ if (node.localName === "t") {
1006
+ parts.push(node.textContent ?? "");
1007
+ }
1008
+ for (const child of Array.from(node.children)) {
1009
+ walk(child);
1010
+ }
1011
+ }
1012
+ walk(el);
1013
+ return parts.join("");
1014
+ }
1015
+ function mergeAdjacentText(nodes) {
1016
+ if (nodes.length <= 1) return nodes;
1017
+ const result = [];
1018
+ for (const node of nodes) {
1019
+ const prev = result[result.length - 1];
1020
+ if (node.type === "text" && prev?.type === "text") {
1021
+ prev.value += node.value;
1022
+ } else {
1023
+ result.push(node);
1024
+ }
1025
+ }
1026
+ return result;
1027
+ }
1028
+
1029
+ export {
1030
+ markdownDocToDocx,
1031
+ docToDocx,
1032
+ docxToMarkdownDoc,
1033
+ docxToDoc
1034
+ };
1035
+ //# sourceMappingURL=chunk-MQHCXI56.js.map