@yinyoudexing/xml2word 0.1.1 → 0.1.2

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.
@@ -7,6 +7,12 @@ function shouldPreserveSpace(text) {
7
7
  if (!text) return false;
8
8
  return /^\s/.test(text) || /\s$/.test(text) || /\s{2,}/.test(text);
9
9
  }
10
+ function shouldKeepWhitespaceOnlyRun(text) {
11
+ if (!text) return false;
12
+ if (/\r|\n/.test(text)) return false;
13
+ if (text.includes("\xA0")) return true;
14
+ return /\s{2,}/.test(text);
15
+ }
10
16
  function parseStyleAttribute(style) {
11
17
  if (!style) return {};
12
18
  const normalized = style.replace(/\r/g, "\n");
@@ -106,6 +112,7 @@ function getTextContent(node) {
106
112
  for (const c of children) out += getTextContent(c);
107
113
  return out;
108
114
  }
115
+ var IMAGE_RELATIONSHIP_ID_OFFSET = 7;
109
116
  function decodeBase64ToUint8Array(base64) {
110
117
  const BufferCtor = globalThis.Buffer;
111
118
  if (BufferCtor) {
@@ -226,7 +233,7 @@ function collectInlineRuns(node, inherited, out, result) {
226
233
  const intrinsic = parseIntrinsicImageSizePx(parsed.contentType, parsed.data);
227
234
  const { widthPx, heightPx } = computeImageSizePx(node, intrinsic);
228
235
  const id = result.images.length + 1;
229
- const relationshipId = `rId${id}`;
236
+ const relationshipId = `rId${id + IMAGE_RELATIONSHIP_ID_OFFSET}`;
230
237
  const target = `media/image${id}.${parsed.extension}`;
231
238
  result.images.push({
232
239
  relationshipId,
@@ -249,7 +256,7 @@ function collectInlineRuns(node, inherited, out, result) {
249
256
  const intrinsic = Number.isFinite(bufferW) && bufferW && Number.isFinite(bufferH) && bufferH ? { widthPx: Math.max(1, Math.round(bufferW)), heightPx: Math.max(1, Math.round(bufferH)) } : parseIntrinsicImageSizePx(parsed.contentType, parsed.data);
250
257
  const { widthPx, heightPx } = computeImageSizePx(node, intrinsic);
251
258
  const id = result.images.length + 1;
252
- const relationshipId = `rId${id}`;
259
+ const relationshipId = `rId${id + IMAGE_RELATIONSHIP_ID_OFFSET}`;
253
260
  const target = `media/image${id}.${parsed.extension}`;
254
261
  result.images.push({
255
262
  relationshipId,
@@ -350,9 +357,10 @@ function inferFirstFontSizeHalfPoints(node) {
350
357
  }
351
358
  return void 0;
352
359
  }
353
- function buildParagraphPrXml(node, baseFontHalfPoints, extraInd) {
360
+ function buildParagraphPrXml(node, baseFontHalfPoints, extraInd, pStyleId) {
354
361
  const css = parseStyleAttribute(node.attribs?.style);
355
362
  const parts = [];
363
+ if (pStyleId) parts.push(`<w:pStyle w:val="${escapeXmlText(pStyleId)}"/>`);
356
364
  const align = css["text-align"]?.trim().toLowerCase();
357
365
  const jcVal = align === "center" ? "center" : align === "right" ? "right" : align === "justify" ? "both" : void 0;
358
366
  if (jcVal) parts.push(`<w:jc w:val="${jcVal}"/>`);
@@ -403,9 +411,9 @@ function buildParagraphPrXml(node, baseFontHalfPoints, extraInd) {
403
411
  if (!parts.length) return "";
404
412
  return `<w:pPr>${parts.join("")}</w:pPr>`;
405
413
  }
406
- function buildParagraphXmlFromContainer(node, baseStyle, extraInd, result) {
414
+ function buildParagraphXmlFromContainer(node, baseStyle, extraInd, pStyleId, result) {
407
415
  const baseFontHalfPoints = baseStyle.fontSizeHalfPoints ?? inferFirstFontSizeHalfPoints(node) ?? 28;
408
- const pPrXml = buildParagraphPrXml(node, baseFontHalfPoints, extraInd);
416
+ const pPrXml = buildParagraphPrXml(node, baseFontHalfPoints, extraInd, pStyleId);
409
417
  const runs = [];
410
418
  const res = result ?? {
411
419
  bodyXml: "",
@@ -424,7 +432,7 @@ function buildParagraphXmlFromContainer(node, baseStyle, extraInd, result) {
424
432
  }
425
433
  const text = token.text;
426
434
  if (!text) continue;
427
- if (!text.trim()) continue;
435
+ if (!text.trim() && !shouldKeepWhitespaceOnlyRun(text)) continue;
428
436
  rXml.push(buildRunXml(token.style, text));
429
437
  }
430
438
  if (!rXml.length) return "";
@@ -445,25 +453,30 @@ function isExplicitPageBreak(node) {
445
453
  if (after?.includes("always") || before?.includes("always")) return true;
446
454
  return false;
447
455
  }
448
- function buildHeadingBaseStyle(level) {
449
- const size = level === 1 ? 44 : level === 2 ? 32 : level === 3 ? 28 : level === 4 ? 24 : 22;
450
- return { bold: true, fontSizeHalfPoints: size };
451
- }
452
- function buildListBlocks(listNode, ordered, result) {
453
- const items = [];
454
- const stack = [...listNode.children ?? []];
455
- while (stack.length) {
456
- const n = stack.shift();
457
- if (n.type === "tag" && n.name?.toLowerCase() === "li") items.push(n);
458
- }
456
+ function buildListBlocks(listNode, ordered, level, result) {
457
+ const liNodes = (listNode.children ?? []).filter(
458
+ (c) => c.type === "tag" && c.name?.toLowerCase() === "li"
459
+ );
460
+ if (!liNodes.length) return [];
459
461
  const out = [];
460
- for (let i = 0; i < items.length; i++) {
461
- const prefix = ordered ? `${i + 1}. ` : "\u2022 ";
462
- const li = items[i];
462
+ const numId = ordered ? 2 : 1;
463
+ const ilvl = Math.max(0, Math.min(8, Math.floor(level)));
464
+ const leftTwips = 720 * (ilvl + 1);
465
+ const hangingTwips = 360;
466
+ for (const li of liNodes) {
467
+ const nestedLists = [];
463
468
  const baseStyle = {};
464
469
  const runs = [];
465
- runs.push({ kind: "text", text: prefix, style: baseStyle });
466
- for (const c of li.children ?? []) collectInlineRuns(c, baseStyle, runs, result);
470
+ for (const c of li.children ?? []) {
471
+ if (c.type === "tag") {
472
+ const tag = c.name?.toLowerCase();
473
+ if (tag === "ul" || tag === "ol") {
474
+ nestedLists.push(c);
475
+ continue;
476
+ }
477
+ }
478
+ collectInlineRuns(c, baseStyle, runs, result);
479
+ }
467
480
  const rXml = [];
468
481
  for (const token of runs) {
469
482
  if (token.kind === "br") {
@@ -476,18 +489,143 @@ function buildListBlocks(listNode, ordered, result) {
476
489
  }
477
490
  const text = token.text;
478
491
  if (!text) continue;
479
- if (!text.trim()) continue;
492
+ if (!text.trim() && !shouldKeepWhitespaceOnlyRun(text)) continue;
480
493
  rXml.push(buildRunXml(token.style, text));
481
494
  }
482
- if (!rXml.length) continue;
483
- const pPrXml = buildParagraphPrXml(li, inferFirstFontSizeHalfPoints(li) ?? 28, {
484
- leftTwips: 720,
485
- hangingTwips: 360
486
- });
487
- out.push(`<w:p>${pPrXml}${rXml.join("")}</w:p>`);
495
+ if (rXml.length) {
496
+ const baseFontHalfPoints = inferFirstFontSizeHalfPoints(li) ?? 28;
497
+ const pPrXml = buildParagraphPrXml(
498
+ li,
499
+ baseFontHalfPoints,
500
+ { leftTwips, hangingTwips },
501
+ void 0
502
+ );
503
+ const numPrXml = `<w:numPr><w:ilvl w:val="${ilvl}"/><w:numId w:val="${numId}"/></w:numPr>`;
504
+ const mergedPPrXml = pPrXml ? pPrXml.replace("<w:pPr>", `<w:pPr>${numPrXml}`) : `<w:pPr>${numPrXml}<w:ind w:left="${leftTwips}" w:hanging="${hangingTwips}"/></w:pPr>`;
505
+ out.push(`<w:p>${mergedPPrXml}${rXml.join("")}</w:p>`);
506
+ }
507
+ for (const nested of nestedLists) {
508
+ const nestedOrdered = nested.name?.toLowerCase() === "ol";
509
+ out.push(...buildListBlocks(nested, nestedOrdered, ilvl + 1, result));
510
+ }
488
511
  }
489
512
  return out;
490
513
  }
514
+ function parseCellWidthTwips(node) {
515
+ const css = parseStyleAttribute(node.attribs?.style);
516
+ const width = parseCssLengthToTwips(css.width, 28);
517
+ if (typeof width !== "number" || width <= 0) return void 0;
518
+ return width;
519
+ }
520
+ function estimateTextWidthTwips(text, baseFontHalfPoints) {
521
+ const basePt = baseFontHalfPoints / 2;
522
+ const cjkRegex = /[\u3400-\u4dbf\u4e00-\u9fff\u3000-\u303f\uff00-\uffef]/;
523
+ let cjk = 0;
524
+ let latin = 0;
525
+ let spaces = 0;
526
+ for (const ch of text) {
527
+ if (ch === " " || ch === " ") {
528
+ spaces++;
529
+ continue;
530
+ }
531
+ if (cjkRegex.test(ch)) {
532
+ cjk++;
533
+ continue;
534
+ }
535
+ latin++;
536
+ }
537
+ const cjkTwips = Math.round(basePt * 20);
538
+ const latinTwips = Math.round(basePt * 11);
539
+ const spaceTwips = Math.round(basePt * 6);
540
+ return cjk * cjkTwips + latin * latinTwips + spaces * spaceTwips;
541
+ }
542
+ function parseBorderShorthand(value, baseFontHalfPoints) {
543
+ if (!value) return void 0;
544
+ const raw = value.trim().toLowerCase();
545
+ if (!raw) return void 0;
546
+ if (raw === "none" || raw === "0") return { val: "nil", sz: 0 };
547
+ const tokens = raw.split(/\s+/).filter(Boolean);
548
+ if (!tokens.length) return void 0;
549
+ const css = Object.fromEntries(tokens.map((t, i) => [`${i}`, t]));
550
+ const widthToken = Object.values(css).find((t) => /^(?:\d+(?:\.\d+)?)(?:px|pt)?$/.test(t));
551
+ const styleToken = Object.values(css).find(
552
+ (t) => ["none", "solid", "dashed", "dotted", "double", "hidden"].includes(t)
553
+ );
554
+ const colorToken = Object.values(css).find((t) => t.startsWith("#") || t.startsWith("rgb("));
555
+ const widthTwips = parseCssLengthToTwips(widthToken, baseFontHalfPoints);
556
+ const sz = (() => {
557
+ if (typeof widthTwips !== "number") return 4;
558
+ if (widthTwips <= 0) return 0;
559
+ return Math.max(2, Math.round(widthTwips * 0.4));
560
+ })();
561
+ const val = (() => {
562
+ if (!styleToken) return "single";
563
+ if (styleToken === "none" || styleToken === "hidden") return "nil";
564
+ if (styleToken === "solid") return "single";
565
+ if (styleToken === "dashed") return "dashed";
566
+ if (styleToken === "dotted") return "dotted";
567
+ if (styleToken === "double") return "double";
568
+ return "single";
569
+ })();
570
+ const colorHex = parseCssColorToHex(colorToken);
571
+ return { val, sz, colorHex };
572
+ }
573
+ function buildBorderTag(tag, border, fallbackColorHex) {
574
+ const b = border ?? { val: "single", sz: 4, colorHex: fallbackColorHex };
575
+ const color = (b.colorHex ?? fallbackColorHex).toUpperCase();
576
+ return `<w:${tag} w:val="${b.val}" w:sz="${b.sz}" w:space="0" w:color="${color}"/>`;
577
+ }
578
+ function injectTableCellParagraphSpacing(pXml) {
579
+ if (!pXml.includes("<w:p")) return pXml;
580
+ if (!pXml.includes("<w:p>")) return pXml;
581
+ const spacingXml = '<w:spacing w:before="0" w:after="0" w:line="360" w:lineRule="auto"/><w:wordWrap w:val="1"/>';
582
+ if (pXml.includes("<w:pPr>")) {
583
+ if (pXml.includes("<w:spacing ")) return pXml;
584
+ return pXml.replace("<w:pPr>", `<w:pPr>${spacingXml}`);
585
+ }
586
+ return pXml.replace("<w:p>", `<w:p><w:pPr>${spacingXml}</w:pPr>`);
587
+ }
588
+ function buildTableCellBlocksXml(cell, baseStyle, result) {
589
+ const children = cell.children ?? [];
590
+ const hasBlocks = children.some((c) => {
591
+ if (c.type !== "tag") return false;
592
+ const tag = c.name?.toLowerCase();
593
+ return tag === "p" || tag === "ul" || tag === "ol" || tag === "img" || tag === "canvas" || /^h[1-6]$/.test(tag ?? "");
594
+ });
595
+ const out = [];
596
+ if (!hasBlocks) {
597
+ const p = buildParagraphXmlFromContainer(cell, baseStyle, void 0, void 0, result);
598
+ if (p) out.push(p);
599
+ return out.length ? out.map(injectTableCellParagraphSpacing).join("") : "<w:p/>";
600
+ }
601
+ for (const c of children) {
602
+ if (c.type === "tag") {
603
+ const tag = c.name?.toLowerCase();
604
+ if (tag === "p") {
605
+ const p = buildParagraphXmlFromContainer(c, baseStyle, void 0, void 0, result);
606
+ if (p) out.push(p);
607
+ continue;
608
+ }
609
+ if (tag && /^h[1-6]$/.test(tag)) {
610
+ const level = Number(tag.slice(1));
611
+ const p = buildParagraphXmlFromContainer(c, baseStyle, void 0, `Heading${level}`, result);
612
+ if (p) out.push(p);
613
+ continue;
614
+ }
615
+ if (tag === "ul" || tag === "ol") {
616
+ out.push(...buildListBlocks(c, tag === "ol", 0, result));
617
+ continue;
618
+ }
619
+ if (tag === "img" || tag === "canvas") {
620
+ const p = buildParagraphXmlFromSingleInlineNode(c, baseStyle, result);
621
+ if (p) out.push(p);
622
+ continue;
623
+ }
624
+ }
625
+ }
626
+ if (!out.length) return "<w:p/>";
627
+ return out.map(injectTableCellParagraphSpacing).join("");
628
+ }
491
629
  function buildTableXml(tableNode, result) {
492
630
  const rows = [];
493
631
  const stack = [...tableNode.children ?? []];
@@ -496,25 +634,137 @@ function buildTableXml(tableNode, result) {
496
634
  if (n.type === "tag" && n.name?.toLowerCase() === "tr") rows.push(n);
497
635
  if (n.children?.length) stack.unshift(...n.children);
498
636
  }
499
- const rowXml = [];
500
- for (const tr of rows) {
501
- const cells = (tr.children ?? []).filter(
502
- (c) => c.type === "tag" && (c.name === "td" || c.name === "th")
637
+ const rowCells = rows.map(
638
+ (tr) => (tr.children ?? []).filter((c) => c.type === "tag" && (c.name === "td" || c.name === "th"))
639
+ );
640
+ const colCount = Math.max(0, ...rowCells.map((cells) => cells.length));
641
+ const maxTableWidthTwips = 9360;
642
+ const estimatedColWidths = new Array(colCount).fill(0).map((_, i) => {
643
+ let explicit;
644
+ let estimated = 0;
645
+ for (const cells of rowCells) {
646
+ const cell = cells[i];
647
+ if (!cell) continue;
648
+ const w = parseCellWidthTwips(cell);
649
+ if (typeof w === "number") explicit = explicit ?? w;
650
+ const text = getTextContent(cell).replace(/\s+/g, " ").trim();
651
+ if (!text) continue;
652
+ const baseFontHalfPoints = inferFirstFontSizeHalfPoints(cell) ?? 28;
653
+ const wTwips = estimateTextWidthTwips(text, baseFontHalfPoints) + 240;
654
+ estimated = Math.max(estimated, wTwips);
655
+ }
656
+ const base = typeof explicit === "number" ? explicit : estimated || Math.round(maxTableWidthTwips / Math.max(1, colCount));
657
+ return Math.max(720, Math.min(6e3, Math.round(base)));
658
+ });
659
+ const normalizedColWidths = (() => {
660
+ const sum = estimatedColWidths.reduce((a, b) => a + b, 0);
661
+ if (!sum) return estimatedColWidths;
662
+ if (sum <= maxTableWidthTwips) return estimatedColWidths;
663
+ const scaled = estimatedColWidths.map(
664
+ (w) => Math.max(720, Math.floor(w * maxTableWidthTwips / sum))
503
665
  );
666
+ const scaledSum = scaled.reduce((a, b) => a + b, 0);
667
+ const diff = maxTableWidthTwips - scaledSum;
668
+ if (diff !== 0 && scaled.length) scaled[scaled.length - 1] = Math.max(720, scaled[scaled.length - 1] + diff);
669
+ return scaled;
670
+ })();
671
+ const tblGrid = `<w:tblGrid>${normalizedColWidths.map((w) => `<w:gridCol w:w="${w}"/>`).join("")}</w:tblGrid>`;
672
+ const rowXml = [];
673
+ for (let rowIdx = 0; rowIdx < rows.length; rowIdx++) {
674
+ const tr = rows[rowIdx];
675
+ const cells = rowCells[rowIdx] ?? [];
504
676
  const cellXml = [];
505
- for (const cell of cells) {
677
+ for (let i = 0; i < cells.length; i++) {
678
+ const cell = cells[i];
506
679
  const isHeader = cell.name === "th";
507
680
  const baseStyle = isHeader ? { bold: true } : {};
508
- const pXml = buildParagraphXmlFromContainer(cell, baseStyle, void 0, result);
509
- const paragraphs = pXml ? pXml : "<w:p/>";
510
- cellXml.push(
511
- `<w:tc><w:tcPr><w:tcW w:w="0" w:type="auto"/></w:tcPr>${paragraphs}</w:tc>`
512
- );
681
+ const paragraphs = buildTableCellBlocksXml(cell, baseStyle, result);
682
+ const css = parseStyleAttribute(cell.attribs?.style);
683
+ const widthTwips = parseCellWidthTwips(cell) ?? normalizedColWidths[i];
684
+ const tcW = typeof widthTwips === "number" ? `<w:tcW w:w="${widthTwips}" w:type="dxa"/>` : `<w:tcW w:w="0" w:type="auto"/>`;
685
+ const vAlign = (() => {
686
+ const v = css["vertical-align"]?.trim().toLowerCase();
687
+ if (!v) return "";
688
+ if (v === "middle" || v === "center") return '<w:vAlign w:val="center"/>';
689
+ if (v === "bottom") return '<w:vAlign w:val="bottom"/>';
690
+ if (v === "top") return '<w:vAlign w:val="top"/>';
691
+ return "";
692
+ })();
693
+ const shd = (() => {
694
+ const hex = parseCssColorToHex(css["background-color"]);
695
+ if (!hex) return "";
696
+ return `<w:shd w:val="clear" w:color="auto" w:fill="${hex}"/>`;
697
+ })();
698
+ const noWrap = (() => {
699
+ const ws = css["white-space"]?.trim().toLowerCase();
700
+ if (ws?.includes("nowrap")) return "<w:noWrap/>";
701
+ return "";
702
+ })();
703
+ const cellBorder = (() => {
704
+ const bAll = parseBorderShorthand(css.border, 28);
705
+ const bTop = parseBorderShorthand(css["border-top"] ?? css.border, 28);
706
+ const bLeft = parseBorderShorthand(css["border-left"] ?? css.border, 28);
707
+ const bBottom = parseBorderShorthand(css["border-bottom"] ?? css.border, 28);
708
+ const bRight = parseBorderShorthand(css["border-right"] ?? css.border, 28);
709
+ const any = bAll || css.border || css["border-top"] || css["border-left"] || css["border-bottom"] || css["border-right"];
710
+ if (!any) return "";
711
+ const fallback = bAll?.colorHex ?? "D9D9D9";
712
+ return `<w:tcBorders>${buildBorderTag("top", bTop, fallback)}${buildBorderTag(
713
+ "left",
714
+ bLeft,
715
+ fallback
716
+ )}${buildBorderTag("bottom", bBottom, fallback)}${buildBorderTag(
717
+ "right",
718
+ bRight,
719
+ fallback
720
+ )}</w:tcBorders>`;
721
+ })();
722
+ cellXml.push(`<w:tc><w:tcPr>${tcW}${vAlign}${shd}${noWrap}${cellBorder}</w:tcPr>${paragraphs}</w:tc>`);
513
723
  }
514
724
  if (cellXml.length) rowXml.push(`<w:tr>${cellXml.join("")}</w:tr>`);
515
725
  }
516
- const tblPr = `<w:tblPr><w:tblW w:w="0" w:type="auto"/><w:tblBorders><w:top w:val="single" w:sz="4" w:space="0" w:color="D9D9D9"/><w:left w:val="single" w:sz="4" w:space="0" w:color="D9D9D9"/><w:bottom w:val="single" w:sz="4" w:space="0" w:color="D9D9D9"/><w:right w:val="single" w:sz="4" w:space="0" w:color="D9D9D9"/><w:insideH w:val="single" w:sz="4" w:space="0" w:color="D9D9D9"/><w:insideV w:val="single" w:sz="4" w:space="0" w:color="D9D9D9"/></w:tblBorders></w:tblPr>`;
517
- const tblGrid = `<w:tblGrid/>`;
726
+ const tblCss = parseStyleAttribute(tableNode.attribs?.style);
727
+ const tblAlign = (() => {
728
+ const ml = tblCss["margin-left"]?.trim().toLowerCase();
729
+ const mr = tblCss["margin-right"]?.trim().toLowerCase();
730
+ const m = tblCss.margin?.trim().toLowerCase();
731
+ if (ml === "auto" && mr === "auto" || (m?.includes("auto") ?? false)) return '<w:tblJc w:val="center"/>';
732
+ const ta = tblCss["text-align"]?.trim().toLowerCase();
733
+ if (ta === "center") return '<w:tblJc w:val="center"/>';
734
+ if (ta === "right") return '<w:tblJc w:val="right"/>';
735
+ return "";
736
+ })();
737
+ const tblBorder = (() => {
738
+ const border = parseBorderShorthand(tblCss.border, 28);
739
+ if (tblCss.border) {
740
+ const fallback2 = border?.colorHex ?? "D9D9D9";
741
+ return `<w:tblBorders>${buildBorderTag("top", border, fallback2)}${buildBorderTag(
742
+ "left",
743
+ border,
744
+ fallback2
745
+ )}${buildBorderTag("bottom", border, fallback2)}${buildBorderTag(
746
+ "right",
747
+ border,
748
+ fallback2
749
+ )}${buildBorderTag("insideH", border, fallback2)}${buildBorderTag(
750
+ "insideV",
751
+ border,
752
+ fallback2
753
+ )}</w:tblBorders>`;
754
+ }
755
+ const fallback = "D9D9D9";
756
+ return `<w:tblBorders>${buildBorderTag("top", void 0, fallback)}${buildBorderTag(
757
+ "left",
758
+ void 0,
759
+ fallback
760
+ )}${buildBorderTag("bottom", void 0, fallback)}${buildBorderTag(
761
+ "right",
762
+ void 0,
763
+ fallback
764
+ )}${buildBorderTag("insideH", void 0, fallback)}${buildBorderTag("insideV", void 0, fallback)}</w:tblBorders>`;
765
+ })();
766
+ const tblW = `<w:tblW w:w="${normalizedColWidths.reduce((a, b) => a + b, 0)}" w:type="dxa"/>`;
767
+ const tblPr = `<w:tblPr>${tblW}<w:tblLayout w:type="fixed"/>${tblAlign}${tblBorder}</w:tblPr>`;
518
768
  return `<w:tbl>${tblPr}${tblGrid}${rowXml.join("")}</w:tbl>`;
519
769
  }
520
770
  function buildParagraphXmlFromSingleInlineNode(node, baseStyle, result) {
@@ -524,7 +774,7 @@ function buildParagraphXmlFromSingleInlineNode(node, baseStyle, result) {
524
774
  attribs: { style: "text-align: center;" },
525
775
  children: [node]
526
776
  };
527
- return buildParagraphXmlFromContainer(wrapper, baseStyle, void 0, result);
777
+ return buildParagraphXmlFromContainer(wrapper, baseStyle, void 0, void 0, result);
528
778
  }
529
779
  function collectBodyBlocks(node, out, result) {
530
780
  if (isSkippableSubtree(node)) return;
@@ -535,7 +785,7 @@ function collectBodyBlocks(node, out, result) {
535
785
  return;
536
786
  }
537
787
  if (tag === "p") {
538
- const pXml = buildParagraphXmlFromContainer(node, {}, void 0, result);
788
+ const pXml = buildParagraphXmlFromContainer(node, {}, void 0, void 0, result);
539
789
  if (pXml) out.push(pXml);
540
790
  return;
541
791
  }
@@ -546,7 +796,7 @@ function collectBodyBlocks(node, out, result) {
546
796
  }
547
797
  if (tag && /^h[1-6]$/.test(tag)) {
548
798
  const level = Number(tag.slice(1));
549
- const hXml = buildParagraphXmlFromContainer(node, buildHeadingBaseStyle(level), void 0, result);
799
+ const hXml = buildParagraphXmlFromContainer(node, {}, void 0, `Heading${level}`, result);
550
800
  if (hXml) out.push(hXml);
551
801
  return;
552
802
  }
@@ -556,7 +806,7 @@ function collectBodyBlocks(node, out, result) {
556
806
  return;
557
807
  }
558
808
  if (tag === "ul" || tag === "ol") {
559
- out.push(...buildListBlocks(node, tag === "ol", result));
809
+ out.push(...buildListBlocks(node, tag === "ol", 0, result));
560
810
  return;
561
811
  }
562
812
  }
@@ -624,4 +874,4 @@ export {
624
874
  htmlToWordBodyXml,
625
875
  textToWordBodyXml
626
876
  };
627
- //# sourceMappingURL=htmlToWordBodyXml-AG3GTZEZ.js.map
877
+ //# sourceMappingURL=htmlToWordBodyXml-LY6DZSTW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/htmlToWordBodyXml.ts"],"sourcesContent":["import { parseDocument } from \"htmlparser2\";\n\ntype HtmlNode = {\n type?: string;\n name?: string;\n data?: string;\n attribs?: Record<string, string | undefined>;\n children?: HtmlNode[];\n};\n\ntype TextStyle = {\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n colorHex?: string;\n fontFamily?: string;\n fontSizeHalfPoints?: number;\n};\n\nfunction escapeXmlText(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n}\n\nfunction shouldPreserveSpace(text: string): boolean {\n if (!text) return false;\n return /^\\s/.test(text) || /\\s$/.test(text) || /\\s{2,}/.test(text);\n}\n\nfunction shouldKeepWhitespaceOnlyRun(text: string): boolean {\n if (!text) return false;\n if (/\\r|\\n/.test(text)) return false;\n if (text.includes(\"\\u00a0\")) return true;\n return /\\s{2,}/.test(text);\n}\n\nfunction parseStyleAttribute(style: string | undefined): Record<string, string> {\n if (!style) return {};\n const normalized = style.replace(/\\r/g, \"\\n\");\n const parts = normalized.split(\";\");\n const entries: [string, string][] = [];\n for (const part of parts) {\n const idx = part.indexOf(\":\");\n if (idx <= 0) continue;\n const key = part.slice(0, idx).trim().toLowerCase();\n const val = part.slice(idx + 1).trim();\n if (!key || !val) continue;\n entries.push([key, val]);\n }\n return Object.fromEntries(entries);\n}\n\nfunction parseRgbToHex(value: string): string | undefined {\n const m = value\n .trim()\n .toLowerCase()\n .match(/^rgb\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*\\)$/);\n if (!m) return undefined;\n const nums = [Number(m[1]), Number(m[2]), Number(m[3])];\n if (nums.some((n) => Number.isNaN(n) || n < 0 || n > 255)) return undefined;\n return nums.map((n) => n.toString(16).padStart(2, \"0\")).join(\"\").toUpperCase();\n}\n\nfunction parseCssColorToHex(value: string | undefined): string | undefined {\n if (!value) return undefined;\n const v = value.trim();\n const hex = v.match(/^#([0-9a-fA-F]{6})$/)?.[1];\n if (hex) return hex.toUpperCase();\n return parseRgbToHex(v);\n}\n\nfunction parseFontSizeToHalfPoints(value: string | undefined): number | undefined {\n if (!value) return undefined;\n const v = value.trim().toLowerCase();\n const pt = v.match(/^(\\d+(?:\\.\\d+)?)pt$/);\n if (pt) return Math.max(1, Math.round(Number(pt[1]) * 2));\n const px = v.match(/^(\\d+(?:\\.\\d+)?)px$/);\n if (px) {\n const ptValue = (Number(px[1]) * 72) / 96;\n return Math.max(1, Math.round(ptValue * 2));\n }\n return undefined;\n}\n\nfunction normalizeFontFamily(value: string | undefined): string | undefined {\n if (!value) return undefined;\n const first = value.split(\",\")[0]?.trim();\n if (!first) return undefined;\n return first.replace(/^[\"']|[\"']$/g, \"\");\n}\n\nfunction mergeTextStyle(base: TextStyle, patch: TextStyle): TextStyle {\n return {\n bold: patch.bold ?? base.bold,\n italic: patch.italic ?? base.italic,\n underline: patch.underline ?? base.underline,\n colorHex: patch.colorHex ?? base.colorHex,\n fontFamily: patch.fontFamily ?? base.fontFamily,\n fontSizeHalfPoints: patch.fontSizeHalfPoints ?? base.fontSizeHalfPoints,\n };\n}\n\nfunction styleFromElement(node: HtmlNode): TextStyle {\n const tag = node.name?.toLowerCase();\n const styleAttr = node.attribs?.style;\n const css = parseStyleAttribute(styleAttr);\n\n const boldFromCss = (() => {\n const v = css[\"font-weight\"]?.trim().toLowerCase();\n if (!v) return undefined;\n if (v === \"bold\" || v === \"bolder\") return true;\n const n = Number(v);\n if (!Number.isNaN(n)) return n >= 600;\n return undefined;\n })();\n\n const italicFromCss = (() => {\n const v = css[\"font-style\"]?.trim().toLowerCase();\n if (!v) return undefined;\n if (v === \"italic\" || v === \"oblique\") return true;\n return undefined;\n })();\n\n const underlineFromCss = (() => {\n const v = css[\"text-decoration\"]?.trim().toLowerCase();\n if (!v) return undefined;\n return v.includes(\"underline\");\n })();\n\n const tagBold = tag === \"b\" || tag === \"strong\" ? true : undefined;\n const tagItalic = tag === \"i\" || tag === \"em\" ? true : undefined;\n const tagUnderline = tag === \"u\" ? true : undefined;\n\n return {\n bold: tagBold ?? boldFromCss,\n italic: tagItalic ?? italicFromCss,\n underline: tagUnderline ?? underlineFromCss,\n colorHex: parseCssColorToHex(css.color),\n fontFamily: normalizeFontFamily(css[\"font-family\"]),\n fontSizeHalfPoints: parseFontSizeToHalfPoints(css[\"font-size\"]),\n };\n}\n\nfunction getTextContent(node: HtmlNode): string {\n if (node.type === \"text\") return node.data ?? \"\";\n let out = \"\";\n const children = node.children ?? [];\n for (const c of children) out += getTextContent(c);\n return out;\n}\n\ntype RunToken =\n | { kind: \"text\"; text: string; style: TextStyle }\n | { kind: \"br\" }\n | { kind: \"image\"; image: EmbeddedImageRef };\n\ntype EmbeddedImage = {\n relationshipId: string;\n target: string;\n data: Uint8Array;\n contentType: string;\n widthPx: number;\n heightPx: number;\n};\n\nconst IMAGE_RELATIONSHIP_ID_OFFSET = 7;\n\ntype EmbeddedImageRef = {\n relationshipId: string;\n widthPx: number;\n heightPx: number;\n};\n\ntype HtmlToWordResult = {\n bodyXml: string;\n images: EmbeddedImage[];\n};\n\nfunction decodeBase64ToUint8Array(base64: string): Uint8Array {\n const BufferCtor = (globalThis as unknown as { Buffer?: typeof Buffer }).Buffer;\n if (BufferCtor) {\n return new Uint8Array(BufferCtor.from(base64, \"base64\"));\n }\n const atobFn = (globalThis as unknown as { atob?: (data: string) => string }).atob;\n if (!atobFn) {\n throw new Error(\"Base64 decode is not available in this environment.\");\n }\n const bin = atobFn(base64);\n const bytes = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);\n return bytes;\n}\n\nfunction parseImageDataUrl(\n src: string,\n): { contentType: string; data: Uint8Array; extension: \"png\" | \"jpeg\" } | undefined {\n const m = src.match(/^data:(image\\/png|image\\/jpeg);base64,([\\s\\S]+)$/i);\n if (!m) return undefined;\n const contentType = m[1].toLowerCase();\n const base64 = m[2].replace(/\\s+/g, \"\");\n const data = decodeBase64ToUint8Array(base64);\n const extension = contentType === \"image/png\" ? \"png\" : \"jpeg\";\n return { contentType, data, extension };\n}\n\nfunction parseCssLengthToPx(value: string | undefined): number | undefined {\n if (!value) return undefined;\n const v = value.trim().toLowerCase();\n const px = v.match(/^(\\d+(?:\\.\\d+)?)px$/);\n if (px) return Math.max(1, Math.round(Number(px[1])));\n return undefined;\n}\n\nfunction readUInt32BE(bytes: Uint8Array, offset: number): number | undefined {\n if (offset < 0 || offset + 4 > bytes.length) return undefined;\n return (\n ((bytes[offset] ?? 0) << 24) |\n ((bytes[offset + 1] ?? 0) << 16) |\n ((bytes[offset + 2] ?? 0) << 8) |\n (bytes[offset + 3] ?? 0)\n ) >>> 0;\n}\n\nfunction parsePngDimensions(data: Uint8Array): { widthPx: number; heightPx: number } | undefined {\n if (data.length < 24) return undefined;\n const signature = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];\n for (let i = 0; i < signature.length; i++) {\n if ((data[i] ?? 0) !== signature[i]) return undefined;\n }\n const widthPx = readUInt32BE(data, 16);\n const heightPx = readUInt32BE(data, 20);\n if (!widthPx || !heightPx) return undefined;\n return { widthPx, heightPx };\n}\n\nfunction parseJpegDimensions(data: Uint8Array): { widthPx: number; heightPx: number } | undefined {\n if (data.length < 4) return undefined;\n if (data[0] !== 0xff || data[1] !== 0xd8) return undefined;\n\n let offset = 2;\n while (offset + 4 <= data.length) {\n if (data[offset] !== 0xff) {\n offset++;\n continue;\n }\n while (offset < data.length && data[offset] === 0xff) offset++;\n if (offset >= data.length) return undefined;\n\n const marker = data[offset] as number;\n offset++;\n\n const isStandalone = marker === 0xd9 || marker === 0xda;\n if (isStandalone) break;\n if (offset + 2 > data.length) return undefined;\n const length = ((data[offset] as number) << 8) | (data[offset + 1] as number);\n if (length < 2 || offset + length > data.length) return undefined;\n\n const isSof =\n marker === 0xc0 ||\n marker === 0xc1 ||\n marker === 0xc2 ||\n marker === 0xc3 ||\n marker === 0xc5 ||\n marker === 0xc6 ||\n marker === 0xc7 ||\n marker === 0xc9 ||\n marker === 0xca ||\n marker === 0xcb ||\n marker === 0xcd ||\n marker === 0xce ||\n marker === 0xcf;\n if (isSof) {\n if (offset + 7 > data.length) return undefined;\n const heightPx = ((data[offset + 3] as number) << 8) | (data[offset + 4] as number);\n const widthPx = ((data[offset + 5] as number) << 8) | (data[offset + 6] as number);\n if (!widthPx || !heightPx) return undefined;\n return { widthPx, heightPx };\n }\n\n offset += length;\n }\n\n return undefined;\n}\n\nfunction parseIntrinsicImageSizePx(\n contentType: string,\n data: Uint8Array,\n): { widthPx: number; heightPx: number } | undefined {\n if (contentType === \"image/png\") return parsePngDimensions(data);\n if (contentType === \"image/jpeg\") return parseJpegDimensions(data);\n return undefined;\n}\n\nfunction applyMaxBoxPx(\n size: { widthPx: number; heightPx: number },\n maxBox: { maxWidthPx: number; maxHeightPx: number },\n): { widthPx: number; heightPx: number } {\n const w = Math.max(1, Math.round(size.widthPx));\n const h = Math.max(1, Math.round(size.heightPx));\n const scale = Math.min(1, maxBox.maxWidthPx / w, maxBox.maxHeightPx / h);\n return { widthPx: Math.max(1, Math.round(w * scale)), heightPx: Math.max(1, Math.round(h * scale)) };\n}\n\nfunction computeImageSizePx(\n node: HtmlNode,\n intrinsic: { widthPx: number; heightPx: number } | undefined,\n): { widthPx: number; heightPx: number } {\n const wAttr = node.attribs?.width ? Number(node.attribs.width) : undefined;\n const hAttr = node.attribs?.height ? Number(node.attribs.height) : undefined;\n const css = parseStyleAttribute(node.attribs?.style);\n const wCss = parseCssLengthToPx(css.width);\n const hCss = parseCssLengthToPx(css.height);\n\n const widthAttrPx = Number.isFinite(wAttr) && wAttr ? Math.max(1, Math.round(wAttr)) : undefined;\n const heightAttrPx = Number.isFinite(hAttr) && hAttr ? Math.max(1, Math.round(hAttr)) : undefined;\n\n const ratio =\n intrinsic && intrinsic.widthPx > 0 && intrinsic.heightPx > 0\n ? intrinsic.heightPx / intrinsic.widthPx\n : widthAttrPx && heightAttrPx\n ? heightAttrPx / widthAttrPx\n : 0.5;\n\n const widthPx =\n typeof wCss === \"number\"\n ? wCss\n : typeof widthAttrPx === \"number\"\n ? widthAttrPx\n : intrinsic?.widthPx ?? 300;\n const heightPx =\n typeof hCss === \"number\"\n ? hCss\n : typeof heightAttrPx === \"number\"\n ? heightAttrPx\n : intrinsic?.heightPx ?? 150;\n\n const finalSize =\n typeof wCss === \"number\" && typeof hCss !== \"number\"\n ? { widthPx, heightPx: Math.max(1, Math.round(widthPx * ratio)) }\n : typeof hCss === \"number\" && typeof wCss !== \"number\"\n ? { widthPx: Math.max(1, Math.round(heightPx / ratio)), heightPx }\n : typeof widthAttrPx === \"number\" && typeof heightAttrPx !== \"number\" && intrinsic\n ? { widthPx, heightPx: Math.max(1, Math.round(widthPx * ratio)) }\n : typeof heightAttrPx === \"number\" && typeof widthAttrPx !== \"number\" && intrinsic\n ? { widthPx: Math.max(1, Math.round(heightPx / ratio)), heightPx }\n : { widthPx, heightPx };\n\n return applyMaxBoxPx(finalSize, { maxWidthPx: 624, maxHeightPx: 864 });\n}\n\nfunction collectInlineRuns(\n node: HtmlNode,\n inherited: TextStyle,\n out: RunToken[],\n result: HtmlToWordResult,\n): void {\n if (node.type === \"text\") {\n const text = node.data ?? \"\";\n if (text) out.push({ kind: \"text\", text, style: inherited });\n return;\n }\n\n if (node.type === \"tag\") {\n const tag = node.name?.toLowerCase();\n if (tag === \"br\") {\n out.push({ kind: \"br\" });\n return;\n }\n if (tag === \"img\") {\n const src = node.attribs?.src;\n if (!src) return;\n const parsed = parseImageDataUrl(src);\n if (!parsed) return;\n const intrinsic = parseIntrinsicImageSizePx(parsed.contentType, parsed.data);\n const { widthPx, heightPx } = computeImageSizePx(node, intrinsic);\n const id = result.images.length + 1;\n const relationshipId = `rId${id + IMAGE_RELATIONSHIP_ID_OFFSET}`;\n const target = `media/image${id}.${parsed.extension}`;\n result.images.push({\n relationshipId,\n target,\n data: parsed.data,\n contentType: parsed.contentType,\n widthPx,\n heightPx,\n });\n out.push({ kind: \"image\", image: { relationshipId, widthPx, heightPx } });\n return;\n }\n if (tag === \"canvas\") {\n const dataUrl = node.attribs?.[\"data-image\"] ?? node.attribs?.[\"data-src\"];\n if (!dataUrl) return;\n const parsed = parseImageDataUrl(dataUrl);\n if (!parsed) return;\n const bufferW = node.attribs?.width ? Number(node.attribs.width) : undefined;\n const bufferH = node.attribs?.height ? Number(node.attribs.height) : undefined;\n const intrinsic =\n Number.isFinite(bufferW) && bufferW && Number.isFinite(bufferH) && bufferH\n ? { widthPx: Math.max(1, Math.round(bufferW)), heightPx: Math.max(1, Math.round(bufferH)) }\n : parseIntrinsicImageSizePx(parsed.contentType, parsed.data);\n const { widthPx, heightPx } = computeImageSizePx(node, intrinsic);\n const id = result.images.length + 1;\n const relationshipId = `rId${id + IMAGE_RELATIONSHIP_ID_OFFSET}`;\n const target = `media/image${id}.${parsed.extension}`;\n result.images.push({\n relationshipId,\n target,\n data: parsed.data,\n contentType: parsed.contentType,\n widthPx,\n heightPx,\n });\n out.push({ kind: \"image\", image: { relationshipId, widthPx, heightPx } });\n return;\n }\n const next = mergeTextStyle(inherited, styleFromElement(node));\n const children = node.children ?? [];\n for (const c of children) collectInlineRuns(c, next, out, result);\n return;\n }\n\n const children = node.children ?? [];\n for (const c of children) collectInlineRuns(c, inherited, out, result);\n}\n\nfunction buildRunXml(style: TextStyle, text: string): string {\n const rPrParts: string[] = [];\n if (style.bold) rPrParts.push(\"<w:b/>\");\n if (style.italic) rPrParts.push(\"<w:i/>\");\n if (style.underline) rPrParts.push('<w:u w:val=\"single\"/>');\n if (style.colorHex) rPrParts.push(`<w:color w:val=\"${style.colorHex}\"/>`);\n if (style.fontFamily) {\n const ff = escapeXmlText(style.fontFamily);\n rPrParts.push(`<w:rFonts w:ascii=\"${ff}\" w:hAnsi=\"${ff}\" w:eastAsia=\"${ff}\"/>`);\n }\n if (typeof style.fontSizeHalfPoints === \"number\") {\n const sz = style.fontSizeHalfPoints;\n rPrParts.push(`<w:sz w:val=\"${sz}\"/><w:szCs w:val=\"${sz}\"/>`);\n }\n\n const rPrXml = rPrParts.length ? `<w:rPr>${rPrParts.join(\"\")}</w:rPr>` : \"\";\n const escaped = escapeXmlText(text);\n const preserve = shouldPreserveSpace(text) ? ' xml:space=\"preserve\"' : \"\";\n return `<w:r>${rPrXml}<w:t${preserve}>${escaped}</w:t></w:r>`;\n}\n\nfunction pxToEmu(px: number): number {\n return Math.max(1, Math.round(px * 9525));\n}\n\nfunction buildImageRunXml(image: EmbeddedImageRef): string {\n const cx = pxToEmu(image.widthPx);\n const cy = pxToEmu(image.heightPx);\n const docPrId = image.relationshipId.replace(/^rId/, \"\");\n const name = `Picture ${docPrId}`;\n\n return `<w:r><w:drawing xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\"><wp:inline distT=\"0\" distB=\"0\" distL=\"0\" distR=\"0\"><wp:extent cx=\"${cx}\" cy=\"${cy}\"/><wp:docPr id=\"${docPrId}\" name=\"${escapeXmlText(name)}\"/><a:graphic><a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\"><pic:pic><pic:nvPicPr><pic:cNvPr id=\"0\" name=\"${escapeXmlText(name)}\"/><pic:cNvPicPr/></pic:nvPicPr><pic:blipFill><a:blip r:embed=\"${image.relationshipId}\"/><a:stretch><a:fillRect/></a:stretch></pic:blipFill><pic:spPr><a:xfrm><a:off x=\"0\" y=\"0\"/><a:ext cx=\"${cx}\" cy=\"${cy}\"/></a:xfrm><a:prstGeom prst=\"rect\"><a:avLst/></a:prstGeom></pic:spPr></pic:pic></a:graphicData></a:graphic></wp:inline></w:drawing></w:r>`;\n}\n\nfunction hasClass(node: HtmlNode, className: string): boolean {\n const cls = node.attribs?.class;\n if (!cls) return false;\n return cls.split(/\\s+/).includes(className);\n}\n\nfunction isSkippableSubtree(node: HtmlNode): boolean {\n if (node.type !== \"tag\") return false;\n const tag = node.name?.toLowerCase();\n if (tag === \"button\") return true;\n if (tag === \"canvas\") {\n const dataUrl = node.attribs?.[\"data-image\"] ?? node.attribs?.[\"data-src\"];\n if (!dataUrl) return true;\n }\n if (tag === \"img\" && hasClass(node, \"ProseMirror-separator\")) return true;\n if (node.attribs?.id === \"pages\") return true;\n if (hasClass(node, \"ProseMirror-widget\")) return true;\n return false;\n}\n\nfunction parseCssLengthToTwips(\n value: string | undefined,\n baseFontHalfPoints: number,\n): number | undefined {\n if (!value) return undefined;\n const v = value.trim().toLowerCase();\n if (!v) return undefined;\n\n const pt = v.match(/^(-?\\d+(?:\\.\\d+)?)pt$/);\n if (pt) return Math.round(Number(pt[1]) * 20);\n\n const px = v.match(/^(-?\\d+(?:\\.\\d+)?)px$/);\n if (px) return Math.round((Number(px[1]) * 72 * 20) / 96);\n\n const em = v.match(/^(-?\\d+(?:\\.\\d+)?)em$/);\n if (em) {\n const basePt = baseFontHalfPoints / 2;\n return Math.round(Number(em[1]) * basePt * 20);\n }\n\n const num = v.match(/^(-?\\d+(?:\\.\\d+)?)$/);\n if (num) return Math.round(Number(num[1]));\n\n return undefined;\n}\n\nfunction inferFirstFontSizeHalfPoints(node: HtmlNode): number | undefined {\n const stack: HtmlNode[] = [node];\n while (stack.length) {\n const cur = stack.pop() as HtmlNode;\n if (cur.type === \"tag\") {\n const css = parseStyleAttribute(cur.attribs?.style);\n const sz = parseFontSizeToHalfPoints(css[\"font-size\"]);\n if (typeof sz === \"number\") return sz;\n }\n const children = cur.children ?? [];\n for (let i = children.length - 1; i >= 0; i--) {\n stack.push(children[i] as HtmlNode);\n }\n }\n return undefined;\n}\n\nfunction buildParagraphPrXml(\n node: HtmlNode,\n baseFontHalfPoints: number,\n extraInd?: { leftTwips?: number; hangingTwips?: number },\n pStyleId?: string,\n): string {\n const css = parseStyleAttribute(node.attribs?.style);\n const parts: string[] = [];\n\n if (pStyleId) parts.push(`<w:pStyle w:val=\"${escapeXmlText(pStyleId)}\"/>`);\n\n const align = css[\"text-align\"]?.trim().toLowerCase();\n const jcVal =\n align === \"center\"\n ? \"center\"\n : align === \"right\"\n ? \"right\"\n : align === \"justify\"\n ? \"both\"\n : undefined;\n if (jcVal) parts.push(`<w:jc w:val=\"${jcVal}\"/>`);\n\n const left = (() => {\n const marginLeft = parseCssLengthToTwips(css[\"margin-left\"], baseFontHalfPoints);\n const paddingLeft = parseCssLengthToTwips(css[\"padding-left\"], baseFontHalfPoints);\n const sum = (marginLeft ?? 0) + (paddingLeft ?? 0);\n if (!sum) return undefined;\n return Math.max(0, sum);\n })();\n\n const firstLine = (() => {\n const textIndent = parseCssLengthToTwips(css[\"text-indent\"], baseFontHalfPoints);\n if (typeof textIndent !== \"number\" || !textIndent) return undefined;\n return Math.max(0, textIndent);\n })();\n\n const indAttrs: string[] = [];\n const leftTwips = extraInd?.leftTwips ?? left;\n if (typeof leftTwips === \"number\") indAttrs.push(`w:left=\"${leftTwips}\"`);\n const hangingTwips = extraInd?.hangingTwips;\n if (typeof hangingTwips === \"number\") indAttrs.push(`w:hanging=\"${hangingTwips}\"`);\n if (typeof firstLine === \"number\") indAttrs.push(`w:firstLine=\"${firstLine}\"`);\n if (indAttrs.length) parts.push(`<w:ind ${indAttrs.join(\" \")}/>`);\n\n const before = parseCssLengthToTwips(css[\"margin-top\"], baseFontHalfPoints);\n const after = parseCssLengthToTwips(css[\"margin-bottom\"], baseFontHalfPoints);\n const lineHeight = (() => {\n const lh = css[\"line-height\"]?.trim().toLowerCase();\n if (!lh || lh === \"normal\") return undefined;\n\n const unitless = lh.match(/^(\\d+(?:\\.\\d+)?)$/);\n if (unitless) {\n const multiplier = Number(unitless[1]);\n if (!Number.isFinite(multiplier) || multiplier <= 0) return undefined;\n const basePt = baseFontHalfPoints / 2;\n return Math.round(basePt * multiplier * 20);\n }\n\n const twips = parseCssLengthToTwips(lh, baseFontHalfPoints);\n if (typeof twips !== \"number\") return undefined;\n return Math.max(1, twips);\n })();\n\n if (\n typeof before === \"number\" ||\n typeof after === \"number\" ||\n typeof lineHeight === \"number\"\n ) {\n const attrs: string[] = [];\n if (typeof before === \"number\") attrs.push(`w:before=\"${Math.max(0, before)}\"`);\n if (typeof after === \"number\") attrs.push(`w:after=\"${Math.max(0, after)}\"`);\n if (typeof lineHeight === \"number\") {\n attrs.push(`w:line=\"${lineHeight}\"`, 'w:lineRule=\"exact\"');\n }\n parts.push(`<w:spacing ${attrs.join(\" \")}/>`);\n }\n\n if (!parts.length) return \"\";\n return `<w:pPr>${parts.join(\"\")}</w:pPr>`;\n}\n\nfunction buildParagraphXmlFromContainer(\n node: HtmlNode,\n baseStyle: TextStyle,\n extraInd?: { leftTwips?: number; hangingTwips?: number },\n pStyleId?: string,\n result?: HtmlToWordResult,\n): string {\n const baseFontHalfPoints = baseStyle.fontSizeHalfPoints ?? inferFirstFontSizeHalfPoints(node) ?? 28;\n const pPrXml = buildParagraphPrXml(node, baseFontHalfPoints, extraInd, pStyleId);\n\n const runs: RunToken[] = [];\n const res =\n result ??\n ({\n bodyXml: \"\",\n images: [],\n } as HtmlToWordResult);\n for (const c of node.children ?? []) collectInlineRuns(c, baseStyle, runs, res);\n\n const rXml: string[] = [];\n for (const token of runs) {\n if (token.kind === \"br\") {\n rXml.push(\"<w:r><w:br/></w:r>\");\n continue;\n }\n if (token.kind === \"image\") {\n rXml.push(buildImageRunXml(token.image));\n continue;\n }\n const text = token.text;\n if (!text) continue;\n if (!text.trim() && !shouldKeepWhitespaceOnlyRun(text)) continue;\n rXml.push(buildRunXml(token.style, text));\n }\n\n if (!rXml.length) return \"\";\n return `<w:p>${pPrXml}${rXml.join(\"\")}</w:p>`;\n}\n\nconst PAGE_BREAK_XML = '<w:p><w:r><w:br w:type=\"page\"/></w:r></w:p>';\n\nfunction isExplicitPageBreak(node: HtmlNode): boolean {\n if (node.type !== \"tag\") return false;\n const tag = node.name?.toLowerCase();\n const css = parseStyleAttribute(node.attribs?.style);\n const cls = node.attribs?.class ?? \"\";\n const classList = cls ? cls.split(/\\s+/) : [];\n\n if (tag === \"hr\" && classList.includes(\"page-break\")) return true;\n if (classList.includes(\"page-break\")) return true;\n if (node.attribs?.[\"data-page-break\"] === \"true\") return true;\n\n const after = css[\"page-break-after\"]?.toLowerCase() ?? css[\"break-after\"]?.toLowerCase();\n const before = css[\"page-break-before\"]?.toLowerCase() ?? css[\"break-before\"]?.toLowerCase();\n if (after?.includes(\"always\") || before?.includes(\"always\")) return true;\n\n return false;\n}\n\nfunction buildHeadingBaseStyle(level: number): TextStyle {\n const size = level === 1 ? 44 : level === 2 ? 32 : level === 3 ? 28 : level === 4 ? 24 : 22;\n return { bold: true, fontSizeHalfPoints: size };\n}\n\nfunction buildListBlocks(\n listNode: HtmlNode,\n ordered: boolean,\n level: number,\n result: HtmlToWordResult,\n): string[] {\n const liNodes = (listNode.children ?? []).filter(\n (c) => c.type === \"tag\" && c.name?.toLowerCase() === \"li\",\n );\n if (!liNodes.length) return [];\n\n const out: string[] = [];\n const numId = ordered ? 2 : 1;\n const ilvl = Math.max(0, Math.min(8, Math.floor(level)));\n const leftTwips = 720 * (ilvl + 1);\n const hangingTwips = 360;\n\n for (const li of liNodes) {\n const nestedLists: HtmlNode[] = [];\n const baseStyle: TextStyle = {};\n const runs: RunToken[] = [];\n for (const c of li.children ?? []) {\n if (c.type === \"tag\") {\n const tag = c.name?.toLowerCase();\n if (tag === \"ul\" || tag === \"ol\") {\n nestedLists.push(c);\n continue;\n }\n }\n collectInlineRuns(c, baseStyle, runs, result);\n }\n\n const rXml: string[] = [];\n for (const token of runs) {\n if (token.kind === \"br\") {\n rXml.push(\"<w:r><w:br/></w:r>\");\n continue;\n }\n if (token.kind === \"image\") {\n rXml.push(buildImageRunXml(token.image));\n continue;\n }\n const text = token.text;\n if (!text) continue;\n if (!text.trim() && !shouldKeepWhitespaceOnlyRun(text)) continue;\n rXml.push(buildRunXml(token.style, text));\n }\n\n if (rXml.length) {\n const baseFontHalfPoints = inferFirstFontSizeHalfPoints(li) ?? 28;\n const pPrXml = buildParagraphPrXml(\n li,\n baseFontHalfPoints,\n { leftTwips, hangingTwips },\n undefined,\n );\n const numPrXml = `<w:numPr><w:ilvl w:val=\"${ilvl}\"/><w:numId w:val=\"${numId}\"/></w:numPr>`;\n const mergedPPrXml = pPrXml\n ? pPrXml.replace(\"<w:pPr>\", `<w:pPr>${numPrXml}`)\n : `<w:pPr>${numPrXml}<w:ind w:left=\"${leftTwips}\" w:hanging=\"${hangingTwips}\"/></w:pPr>`;\n out.push(`<w:p>${mergedPPrXml}${rXml.join(\"\")}</w:p>`);\n }\n\n for (const nested of nestedLists) {\n const nestedOrdered = nested.name?.toLowerCase() === \"ol\";\n out.push(...buildListBlocks(nested, nestedOrdered, ilvl + 1, result));\n }\n }\n\n return out;\n}\n\nfunction parseCellWidthTwips(node: HtmlNode): number | undefined {\n const css = parseStyleAttribute(node.attribs?.style);\n const width = parseCssLengthToTwips(css.width, 28);\n if (typeof width !== \"number\" || width <= 0) return undefined;\n return width;\n}\n\nfunction estimateTextWidthTwips(text: string, baseFontHalfPoints: number): number {\n const basePt = baseFontHalfPoints / 2;\n const cjkRegex = /[\\u3400-\\u4dbf\\u4e00-\\u9fff\\u3000-\\u303f\\uff00-\\uffef]/;\n let cjk = 0;\n let latin = 0;\n let spaces = 0;\n for (const ch of text) {\n if (ch === \" \" || ch === \"\\t\") {\n spaces++;\n continue;\n }\n if (cjkRegex.test(ch)) {\n cjk++;\n continue;\n }\n latin++;\n }\n const cjkTwips = Math.round(basePt * 20);\n const latinTwips = Math.round(basePt * 11);\n const spaceTwips = Math.round(basePt * 6);\n return cjk * cjkTwips + latin * latinTwips + spaces * spaceTwips;\n}\n\ntype WordBorder = { val: string; sz: number; colorHex?: string };\n\nfunction parseBorderShorthand(value: string | undefined, baseFontHalfPoints: number): WordBorder | undefined {\n if (!value) return undefined;\n const raw = value.trim().toLowerCase();\n if (!raw) return undefined;\n if (raw === \"none\" || raw === \"0\") return { val: \"nil\", sz: 0 };\n\n const tokens = raw.split(/\\s+/).filter(Boolean);\n if (!tokens.length) return undefined;\n\n const css = Object.fromEntries(tokens.map((t, i) => [`${i}`, t]));\n const widthToken = Object.values(css).find((t) => /^(?:\\d+(?:\\.\\d+)?)(?:px|pt)?$/.test(t));\n const styleToken = Object.values(css).find((t) =>\n [\"none\", \"solid\", \"dashed\", \"dotted\", \"double\", \"hidden\"].includes(t),\n );\n const colorToken = Object.values(css).find((t) => t.startsWith(\"#\") || t.startsWith(\"rgb(\"));\n\n const widthTwips = parseCssLengthToTwips(widthToken, baseFontHalfPoints);\n const sz = (() => {\n if (typeof widthTwips !== \"number\") return 4;\n if (widthTwips <= 0) return 0;\n return Math.max(2, Math.round(widthTwips * 0.4));\n })();\n\n const val = (() => {\n if (!styleToken) return \"single\";\n if (styleToken === \"none\" || styleToken === \"hidden\") return \"nil\";\n if (styleToken === \"solid\") return \"single\";\n if (styleToken === \"dashed\") return \"dashed\";\n if (styleToken === \"dotted\") return \"dotted\";\n if (styleToken === \"double\") return \"double\";\n return \"single\";\n })();\n\n const colorHex = parseCssColorToHex(colorToken);\n return { val, sz, colorHex };\n}\n\nfunction buildBorderTag(tag: string, border: WordBorder | undefined, fallbackColorHex: string): string {\n const b = border ?? { val: \"single\", sz: 4, colorHex: fallbackColorHex };\n const color = (b.colorHex ?? fallbackColorHex).toUpperCase();\n return `<w:${tag} w:val=\"${b.val}\" w:sz=\"${b.sz}\" w:space=\"0\" w:color=\"${color}\"/>`;\n}\n\nfunction injectTableCellParagraphSpacing(pXml: string): string {\n if (!pXml.includes(\"<w:p\")) return pXml;\n if (!pXml.includes(\"<w:p>\")) return pXml;\n const spacingXml = '<w:spacing w:before=\"0\" w:after=\"0\" w:line=\"360\" w:lineRule=\"auto\"/><w:wordWrap w:val=\"1\"/>';\n if (pXml.includes(\"<w:pPr>\")) {\n if (pXml.includes(\"<w:spacing \")) return pXml;\n return pXml.replace(\"<w:pPr>\", `<w:pPr>${spacingXml}`);\n }\n return pXml.replace(\"<w:p>\", `<w:p><w:pPr>${spacingXml}</w:pPr>`);\n}\n\nfunction buildTableCellBlocksXml(cell: HtmlNode, baseStyle: TextStyle, result: HtmlToWordResult): string {\n const children = cell.children ?? [];\n const hasBlocks = children.some((c) => {\n if (c.type !== \"tag\") return false;\n const tag = c.name?.toLowerCase();\n return tag === \"p\" || tag === \"ul\" || tag === \"ol\" || tag === \"img\" || tag === \"canvas\" || /^h[1-6]$/.test(tag ?? \"\");\n });\n\n const out: string[] = [];\n if (!hasBlocks) {\n const p = buildParagraphXmlFromContainer(cell, baseStyle, undefined, undefined, result);\n if (p) out.push(p);\n return out.length ? out.map(injectTableCellParagraphSpacing).join(\"\") : \"<w:p/>\";\n }\n\n for (const c of children) {\n if (c.type === \"tag\") {\n const tag = c.name?.toLowerCase();\n if (tag === \"p\") {\n const p = buildParagraphXmlFromContainer(c, baseStyle, undefined, undefined, result);\n if (p) out.push(p);\n continue;\n }\n if (tag && /^h[1-6]$/.test(tag)) {\n const level = Number(tag.slice(1));\n const p = buildParagraphXmlFromContainer(c, baseStyle, undefined, `Heading${level}`, result);\n if (p) out.push(p);\n continue;\n }\n if (tag === \"ul\" || tag === \"ol\") {\n out.push(...buildListBlocks(c, tag === \"ol\", 0, result));\n continue;\n }\n if (tag === \"img\" || tag === \"canvas\") {\n const p = buildParagraphXmlFromSingleInlineNode(c, baseStyle, result);\n if (p) out.push(p);\n continue;\n }\n }\n }\n\n if (!out.length) return \"<w:p/>\";\n return out.map(injectTableCellParagraphSpacing).join(\"\");\n}\n\nfunction buildTableXml(tableNode: HtmlNode, result: HtmlToWordResult): string {\n const rows: HtmlNode[] = [];\n const stack: HtmlNode[] = [...(tableNode.children ?? [])];\n while (stack.length) {\n const n = stack.shift() as HtmlNode;\n if (n.type === \"tag\" && n.name?.toLowerCase() === \"tr\") rows.push(n);\n if (n.children?.length) stack.unshift(...n.children);\n }\n\n const rowCells = rows.map((tr) =>\n (tr.children ?? []).filter((c) => c.type === \"tag\" && (c.name === \"td\" || c.name === \"th\")),\n );\n const colCount = Math.max(0, ...rowCells.map((cells) => cells.length));\n const maxTableWidthTwips = 9360;\n\n const estimatedColWidths = new Array(colCount).fill(0).map((_, i) => {\n let explicit: number | undefined;\n let estimated = 0;\n for (const cells of rowCells) {\n const cell = cells[i] as HtmlNode | undefined;\n if (!cell) continue;\n const w = parseCellWidthTwips(cell);\n if (typeof w === \"number\") explicit = explicit ?? w;\n const text = getTextContent(cell).replace(/\\s+/g, \" \").trim();\n if (!text) continue;\n const baseFontHalfPoints = inferFirstFontSizeHalfPoints(cell) ?? 28;\n const wTwips = estimateTextWidthTwips(text, baseFontHalfPoints) + 240;\n estimated = Math.max(estimated, wTwips);\n }\n const base = typeof explicit === \"number\" ? explicit : estimated || Math.round(maxTableWidthTwips / Math.max(1, colCount));\n return Math.max(720, Math.min(6000, Math.round(base)));\n });\n\n const normalizedColWidths = (() => {\n const sum = estimatedColWidths.reduce((a, b) => a + b, 0);\n if (!sum) return estimatedColWidths;\n if (sum <= maxTableWidthTwips) return estimatedColWidths;\n const scaled = estimatedColWidths.map((w) =>\n Math.max(720, Math.floor((w * maxTableWidthTwips) / sum)),\n );\n const scaledSum = scaled.reduce((a, b) => a + b, 0);\n const diff = maxTableWidthTwips - scaledSum;\n if (diff !== 0 && scaled.length) scaled[scaled.length - 1] = Math.max(720, scaled[scaled.length - 1] + diff);\n return scaled;\n })();\n\n const tblGrid = `<w:tblGrid>${normalizedColWidths.map((w) => `<w:gridCol w:w=\"${w}\"/>`).join(\"\")}</w:tblGrid>`;\n\n const rowXml: string[] = [];\n for (let rowIdx = 0; rowIdx < rows.length; rowIdx++) {\n const tr = rows[rowIdx] as HtmlNode;\n const cells = rowCells[rowIdx] ?? [];\n\n const cellXml: string[] = [];\n for (let i = 0; i < cells.length; i++) {\n const cell = cells[i] as HtmlNode;\n const isHeader = cell.name === \"th\";\n const baseStyle: TextStyle = isHeader ? { bold: true } : {};\n const paragraphs = buildTableCellBlocksXml(cell, baseStyle, result);\n const css = parseStyleAttribute(cell.attribs?.style);\n const widthTwips = parseCellWidthTwips(cell) ?? normalizedColWidths[i];\n const tcW =\n typeof widthTwips === \"number\"\n ? `<w:tcW w:w=\"${widthTwips}\" w:type=\"dxa\"/>`\n : `<w:tcW w:w=\"0\" w:type=\"auto\"/>`;\n const vAlign = (() => {\n const v = css[\"vertical-align\"]?.trim().toLowerCase();\n if (!v) return \"\";\n if (v === \"middle\" || v === \"center\") return '<w:vAlign w:val=\"center\"/>';\n if (v === \"bottom\") return '<w:vAlign w:val=\"bottom\"/>';\n if (v === \"top\") return '<w:vAlign w:val=\"top\"/>';\n return \"\";\n })();\n const shd = (() => {\n const hex = parseCssColorToHex(css[\"background-color\"]);\n if (!hex) return \"\";\n return `<w:shd w:val=\"clear\" w:color=\"auto\" w:fill=\"${hex}\"/>`;\n })();\n const noWrap = (() => {\n const ws = css[\"white-space\"]?.trim().toLowerCase();\n if (ws?.includes(\"nowrap\")) return \"<w:noWrap/>\";\n return \"\";\n })();\n const cellBorder = (() => {\n const bAll = parseBorderShorthand(css.border, 28);\n const bTop = parseBorderShorthand(css[\"border-top\"] ?? css.border, 28);\n const bLeft = parseBorderShorthand(css[\"border-left\"] ?? css.border, 28);\n const bBottom = parseBorderShorthand(css[\"border-bottom\"] ?? css.border, 28);\n const bRight = parseBorderShorthand(css[\"border-right\"] ?? css.border, 28);\n const any =\n bAll || css.border || css[\"border-top\"] || css[\"border-left\"] || css[\"border-bottom\"] || css[\"border-right\"];\n if (!any) return \"\";\n const fallback = bAll?.colorHex ?? \"D9D9D9\";\n return `<w:tcBorders>${buildBorderTag(\"top\", bTop, fallback)}${buildBorderTag(\n \"left\",\n bLeft,\n fallback,\n )}${buildBorderTag(\"bottom\", bBottom, fallback)}${buildBorderTag(\n \"right\",\n bRight,\n fallback,\n )}</w:tcBorders>`;\n })();\n cellXml.push(`<w:tc><w:tcPr>${tcW}${vAlign}${shd}${noWrap}${cellBorder}</w:tcPr>${paragraphs}</w:tc>`);\n }\n if (cellXml.length) rowXml.push(`<w:tr>${cellXml.join(\"\")}</w:tr>`);\n }\n\n const tblCss = parseStyleAttribute(tableNode.attribs?.style);\n const tblAlign = (() => {\n const ml = tblCss[\"margin-left\"]?.trim().toLowerCase();\n const mr = tblCss[\"margin-right\"]?.trim().toLowerCase();\n const m = tblCss.margin?.trim().toLowerCase();\n if ((ml === \"auto\" && mr === \"auto\") || (m?.includes(\"auto\") ?? false)) return '<w:tblJc w:val=\"center\"/>';\n const ta = tblCss[\"text-align\"]?.trim().toLowerCase();\n if (ta === \"center\") return '<w:tblJc w:val=\"center\"/>';\n if (ta === \"right\") return '<w:tblJc w:val=\"right\"/>';\n return \"\";\n })();\n const tblBorder = (() => {\n const border = parseBorderShorthand(tblCss.border, 28);\n if (tblCss.border) {\n const fallback = border?.colorHex ?? \"D9D9D9\";\n return `<w:tblBorders>${buildBorderTag(\"top\", border, fallback)}${buildBorderTag(\n \"left\",\n border,\n fallback,\n )}${buildBorderTag(\"bottom\", border, fallback)}${buildBorderTag(\n \"right\",\n border,\n fallback,\n )}${buildBorderTag(\"insideH\", border, fallback)}${buildBorderTag(\n \"insideV\",\n border,\n fallback,\n )}</w:tblBorders>`;\n }\n const fallback = \"D9D9D9\";\n return `<w:tblBorders>${buildBorderTag(\"top\", undefined, fallback)}${buildBorderTag(\n \"left\",\n undefined,\n fallback,\n )}${buildBorderTag(\"bottom\", undefined, fallback)}${buildBorderTag(\n \"right\",\n undefined,\n fallback,\n )}${buildBorderTag(\"insideH\", undefined, fallback)}${buildBorderTag(\"insideV\", undefined, fallback)}</w:tblBorders>`;\n })();\n const tblW = `<w:tblW w:w=\"${normalizedColWidths.reduce((a, b) => a + b, 0)}\" w:type=\"dxa\"/>`;\n const tblPr = `<w:tblPr>${tblW}<w:tblLayout w:type=\"fixed\"/>${tblAlign}${tblBorder}</w:tblPr>`;\n return `<w:tbl>${tblPr}${tblGrid}${rowXml.join(\"\")}</w:tbl>`;\n}\n\nfunction buildParagraphXmlFromSingleInlineNode(\n node: HtmlNode,\n baseStyle: TextStyle,\n result: HtmlToWordResult,\n): string {\n const wrapper: HtmlNode = {\n type: \"tag\",\n name: \"p\",\n attribs: { style: \"text-align: center;\" },\n children: [node],\n };\n return buildParagraphXmlFromContainer(wrapper, baseStyle, undefined, undefined, result);\n}\n\nfunction collectBodyBlocks(node: HtmlNode, out: string[], result: HtmlToWordResult): void {\n if (isSkippableSubtree(node)) return;\n\n if (node.type === \"tag\") {\n const tag = node.name?.toLowerCase();\n\n if (isExplicitPageBreak(node)) {\n out.push(PAGE_BREAK_XML);\n return;\n }\n\n if (tag === \"p\") {\n const pXml = buildParagraphXmlFromContainer(node, {}, undefined, undefined, result);\n if (pXml) out.push(pXml);\n return;\n }\n\n if (tag === \"img\" || tag === \"canvas\") {\n const pXml = buildParagraphXmlFromSingleInlineNode(node, {}, result);\n if (pXml) out.push(pXml);\n return;\n }\n\n if (tag && /^h[1-6]$/.test(tag)) {\n const level = Number(tag.slice(1));\n const hXml = buildParagraphXmlFromContainer(node, {}, undefined, `Heading${level}`, result);\n if (hXml) out.push(hXml);\n return;\n }\n\n if (tag === \"table\") {\n const tblXml = buildTableXml(node, result);\n if (tblXml) out.push(tblXml);\n return;\n }\n\n if (tag === \"ul\" || tag === \"ol\") {\n out.push(...buildListBlocks(node, tag === \"ol\", 0, result));\n return;\n }\n }\n\n for (const c of node.children ?? []) collectBodyBlocks(c, out, result);\n}\n\nexport function textToWordBodyXml(text: string): string {\n const normalized = text.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n if (!normalized.trim()) {\n throw new Error(\"Text is empty.\");\n }\n\n const lines = normalized.split(\"\\n\");\n const out: string[] = [];\n for (const line of lines) {\n if (!line) {\n out.push(\"<w:p/>\");\n continue;\n }\n out.push(`<w:p>${buildRunXml({}, line)}</w:p>`);\n }\n return out.join(\"\");\n}\n\nfunction htmlToWordBody(html: string): HtmlToWordResult {\n const normalized = html.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n const doc = parseDocument(normalized, {\n lowerCaseAttributeNames: true,\n lowerCaseTags: true,\n recognizeSelfClosing: true,\n }) as unknown as HtmlNode;\n\n const result: HtmlToWordResult = { bodyXml: \"\", images: [] };\n const out: string[] = [];\n collectBodyBlocks(doc, out, result);\n result.bodyXml = out.join(\"\");\n return result;\n}\n\n/**\n * 把 HTML 字符串转换成 WordprocessingML 的 body 片段(由 <w:p> / <w:tbl> 等组成)。\n * 说明:\n * - 这个函数只生成 body 内容,不生成完整的 <w:document> 包装\n * - 支持:p/span/strong/br、h1~h6、ul/ol/li、table/tr/td/th、基础分页标记\n * - 不支持:canvas 图表、复杂 CSS、HTML 图片(需要额外提供图片二进制)\n */\nexport function htmlToWordBodyXml(html: string): string {\n const { bodyXml } = htmlToWordBody(html);\n if (!bodyXml) {\n const text = getTextContent(\n parseDocument(html, {\n lowerCaseAttributeNames: true,\n lowerCaseTags: true,\n recognizeSelfClosing: true,\n }) as unknown as HtmlNode,\n );\n return textToWordBodyXml(text);\n }\n return bodyXml;\n}\n\nexport function htmlToWordBodyWithAssets(html: string): HtmlToWordResult {\n const result = htmlToWordBody(html);\n if (!result.bodyXml) {\n const text = getTextContent(\n parseDocument(html, {\n lowerCaseAttributeNames: true,\n lowerCaseTags: true,\n recognizeSelfClosing: true,\n }) as unknown as HtmlNode,\n );\n return { bodyXml: textToWordBodyXml(text), images: [] };\n }\n return result;\n}\n"],"mappings":"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","names":["children","fallback"]}