@office-open/docx 0.9.4 → 0.9.5

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.
@@ -1,5 +1,5 @@
1
1
  import { TargetModeType, ThemeColor, convertEmuToPixels, convertPixelsToEmu, convertToEmu, convertToTwip, convertUniversalMeasureToEmu, decimalNumber, eighthPointMeasureValue, hexColorValue, hpsMeasureValue, measurementOrPercentValue, pointMeasureValue, signedTwipsMeasureValue, toUint8Array, twipsMeasureValue, uCharHexNumber, uniqueId, uniqueNumericIdCreator, xsdVerticalMergeRev } from "@office-open/core";
2
- import { attr, attrBool, attrNum, children, element, escapeXml, findChild, findDeep, textOf } from "@office-open/xml";
2
+ import { attr, attrBool, attrNum, children, colorAttr, element, escapeXml, findChild, findDeep, textOf } from "@office-open/xml";
3
3
  import { calculateEffectExtent, createEffectDag, createScene3D, createShape3D, customGeometryDesc, effectListDesc, extractBlipFillMedia, fillDesc, outlineDesc, scene3DDesc, shape3DDesc, transform2DDesc } from "@office-open/core/drawingml";
4
4
  import { chartSpaceDesc } from "@office-open/core/chart";
5
5
  import { createDataModel } from "@office-open/core/smartart";
@@ -632,6 +632,1288 @@ const WidthType = {
632
632
  PERCENTAGE: "pct"
633
633
  };
634
634
  //#endregion
635
+ //#region src/parts/paragraph/run/run-parse.ts
636
+ /**
637
+ * Run properties parser for DOCX documents.
638
+ *
639
+ * Parses w:rPr Element trees into RunPropertiesOptions objects.
640
+ *
641
+ * @module
642
+ */
643
+ /**
644
+ * Parse a w:rPr element into RunPropertiesOptions.
645
+ */
646
+ function parseRunProperties(el) {
647
+ const opts = {};
648
+ const rStyle = findChild(el, "w:rStyle");
649
+ if (rStyle) opts.style = attr(rStyle, "w:val");
650
+ const font = findChild(el, "w:rFonts");
651
+ if (font) {
652
+ const ascii = attr(font, "w:ascii");
653
+ const eastAsia = attr(font, "w:eastAsia");
654
+ const hAnsi = attr(font, "w:hAnsi");
655
+ const cs = attr(font, "w:cs");
656
+ const hint = attr(font, "w:hint");
657
+ if (ascii && !eastAsia && !hAnsi && !cs) opts.font = hint ? {
658
+ name: ascii,
659
+ hint
660
+ } : ascii;
661
+ else {
662
+ const fontObj = {};
663
+ if (ascii) fontObj.ascii = ascii;
664
+ if (eastAsia) fontObj.eastAsia = eastAsia;
665
+ if (hAnsi) fontObj.hAnsi = hAnsi;
666
+ if (cs) fontObj.cs = cs;
667
+ if (hint) fontObj.hint = hint;
668
+ opts.font = fontObj;
669
+ }
670
+ }
671
+ const bold = findChild(el, "w:b");
672
+ if (bold) opts.bold = attrBool(bold, "w:val") ?? true;
673
+ const boldCs = findChild(el, "w:bCs");
674
+ if (boldCs) opts.boldComplexScript = attrBool(boldCs, "w:val") ?? true;
675
+ const italic = findChild(el, "w:i");
676
+ if (italic) opts.italic = attrBool(italic, "w:val") ?? true;
677
+ const italicCs = findChild(el, "w:iCs");
678
+ if (italicCs) opts.italicComplexScript = attrBool(italicCs, "w:val") ?? true;
679
+ const underline = findChild(el, "w:u");
680
+ if (underline) {
681
+ const ul = {};
682
+ const uType = attr(underline, "w:val");
683
+ if (uType) ul.type = uType;
684
+ const uColor = colorAttr(underline, "w:color");
685
+ if (uColor) ul.color = uColor;
686
+ opts.underline = ul;
687
+ }
688
+ for (const [name, optKey] of [
689
+ ["w:strike", "strike"],
690
+ ["w:dstrike", "doubleStrike"],
691
+ ["w:outline", "outline"],
692
+ ["w:shadow", "shadow"],
693
+ ["w:emboss", "emboss"],
694
+ ["w:imprint", "imprint"],
695
+ ["w:vanish", "vanish"],
696
+ ["w:webHidden", "webHidden"],
697
+ ["w:noProof", "noProof"],
698
+ ["w:snapToGrid", "snapToGrid"],
699
+ ["w:smallCaps", "smallCaps"],
700
+ ["w:caps", "allCaps"],
701
+ ["w:rtl", "rightToLeft"],
702
+ ["w:cs", "complexScript"],
703
+ ["w:specVanish", "specVanish"],
704
+ ["w:oMath", "math"]
705
+ ]) {
706
+ const child = findChild(el, name);
707
+ if (child) opts[optKey] = attrBool(child, "w:val") ?? true;
708
+ }
709
+ const color = findChild(el, "w:color");
710
+ if (color) {
711
+ const c = colorAttr(color, "w:val");
712
+ const themeColor = attr(color, "w:themeColor");
713
+ const themeTint = attr(color, "w:themeTint");
714
+ const themeShade = attr(color, "w:themeShade");
715
+ if (themeColor || themeTint || themeShade) {
716
+ const colorObj = {};
717
+ if (c) colorObj.val = c;
718
+ if (themeColor) colorObj.themeColor = themeColor;
719
+ if (themeTint) colorObj.themeTint = themeTint;
720
+ if (themeShade) colorObj.themeShade = themeShade;
721
+ opts.color = colorObj;
722
+ } else if (c) opts.color = c;
723
+ }
724
+ const sz = findChild(el, "w:sz");
725
+ if (sz) {
726
+ const halfPts = attrNum(sz, "w:val");
727
+ if (halfPts !== void 0) opts.size = halfPts / 2;
728
+ }
729
+ const szCs = findChild(el, "w:szCs");
730
+ if (szCs) {
731
+ const halfPts = attrNum(szCs, "w:val");
732
+ if (halfPts !== void 0) opts.sizeComplexScript = halfPts / 2;
733
+ }
734
+ const highlight = findChild(el, "w:highlight");
735
+ if (highlight) {
736
+ const val = attr(highlight, "w:val");
737
+ if (val) opts.highlight = val;
738
+ }
739
+ const highlightCs = findChild(el, "w:highlightCs");
740
+ if (highlightCs) {
741
+ const val = attr(highlightCs, "w:val");
742
+ if (val) opts.highlightComplexScript = val;
743
+ }
744
+ const vertAlign = findChild(el, "w:vertAlign");
745
+ if (vertAlign) {
746
+ const val = attr(vertAlign, "w:val");
747
+ if (val === "subscript") opts.subScript = true;
748
+ else if (val === "superscript") opts.superScript = true;
749
+ }
750
+ const effect = findChild(el, "w:effect");
751
+ if (effect) {
752
+ const val = attr(effect, "w:val");
753
+ if (val) opts.effect = val;
754
+ }
755
+ const emphasisMark = findChild(el, "w:em");
756
+ if (emphasisMark) {
757
+ const val = attr(emphasisMark, "w:val");
758
+ if (val) opts.emphasisMark = { type: val };
759
+ }
760
+ const spacing = findChild(el, "w:spacing");
761
+ if (spacing) {
762
+ const val = attrNum(spacing, "w:val");
763
+ if (val !== void 0) opts.characterSpacing = val;
764
+ }
765
+ const scale = findChild(el, "w:w");
766
+ if (scale) {
767
+ const val = attrNum(scale, "w:val");
768
+ if (val !== void 0) opts.scale = val;
769
+ }
770
+ const kern = findChild(el, "w:kern");
771
+ if (kern) {
772
+ const val = attrNum(kern, "w:val");
773
+ if (val !== void 0) opts.kern = val;
774
+ }
775
+ const position = findChild(el, "w:position");
776
+ if (position) {
777
+ const val = attr(position, "w:val");
778
+ if (val !== void 0) opts.position = val;
779
+ }
780
+ const fitText = findChild(el, "w:fitText");
781
+ if (fitText) {
782
+ const val = attrNum(fitText, "w:val");
783
+ if (val !== void 0) opts.fitText = val;
784
+ }
785
+ const lang = findChild(el, "w:lang");
786
+ if (lang) {
787
+ const langObj = {};
788
+ const val = attr(lang, "w:val");
789
+ if (val) langObj.value = val;
790
+ const eastAsia = attr(lang, "w:eastAsia");
791
+ if (eastAsia) langObj.eastAsia = eastAsia;
792
+ const bidi = attr(lang, "w:bidi");
793
+ if (bidi) langObj.bidirectional = bidi;
794
+ if (Object.keys(langObj).length > 0) opts.language = langObj;
795
+ }
796
+ const bdr = findChild(el, "w:bdr");
797
+ if (bdr) opts.border = parseBorder(bdr);
798
+ const shd = findChild(el, "w:shd");
799
+ if (shd) opts.shading = parseShading(shd);
800
+ const eastAsianLayout = findChild(el, "w:eastAsianLayout");
801
+ if (eastAsianLayout) opts.eastAsianLayout = parseEastAsianLayout(eastAsianLayout);
802
+ const contentPart = findChild(el, "w:contentPart");
803
+ if (contentPart) {
804
+ const rId = attr(contentPart, "r:id");
805
+ if (rId) opts.contentPartRId = rId;
806
+ }
807
+ const rPrChange = findChild(el, "w:rPrChange");
808
+ if (rPrChange) {
809
+ const rev = {};
810
+ const author = attr(rPrChange, "w:author");
811
+ if (author) rev.author = author;
812
+ const date = attr(rPrChange, "w:date");
813
+ if (date) rev.date = date;
814
+ const id = attrNum(rPrChange, "w:id");
815
+ if (id !== void 0) rev.id = id;
816
+ const innerRPr = findChild(rPrChange, "w:rPr");
817
+ if (innerRPr) Object.assign(rev, parseRunProperties(innerRPr));
818
+ if (Object.keys(rev).length > 0) opts.revision = rev;
819
+ }
820
+ return opts;
821
+ }
822
+ /**
823
+ * Parse a w:bdr element into BorderOptions.
824
+ */
825
+ function parseBorder(el) {
826
+ const opts = {};
827
+ const style = attr(el, "w:val");
828
+ if (style) opts.style = style;
829
+ const color = colorAttr(el, "w:color");
830
+ if (color) opts.color = color;
831
+ const size = attrNum(el, "w:sz");
832
+ if (size !== void 0) opts.size = size;
833
+ const space = attrNum(el, "w:space");
834
+ if (space !== void 0) opts.space = space;
835
+ const shadow = attrBool(el, "w:shadow");
836
+ if (shadow !== void 0) opts.shadow = shadow;
837
+ const frame = attrBool(el, "w:frame");
838
+ if (frame !== void 0) opts.frame = frame;
839
+ return opts;
840
+ }
841
+ /**
842
+ * Parse a w:shd element into ShadingAttributesProperties.
843
+ */
844
+ function parseShading(el) {
845
+ const opts = {};
846
+ const fill = colorAttr(el, "w:fill");
847
+ if (fill) opts.fill = fill;
848
+ const color = colorAttr(el, "w:color");
849
+ if (color) opts.color = color;
850
+ const type = attr(el, "w:val");
851
+ if (type) opts.type = type;
852
+ return opts;
853
+ }
854
+ /**
855
+ * Parse a w:eastAsianLayout element into EastAsianLayoutOptions.
856
+ */
857
+ function parseEastAsianLayout(el) {
858
+ const opts = {};
859
+ const id = attrNum(el, "w:id");
860
+ if (id !== void 0) opts.id = id;
861
+ const combine = attrBool(el, "w:combine");
862
+ if (combine !== void 0) opts.combine = combine;
863
+ const combineBrackets = attr(el, "w:combineBrackets");
864
+ if (combineBrackets) opts.combineBrackets = combineBrackets;
865
+ const vert = attrBool(el, "w:vert");
866
+ if (vert !== void 0) opts.vert = vert;
867
+ const vertCompress = attrBool(el, "w:vertCompress");
868
+ if (vertCompress !== void 0) opts.vertCompress = vertCompress;
869
+ return opts;
870
+ }
871
+ /** Matches w:br[@w:type="page"] → PageBreak */
872
+ const PARSED_PAGE_BREAK = Symbol("PageBreak");
873
+ /** Matches w:br (line break) */
874
+ const PARSED_LINE_BREAK = Symbol("LineBreak");
875
+ /** Matches w:tab */
876
+ const PARSED_TAB = Symbol("Tab");
877
+ /** Matches w:cr */
878
+ const PARSED_CR = Symbol("CarriageReturn");
879
+ /** Matches w:noBreakHyphen */
880
+ const PARSED_NO_BREAK_HYPHEN = Symbol("NoBreakHyphen");
881
+ /** Matches w:softHyphen */
882
+ const PARSED_SOFT_HYPHEN = Symbol("SoftHyphen");
883
+ /** Matches w:footnoteRef — auto-generated by Footnote class */
884
+ const PARSED_FOOTNOTE_REF = Symbol("FootnoteRef");
885
+ /** Matches w:br[@w:type="column"] */
886
+ const PARSED_COLUMN_BREAK = Symbol("ColumnBreak");
887
+ /** Matches w:dayShort */
888
+ const PARSED_DAY_SHORT = Symbol("DayShort");
889
+ /** Matches w:monthShort */
890
+ const PARSED_MONTH_SHORT = Symbol("MonthShort");
891
+ /** Matches w:yearShort */
892
+ const PARSED_YEAR_SHORT = Symbol("YearShort");
893
+ /** Matches w:dayLong */
894
+ const PARSED_DAY_LONG = Symbol("DayLong");
895
+ /** Matches w:monthLong */
896
+ const PARSED_MONTH_LONG = Symbol("MonthLong");
897
+ /** Matches w:yearLong */
898
+ const PARSED_YEAR_LONG = Symbol("YearLong");
899
+ /** Matches w:annotationRef */
900
+ const PARSED_ANNOTATION_REF = Symbol("AnnotationRef");
901
+ /** Matches w:separator */
902
+ const PARSED_SEPARATOR = Symbol("Separator");
903
+ /** Matches w:continuationSeparator */
904
+ const PARSED_CONTINUATION_SEPARATOR = Symbol("ContinuationSeparator");
905
+ /** Matches w:pgNum */
906
+ const PARSED_PG_NUM = Symbol("PgNum");
907
+ /** Matches w:lastRenderedPageBreak */
908
+ const PARSED_LAST_RENDERED_PAGE_BREAK = Symbol("LastRenderedPageBreak");
909
+ /**
910
+ * Parse a w:r element into run data.
911
+ * Returns { properties, children } where children are parsed run content items.
912
+ */
913
+ function parseRun(el, _ctx) {
914
+ const rPr = findChild(el, "w:rPr");
915
+ const properties = rPr ? parseRunProperties(rPr) : void 0;
916
+ const children = [];
917
+ for (const child of el.elements ?? []) switch (child.name) {
918
+ case "w:rPr": break;
919
+ case "w:t": {
920
+ const preserveSpace = attrBool(child, "xml:space");
921
+ let text = textOf(child);
922
+ if (preserveSpace && text) {}
923
+ children.push(text);
924
+ break;
925
+ }
926
+ case "w:delText": {
927
+ const text = textOf(child);
928
+ if (text) children.push(text);
929
+ break;
930
+ }
931
+ case "w:br": {
932
+ const brType = attr(child, "w:type");
933
+ if (brType === "page") children.push(PARSED_PAGE_BREAK);
934
+ else if (brType === "column") children.push(PARSED_COLUMN_BREAK);
935
+ else children.push(PARSED_LINE_BREAK);
936
+ break;
937
+ }
938
+ case "w:tab":
939
+ children.push(PARSED_TAB);
940
+ break;
941
+ case "w:cr":
942
+ children.push(PARSED_CR);
943
+ break;
944
+ case "w:noBreakHyphen":
945
+ children.push(PARSED_NO_BREAK_HYPHEN);
946
+ break;
947
+ case "w:softHyphen":
948
+ children.push(PARSED_SOFT_HYPHEN);
949
+ break;
950
+ case "w:commentReference": {
951
+ const id = attrNum(child, "w:id");
952
+ if (id !== void 0) children.push({ commentReference: id });
953
+ break;
954
+ }
955
+ case "w:drawing":
956
+ case "w:pict": break;
957
+ case "w:sym": {
958
+ const charVal = attr(child, "w:char");
959
+ const fontVal = attr(child, "w:font");
960
+ if (charVal) children.push({ symbolRun: {
961
+ char: charVal,
962
+ symbolfont: fontVal ?? "Wingdings"
963
+ } });
964
+ break;
965
+ }
966
+ case "w:footnoteReference": {
967
+ const id = attrNum(child, "w:id");
968
+ if (id !== void 0) children.push({ footnoteReference: id });
969
+ break;
970
+ }
971
+ case "w:endnoteReference": {
972
+ const id = attrNum(child, "w:id");
973
+ if (id !== void 0) children.push({ endnoteReference: id });
974
+ break;
975
+ }
976
+ case "w:footnoteRef":
977
+ case "w:endnoteRef":
978
+ children.push(PARSED_FOOTNOTE_REF);
979
+ break;
980
+ case "w:dayShort":
981
+ children.push(PARSED_DAY_SHORT);
982
+ break;
983
+ case "w:monthShort":
984
+ children.push(PARSED_MONTH_SHORT);
985
+ break;
986
+ case "w:yearShort":
987
+ children.push(PARSED_YEAR_SHORT);
988
+ break;
989
+ case "w:dayLong":
990
+ children.push(PARSED_DAY_LONG);
991
+ break;
992
+ case "w:monthLong":
993
+ children.push(PARSED_MONTH_LONG);
994
+ break;
995
+ case "w:yearLong":
996
+ children.push(PARSED_YEAR_LONG);
997
+ break;
998
+ case "w:annotationRef":
999
+ children.push(PARSED_ANNOTATION_REF);
1000
+ break;
1001
+ case "w:separator":
1002
+ children.push(PARSED_SEPARATOR);
1003
+ break;
1004
+ case "w:continuationSeparator":
1005
+ children.push(PARSED_CONTINUATION_SEPARATOR);
1006
+ break;
1007
+ case "w:pgNum":
1008
+ children.push(PARSED_PG_NUM);
1009
+ break;
1010
+ case "w:lastRenderedPageBreak":
1011
+ children.push(PARSED_LAST_RENDERED_PAGE_BREAK);
1012
+ break;
1013
+ default: break;
1014
+ }
1015
+ return {
1016
+ properties,
1017
+ children
1018
+ };
1019
+ }
1020
+ /**
1021
+ * Convert parsed run data into an RunOptions suitable for the Document constructor.
1022
+ * Simplifies the parsed children into text + break format.
1023
+ * If the run contains only a commentReference, returns { commentReference: id } instead.
1024
+ * If the run only contains footnoteRef/endnoteRef (auto-generated), returns empty options.
1025
+ *
1026
+ * When empty run elements (tab, noBreakHyphen, date fields, etc.) are present,
1027
+ * uses children[] format to preserve them for round-trip fidelity.
1028
+ */
1029
+ /** Mapping from parse symbols to RunOptions child objects for empty elements. */
1030
+ const SYMBOL_TO_CHILD = new Map([
1031
+ [PARSED_TAB, { tab: true }],
1032
+ [PARSED_CR, { carriageReturn: true }],
1033
+ [PARSED_NO_BREAK_HYPHEN, { noBreakHyphen: true }],
1034
+ [PARSED_SOFT_HYPHEN, { softHyphen: true }],
1035
+ [PARSED_DAY_SHORT, { dayShort: true }],
1036
+ [PARSED_MONTH_SHORT, { monthShort: true }],
1037
+ [PARSED_YEAR_SHORT, { yearShort: true }],
1038
+ [PARSED_DAY_LONG, { dayLong: true }],
1039
+ [PARSED_MONTH_LONG, { monthLong: true }],
1040
+ [PARSED_YEAR_LONG, { yearLong: true }],
1041
+ [PARSED_ANNOTATION_REF, { annotationRef: true }],
1042
+ [PARSED_SEPARATOR, { separator: true }],
1043
+ [PARSED_CONTINUATION_SEPARATOR, { continuationSeparator: true }],
1044
+ [PARSED_PG_NUM, { pgNum: true }],
1045
+ [PARSED_LAST_RENDERED_PAGE_BREAK, { lastRenderedPageBreak: true }]
1046
+ ]);
1047
+ function parsedRunToOptions(parsed) {
1048
+ const contentChildren = parsed.children.filter((c) => c !== PARSED_FOOTNOTE_REF);
1049
+ if (contentChildren.length === 0 && parsed.children.some((c) => c === PARSED_FOOTNOTE_REF)) return null;
1050
+ const opts = { ...parsed.properties };
1051
+ const isRefChild = (c) => typeof c === "object" && c !== null && ("commentReference" in c || "footnoteReference" in c || "endnoteReference" in c);
1052
+ const refChildren = contentChildren.filter(isRefChild);
1053
+ const nonRefChildren = contentChildren.filter((c) => !isRefChild(c));
1054
+ if (refChildren.length > 0 && nonRefChildren.length === 0) return refChildren[0];
1055
+ const symbolIdx = nonRefChildren.findIndex((c) => typeof c === "object" && c !== null && "symbolRun" in c);
1056
+ if (symbolIdx >= 0 && nonRefChildren.length === 1 && !parsed.properties) return nonRefChildren[symbolIdx];
1057
+ const textParts = [];
1058
+ let breakCount = 0;
1059
+ let hasPageBreak = false;
1060
+ let hasColumnBreak = false;
1061
+ const extraChildren = [];
1062
+ for (const child of nonRefChildren) if (typeof child === "string") textParts.push(child);
1063
+ else if (child === PARSED_LINE_BREAK) breakCount++;
1064
+ else if (child === PARSED_PAGE_BREAK) hasPageBreak = true;
1065
+ else if (child === PARSED_COLUMN_BREAK) hasColumnBreak = true;
1066
+ else {
1067
+ const mapped = SYMBOL_TO_CHILD.get(child);
1068
+ if (mapped) extraChildren.push(mapped);
1069
+ }
1070
+ if (extraChildren.length > 0) {
1071
+ const children = [];
1072
+ for (const child of nonRefChildren) if (typeof child === "string") children.push(child);
1073
+ else if (child === PARSED_LINE_BREAK) children.push({ break: 1 });
1074
+ else if (child === PARSED_PAGE_BREAK) children.push({ pageBreak: true });
1075
+ else if (child === PARSED_COLUMN_BREAK) children.push({ columnBreak: true });
1076
+ else {
1077
+ const mapped = SYMBOL_TO_CHILD.get(child);
1078
+ if (mapped) children.push(mapped);
1079
+ }
1080
+ opts.children = children;
1081
+ } else {
1082
+ if (textParts.length > 0) opts.text = textParts.join("");
1083
+ if (breakCount > 0) opts.break = breakCount;
1084
+ if (hasPageBreak) opts.pageBreak = true;
1085
+ if (hasColumnBreak) opts.columnBreak = true;
1086
+ }
1087
+ if (Object.keys(opts).length === 0 && textParts.length === 0 && breakCount === 0 && !hasPageBreak && !hasColumnBreak && extraChildren.length === 0) return null;
1088
+ return opts;
1089
+ }
1090
+ //#endregion
1091
+ //#region src/parts/paragraph/stringify.ts
1092
+ /**
1093
+ * Direct XML string builders for paragraph and run properties.
1094
+ *
1095
+ * Replaces `buildParagraphProperties() + xml()` and `buildRunProperties() + xml()`
1096
+ * with direct string concatenation — zero intermediate IXmlableObject allocation,
1097
+ * zero recursive xml() traversal. Follows PPTX/XLSX pattern.
1098
+ *
1099
+ * @module
1100
+ */
1101
+ /** On/off: `<w:name/>` for true, `<w:name w:val="0"/>` for false */
1102
+ function onOff(name, val) {
1103
+ return val ? `<${name}/>` : `<${name} w:val="0"/>`;
1104
+ }
1105
+ /** Build attrs string from key-value pairs, skipping undefined */
1106
+ function attrParts(attrs) {
1107
+ const parts = [];
1108
+ for (const [key, val] of Object.entries(attrs)) if (val !== void 0) parts.push(`${key}="${val}"`);
1109
+ return parts.join(" ");
1110
+ }
1111
+ function borderStr(name, opts) {
1112
+ return `<${name} ${attrParts({
1113
+ "w:val": opts.style,
1114
+ "w:color": opts.color !== void 0 ? hexColorValue(opts.color) : void 0,
1115
+ "w:sz": opts.size !== void 0 ? eighthPointMeasureValue(opts.size) : void 0,
1116
+ "w:space": opts.space !== void 0 ? pointMeasureValue(opts.space) : void 0,
1117
+ "w:themeColor": opts.themeColor,
1118
+ "w:themeTint": opts.themeTint !== void 0 ? uCharHexNumber(opts.themeTint) : void 0,
1119
+ "w:themeShade": opts.themeShade !== void 0 ? uCharHexNumber(opts.themeShade) : void 0,
1120
+ "w:shadow": opts.shadow !== void 0 ? opts.shadow ? 1 : 0 : void 0,
1121
+ "w:frame": opts.frame !== void 0 ? opts.frame ? 1 : 0 : void 0
1122
+ })}/>`;
1123
+ }
1124
+ function shadingStr(opts) {
1125
+ return `<w:shd ${attrParts({
1126
+ "w:val": opts.type ?? "clear",
1127
+ "w:color": opts.color !== void 0 ? hexColorValue(opts.color) : void 0,
1128
+ "w:fill": opts.fill !== void 0 ? hexColorValue(opts.fill) : void 0,
1129
+ "w:themeColor": opts.themeColor,
1130
+ "w:themeTint": opts.themeTint !== void 0 ? uCharHexNumber(opts.themeTint) : void 0,
1131
+ "w:themeShade": opts.themeShade !== void 0 ? uCharHexNumber(opts.themeShade) : void 0,
1132
+ "w:themeFill": opts.themeFill,
1133
+ "w:themeFillTint": opts.themeFillTint !== void 0 ? uCharHexNumber(opts.themeFillTint) : void 0,
1134
+ "w:themeFillShade": opts.themeFillShade !== void 0 ? uCharHexNumber(opts.themeFillShade) : void 0
1135
+ })}/>`;
1136
+ }
1137
+ function spacingStr(opts) {
1138
+ return `<w:spacing ${attrParts({
1139
+ "w:after": opts.after,
1140
+ "w:afterAutospacing": opts.afterAutoSpacing !== void 0 ? opts.afterAutoSpacing ? 1 : 0 : void 0,
1141
+ "w:afterLines": opts.afterLines !== void 0 ? decimalNumber(opts.afterLines) : void 0,
1142
+ "w:before": opts.before,
1143
+ "w:beforeAutospacing": opts.beforeAutoSpacing !== void 0 ? opts.beforeAutoSpacing ? 1 : 0 : void 0,
1144
+ "w:beforeLines": opts.beforeLines !== void 0 ? decimalNumber(opts.beforeLines) : void 0,
1145
+ "w:line": opts.line,
1146
+ "w:lineRule": opts.lineRule
1147
+ })}/>`;
1148
+ }
1149
+ function indentStr(opts) {
1150
+ return `<w:ind ${attrParts({
1151
+ "w:start": opts.start !== void 0 ? signedTwipsMeasureValue(opts.start) : void 0,
1152
+ "w:startChars": opts.startChars !== void 0 ? decimalNumber(opts.startChars) : void 0,
1153
+ "w:end": opts.end !== void 0 ? signedTwipsMeasureValue(opts.end) : void 0,
1154
+ "w:endChars": opts.endChars !== void 0 ? decimalNumber(opts.endChars) : void 0,
1155
+ "w:left": opts.left !== void 0 ? signedTwipsMeasureValue(opts.left) : void 0,
1156
+ "w:leftChars": opts.leftChars !== void 0 ? decimalNumber(opts.leftChars) : void 0,
1157
+ "w:right": opts.right !== void 0 ? signedTwipsMeasureValue(opts.right) : void 0,
1158
+ "w:rightChars": opts.rightChars !== void 0 ? decimalNumber(opts.rightChars) : void 0,
1159
+ "w:hanging": opts.hanging !== void 0 ? twipsMeasureValue(opts.hanging) : void 0,
1160
+ "w:hangingChars": opts.hangingChars !== void 0 ? decimalNumber(opts.hangingChars) : void 0,
1161
+ "w:firstLine": opts.firstLine !== void 0 ? twipsMeasureValue(opts.firstLine) : void 0,
1162
+ "w:firstLineChars": opts.firstLineChars !== void 0 ? decimalNumber(opts.firstLineChars) : void 0
1163
+ })}/>`;
1164
+ }
1165
+ function tabStopsStr(defs) {
1166
+ return `<w:tabs>${defs.map(({ type, position, leader }) => {
1167
+ return `<w:tab ${attrParts({
1168
+ "w:val": type,
1169
+ "w:pos": position,
1170
+ "w:leader": leader
1171
+ })}/>`;
1172
+ }).join("")}</w:tabs>`;
1173
+ }
1174
+ function cnfStyleStr(opts) {
1175
+ return `<w:cnfStyle ${attrParts({
1176
+ "w:firstRow": opts.firstRow ? "1" : "0",
1177
+ "w:lastRow": opts.lastRow ? "1" : "0",
1178
+ "w:firstColumn": opts.firstColumn ? "1" : "0",
1179
+ "w:lastColumn": opts.lastColumn ? "1" : "0",
1180
+ "w:oddVBand": opts.oddVBand ? "1" : "0",
1181
+ "w:evenVBand": opts.evenVBand ? "1" : "0",
1182
+ "w:oddHBand": opts.oddHBand ? "1" : "0",
1183
+ "w:evenHBand": opts.evenHBand ? "1" : "0",
1184
+ "w:firstRowFirstColumn": opts.firstRowFirstColumn ? "1" : "0",
1185
+ "w:firstRowLastColumn": opts.firstRowLastColumn ? "1" : "0",
1186
+ "w:lastRowFirstColumn": opts.lastRowFirstColumn ? "1" : "0",
1187
+ "w:lastRowLastColumn": opts.lastRowLastColumn ? "1" : "0"
1188
+ })}/>`;
1189
+ }
1190
+ function framePrStr(opts) {
1191
+ const alignment = opts.alignment;
1192
+ const position = opts.position;
1193
+ return `<w:framePr ${attrParts({
1194
+ "w:xAlign": alignment?.x,
1195
+ "w:yAlign": alignment?.y,
1196
+ "w:hAnchor": opts.anchor?.horizontal,
1197
+ "w:anchorLock": opts.anchorLock,
1198
+ "w:vAnchor": opts.anchor?.vertical,
1199
+ "w:dropCap": opts.dropCap,
1200
+ "w:h": opts.height,
1201
+ "w:lines": opts.lines,
1202
+ "w:hRule": opts.rule,
1203
+ "w:hSpace": opts.space?.horizontal,
1204
+ "w:vSpace": opts.space?.vertical,
1205
+ "w:w": opts.width,
1206
+ "w:wrap": opts.wrap,
1207
+ "w:x": position?.x,
1208
+ "w:y": position?.y
1209
+ })}/>`;
1210
+ }
1211
+ function numPrStr(numberId, indentLevel, numberingChange) {
1212
+ const idVal = typeof numberId === "string" ? `{${numberId}}` : numberId;
1213
+ const parts = [`<w:ilvl w:val="${Math.min(indentLevel, 9)}"/>`, `<w:numId w:val="${idVal}"/>`];
1214
+ if (numberingChange) {
1215
+ const a = attrParts({
1216
+ "w:original": numberingChange.original,
1217
+ "w:id": numberingChange.id,
1218
+ "w:author": numberingChange.author,
1219
+ "w:date": numberingChange.date
1220
+ });
1221
+ parts.push(`<w:numberingChange ${a}/>`);
1222
+ }
1223
+ return `<w:numPr>${parts.join("")}</w:numPr>`;
1224
+ }
1225
+ function colorStr(colorOrOptions) {
1226
+ if (typeof colorOrOptions === "string") return `<w:color w:val="${hexColorValue(colorOrOptions)}"/>`;
1227
+ const opts = colorOrOptions;
1228
+ return `<w:color ${attrParts({
1229
+ "w:val": opts.val !== void 0 ? hexColorValue(opts.val) : void 0,
1230
+ "w:themeColor": opts.themeColor,
1231
+ "w:themeTint": opts.themeTint !== void 0 ? uCharHexNumber(opts.themeTint) : void 0,
1232
+ "w:themeShade": opts.themeShade !== void 0 ? uCharHexNumber(opts.themeShade) : void 0
1233
+ })}/>`;
1234
+ }
1235
+ function runFontsStr(nameOrAttrs, hint) {
1236
+ if (typeof nameOrAttrs === "string") return `<w:rFonts ${attrParts({
1237
+ "w:ascii": nameOrAttrs,
1238
+ "w:cs": nameOrAttrs,
1239
+ "w:eastAsia": nameOrAttrs,
1240
+ "w:hAnsi": nameOrAttrs,
1241
+ "w:hint": hint
1242
+ })}/>`;
1243
+ const attrs = nameOrAttrs;
1244
+ return `<w:rFonts ${attrParts({
1245
+ "w:ascii": attrs.ascii,
1246
+ "w:asciiTheme": attrs.asciiTheme,
1247
+ "w:cs": attrs.cs,
1248
+ "w:cstheme": attrs.cstheme,
1249
+ "w:eastAsia": attrs.eastAsia,
1250
+ "w:eastAsiaTheme": attrs.eastAsiaTheme,
1251
+ "w:hAnsi": attrs.hAnsi,
1252
+ "w:hAnsiTheme": attrs.hAnsiTheme,
1253
+ "w:hint": attrs.hint
1254
+ })}/>`;
1255
+ }
1256
+ function underlineStr(type, color) {
1257
+ return `<w:u ${attrParts({
1258
+ "w:val": type ?? "single",
1259
+ "w:color": color !== void 0 ? hexColorValue(color) : void 0
1260
+ })}/>`;
1261
+ }
1262
+ function eastAsianLayoutStr(opts) {
1263
+ return `<w:eastAsianLayout ${attrParts({
1264
+ "w:id": opts.id !== void 0 ? decimalNumber(opts.id) : void 0,
1265
+ "w:combine": opts.combine !== void 0 ? opts.combine ? 1 : 0 : void 0,
1266
+ "w:combineBrackets": opts.combineBrackets,
1267
+ "w:vert": opts.vert !== void 0 ? opts.vert ? 1 : 0 : void 0,
1268
+ "w:vertCompress": opts.vertCompress !== void 0 ? opts.vertCompress ? 1 : 0 : void 0
1269
+ })}/>`;
1270
+ }
1271
+ function languageStr(opts) {
1272
+ return `<w:lang ${attrParts({
1273
+ "w:val": opts.value,
1274
+ "w:eastAsia": opts.eastAsia,
1275
+ "w:bidi": opts.bidirectional
1276
+ })}/>`;
1277
+ }
1278
+ /**
1279
+ * Build `<w:pPr>` XML string directly from options — zero IXmlableObject allocation.
1280
+ *
1281
+ * Replaces `buildParagraphProperties() + xml()` with a single-pass string builder.
1282
+ */
1283
+ function stringifyParagraphProperties(options) {
1284
+ const numberingReferences = [];
1285
+ if (!options) return {
1286
+ xml: void 0,
1287
+ numberingReferences
1288
+ };
1289
+ const parts = [];
1290
+ if (options.heading) parts.push(`<w:pStyle w:val="${escapeXml(options.heading)}"/>`);
1291
+ if (options.bullet) parts.push("<w:pStyle w:val=\"ListParagraph\"/>");
1292
+ if (options.numbering) {
1293
+ if (!options.style && !options.heading) {
1294
+ if (!options.numbering.custom) parts.push("<w:pStyle w:val=\"ListParagraph\"/>");
1295
+ }
1296
+ }
1297
+ if (options.style) parts.push(`<w:pStyle w:val="${escapeXml(options.style)}"/>`);
1298
+ if (options.keepNext !== void 0) parts.push(onOff("w:keepNext", options.keepNext));
1299
+ if (options.keepLines !== void 0) parts.push(onOff("w:keepLines", options.keepLines));
1300
+ if (options.pageBreakBefore) parts.push("<w:pageBreakBefore/>");
1301
+ if (options.frame) parts.push(framePrStr(options.frame));
1302
+ if (options.widowControl !== void 0) parts.push(onOff("w:widowControl", options.widowControl));
1303
+ if (options.bullet) parts.push(`<w:numPr><w:ilvl w:val="${Math.min(options.bullet.level, 9)}"/><w:numId w:val="1"/></w:numPr>`);
1304
+ if (options.numbering) {
1305
+ numberingReferences.push({
1306
+ instance: options.numbering.instance ?? 0,
1307
+ reference: options.numbering.reference
1308
+ });
1309
+ const numId = `${options.numbering.reference}-${options.numbering.instance ?? 0}`;
1310
+ parts.push(numPrStr(numId, options.numbering.level, options.numbering.numberingChange));
1311
+ } else if (options.numbering === false) parts.push(numPrStr(0, 0));
1312
+ if (options.border) {
1313
+ const bParts = [];
1314
+ if (options.border.top) bParts.push(borderStr("w:top", options.border.top));
1315
+ if (options.border.left) bParts.push(borderStr("w:left", options.border.left));
1316
+ if (options.border.bottom) bParts.push(borderStr("w:bottom", options.border.bottom));
1317
+ if (options.border.right) bParts.push(borderStr("w:right", options.border.right));
1318
+ if (options.border.between) bParts.push(borderStr("w:between", options.border.between));
1319
+ if (options.border.bar) bParts.push(borderStr("w:bar", options.border.bar));
1320
+ if (bParts.length) parts.push(`<w:pBdr>${bParts.join("")}</w:pBdr>`);
1321
+ }
1322
+ if (options.thematicBreak) parts.push(`<w:pBdr>${borderStr("w:bottom", {
1323
+ color: "auto",
1324
+ size: 6,
1325
+ space: 1,
1326
+ style: BorderStyle.SINGLE
1327
+ })}</w:pBdr>`);
1328
+ if (options.shading) parts.push(shadingStr(options.shading));
1329
+ if (options.wordWrap) parts.push("<w:wordWrap w:val=\"0\"/>");
1330
+ if (options.overflowPunctuation) parts.push(onOff("w:overflowPunct", options.overflowPunctuation));
1331
+ const tabDefs = [
1332
+ ...options.rightTabStop !== void 0 ? [{
1333
+ position: options.rightTabStop,
1334
+ type: "right"
1335
+ }] : [],
1336
+ ...options.tabStops ? options.tabStops : [],
1337
+ ...options.leftTabStop !== void 0 ? [{
1338
+ position: options.leftTabStop,
1339
+ type: "left"
1340
+ }] : []
1341
+ ];
1342
+ if (tabDefs.length > 0) parts.push(tabStopsStr(tabDefs));
1343
+ if (options.bidirectional !== void 0) parts.push(onOff("w:bidi", options.bidirectional));
1344
+ if (options.spacing) parts.push(spacingStr(options.spacing));
1345
+ if (options.indent) parts.push(indentStr(options.indent));
1346
+ if (options.contextualSpacing !== void 0) parts.push(onOff("w:contextualSpacing", options.contextualSpacing));
1347
+ if (options.alignment) parts.push(`<w:jc w:val="${options.alignment}"/>`);
1348
+ if (options.outlineLevel !== void 0) parts.push(`<w:outlineLvl w:val="${options.outlineLevel}"/>`);
1349
+ if (options.divId !== void 0) parts.push(`<w:divId w:val="${options.divId}"/>`);
1350
+ if (options.cnfStyle) parts.push(cnfStyleStr(options.cnfStyle));
1351
+ if (options.suppressLineNumbers !== void 0) parts.push(onOff("w:suppressLineNumbers", options.suppressLineNumbers));
1352
+ if (options.autoSpaceEastAsianText !== void 0) parts.push(onOff("w:autoSpaceDN", options.autoSpaceEastAsianText));
1353
+ if (options.suppressAutoHyphens !== void 0) parts.push(onOff("w:suppressAutoHyphens", options.suppressAutoHyphens));
1354
+ if (options.adjustRightInd !== void 0) parts.push(onOff("w:adjustRightInd", options.adjustRightInd));
1355
+ if (options.snapToGrid !== void 0) parts.push(onOff("w:snapToGrid", options.snapToGrid));
1356
+ if (options.mirrorIndents !== void 0) parts.push(onOff("w:mirrorIndents", options.mirrorIndents));
1357
+ if (options.kinsoku !== void 0) parts.push(onOff("w:kinsoku", options.kinsoku));
1358
+ if (options.topLinePunct !== void 0) parts.push(onOff("w:topLinePunct", options.topLinePunct));
1359
+ if (options.autoSpaceDE !== void 0) parts.push(onOff("w:autoSpaceDE", options.autoSpaceDE));
1360
+ if (options.textAlignment !== void 0) parts.push(`<w:textAlignment w:val="${options.textAlignment}"/>`);
1361
+ if (options.textboxTightWrap !== void 0) parts.push(`<w:textboxTightWrap w:val="${options.textboxTightWrap}"/>`);
1362
+ if (options.textDirection !== void 0) parts.push(`<w:textDirection w:val="${options.textDirection}"/>`);
1363
+ if (options.suppressOverlap !== void 0) parts.push(onOff("w:suppressOverlap", options.suppressOverlap));
1364
+ if (options.run) {
1365
+ const inner = stringifyRunPropertiesInner(options.run);
1366
+ if (inner !== void 0) {
1367
+ const extra = [];
1368
+ const runOpts = options.run;
1369
+ if (runOpts.insertion) {
1370
+ const { id, author, date } = runOpts.insertion;
1371
+ extra.push(`<w:ins w:id="${id}" w:author="${escapeXml(author)}" w:date="${date}"/>`);
1372
+ }
1373
+ if (runOpts.deletion) {
1374
+ const { id, author, date } = runOpts.deletion;
1375
+ extra.push(`<w:del w:id="${id}" w:author="${escapeXml(author)}" w:date="${date}"/>`);
1376
+ }
1377
+ const body = inner + extra.join("");
1378
+ parts.push(`<w:rPr>${body}</w:rPr>`);
1379
+ }
1380
+ }
1381
+ if (options.revision) {
1382
+ const rev = options.revision;
1383
+ const { author: _a, date: _d, id: _i, ...originalProps } = rev;
1384
+ const inner = stringifyParagraphProperties({
1385
+ ...originalProps,
1386
+ includeIfEmpty: true
1387
+ });
1388
+ parts.push(`<w:pPrChange w:author="${escapeXml(rev.author)}" w:date="${rev.date}" w:id="${rev.id}">${inner.xml ?? "<w:pPr/>"}</w:pPrChange>`);
1389
+ }
1390
+ const body = parts.join("");
1391
+ return {
1392
+ xml: options.includeIfEmpty || body.length > 0 ? `<w:pPr>${body}</w:pPr>` : void 0,
1393
+ numberingReferences
1394
+ };
1395
+ }
1396
+ /**
1397
+ * Build the inner content of `<w:rPr>` as a string.
1398
+ * Returns undefined if no properties are set.
1399
+ */
1400
+ function stringifyRunPropertiesInner(opts) {
1401
+ if (!opts) return void 0;
1402
+ const parts = [];
1403
+ if (opts.style) parts.push(`<w:rStyle w:val="${escapeXml(opts.style)}"/>`);
1404
+ if (opts.font) if (typeof opts.font === "string") parts.push(runFontsStr(opts.font));
1405
+ else if ("name" in opts.font) parts.push(runFontsStr(opts.font.name, opts.font.hint));
1406
+ else parts.push(runFontsStr(opts.font));
1407
+ if (opts.bold !== void 0) parts.push(onOff("w:b", opts.bold));
1408
+ if ((opts.boldComplexScript === void 0 && opts.bold !== void 0 || opts.boldComplexScript) !== void 0) parts.push(onOff("w:bCs", opts.boldComplexScript ?? opts.bold));
1409
+ if (opts.italic !== void 0) parts.push(onOff("w:i", opts.italic));
1410
+ if ((opts.italicComplexScript === void 0 && opts.italic !== void 0 || opts.italicComplexScript) !== void 0) parts.push(onOff("w:iCs", opts.italicComplexScript ?? opts.italic));
1411
+ if (opts.smallCaps !== void 0) parts.push(onOff("w:smallCaps", opts.smallCaps));
1412
+ else if (opts.allCaps !== void 0) parts.push(onOff("w:caps", opts.allCaps));
1413
+ if (opts.strike !== void 0) parts.push(onOff("w:strike", opts.strike));
1414
+ if (opts.doubleStrike !== void 0) parts.push(onOff("w:dstrike", opts.doubleStrike));
1415
+ if (opts.emboss !== void 0) parts.push(onOff("w:emboss", opts.emboss));
1416
+ if (opts.imprint !== void 0) parts.push(onOff("w:imprint", opts.imprint));
1417
+ if (opts.outline !== void 0) parts.push(onOff("w:outline", opts.outline));
1418
+ if (opts.shadow !== void 0) parts.push(onOff("w:shadow", opts.shadow));
1419
+ if (opts.webHidden !== void 0) parts.push(onOff("w:webHidden", opts.webHidden));
1420
+ if (opts.noProof !== void 0) parts.push(onOff("w:noProof", opts.noProof));
1421
+ if (opts.snapToGrid !== void 0) parts.push(onOff("w:snapToGrid", opts.snapToGrid));
1422
+ if (opts.vanish) parts.push(onOff("w:vanish", opts.vanish));
1423
+ if (opts.color) parts.push(colorStr(opts.color));
1424
+ if (opts.characterSpacing) parts.push(`<w:spacing w:val="${signedTwipsMeasureValue(opts.characterSpacing)}"/>`);
1425
+ if (opts.scale !== void 0) parts.push(`<w:w w:val="${opts.scale}"/>`);
1426
+ if (opts.kern) parts.push(`<w:kern w:val="${hpsMeasureValue(opts.kern)}"/>`);
1427
+ if (opts.position) parts.push(`<w:position w:val="${opts.position}"/>`);
1428
+ if (opts.size !== void 0) parts.push(`<w:sz w:val="${hpsMeasureValue(opts.size * 2)}"/>`);
1429
+ const szCs = opts.sizeComplexScript === void 0 || opts.sizeComplexScript === true ? opts.size : opts.sizeComplexScript;
1430
+ if (szCs) parts.push(`<w:szCs w:val="${hpsMeasureValue(szCs * 2)}"/>`);
1431
+ if (opts.highlight) parts.push(`<w:highlight w:val="${opts.highlight}"/>`);
1432
+ if (opts.highlightComplexScript === true) {
1433
+ if (opts.highlight) parts.push(`<w:highlightCs w:val="${opts.highlight}"/>`);
1434
+ } else if (opts.highlightComplexScript !== void 0 && opts.highlightComplexScript !== false) parts.push(`<w:highlightCs w:val="${opts.highlightComplexScript}"/>`);
1435
+ if (opts.underline) parts.push(underlineStr(opts.underline.type, opts.underline.color));
1436
+ if (opts.effect) parts.push(`<w:effect w:val="${opts.effect}"/>`);
1437
+ if (opts.border) parts.push(borderStr("w:bdr", opts.border));
1438
+ if (opts.shading) parts.push(shadingStr(opts.shading));
1439
+ if (opts.subScript) parts.push("<w:vertAlign w:val=\"subscript\"/>");
1440
+ if (opts.superScript) parts.push("<w:vertAlign w:val=\"superscript\"/>");
1441
+ if (opts.rightToLeft !== void 0) parts.push(onOff("w:rtl", opts.rightToLeft));
1442
+ if (opts.emphasisMark) parts.push(`<w:em w:val="${opts.emphasisMark.type ?? "dot"}"/>`);
1443
+ if (opts.language) parts.push(languageStr(opts.language));
1444
+ if (opts.specVanish) parts.push("<w:specVanish/>");
1445
+ if (opts.math) parts.push(onOff("w:oMath", opts.math));
1446
+ if (opts.fitText !== void 0) parts.push(`<w:fitText w:val="${opts.fitText}"/>`);
1447
+ if (opts.complexScript !== void 0) parts.push(onOff("w:cs", opts.complexScript));
1448
+ if (opts.eastAsianLayout) parts.push(eastAsianLayoutStr(opts.eastAsianLayout));
1449
+ if (opts.contentPartRId) parts.push(`<w:contentPart r:id="${opts.contentPartRId}"/>`);
1450
+ if (opts.revision) {
1451
+ const rev = opts.revision;
1452
+ const { author: _a, date: _d, id: _i, ...originalProps } = rev;
1453
+ const inner = stringifyRunPropertiesInner(originalProps);
1454
+ parts.push(`<w:rPrChange w:author="${escapeXml(rev.author)}" w:date="${rev.date}" w:id="${rev.id}"><w:rPr>${inner ?? ""}</w:rPr></w:rPrChange>`);
1455
+ }
1456
+ return parts.length > 0 ? parts.join("") : void 0;
1457
+ }
1458
+ /**
1459
+ * Build `<w:rPr>` XML string directly from options — zero IXmlableObject allocation.
1460
+ *
1461
+ * Replaces `buildRunProperties() + xml()` with a single-pass string builder.
1462
+ */
1463
+ function stringifyRunProperties(opts) {
1464
+ const inner = stringifyRunPropertiesInner(opts);
1465
+ return inner ? `<w:rPr>${inner}</w:rPr>` : void 0;
1466
+ }
1467
+ //#endregion
1468
+ //#region src/parts/bodychildren.ts
1469
+ /**
1470
+ * Body-level child descriptors for DOCX.
1471
+ *
1472
+ * Provides descriptor-based stringification for section children.
1473
+ * All types use pure string builders — zero class instantiation, zero toXml().
1474
+ *
1475
+ * @module
1476
+ */
1477
+ function escapeAttr(s) {
1478
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1479
+ }
1480
+ const ALTCHUNK_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk";
1481
+ function wrapHtmlDocument(fragment) {
1482
+ if (/<(!DOCTYPE|html|HTML)/i.test(fragment)) return fragment;
1483
+ return `<!DOCTYPE html>\n<html><head><meta charset="utf-8"></head>\n<body>${fragment}</body></html>`;
1484
+ }
1485
+ const altChunkDesc = {
1486
+ kind: "custom",
1487
+ stringify(opts, ctx) {
1488
+ const relId = uniqueId();
1489
+ const extension = opts.extension;
1490
+ const partPath = `afchunks/afchunk${relId}.${extension}`;
1491
+ const rawData = typeof opts.data === "string" ? new TextEncoder().encode(opts.data) : opts.data;
1492
+ const data = opts.contentType === "text/html" && typeof opts.data === "string" ? new TextEncoder().encode(wrapHtmlDocument(opts.data)) : rawData;
1493
+ ctx.fileData.document.relationships.addRelationship(relId, ALTCHUNK_REL_TYPE, partPath);
1494
+ ctx.fileData.altChunks.addAltChunk(relId, {
1495
+ key: relId,
1496
+ data,
1497
+ path: partPath,
1498
+ extension,
1499
+ contentType: opts.contentType
1500
+ });
1501
+ const rId = `rId${relId}`;
1502
+ if (opts.matchSrc) return `<w:altChunk r:id="${rId}"><w:altChunkPr><w:matchSrc/></w:altChunkPr></w:altChunk>`;
1503
+ return `<w:altChunk r:id="${rId}"/>`;
1504
+ },
1505
+ parse(el, ctx) {
1506
+ const rId = attr(el, "r:id");
1507
+ const opts = {};
1508
+ const altChunkPr = findChild(el, "w:altChunkPr");
1509
+ if (altChunkPr && findChild(altChunkPr, "w:matchSrc")) opts.matchSrc = true;
1510
+ const dctx = ctx;
1511
+ if (rId) {
1512
+ const path = dctx.resolveRelationship(rId);
1513
+ if (path) {
1514
+ const data = dctx.getRaw(path);
1515
+ if (data) {
1516
+ opts.data = data;
1517
+ switch (path.split(".").pop() ?? "txt") {
1518
+ case "html":
1519
+ opts.contentType = "text/html";
1520
+ opts.extension = "html";
1521
+ break;
1522
+ case "rtf":
1523
+ opts.contentType = "application/rtf";
1524
+ opts.extension = "rtf";
1525
+ break;
1526
+ default:
1527
+ opts.contentType = "text/plain";
1528
+ opts.extension = "txt";
1529
+ break;
1530
+ }
1531
+ }
1532
+ }
1533
+ }
1534
+ return opts;
1535
+ }
1536
+ };
1537
+ const SUBDOC_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/subDocument";
1538
+ const subDocDesc = {
1539
+ kind: "custom",
1540
+ stringify(opts, ctx) {
1541
+ const relId = uniqueId();
1542
+ const partPath = `subdocs/subdoc${relId}.docx`;
1543
+ const data = typeof opts.data === "string" ? new TextEncoder().encode(opts.data) : opts.data;
1544
+ ctx.fileData.document.relationships.addRelationship(relId, SUBDOC_REL_TYPE, partPath);
1545
+ ctx.fileData.subDocs.addSubDoc(relId, {
1546
+ data,
1547
+ path: partPath
1548
+ });
1549
+ return `<w:subDoc r:id="rId${relId}"/>`;
1550
+ },
1551
+ parse(el, ctx) {
1552
+ const rId = attr(el, "r:id");
1553
+ const dctx = ctx;
1554
+ if (rId) {
1555
+ const path = dctx.resolveRelationship(rId);
1556
+ if (path) {
1557
+ const data = dctx.getRaw(path);
1558
+ if (data) return { data };
1559
+ }
1560
+ }
1561
+ return { data: new Uint8Array(0) };
1562
+ }
1563
+ };
1564
+ function escapeXml$1(s) {
1565
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1566
+ }
1567
+ function sdtListItemXml(item, forceValue) {
1568
+ const attrs = [];
1569
+ if (item.displayText !== void 0) attrs.push(`w:displayText="${escapeXml$1(item.displayText)}"`);
1570
+ const value = item.value ?? (forceValue ? item.displayText : void 0);
1571
+ if (value !== void 0) attrs.push(`w:value="${escapeXml$1(value)}"`);
1572
+ return `<w:listItem ${attrs.join(" ")}/>`;
1573
+ }
1574
+ function sdtListTypeXml(name, options) {
1575
+ const parts = [];
1576
+ if (options.items) for (const item of options.items) parts.push(sdtListItemXml(item, name === "w:dropDownList"));
1577
+ const attrs = [];
1578
+ if (options.lastValue !== void 0) attrs.push(`w:lastValue="${escapeXml$1(options.lastValue)}"`);
1579
+ const attrStr = attrs.length ? " " + attrs.join(" ") : "";
1580
+ return parts.length ? `<${name}${attrStr}>${parts.join("")}</${name}>` : `<${name}${attrStr}/>`;
1581
+ }
1582
+ function sdtDateXml(options) {
1583
+ const parts = [];
1584
+ if (options.dateFormat !== void 0) parts.push(`<w:dateFormat w:val="${escapeXml$1(options.dateFormat)}"/>`);
1585
+ if (options.languageId !== void 0) parts.push(`<w:lid w:val="${escapeXml$1(options.languageId)}"/>`);
1586
+ if (options.storeMappedDataAs !== void 0) parts.push(`<w:storeMappedDataAs w:val="${options.storeMappedDataAs}"/>`);
1587
+ if (options.calendar !== void 0) parts.push(`<w:calendar w:val="${options.calendar}"/>`);
1588
+ const attrs = [];
1589
+ if (options.fullDate !== void 0) attrs.push(`w:fullDate="${options.fullDate}"`);
1590
+ const attrStr = attrs.length ? " " + attrs.join(" ") : "";
1591
+ return parts.length ? `<w:date${attrStr}>${parts.join("")}</w:date>` : `<w:date${attrStr}/>`;
1592
+ }
1593
+ function sdtDataBindingXml(options) {
1594
+ const attrs = [`w:xpath="${escapeXml$1(options.xpath)}"`, `w:storeItemID="${escapeXml$1(options.storeItemID)}"`];
1595
+ if (options.prefixMappings !== void 0) attrs.push(`w:prefixMappings="${escapeXml$1(options.prefixMappings)}"`);
1596
+ return `<w:dataBinding ${attrs.join(" ")}/>`;
1597
+ }
1598
+ function sdtDocPartXml(name, options) {
1599
+ const parts = [];
1600
+ if (options.gallery !== void 0) parts.push(`<w:docPartGallery w:val="${escapeXml$1(options.gallery)}"/>`);
1601
+ if (options.category !== void 0) parts.push(`<w:docPartCategory w:val="${escapeXml$1(options.category)}"/>`);
1602
+ if (options.unique !== void 0) parts.push(options.unique ? "<w:docPartUnique/>" : "<w:docPartUnique w:val=\"0\"/>");
1603
+ return parts.length ? `<${name}>${parts.join("")}</${name}>` : `<${name}/>`;
1604
+ }
1605
+ function onOffAttr(name, val) {
1606
+ return val ? `<${name}/>` : `<${name} w:val="0"/>`;
1607
+ }
1608
+ const W14_NS = "xmlns:w14=\"http://schemas.microsoft.com/office/word/2010/wordml\"";
1609
+ /** Default symbol font for checkbox content controls (CT_SdtCheckboxSymbol). */
1610
+ const CHECKBOX_FONT = "MS Gothic";
1611
+ const DEFAULT_CHECKED = {
1612
+ val: "2612",
1613
+ font: CHECKBOX_FONT
1614
+ };
1615
+ const DEFAULT_UNCHECKED = {
1616
+ val: "2610",
1617
+ font: CHECKBOX_FONT
1618
+ };
1619
+ /**
1620
+ * Build a w14:checkbox element (Word 2010+ content control checkbox).
1621
+ *
1622
+ * Lives in the w14 extension namespace; emitted with an inline xmlns:w14 so it
1623
+ * is valid wherever w:sdtPr appears. validate.ts tolerates the w14 namespace.
1624
+ */
1625
+ function sdtCheckboxXml(opts) {
1626
+ const checked = opts.checkedState ?? DEFAULT_CHECKED;
1627
+ const unchecked = opts.uncheckedState ?? DEFAULT_UNCHECKED;
1628
+ return `<w14:checkbox ${W14_NS}>${(opts.checked ? "<w14:checked/>" : "<w14:checked w14:val=\"0\"/>") + `<w14:checkedState w14:val="${escapeXml$1(checked.val)}" w14:font="${escapeXml$1(checked.font ?? CHECKBOX_FONT)}"/><w14:uncheckedState w14:val="${escapeXml$1(unchecked.val)}" w14:font="${escapeXml$1(unchecked.font ?? CHECKBOX_FONT)}"/>`}</w14:checkbox>`;
1629
+ }
1630
+ /** Build the run that renders a checkbox content control's current state symbol. */
1631
+ function checkboxSymbolRunInner(cb) {
1632
+ const symbol = cb.checked ?? false ? cb.checkedState ?? DEFAULT_CHECKED : cb.uncheckedState ?? DEFAULT_UNCHECKED;
1633
+ const font = escapeXml$1(symbol.font ?? CHECKBOX_FONT);
1634
+ return `<w:r><w:rPr><w:rFonts w:ascii="${font}" w:hAnsi="${font}"/></w:rPr><w:t>${escapeXml$1(String.fromCodePoint(parseInt(symbol.val, 16)))}</w:t></w:r>`;
1635
+ }
1636
+ function stringifySdtPr(opts) {
1637
+ const parts = [];
1638
+ if (opts.alias !== void 0) parts.push(`<w:alias w:val="${escapeXml$1(opts.alias)}"/>`);
1639
+ if (opts.tag !== void 0) parts.push(`<w:tag w:val="${escapeXml$1(opts.tag)}"/>`);
1640
+ if (opts.id !== void 0) parts.push(`<w:id w:val="${opts.id}"/>`);
1641
+ if (opts.lock !== void 0) parts.push(`<w:lock w:val="${opts.lock}"/>`);
1642
+ if (opts.temporary !== void 0) parts.push(onOffAttr("w:temporary", opts.temporary));
1643
+ const effectiveShowingPlcHdr = opts.showingPlaceholder ?? false;
1644
+ if (opts.showingPlaceholder !== void 0 || effectiveShowingPlcHdr) parts.push(onOffAttr("w:showingPlcHdr", effectiveShowingPlcHdr));
1645
+ if (opts.dataBinding) parts.push(sdtDataBindingXml(opts.dataBinding));
1646
+ if (opts.label !== void 0) parts.push(`<w:label w:val="${opts.label}"/>`);
1647
+ if (opts.tabIndex !== void 0) parts.push(`<w:tabIndex w:val="${opts.tabIndex}"/>`);
1648
+ if (opts.equation) parts.push("<w:equation/>");
1649
+ else if (opts.comboBox) parts.push(sdtListTypeXml("w:comboBox", opts.comboBox));
1650
+ else if (opts.date) parts.push(sdtDateXml(opts.date));
1651
+ else if (opts.docPartObj) parts.push(sdtDocPartXml("w:docPartObj", opts.docPartObj));
1652
+ else if (opts.docPartList) parts.push(sdtDocPartXml("w:docPartList", opts.docPartList));
1653
+ else if (opts.dropDownList) parts.push(sdtListTypeXml("w:dropDownList", opts.dropDownList));
1654
+ else if (opts.picture) parts.push("<w:picture/>");
1655
+ else if (opts.richText) parts.push("<w:richText/>");
1656
+ else if (opts.text !== void 0) {
1657
+ const multiLine = opts.text.multiLine ?? false;
1658
+ parts.push(`<w:text w:multiLine="${multiLine}"/>`);
1659
+ } else if (opts.citation) parts.push("<w:citation/>");
1660
+ else if (opts.group) parts.push("<w:group/>");
1661
+ else if (opts.bibliography) parts.push("<w:bibliography/>");
1662
+ else if (opts.checkbox) parts.push(sdtCheckboxXml(opts.checkbox));
1663
+ return parts.length ? `<w:sdtPr>${parts.join("")}</w:sdtPr>` : "<w:sdtPr/>";
1664
+ }
1665
+ /**
1666
+ * Build the <w:sdt> shell shared by all four SDT levels (block/run/cell/row).
1667
+ * The caller supplies the sdtContent body; sdtPr/sdtEndPr are handled uniformly.
1668
+ */
1669
+ function stringifySdtShell(properties, endProperties, contentXml) {
1670
+ const endPrInner = endProperties ? stringifyRunPropertiesInner(endProperties) : void 0;
1671
+ const endPr = endPrInner ? `<w:sdtEndPr>${endPrInner}</w:sdtEndPr>` : "<w:sdtEndPr/>";
1672
+ const content = contentXml ? `<w:sdtContent>${contentXml}</w:sdtContent>` : "<w:sdtContent/>";
1673
+ return `<w:sdt>${stringifySdtPr(properties)}${endPr}${content}</w:sdt>`;
1674
+ }
1675
+ /** Parse w:sdtPr element into SdtPropertiesOptions. */
1676
+ function parseSdtPr(el) {
1677
+ const opts = {};
1678
+ const alias = findChild(el, "w:alias");
1679
+ if (alias) opts.alias = attr(alias, "w:val");
1680
+ const tag = findChild(el, "w:tag");
1681
+ if (tag) {
1682
+ const val = attr(tag, "w:val");
1683
+ if (val) opts.tag = val;
1684
+ }
1685
+ const id = findChild(el, "w:id");
1686
+ if (id) {
1687
+ const val = attrNum(id, "w:val");
1688
+ if (val !== void 0) opts.id = val;
1689
+ }
1690
+ const lock = findChild(el, "w:lock");
1691
+ if (lock) {
1692
+ const val = attr(lock, "w:val");
1693
+ if (val) opts.lock = val;
1694
+ }
1695
+ const temporary = findChild(el, "w:temporary");
1696
+ if (temporary) opts.temporary = attrBool(temporary, "w:val") ?? true;
1697
+ const showingPlcHdr = findChild(el, "w:showingPlcHdr");
1698
+ if (showingPlcHdr) opts.showingPlaceholder = attrBool(showingPlcHdr, "w:val") ?? true;
1699
+ const label = findChild(el, "w:label");
1700
+ if (label) {
1701
+ const val = attrNum(label, "w:val");
1702
+ if (val !== void 0) opts.label = val;
1703
+ }
1704
+ const tabIndex = findChild(el, "w:tabIndex");
1705
+ if (tabIndex) {
1706
+ const val = attrNum(tabIndex, "w:val");
1707
+ if (val !== void 0) opts.tabIndex = val;
1708
+ }
1709
+ const dataBinding = findChild(el, "w:dataBinding");
1710
+ if (dataBinding) opts.dataBinding = {
1711
+ xpath: attr(dataBinding, "w:xpath") ?? "",
1712
+ storeItemID: attr(dataBinding, "w:storeItemID") ?? "",
1713
+ prefixMappings: attr(dataBinding, "w:prefixMappings")
1714
+ };
1715
+ if (findChild(el, "w:equation")) opts.equation = true;
1716
+ else if (findChild(el, "w:comboBox")) {
1717
+ const comboBox = findChild(el, "w:comboBox");
1718
+ const items = [];
1719
+ for (const li of children(comboBox, "w:listItem")) items.push({
1720
+ displayText: attr(li, "w:displayText"),
1721
+ value: attr(li, "w:value")
1722
+ });
1723
+ opts.comboBox = {
1724
+ items: items.length > 0 ? items : void 0,
1725
+ lastValue: attr(comboBox, "w:lastValue")
1726
+ };
1727
+ } else if (findChild(el, "w:date")) {
1728
+ const date = findChild(el, "w:date");
1729
+ const dateOpts = {};
1730
+ const dateFormat = findChild(date, "w:dateFormat");
1731
+ if (dateFormat) dateOpts.dateFormat = textOf(dateFormat);
1732
+ const lid = findChild(date, "w:lid");
1733
+ if (lid) dateOpts.languageId = textOf(lid);
1734
+ const storeMapped = findChild(date, "w:storeMappedDataAs");
1735
+ if (storeMapped) dateOpts.storeMappedDataAs = attr(storeMapped, "w:val");
1736
+ const calendar = findChild(date, "w:calendar");
1737
+ if (calendar) dateOpts.calendar = attr(calendar, "w:val");
1738
+ const fullDate = attr(date, "w:fullDate");
1739
+ if (fullDate) dateOpts.fullDate = fullDate;
1740
+ opts.date = dateOpts;
1741
+ } else if (findChild(el, "w:docPartObj")) {
1742
+ const dp = findChild(el, "w:docPartObj");
1743
+ const dpObj = {};
1744
+ const gallery = findChild(dp, "w:docPartGallery");
1745
+ if (gallery) dpObj.gallery = attr(gallery, "w:val");
1746
+ const category = findChild(dp, "w:docPartCategory");
1747
+ if (category) dpObj.category = attr(category, "w:val");
1748
+ if (findChild(dp, "w:docPartUnique")) dpObj.unique = true;
1749
+ opts.docPartObj = dpObj;
1750
+ } else if (findChild(el, "w:docPartList")) {
1751
+ const dp = findChild(el, "w:docPartList");
1752
+ const dpObj = {};
1753
+ const gallery = findChild(dp, "w:docPartGallery");
1754
+ if (gallery) dpObj.gallery = attr(gallery, "w:val");
1755
+ const category = findChild(dp, "w:docPartCategory");
1756
+ if (category) dpObj.category = attr(category, "w:val");
1757
+ if (findChild(dp, "w:docPartUnique")) dpObj.unique = true;
1758
+ opts.docPartList = dpObj;
1759
+ } else if (findChild(el, "w:dropDownList")) {
1760
+ const ddl = findChild(el, "w:dropDownList");
1761
+ const items = [];
1762
+ for (const li of children(ddl, "w:listItem")) items.push({
1763
+ displayText: attr(li, "w:displayText"),
1764
+ value: attr(li, "w:value")
1765
+ });
1766
+ opts.dropDownList = {
1767
+ items: items.length > 0 ? items : void 0,
1768
+ lastValue: attr(ddl, "w:lastValue")
1769
+ };
1770
+ } else if (findChild(el, "w:picture")) opts.picture = true;
1771
+ else if (findChild(el, "w:richText")) opts.richText = true;
1772
+ else if (findChild(el, "w:text")) opts.text = { multiLine: attrBool(findChild(el, "w:text"), "w:multiLine") };
1773
+ else if (findChild(el, "w:citation")) opts.citation = true;
1774
+ else if (findChild(el, "w:group")) opts.group = true;
1775
+ else if (findChild(el, "w:bibliography")) opts.bibliography = true;
1776
+ else if (findChild(el, "w14:checkbox")) {
1777
+ const cb = findChild(el, "w14:checkbox");
1778
+ const cbObj = {};
1779
+ const checked = findChild(cb, "w14:checked");
1780
+ if (checked) cbObj.checked = attrBool(checked, "w14:val") ?? true;
1781
+ const checkedState = findChild(cb, "w14:checkedState");
1782
+ if (checkedState) cbObj.checkedState = {
1783
+ val: attr(checkedState, "w14:val") ?? "",
1784
+ font: attr(checkedState, "w14:font")
1785
+ };
1786
+ const uncheckedState = findChild(cb, "w14:uncheckedState");
1787
+ if (uncheckedState) cbObj.uncheckedState = {
1788
+ val: attr(uncheckedState, "w14:val") ?? "",
1789
+ font: attr(uncheckedState, "w14:font")
1790
+ };
1791
+ opts.checkbox = cbObj;
1792
+ }
1793
+ return opts;
1794
+ }
1795
+ /** Parse w:customXmlPr element into CustomXmlPrOptions. */
1796
+ function parseCustomXmlPr(el) {
1797
+ const opts = {};
1798
+ const placeholder = findChild(el, "w:placeholder");
1799
+ if (placeholder) {
1800
+ const val = attr(placeholder, "w:val");
1801
+ if (val) opts.placeholder = val;
1802
+ }
1803
+ const attributes = [];
1804
+ for (const child of el.elements ?? []) {
1805
+ if (child.name !== "w:attr") continue;
1806
+ const name = attr(child, "w:name");
1807
+ const val = attr(child, "w:val");
1808
+ if (name && val) {
1809
+ const attrOpts = {
1810
+ name,
1811
+ val
1812
+ };
1813
+ const uriVal = attr(child, "w:uri");
1814
+ if (uriVal) attrOpts.uri = uriVal;
1815
+ attributes.push(attrOpts);
1816
+ }
1817
+ }
1818
+ if (attributes.length > 0) opts.attributes = attributes;
1819
+ return opts;
1820
+ }
1821
+ /** Body child element parsing callback for SDT/customXml content. */
1822
+ let _parseBodyChild;
1823
+ /** Register the body child parser (called from parse/body.ts to break circular dependency). */
1824
+ function setBodyParseChild(parser) {
1825
+ _parseBodyChild = parser;
1826
+ }
1827
+ function parseBodyChildren(elements, ctx) {
1828
+ if (!_parseBodyChild) return [];
1829
+ const result = [];
1830
+ for (const el of elements) result.push(_parseBodyChild(el, ctx));
1831
+ return result;
1832
+ }
1833
+ const sdtBlockDesc = {
1834
+ kind: "custom",
1835
+ stringify(opts, ctx) {
1836
+ const parts = ["<w:sdt>"];
1837
+ parts.push(stringifySdtPr(opts.properties));
1838
+ const endPrInner = opts.endProperties ? stringifyRunPropertiesInner(opts.endProperties) : void 0;
1839
+ parts.push(endPrInner ? `<w:sdtEndPr>${endPrInner}</w:sdtEndPr>` : "<w:sdtEndPr/>");
1840
+ if (opts.properties.checkbox) parts.push(`<w:sdtContent><w:p>${checkboxSymbolRunInner(opts.properties.checkbox)}</w:p></w:sdtContent>`);
1841
+ else if (opts.children && opts.children.length > 0) {
1842
+ const contentParts = [];
1843
+ for (const child of opts.children) contentParts.push(ctx.stringifyChild(child, ctx));
1844
+ const contentBody = contentParts.join("");
1845
+ parts.push(contentBody ? `<w:sdtContent>${contentBody}</w:sdtContent>` : "<w:sdtContent/>");
1846
+ }
1847
+ parts.push("</w:sdt>");
1848
+ return parts.join("");
1849
+ },
1850
+ parse(el, ctx) {
1851
+ const dctx = ctx;
1852
+ const sdtPr = findChild(el, "w:sdtPr");
1853
+ const properties = sdtPr ? parseSdtPr(sdtPr) : {};
1854
+ let endProperties;
1855
+ const sdtEndPr = findChild(el, "w:sdtEndPr");
1856
+ if (sdtEndPr) endProperties = parseRunProperties(sdtEndPr);
1857
+ const sdtContent = findChild(el, "w:sdtContent");
1858
+ let childList;
1859
+ if (sdtContent && sdtContent.elements?.length) {
1860
+ childList = parseBodyChildren(sdtContent.elements, dctx);
1861
+ if (childList.length === 0) childList = void 0;
1862
+ }
1863
+ return {
1864
+ properties,
1865
+ children: childList,
1866
+ endProperties
1867
+ };
1868
+ }
1869
+ };
1870
+ function buildCustomXmlPrXml(pr) {
1871
+ const parts = ["<w:customXmlPr>"];
1872
+ if (pr.placeholder !== void 0) parts.push(`<w:placeholder w:val="${escapeAttr(pr.placeholder)}"/>`);
1873
+ if (pr.attributes) for (const attr of pr.attributes) {
1874
+ const attrParts = [`w:name="${escapeAttr(attr.name)}"`, `w:val="${escapeAttr(attr.val)}"`];
1875
+ if (attr.uri !== void 0) attrParts.push(`w:uri="${escapeAttr(attr.uri)}"`);
1876
+ parts.push(`<w:attr ${attrParts.join(" ")}/>`);
1877
+ }
1878
+ parts.push("</w:customXmlPr>");
1879
+ return parts.join("");
1880
+ }
1881
+ /**
1882
+ * Serialize the common customXml shell (element/uri/customXmlPr) wrapping
1883
+ * arbitrary content. Shared by all four customXml levels (block/run/row/cell).
1884
+ */
1885
+ function stringifyCustomXmlShell(opts, contentXml) {
1886
+ const attrs = [`w:element="${escapeAttr(opts.element)}"`];
1887
+ if (opts.uri !== void 0) attrs.push(`w:uri="${escapeAttr(opts.uri)}"`);
1888
+ const prXml = opts.customXmlPr ? buildCustomXmlPrXml(opts.customXmlPr) : "";
1889
+ return `<w:customXml ${attrs.join(" ")}>${prXml}${contentXml}</w:customXml>`;
1890
+ }
1891
+ const customXmlBlockDesc = {
1892
+ kind: "custom",
1893
+ stringify(opts, ctx) {
1894
+ const contentParts = [];
1895
+ if (opts.children) for (const child of opts.children) contentParts.push(ctx.stringifyChild(child, ctx));
1896
+ return stringifyCustomXmlShell(opts, contentParts.join(""));
1897
+ },
1898
+ parse(el, ctx) {
1899
+ const dctx = ctx;
1900
+ const opts = {};
1901
+ const element = attr(el, "w:element");
1902
+ if (element) opts.element = element;
1903
+ const uri = attr(el, "w:uri");
1904
+ if (uri) opts.uri = uri;
1905
+ const xmlPr = findChild(el, "w:customXmlPr");
1906
+ if (xmlPr) opts.customXmlPr = parseCustomXmlPr(xmlPr);
1907
+ const childList = [];
1908
+ for (const child of el.elements ?? []) {
1909
+ if (child.name === "w:customXmlPr") continue;
1910
+ if (_parseBodyChild) childList.push(_parseBodyChild(child, dctx));
1911
+ }
1912
+ if (childList.length > 0) opts.children = childList;
1913
+ return opts;
1914
+ }
1915
+ };
1916
+ //#endregion
635
1917
  //#region src/parts/drawing/text-wrap/text-wrapping.ts
636
1918
  /**
637
1919
  * Enumeration of text wrapping types for floating drawings.
@@ -2342,420 +3624,43 @@ const createFieldChar = (type, dirty, ffData, fldData, fieldLock) => {
2342
3624
  }, children.length > 0 ? children : void 0);
2343
3625
  };
2344
3626
  /**
2345
- * Creates the beginning of a complex field.
2346
- *
2347
- * The Begin element marks the start of a field. A field consists of a begin character,
2348
- * field instructions, an optional separate character, field result, and an end character.
2349
- *
2350
- * For form fields, pass `formField` to embed `w:ffData` within the begin `w:fldChar`.
2351
- *
2352
- * @param dirty - Whether the field should be recalculated
2353
- * @param formField - Optional form field data to embed in the begin character
2354
- *
2355
- * @example
2356
- * ```typescript
2357
- * // Simple field begin
2358
- * createBegin();
2359
- *
2360
- * // Form field (checkbox)
2361
- * createBegin(false, {
2362
- * name: "Check1",
2363
- * checkBox: { checked: true, sizeAuto: true },
2364
- * });
2365
- * ```
2366
- */
2367
- const createBegin = (dirty, formField, fieldLock) => createFieldChar(FieldCharacterType.BEGIN, dirty, formField ? createFormFieldData(formField) : void 0, void 0, fieldLock);
2368
- /**
2369
- * Creates the separator between field code and field result in a complex field.
2370
- *
2371
- * The Separate element divides the field code (instructions) from the field result
2372
- * (the computed value).
2373
- */
2374
- const createSeparate = (dirty) => createFieldChar(FieldCharacterType.SEPARATE, dirty);
2375
- /**
2376
- * Creates the end of a complex field.
2377
- *
2378
- * The End element marks the end of a field. Every field that begins with a Begin
2379
- * element must be terminated with an End element.
2380
- */
2381
- const createEnd = (dirty) => createFieldChar(FieldCharacterType.END, dirty);
2382
- //#endregion
2383
- //#region src/parts/paragraph/stringify.ts
2384
- /**
2385
- * Direct XML string builders for paragraph and run properties.
2386
- *
2387
- * Replaces `buildParagraphProperties() + xml()` and `buildRunProperties() + xml()`
2388
- * with direct string concatenation — zero intermediate IXmlableObject allocation,
2389
- * zero recursive xml() traversal. Follows PPTX/XLSX pattern.
2390
- *
2391
- * @module
2392
- */
2393
- /** On/off: `<w:name/>` for true, `<w:name w:val="0"/>` for false */
2394
- function onOff(name, val) {
2395
- return val ? `<${name}/>` : `<${name} w:val="0"/>`;
2396
- }
2397
- /** Build attrs string from key-value pairs, skipping undefined */
2398
- function attrParts(attrs) {
2399
- const parts = [];
2400
- for (const [key, val] of Object.entries(attrs)) if (val !== void 0) parts.push(`${key}="${val}"`);
2401
- return parts.join(" ");
2402
- }
2403
- function borderStr(name, opts) {
2404
- return `<${name} ${attrParts({
2405
- "w:val": opts.style,
2406
- "w:color": opts.color !== void 0 ? hexColorValue(opts.color) : void 0,
2407
- "w:sz": opts.size !== void 0 ? eighthPointMeasureValue(opts.size) : void 0,
2408
- "w:space": opts.space !== void 0 ? pointMeasureValue(opts.space) : void 0,
2409
- "w:themeColor": opts.themeColor,
2410
- "w:themeTint": opts.themeTint !== void 0 ? uCharHexNumber(opts.themeTint) : void 0,
2411
- "w:themeShade": opts.themeShade !== void 0 ? uCharHexNumber(opts.themeShade) : void 0,
2412
- "w:shadow": opts.shadow !== void 0 ? opts.shadow ? 1 : 0 : void 0,
2413
- "w:frame": opts.frame !== void 0 ? opts.frame ? 1 : 0 : void 0
2414
- })}/>`;
2415
- }
2416
- function shadingStr(opts) {
2417
- return `<w:shd ${attrParts({
2418
- "w:val": opts.type ?? "clear",
2419
- "w:color": opts.color !== void 0 ? hexColorValue(opts.color) : void 0,
2420
- "w:fill": opts.fill !== void 0 ? hexColorValue(opts.fill) : void 0,
2421
- "w:themeColor": opts.themeColor,
2422
- "w:themeTint": opts.themeTint !== void 0 ? uCharHexNumber(opts.themeTint) : void 0,
2423
- "w:themeShade": opts.themeShade !== void 0 ? uCharHexNumber(opts.themeShade) : void 0,
2424
- "w:themeFill": opts.themeFill,
2425
- "w:themeFillTint": opts.themeFillTint !== void 0 ? uCharHexNumber(opts.themeFillTint) : void 0,
2426
- "w:themeFillShade": opts.themeFillShade !== void 0 ? uCharHexNumber(opts.themeFillShade) : void 0
2427
- })}/>`;
2428
- }
2429
- function spacingStr(opts) {
2430
- return `<w:spacing ${attrParts({
2431
- "w:after": opts.after,
2432
- "w:afterAutospacing": opts.afterAutoSpacing !== void 0 ? opts.afterAutoSpacing ? 1 : 0 : void 0,
2433
- "w:afterLines": opts.afterLines !== void 0 ? decimalNumber(opts.afterLines) : void 0,
2434
- "w:before": opts.before,
2435
- "w:beforeAutospacing": opts.beforeAutoSpacing !== void 0 ? opts.beforeAutoSpacing ? 1 : 0 : void 0,
2436
- "w:beforeLines": opts.beforeLines !== void 0 ? decimalNumber(opts.beforeLines) : void 0,
2437
- "w:line": opts.line,
2438
- "w:lineRule": opts.lineRule
2439
- })}/>`;
2440
- }
2441
- function indentStr(opts) {
2442
- return `<w:ind ${attrParts({
2443
- "w:start": opts.start !== void 0 ? signedTwipsMeasureValue(opts.start) : void 0,
2444
- "w:startChars": opts.startChars !== void 0 ? decimalNumber(opts.startChars) : void 0,
2445
- "w:end": opts.end !== void 0 ? signedTwipsMeasureValue(opts.end) : void 0,
2446
- "w:endChars": opts.endChars !== void 0 ? decimalNumber(opts.endChars) : void 0,
2447
- "w:left": opts.left !== void 0 ? signedTwipsMeasureValue(opts.left) : void 0,
2448
- "w:leftChars": opts.leftChars !== void 0 ? decimalNumber(opts.leftChars) : void 0,
2449
- "w:right": opts.right !== void 0 ? signedTwipsMeasureValue(opts.right) : void 0,
2450
- "w:rightChars": opts.rightChars !== void 0 ? decimalNumber(opts.rightChars) : void 0,
2451
- "w:hanging": opts.hanging !== void 0 ? twipsMeasureValue(opts.hanging) : void 0,
2452
- "w:hangingChars": opts.hangingChars !== void 0 ? decimalNumber(opts.hangingChars) : void 0,
2453
- "w:firstLine": opts.firstLine !== void 0 ? twipsMeasureValue(opts.firstLine) : void 0,
2454
- "w:firstLineChars": opts.firstLineChars !== void 0 ? decimalNumber(opts.firstLineChars) : void 0
2455
- })}/>`;
2456
- }
2457
- function tabStopsStr(defs) {
2458
- return `<w:tabs>${defs.map(({ type, position, leader }) => {
2459
- return `<w:tab ${attrParts({
2460
- "w:val": type,
2461
- "w:pos": position,
2462
- "w:leader": leader
2463
- })}/>`;
2464
- }).join("")}</w:tabs>`;
2465
- }
2466
- function cnfStyleStr(opts) {
2467
- return `<w:cnfStyle ${attrParts({
2468
- "w:firstRow": opts.firstRow ? "1" : "0",
2469
- "w:lastRow": opts.lastRow ? "1" : "0",
2470
- "w:firstColumn": opts.firstColumn ? "1" : "0",
2471
- "w:lastColumn": opts.lastColumn ? "1" : "0",
2472
- "w:oddVBand": opts.oddVBand ? "1" : "0",
2473
- "w:evenVBand": opts.evenVBand ? "1" : "0",
2474
- "w:oddHBand": opts.oddHBand ? "1" : "0",
2475
- "w:evenHBand": opts.evenHBand ? "1" : "0",
2476
- "w:firstRowFirstColumn": opts.firstRowFirstColumn ? "1" : "0",
2477
- "w:firstRowLastColumn": opts.firstRowLastColumn ? "1" : "0",
2478
- "w:lastRowFirstColumn": opts.lastRowFirstColumn ? "1" : "0",
2479
- "w:lastRowLastColumn": opts.lastRowLastColumn ? "1" : "0"
2480
- })}/>`;
2481
- }
2482
- function framePrStr(opts) {
2483
- const alignment = opts.alignment;
2484
- const position = opts.position;
2485
- return `<w:framePr ${attrParts({
2486
- "w:xAlign": alignment?.x,
2487
- "w:yAlign": alignment?.y,
2488
- "w:hAnchor": opts.anchor?.horizontal,
2489
- "w:anchorLock": opts.anchorLock,
2490
- "w:vAnchor": opts.anchor?.vertical,
2491
- "w:dropCap": opts.dropCap,
2492
- "w:h": opts.height,
2493
- "w:lines": opts.lines,
2494
- "w:hRule": opts.rule,
2495
- "w:hSpace": opts.space?.horizontal,
2496
- "w:vSpace": opts.space?.vertical,
2497
- "w:w": opts.width,
2498
- "w:wrap": opts.wrap,
2499
- "w:x": position?.x,
2500
- "w:y": position?.y
2501
- })}/>`;
2502
- }
2503
- function numPrStr(numberId, indentLevel, numberingChange) {
2504
- const idVal = typeof numberId === "string" ? `{${numberId}}` : numberId;
2505
- const parts = [`<w:ilvl w:val="${Math.min(indentLevel, 9)}"/>`, `<w:numId w:val="${idVal}"/>`];
2506
- if (numberingChange) {
2507
- const a = attrParts({
2508
- "w:original": numberingChange.original,
2509
- "w:id": numberingChange.id,
2510
- "w:author": numberingChange.author,
2511
- "w:date": numberingChange.date
2512
- });
2513
- parts.push(`<w:numberingChange ${a}/>`);
2514
- }
2515
- return `<w:numPr>${parts.join("")}</w:numPr>`;
2516
- }
2517
- function colorStr(colorOrOptions) {
2518
- if (typeof colorOrOptions === "string") return `<w:color w:val="${hexColorValue(colorOrOptions)}"/>`;
2519
- const opts = colorOrOptions;
2520
- return `<w:color ${attrParts({
2521
- "w:val": opts.val !== void 0 ? hexColorValue(opts.val) : void 0,
2522
- "w:themeColor": opts.themeColor,
2523
- "w:themeTint": opts.themeTint !== void 0 ? uCharHexNumber(opts.themeTint) : void 0,
2524
- "w:themeShade": opts.themeShade !== void 0 ? uCharHexNumber(opts.themeShade) : void 0
2525
- })}/>`;
2526
- }
2527
- function runFontsStr(nameOrAttrs, hint) {
2528
- if (typeof nameOrAttrs === "string") return `<w:rFonts ${attrParts({
2529
- "w:ascii": nameOrAttrs,
2530
- "w:cs": nameOrAttrs,
2531
- "w:eastAsia": nameOrAttrs,
2532
- "w:hAnsi": nameOrAttrs,
2533
- "w:hint": hint
2534
- })}/>`;
2535
- const attrs = nameOrAttrs;
2536
- return `<w:rFonts ${attrParts({
2537
- "w:ascii": attrs.ascii,
2538
- "w:asciiTheme": attrs.asciiTheme,
2539
- "w:cs": attrs.cs,
2540
- "w:cstheme": attrs.cstheme,
2541
- "w:eastAsia": attrs.eastAsia,
2542
- "w:eastAsiaTheme": attrs.eastAsiaTheme,
2543
- "w:hAnsi": attrs.hAnsi,
2544
- "w:hAnsiTheme": attrs.hAnsiTheme,
2545
- "w:hint": attrs.hint
2546
- })}/>`;
2547
- }
2548
- function underlineStr(type, color) {
2549
- return `<w:u ${attrParts({
2550
- "w:val": type ?? "single",
2551
- "w:color": color !== void 0 ? hexColorValue(color) : void 0
2552
- })}/>`;
2553
- }
2554
- function eastAsianLayoutStr(opts) {
2555
- return `<w:eastAsianLayout ${attrParts({
2556
- "w:id": opts.id !== void 0 ? decimalNumber(opts.id) : void 0,
2557
- "w:combine": opts.combine !== void 0 ? opts.combine ? 1 : 0 : void 0,
2558
- "w:combineBrackets": opts.combineBrackets,
2559
- "w:vert": opts.vert !== void 0 ? opts.vert ? 1 : 0 : void 0,
2560
- "w:vertCompress": opts.vertCompress !== void 0 ? opts.vertCompress ? 1 : 0 : void 0
2561
- })}/>`;
2562
- }
2563
- function languageStr(opts) {
2564
- return `<w:lang ${attrParts({
2565
- "w:val": opts.value,
2566
- "w:eastAsia": opts.eastAsia,
2567
- "w:bidi": opts.bidirectional
2568
- })}/>`;
2569
- }
2570
- /**
2571
- * Build `<w:pPr>` XML string directly from options — zero IXmlableObject allocation.
3627
+ * Creates the beginning of a complex field.
2572
3628
  *
2573
- * Replaces `buildParagraphProperties() + xml()` with a single-pass string builder.
3629
+ * The Begin element marks the start of a field. A field consists of a begin character,
3630
+ * field instructions, an optional separate character, field result, and an end character.
3631
+ *
3632
+ * For form fields, pass `formField` to embed `w:ffData` within the begin `w:fldChar`.
3633
+ *
3634
+ * @param dirty - Whether the field should be recalculated
3635
+ * @param formField - Optional form field data to embed in the begin character
3636
+ *
3637
+ * @example
3638
+ * ```typescript
3639
+ * // Simple field begin
3640
+ * createBegin();
3641
+ *
3642
+ * // Form field (checkbox)
3643
+ * createBegin(false, {
3644
+ * name: "Check1",
3645
+ * checkBox: { checked: true, sizeAuto: true },
3646
+ * });
3647
+ * ```
2574
3648
  */
2575
- function stringifyParagraphProperties(options) {
2576
- const numberingReferences = [];
2577
- if (!options) return {
2578
- xml: void 0,
2579
- numberingReferences
2580
- };
2581
- const parts = [];
2582
- if (options.heading) parts.push(`<w:pStyle w:val="${escapeXml(options.heading)}"/>`);
2583
- if (options.bullet) parts.push("<w:pStyle w:val=\"ListParagraph\"/>");
2584
- if (options.numbering) {
2585
- if (!options.style && !options.heading) {
2586
- if (!options.numbering.custom) parts.push("<w:pStyle w:val=\"ListParagraph\"/>");
2587
- }
2588
- }
2589
- if (options.style) parts.push(`<w:pStyle w:val="${escapeXml(options.style)}"/>`);
2590
- if (options.keepNext !== void 0) parts.push(onOff("w:keepNext", options.keepNext));
2591
- if (options.keepLines !== void 0) parts.push(onOff("w:keepLines", options.keepLines));
2592
- if (options.pageBreakBefore) parts.push("<w:pageBreakBefore/>");
2593
- if (options.frame) parts.push(framePrStr(options.frame));
2594
- if (options.widowControl !== void 0) parts.push(onOff("w:widowControl", options.widowControl));
2595
- if (options.bullet) parts.push(`<w:numPr><w:ilvl w:val="${Math.min(options.bullet.level, 9)}"/><w:numId w:val="1"/></w:numPr>`);
2596
- if (options.numbering) {
2597
- numberingReferences.push({
2598
- instance: options.numbering.instance ?? 0,
2599
- reference: options.numbering.reference
2600
- });
2601
- const numId = `${options.numbering.reference}-${options.numbering.instance ?? 0}`;
2602
- parts.push(numPrStr(numId, options.numbering.level, options.numbering.numberingChange));
2603
- } else if (options.numbering === false) parts.push(numPrStr(0, 0));
2604
- if (options.border) {
2605
- const bParts = [];
2606
- if (options.border.top) bParts.push(borderStr("w:top", options.border.top));
2607
- if (options.border.left) bParts.push(borderStr("w:left", options.border.left));
2608
- if (options.border.bottom) bParts.push(borderStr("w:bottom", options.border.bottom));
2609
- if (options.border.right) bParts.push(borderStr("w:right", options.border.right));
2610
- if (options.border.between) bParts.push(borderStr("w:between", options.border.between));
2611
- if (options.border.bar) bParts.push(borderStr("w:bar", options.border.bar));
2612
- if (bParts.length) parts.push(`<w:pBdr>${bParts.join("")}</w:pBdr>`);
2613
- }
2614
- if (options.thematicBreak) parts.push(`<w:pBdr>${borderStr("w:bottom", {
2615
- color: "auto",
2616
- size: 6,
2617
- space: 1,
2618
- style: BorderStyle.SINGLE
2619
- })}</w:pBdr>`);
2620
- if (options.shading) parts.push(shadingStr(options.shading));
2621
- if (options.wordWrap) parts.push("<w:wordWrap w:val=\"0\"/>");
2622
- if (options.overflowPunctuation) parts.push(onOff("w:overflowPunct", options.overflowPunctuation));
2623
- const tabDefs = [
2624
- ...options.rightTabStop !== void 0 ? [{
2625
- position: options.rightTabStop,
2626
- type: "right"
2627
- }] : [],
2628
- ...options.tabStops ? options.tabStops : [],
2629
- ...options.leftTabStop !== void 0 ? [{
2630
- position: options.leftTabStop,
2631
- type: "left"
2632
- }] : []
2633
- ];
2634
- if (tabDefs.length > 0) parts.push(tabStopsStr(tabDefs));
2635
- if (options.bidirectional !== void 0) parts.push(onOff("w:bidi", options.bidirectional));
2636
- if (options.spacing) parts.push(spacingStr(options.spacing));
2637
- if (options.indent) parts.push(indentStr(options.indent));
2638
- if (options.contextualSpacing !== void 0) parts.push(onOff("w:contextualSpacing", options.contextualSpacing));
2639
- if (options.alignment) parts.push(`<w:jc w:val="${options.alignment}"/>`);
2640
- if (options.outlineLevel !== void 0) parts.push(`<w:outlineLvl w:val="${options.outlineLevel}"/>`);
2641
- if (options.divId !== void 0) parts.push(`<w:divId w:val="${options.divId}"/>`);
2642
- if (options.cnfStyle) parts.push(cnfStyleStr(options.cnfStyle));
2643
- if (options.suppressLineNumbers !== void 0) parts.push(onOff("w:suppressLineNumbers", options.suppressLineNumbers));
2644
- if (options.autoSpaceEastAsianText !== void 0) parts.push(onOff("w:autoSpaceDN", options.autoSpaceEastAsianText));
2645
- if (options.suppressAutoHyphens !== void 0) parts.push(onOff("w:suppressAutoHyphens", options.suppressAutoHyphens));
2646
- if (options.adjustRightInd !== void 0) parts.push(onOff("w:adjustRightInd", options.adjustRightInd));
2647
- if (options.snapToGrid !== void 0) parts.push(onOff("w:snapToGrid", options.snapToGrid));
2648
- if (options.mirrorIndents !== void 0) parts.push(onOff("w:mirrorIndents", options.mirrorIndents));
2649
- if (options.kinsoku !== void 0) parts.push(onOff("w:kinsoku", options.kinsoku));
2650
- if (options.topLinePunct !== void 0) parts.push(onOff("w:topLinePunct", options.topLinePunct));
2651
- if (options.autoSpaceDE !== void 0) parts.push(onOff("w:autoSpaceDE", options.autoSpaceDE));
2652
- if (options.textAlignment !== void 0) parts.push(`<w:textAlignment w:val="${options.textAlignment}"/>`);
2653
- if (options.textboxTightWrap !== void 0) parts.push(`<w:textboxTightWrap w:val="${options.textboxTightWrap}"/>`);
2654
- if (options.textDirection !== void 0) parts.push(`<w:textDirection w:val="${options.textDirection}"/>`);
2655
- if (options.suppressOverlap !== void 0) parts.push(onOff("w:suppressOverlap", options.suppressOverlap));
2656
- if (options.run) {
2657
- const inner = stringifyRunPropertiesInner(options.run);
2658
- if (inner !== void 0) {
2659
- const extra = [];
2660
- const runOpts = options.run;
2661
- if (runOpts.insertion) {
2662
- const { id, author, date } = runOpts.insertion;
2663
- extra.push(`<w:ins w:id="${id}" w:author="${escapeXml(author)}" w:date="${date}"/>`);
2664
- }
2665
- if (runOpts.deletion) {
2666
- const { id, author, date } = runOpts.deletion;
2667
- extra.push(`<w:del w:id="${id}" w:author="${escapeXml(author)}" w:date="${date}"/>`);
2668
- }
2669
- const body = inner + extra.join("");
2670
- parts.push(`<w:rPr>${body}</w:rPr>`);
2671
- }
2672
- }
2673
- if (options.revision) {
2674
- const rev = options.revision;
2675
- const { author: _a, date: _d, id: _i, ...originalProps } = rev;
2676
- const inner = stringifyParagraphProperties({
2677
- ...originalProps,
2678
- includeIfEmpty: true
2679
- });
2680
- parts.push(`<w:pPrChange w:author="${escapeXml(rev.author)}" w:date="${rev.date}" w:id="${rev.id}">${inner.xml ?? "<w:pPr/>"}</w:pPrChange>`);
2681
- }
2682
- const body = parts.join("");
2683
- return {
2684
- xml: options.includeIfEmpty || body.length > 0 ? `<w:pPr>${body}</w:pPr>` : void 0,
2685
- numberingReferences
2686
- };
2687
- }
3649
+ const createBegin = (dirty, formField, fieldLock) => createFieldChar(FieldCharacterType.BEGIN, dirty, formField ? createFormFieldData(formField) : void 0, void 0, fieldLock);
2688
3650
  /**
2689
- * Build the inner content of `<w:rPr>` as a string.
2690
- * Returns undefined if no properties are set.
3651
+ * Creates the separator between field code and field result in a complex field.
3652
+ *
3653
+ * The Separate element divides the field code (instructions) from the field result
3654
+ * (the computed value).
2691
3655
  */
2692
- function stringifyRunPropertiesInner(opts) {
2693
- if (!opts) return void 0;
2694
- const parts = [];
2695
- if (opts.style) parts.push(`<w:rStyle w:val="${escapeXml(opts.style)}"/>`);
2696
- if (opts.font) if (typeof opts.font === "string") parts.push(runFontsStr(opts.font));
2697
- else if ("name" in opts.font) parts.push(runFontsStr(opts.font.name, opts.font.hint));
2698
- else parts.push(runFontsStr(opts.font));
2699
- if (opts.bold !== void 0) parts.push(onOff("w:b", opts.bold));
2700
- if ((opts.boldComplexScript === void 0 && opts.bold !== void 0 || opts.boldComplexScript) !== void 0) parts.push(onOff("w:bCs", opts.boldComplexScript ?? opts.bold));
2701
- if (opts.italic !== void 0) parts.push(onOff("w:i", opts.italic));
2702
- if ((opts.italicComplexScript === void 0 && opts.italic !== void 0 || opts.italicComplexScript) !== void 0) parts.push(onOff("w:iCs", opts.italicComplexScript ?? opts.italic));
2703
- if (opts.smallCaps !== void 0) parts.push(onOff("w:smallCaps", opts.smallCaps));
2704
- else if (opts.allCaps !== void 0) parts.push(onOff("w:caps", opts.allCaps));
2705
- if (opts.strike !== void 0) parts.push(onOff("w:strike", opts.strike));
2706
- if (opts.doubleStrike !== void 0) parts.push(onOff("w:dstrike", opts.doubleStrike));
2707
- if (opts.emboss !== void 0) parts.push(onOff("w:emboss", opts.emboss));
2708
- if (opts.imprint !== void 0) parts.push(onOff("w:imprint", opts.imprint));
2709
- if (opts.outline !== void 0) parts.push(onOff("w:outline", opts.outline));
2710
- if (opts.shadow !== void 0) parts.push(onOff("w:shadow", opts.shadow));
2711
- if (opts.webHidden !== void 0) parts.push(onOff("w:webHidden", opts.webHidden));
2712
- if (opts.noProof !== void 0) parts.push(onOff("w:noProof", opts.noProof));
2713
- if (opts.snapToGrid !== void 0) parts.push(onOff("w:snapToGrid", opts.snapToGrid));
2714
- if (opts.vanish) parts.push(onOff("w:vanish", opts.vanish));
2715
- if (opts.color) parts.push(colorStr(opts.color));
2716
- if (opts.characterSpacing) parts.push(`<w:spacing w:val="${signedTwipsMeasureValue(opts.characterSpacing)}"/>`);
2717
- if (opts.scale !== void 0) parts.push(`<w:w w:val="${opts.scale}"/>`);
2718
- if (opts.kern) parts.push(`<w:kern w:val="${hpsMeasureValue(opts.kern)}"/>`);
2719
- if (opts.position) parts.push(`<w:position w:val="${opts.position}"/>`);
2720
- if (opts.size !== void 0) parts.push(`<w:sz w:val="${hpsMeasureValue(opts.size * 2)}"/>`);
2721
- const szCs = opts.sizeComplexScript === void 0 || opts.sizeComplexScript === true ? opts.size : opts.sizeComplexScript;
2722
- if (szCs) parts.push(`<w:szCs w:val="${hpsMeasureValue(szCs * 2)}"/>`);
2723
- if (opts.highlight) parts.push(`<w:highlight w:val="${opts.highlight}"/>`);
2724
- if (opts.highlightComplexScript === true) {
2725
- if (opts.highlight) parts.push(`<w:highlightCs w:val="${opts.highlight}"/>`);
2726
- } else if (opts.highlightComplexScript !== void 0 && opts.highlightComplexScript !== false) parts.push(`<w:highlightCs w:val="${opts.highlightComplexScript}"/>`);
2727
- if (opts.underline) parts.push(underlineStr(opts.underline.type, opts.underline.color));
2728
- if (opts.effect) parts.push(`<w:effect w:val="${opts.effect}"/>`);
2729
- if (opts.border) parts.push(borderStr("w:bdr", opts.border));
2730
- if (opts.shading) parts.push(shadingStr(opts.shading));
2731
- if (opts.subScript) parts.push("<w:vertAlign w:val=\"subscript\"/>");
2732
- if (opts.superScript) parts.push("<w:vertAlign w:val=\"superscript\"/>");
2733
- if (opts.rightToLeft !== void 0) parts.push(onOff("w:rtl", opts.rightToLeft));
2734
- if (opts.emphasisMark) parts.push(`<w:em w:val="${opts.emphasisMark.type ?? "dot"}"/>`);
2735
- if (opts.language) parts.push(languageStr(opts.language));
2736
- if (opts.specVanish) parts.push("<w:specVanish/>");
2737
- if (opts.math) parts.push(onOff("w:oMath", opts.math));
2738
- if (opts.fitText !== void 0) parts.push(`<w:fitText w:val="${opts.fitText}"/>`);
2739
- if (opts.complexScript !== void 0) parts.push(onOff("w:cs", opts.complexScript));
2740
- if (opts.eastAsianLayout) parts.push(eastAsianLayoutStr(opts.eastAsianLayout));
2741
- if (opts.contentPartRId) parts.push(`<w:contentPart r:id="${opts.contentPartRId}"/>`);
2742
- if (opts.revision) {
2743
- const rev = opts.revision;
2744
- const { author: _a, date: _d, id: _i, ...originalProps } = rev;
2745
- const inner = stringifyRunPropertiesInner(originalProps);
2746
- parts.push(`<w:rPrChange w:author="${escapeXml(rev.author)}" w:date="${rev.date}" w:id="${rev.id}"><w:rPr>${inner ?? ""}</w:rPr></w:rPrChange>`);
2747
- }
2748
- return parts.length > 0 ? parts.join("") : void 0;
2749
- }
3656
+ const createSeparate = (dirty) => createFieldChar(FieldCharacterType.SEPARATE, dirty);
2750
3657
  /**
2751
- * Build `<w:rPr>` XML string directly from options — zero IXmlableObject allocation.
3658
+ * Creates the end of a complex field.
2752
3659
  *
2753
- * Replaces `buildRunProperties() + xml()` with a single-pass string builder.
3660
+ * The End element marks the end of a field. Every field that begins with a Begin
3661
+ * element must be terminated with an End element.
2754
3662
  */
2755
- function stringifyRunProperties(opts) {
2756
- const inner = stringifyRunPropertiesInner(opts);
2757
- return inner ? `<w:rPr>${inner}</w:rPr>` : void 0;
2758
- }
3663
+ const createEnd = (dirty) => createFieldChar(FieldCharacterType.END, dirty);
2759
3664
  //#endregion
2760
3665
  //#region src/parts/inline.ts
2761
3666
  /**
@@ -3115,26 +4020,30 @@ function stringifyChildDispatch(child, ctx) {
3115
4020
  }
3116
4021
  if ("customXml" in child) {
3117
4022
  const cx = child.customXml;
3118
- const attrs = [`w:element="${escapeXml(cx.element)}"`];
3119
- if (cx.uri) attrs.push(`w:uri="${escapeXml(cx.uri)}"`);
3120
- const parts = [];
3121
- if (cx.customXmlPr) {
3122
- const prParts = [];
3123
- if (cx.customXmlPr.placeholder) prParts.push(`<w:placeholder w:val="${escapeXml(cx.customXmlPr.placeholder)}"/>`);
3124
- if (cx.customXmlPr.attrs?.length) for (const a of cx.customXmlPr.attrs) {
3125
- const aa = [`w:name="${escapeXml(a.name)}"`, `w:val="${escapeXml(a.val)}"`];
3126
- if (a.uri) aa.push(`w:uri="${escapeXml(a.uri)}"`);
3127
- prParts.push(`<w:attr ${aa.join(" ")}/>`);
3128
- }
3129
- if (prParts.length) parts.push(`<w:customXmlPr>${prParts.join("")}</w:customXmlPr>`);
3130
- }
3131
- if (cx.children) for (const c of cx.children) if (typeof c === "string") parts.push(stringifyRunInline({ text: c }, ctx));
4023
+ const contentParts = [];
4024
+ if (cx.children) for (const c of cx.children) if (typeof c === "string") contentParts.push(stringifyRunInline({ text: c }, ctx));
3132
4025
  else {
3133
4026
  const jr = stringifyChildDispatch(c, ctx);
3134
- if (jr !== void 0) parts.push(Array.isArray(jr) ? jr.join("") : jr);
3135
- else parts.push(stringifyRunInline(c, ctx));
4027
+ if (jr !== void 0) contentParts.push(Array.isArray(jr) ? jr.join("") : jr);
4028
+ else contentParts.push(stringifyRunInline(c, ctx));
4029
+ }
4030
+ return stringifyCustomXmlShell(cx, contentParts.join(""));
4031
+ }
4032
+ if ("sdt" in child) {
4033
+ const s = child.sdt;
4034
+ let contentXml = "";
4035
+ if (s.properties.checkbox) contentXml = checkboxSymbolRunInner(s.properties.checkbox);
4036
+ else if (s.children && s.children.length > 0) {
4037
+ const cparts = [];
4038
+ for (const c of s.children) if (typeof c === "string") cparts.push(stringifyRunInline({ text: c }, ctx));
4039
+ else {
4040
+ const jr = stringifyChildDispatch(c, ctx);
4041
+ if (jr !== void 0) cparts.push(Array.isArray(jr) ? jr.join("") : jr);
4042
+ else if ("text" in c || "children" in c || "break" in c) cparts.push(stringifyRunInline(c, ctx));
4043
+ }
4044
+ contentXml = cparts.join("");
3136
4045
  }
3137
- return `<w:customXml ${attrs.join(" ")}>${parts.join("")}</w:customXml>`;
4046
+ return stringifySdtShell(s.properties, s.endProperties, contentXml);
3138
4047
  }
3139
4048
  }
3140
4049
  /** Serialize children of Dir/Bdo containers. */
@@ -3175,6 +4084,151 @@ function stringifyParagraphInline(opts, ctx) {
3175
4084
  return body ? `<w:p>${body}</w:p>` : "<w:p/>";
3176
4085
  }
3177
4086
  //#endregion
4087
+ //#region src/parts/sdt/sdt-parse.ts
4088
+ /**
4089
+ * Structured Document Tag parser for DOCX documents.
4090
+ *
4091
+ * Parses w:sdt elements into SdtPropertiesOptions + children.
4092
+ *
4093
+ * @module
4094
+ */
4095
+ /**
4096
+ * Parse w:sdtPr element into SdtPropertiesOptions.
4097
+ */
4098
+ function parseSdtProperties(el) {
4099
+ const opts = {};
4100
+ const alias = findChild(el, "w:alias");
4101
+ if (alias) opts.alias = attr(alias, "w:val");
4102
+ const tag = findChild(el, "w:tag");
4103
+ if (tag) {
4104
+ const val = attr(tag, "w:val");
4105
+ if (val) opts.tag = val;
4106
+ }
4107
+ const id = findChild(el, "w:id");
4108
+ if (id) {
4109
+ const val = attrNum(id, "w:val");
4110
+ if (val !== void 0) opts.id = val;
4111
+ }
4112
+ const lock = findChild(el, "w:lock");
4113
+ if (lock) {
4114
+ const val = attr(lock, "w:val");
4115
+ if (val) opts.lock = val;
4116
+ }
4117
+ const temporary = findChild(el, "w:temporary");
4118
+ if (temporary) opts.temporary = attrBool(temporary, "w:val") ?? true;
4119
+ const showingPlcHdr = findChild(el, "w:showingPlcHdr");
4120
+ if (showingPlcHdr) opts.showingPlaceholder = attrBool(showingPlcHdr, "w:val") ?? true;
4121
+ const label = findChild(el, "w:label");
4122
+ if (label) {
4123
+ const val = attrNum(label, "w:val");
4124
+ if (val !== void 0) opts.label = val;
4125
+ }
4126
+ const tabIndex = findChild(el, "w:tabIndex");
4127
+ if (tabIndex) {
4128
+ const val = attrNum(tabIndex, "w:val");
4129
+ if (val !== void 0) opts.tabIndex = val;
4130
+ }
4131
+ const dataBinding = findChild(el, "w:dataBinding");
4132
+ if (dataBinding) opts.dataBinding = {
4133
+ xpath: attr(dataBinding, "w:xpath") ?? "",
4134
+ storeItemID: attr(dataBinding, "w:storeItemID") ?? "",
4135
+ prefixMappings: attr(dataBinding, "w:prefixMappings")
4136
+ };
4137
+ if (findChild(el, "w:equation")) opts.equation = true;
4138
+ else if (findChild(el, "w:comboBox")) {
4139
+ const comboBox = findChild(el, "w:comboBox");
4140
+ const items = [];
4141
+ for (const li of children(comboBox, "w:listItem")) items.push({
4142
+ displayText: attr(li, "w:displayText"),
4143
+ value: attr(li, "w:value")
4144
+ });
4145
+ opts.comboBox = {
4146
+ items: items.length > 0 ? items : void 0,
4147
+ lastValue: attr(comboBox, "w:lastValue")
4148
+ };
4149
+ } else if (findChild(el, "w:date")) {
4150
+ const date = findChild(el, "w:date");
4151
+ const dateOpts = {};
4152
+ const dateFormat = findChild(date, "w:dateFormat");
4153
+ if (dateFormat) dateOpts.dateFormat = textOf(dateFormat);
4154
+ const lid = findChild(date, "w:lid");
4155
+ if (lid) dateOpts.languageId = textOf(lid);
4156
+ const storeMapped = findChild(date, "w:storeMappedDataAs");
4157
+ if (storeMapped) dateOpts.storeMappedDataAs = attr(storeMapped, "w:val");
4158
+ const calendar = findChild(date, "w:calendar");
4159
+ if (calendar) dateOpts.calendar = attr(calendar, "w:val");
4160
+ const fullDate = attr(date, "w:fullDate");
4161
+ if (fullDate) dateOpts.fullDate = fullDate;
4162
+ opts.date = dateOpts;
4163
+ } else if (findChild(el, "w:dropDownList")) {
4164
+ const ddl = findChild(el, "w:dropDownList");
4165
+ const items = [];
4166
+ for (const li of children(ddl, "w:listItem")) items.push({
4167
+ displayText: attr(li, "w:displayText"),
4168
+ value: attr(li, "w:value")
4169
+ });
4170
+ opts.dropDownList = {
4171
+ items: items.length > 0 ? items : void 0,
4172
+ lastValue: attr(ddl, "w:lastValue")
4173
+ };
4174
+ } else if (findChild(el, "w:picture")) opts.picture = true;
4175
+ else if (findChild(el, "w:richText")) opts.richText = true;
4176
+ else if (findChild(el, "w:text")) opts.text = { multiLine: attrBool(findChild(el, "w:text"), "w:multiLine") };
4177
+ else if (findChild(el, "w:citation")) opts.citation = true;
4178
+ else if (findChild(el, "w:group")) opts.group = true;
4179
+ else if (findChild(el, "w:bibliography")) opts.bibliography = true;
4180
+ else if (findChild(el, "w:docPartObj")) {
4181
+ const dp = findChild(el, "w:docPartObj");
4182
+ opts.docPartObj = {};
4183
+ const gallery = findChild(dp, "w:docPartGallery");
4184
+ if (gallery) opts.docPartObj.gallery = attr(gallery, "w:val");
4185
+ const category = findChild(dp, "w:docPartCategory");
4186
+ if (category) opts.docPartObj.category = attr(category, "w:val");
4187
+ } else if (findChild(el, "w:docPartList")) {
4188
+ const dp = findChild(el, "w:docPartList");
4189
+ opts.docPartList = {};
4190
+ const gallery = findChild(dp, "w:docPartGallery");
4191
+ if (gallery) opts.docPartList.gallery = attr(gallery, "w:val");
4192
+ const category = findChild(dp, "w:docPartCategory");
4193
+ if (category) opts.docPartList.category = attr(category, "w:val");
4194
+ } else if (findChild(el, "w14:checkbox")) {
4195
+ const cb = findChild(el, "w14:checkbox");
4196
+ const cbObj = {};
4197
+ const checked = findChild(cb, "w14:checked");
4198
+ if (checked) cbObj.checked = attrBool(checked, "w14:val") ?? true;
4199
+ const checkedState = findChild(cb, "w14:checkedState");
4200
+ if (checkedState) cbObj.checkedState = {
4201
+ val: attr(checkedState, "w14:val") ?? "",
4202
+ font: attr(checkedState, "w14:font")
4203
+ };
4204
+ const uncheckedState = findChild(cb, "w14:uncheckedState");
4205
+ if (uncheckedState) cbObj.uncheckedState = {
4206
+ val: attr(uncheckedState, "w14:val") ?? "",
4207
+ font: attr(uncheckedState, "w14:font")
4208
+ };
4209
+ opts.checkbox = cbObj;
4210
+ }
4211
+ return opts;
4212
+ }
4213
+ /**
4214
+ * Parse a block-level w:sdt element.
4215
+ * Returns an object suitable for the { sdt: ... } SectionChild variant.
4216
+ */
4217
+ function parseSdtBlock(el, ctx, parseChildren) {
4218
+ const sdtPr = findChild(el, "w:sdtPr");
4219
+ const properties = sdtPr ? parseSdtProperties(sdtPr) : {};
4220
+ const sdtContent = findChild(el, "w:sdtContent");
4221
+ let childList;
4222
+ if (sdtContent) {
4223
+ childList = parseChildren(sdtContent.elements ?? [], ctx);
4224
+ if (childList.length === 0) childList = void 0;
4225
+ }
4226
+ return {
4227
+ properties,
4228
+ children: childList
4229
+ };
4230
+ }
4231
+ //#endregion
3178
4232
  //#region src/parts/table/stringify.ts
3179
4233
  /**
3180
4234
  * Direct XML string builders for table properties.
@@ -3526,7 +4580,15 @@ function stringifyTableRow(row, ctx, extraCells) {
3526
4580
  const trPr = stringifyTableRowProperties(row);
3527
4581
  if (trPr) parts.push(trPr);
3528
4582
  const prefixCount = parts.length;
3529
- for (const cell of row.cells) parts.push(stringifyTableCell(cell, ctx));
4583
+ for (const cell of row.cells) if ("sdt" in cell) {
4584
+ const s = cell.sdt;
4585
+ const contentXml = (s.cells ?? []).map((c) => stringifyTableCell(c, ctx)).join("");
4586
+ parts.push(stringifySdtShell(s.properties, s.endProperties, contentXml));
4587
+ } else if ("customXml" in cell) {
4588
+ const cx = cell.customXml;
4589
+ const contentXml = (cx.children ?? []).map((c) => stringifyTableCell(c, ctx)).join("");
4590
+ parts.push(stringifyCustomXmlShell(cx, contentXml));
4591
+ } else parts.push(stringifyTableCell(cell, ctx));
3530
4592
  if (extraCells && extraCells.length > 0) for (const { cell, columnIndex } of extraCells) {
3531
4593
  const insertIdx = findInsertIndex(row.cells, columnIndex, prefixCount);
3532
4594
  parts.splice(insertIdx, 0, stringifyTableCell(cell, ctx));
@@ -3540,10 +4602,20 @@ function stringifyTableRow(row, ctx, extraCells) {
3540
4602
  const body = parts.join("");
3541
4603
  return body ? `<w:tr${attr}>${body}</w:tr>` : attr ? `<w:tr${attr}/>` : "<w:tr/>";
3542
4604
  }
4605
+ /** Type guard: a plain row (not SDT/customXml-wrapped). */
4606
+ function isPlainRow(r) {
4607
+ return !("sdt" in r) && !("customXml" in r);
4608
+ }
4609
+ /** Type guard: a plain cell (not SDT/customXml-wrapped). */
4610
+ function isPlainCell(c) {
4611
+ return !("sdt" in c) && !("customXml" in c);
4612
+ }
3543
4613
  function findInsertIndex(cells, columnIndex, prefixCount) {
3544
4614
  let colIdx = 0;
3545
4615
  for (let i = 0; i < cells.length; i++) {
3546
- const { columnSpan } = getCellSpans(cells[i]);
4616
+ const c = cells[i];
4617
+ if (!isPlainCell(c)) continue;
4618
+ const { columnSpan } = getCellSpans(c);
3547
4619
  colIdx += columnSpan;
3548
4620
  if (colIdx > columnIndex) return i + prefixCount;
3549
4621
  }
@@ -3555,9 +4627,12 @@ function findInsertIndex(cells, columnIndex, prefixCount) {
3555
4627
  function computeVerticalMergeCells(rows) {
3556
4628
  const extraMap = /* @__PURE__ */ new Map();
3557
4629
  for (let ri = 0; ri < rows.length - 1; ri++) {
3558
- const cells = rows[ri].cells;
4630
+ const row = rows[ri];
4631
+ if (!isPlainRow(row)) continue;
4632
+ const cells = row.cells;
3559
4633
  let colIdx = 0;
3560
4634
  for (const cell of cells) {
4635
+ if (!isPlainCell(cell)) continue;
3561
4636
  const typedCell = cell;
3562
4637
  const { columnSpan, rowSpan } = getCellSpans(typedCell);
3563
4638
  if (rowSpan > 1) {
@@ -3603,13 +4678,23 @@ const tableDesc = {
3603
4678
  includeIfEmpty: true
3604
4679
  };
3605
4680
  parts.push(stringifyTableProperties(tblPrOpts));
3606
- const columnWidths = opts.columnWidths ?? Array(Math.max(...opts.rows.map((r) => r.cells.length))).fill(100);
4681
+ const columnWidths = opts.columnWidths ?? Array(Math.max(1, ...opts.rows.map((r) => isPlainRow(r) ? r.cells.length : 0))).fill(100);
3607
4682
  parts.push(buildTableGridXml(columnWidths, opts.columnWidthsRevision));
3608
4683
  const extraCells = computeVerticalMergeCells(opts.rows);
3609
4684
  for (let ri = 0; ri < opts.rows.length; ri++) {
3610
- const row = opts.rows[ri];
3611
- const extras = extraCells.get(ri);
3612
- parts.push(stringifyTableRow(row, ctx, extras));
4685
+ const r = opts.rows[ri];
4686
+ if ("sdt" in r) {
4687
+ const sdt = r.sdt;
4688
+ const contentXml = (sdt.rows ?? []).map((rr) => stringifyTableRow(rr, ctx)).join("");
4689
+ parts.push(stringifySdtShell(sdt.properties, sdt.endProperties, contentXml));
4690
+ } else if ("customXml" in r) {
4691
+ const cx = r.customXml;
4692
+ const contentXml = (cx.children ?? []).map((rr) => stringifyTableRow(rr, ctx)).join("");
4693
+ parts.push(stringifyCustomXmlShell(cx, contentXml));
4694
+ } else {
4695
+ const extras = extraCells.get(ri);
4696
+ parts.push(stringifyTableRow(r, ctx, extras));
4697
+ }
3613
4698
  }
3614
4699
  return `<w:tbl>${parts.join("")}</w:tbl>`;
3615
4700
  },
@@ -4087,6 +5172,34 @@ function parseTableRowEl(el, ctx) {
4087
5172
  }
4088
5173
  const childCells = [];
4089
5174
  for (const child of el.elements ?? []) if (child.name === "w:tc") childCells.push(parseTableCellEl(child, ctx));
5175
+ else if (child.name === "w:sdt") {
5176
+ const sdtPr = findChild(child, "w:sdtPr");
5177
+ const properties = sdtPr ? parseSdtProperties(sdtPr) : {};
5178
+ const sdtEndPr = findChild(child, "w:sdtEndPr");
5179
+ const endProperties = sdtEndPr ? parseRunProperties(sdtEndPr) : void 0;
5180
+ const sdtContent = findChild(child, "w:sdtContent");
5181
+ const sdtCells = [];
5182
+ if (sdtContent) {
5183
+ for (const sub of sdtContent.elements ?? []) if (sub.name === "w:tc") sdtCells.push(parseTableCellEl(sub, ctx));
5184
+ }
5185
+ const sdt = { properties };
5186
+ if (sdtCells.length > 0) sdt.cells = sdtCells;
5187
+ if (endProperties) sdt.endProperties = endProperties;
5188
+ childCells.push({ sdt });
5189
+ } else if (child.name === "w:customXml") {
5190
+ const cx = { element: attr(child, "w:element") ?? "" };
5191
+ const cxUri = attr(child, "w:uri");
5192
+ if (cxUri) cx.uri = cxUri;
5193
+ const xmlPr = findChild(child, "w:customXmlPr");
5194
+ if (xmlPr) {
5195
+ const parsed = parseCustomXmlPr(xmlPr);
5196
+ if (parsed.placeholder !== void 0 || parsed.attributes !== void 0) cx.customXmlPr = parsed;
5197
+ }
5198
+ const cxCells = [];
5199
+ for (const sub of child.elements ?? []) if (sub.name === "w:tc") cxCells.push(parseTableCellEl(sub, ctx));
5200
+ if (cxCells.length > 0) cx.children = cxCells;
5201
+ childCells.push({ customXml: cx });
5202
+ }
4090
5203
  opts.cells = childCells;
4091
5204
  return opts;
4092
5205
  }
@@ -4098,6 +5211,34 @@ function parseTableEl(el, ctx) {
4098
5211
  if (colWidths.length > 0) opts.columnWidths = colWidths;
4099
5212
  const rows = [];
4100
5213
  for (const child of el.elements ?? []) if (child.name === "w:tr") rows.push(parseTableRowEl(child, ctx));
5214
+ else if (child.name === "w:sdt") {
5215
+ const sdtPr = findChild(child, "w:sdtPr");
5216
+ const properties = sdtPr ? parseSdtProperties(sdtPr) : {};
5217
+ const sdtEndPr = findChild(child, "w:sdtEndPr");
5218
+ const endProperties = sdtEndPr ? parseRunProperties(sdtEndPr) : void 0;
5219
+ const sdtContent = findChild(child, "w:sdtContent");
5220
+ const sdtRows = [];
5221
+ if (sdtContent) {
5222
+ for (const sub of sdtContent.elements ?? []) if (sub.name === "w:tr") sdtRows.push(parseTableRowEl(sub, ctx));
5223
+ }
5224
+ const sdt = { properties };
5225
+ if (sdtRows.length > 0) sdt.rows = sdtRows;
5226
+ if (endProperties) sdt.endProperties = endProperties;
5227
+ rows.push({ sdt });
5228
+ } else if (child.name === "w:customXml") {
5229
+ const cx = { element: attr(child, "w:element") ?? "" };
5230
+ const cxUri = attr(child, "w:uri");
5231
+ if (cxUri) cx.uri = cxUri;
5232
+ const xmlPr = findChild(child, "w:customXmlPr");
5233
+ if (xmlPr) {
5234
+ const parsed = parseCustomXmlPr(xmlPr);
5235
+ if (parsed.placeholder !== void 0 || parsed.attributes !== void 0) cx.customXmlPr = parsed;
5236
+ }
5237
+ const cxRows = [];
5238
+ for (const sub of child.elements ?? []) if (sub.name === "w:tr") cxRows.push(parseTableRowEl(sub, ctx));
5239
+ if (cxRows.length > 0) cx.children = cxRows;
5240
+ rows.push({ customXml: cx });
5241
+ }
4101
5242
  opts.rows = rows;
4102
5243
  return opts;
4103
5244
  }
@@ -5081,6 +6222,6 @@ function parseNotePropertiesEl(el) {
5081
6222
  return opts;
5082
6223
  }
5083
6224
  //#endregion
5084
- export { FormFieldTextType as $, stringifyParagraphProperties as A, VerticalPositionRelativeFrom as B, createPageSize as C, stringifyChildDispatch as D, tableDesc as E, resetDrawingIdGen as F, createWrapThrough as G, NumberFormat as H, parseDrawingRun as I, TextWrappingType as J, createWrapTight as K, createVerticalPosition as L, stringifyRunPropertiesInner as M, parseMathChildren as N, stringifyParagraphInline as O, drawingDesc as P, VerticalMergeType as Q, createHorizontalPosition as R, PageOrientation as S, setTableParseChild as T, SpaceType as U, HorizontalPositionAlign as V, VerticalPositionAlign as W, BorderStyle as X, WidthType as Y, TextDirection as Z, DocumentGridType as _, HeaderFooterType as a, TextVerticalType as at, sectionPageSizeDefaults as b, createSectionType as c, WORKAROUND2 as ct, createPageMargin as d, createFormFieldData as et, PageBorderDisplay as f, createPageNumberType as g, PageNumberSeparator as h, HeaderFooterReferenceType as i, TextVertOverflowType as it, stringifyRunProperties as j, stringifyRunInline as k, LineNumberRestartFormat as l, Media as lt, PageBorderZOrder as m, sectionPropertiesDesc as n, TextBodyWrappingType as nt, createHeaderFooterReference as o, VerticalAnchor as ot, PageBorderOffsetFrom as p, TextWrappingSide as q, stringifySectionPropertiesXml as r, TextHorzOverflowType as rt, SectionType as s, createBodyProperties as st, parseSectionPropertiesEl as t, parseFormFieldData as tt, createLineNumberType as u, createTransformation as ut, createDocumentGrid as v, DocumentAttributeNamespaces as w, PageTextDirectionType as x, sectionMarginDefaults as y, HorizontalPositionRelativeFrom as z };
6225
+ export { setBodyParseChild as $, stringifyParagraphInline as A, HorizontalPositionAlign as B, createPageSize as C, Media as Ct, parseSdtBlock as D, tableDesc as E, parseDrawingRun as F, createWrapTight as G, SpaceType as H, createVerticalPosition as I, altChunkDesc as J, TextWrappingSide as K, createHorizontalPosition as L, parseMathChildren as M, drawingDesc as N, parseSdtProperties as O, resetDrawingIdGen as P, sdtBlockDesc as Q, HorizontalPositionRelativeFrom as R, PageOrientation as S, WORKAROUND2 as St, setTableParseChild as T, VerticalPositionAlign as U, NumberFormat as V, createWrapThrough as W, customXmlBlockDesc as X, checkboxSymbolRunInner as Y, parseCustomXmlPr as Z, DocumentGridType as _, TextHorzOverflowType as _t, HeaderFooterType as a, stringifyRunProperties as at, sectionPageSizeDefaults as b, VerticalAnchor as bt, createSectionType as c, parsedRunToOptions as ct, createPageMargin as d, TextDirection as dt, stringifyCustomXmlShell as et, PageBorderDisplay as f, VerticalMergeType as ft, createPageNumberType as g, TextBodyWrappingType as gt, PageNumberSeparator as h, parseFormFieldData as ht, HeaderFooterReferenceType as i, stringifyParagraphProperties as it, stringifyRunInline as j, stringifyChildDispatch as k, LineNumberRestartFormat as l, WidthType as lt, PageBorderZOrder as m, createFormFieldData as mt, sectionPropertiesDesc as n, stringifySdtShell as nt, createHeaderFooterReference as o, parseRun as ot, PageBorderOffsetFrom as p, FormFieldTextType as pt, TextWrappingType as q, stringifySectionPropertiesXml as r, subDocDesc as rt, SectionType as s, parseRunProperties as st, parseSectionPropertiesEl as t, stringifySdtPr as tt, createLineNumberType as u, BorderStyle as ut, createDocumentGrid as v, TextVertOverflowType as vt, DocumentAttributeNamespaces as w, createTransformation as wt, PageTextDirectionType as x, createBodyProperties as xt, sectionMarginDefaults as y, TextVerticalType as yt, VerticalPositionRelativeFrom as z };
5085
6226
 
5086
- //# sourceMappingURL=document-B_uvEH8b.mjs.map
6227
+ //# sourceMappingURL=document-DYH7tGnw.mjs.map