@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.
- package/dist/{context-CA7wUvmY.mjs → context-CSBntKXD.mjs} +43 -1076
- package/dist/context-CSBntKXD.mjs.map +1 -0
- package/dist/{core-properties-CR-T1Wqh.d.mts → core-properties-BMagGcpC.d.mts} +429 -425
- package/dist/core-properties-BMagGcpC.d.mts.map +1 -0
- package/dist/{document-B_uvEH8b.mjs → document-DYH7tGnw.mjs} +1575 -434
- package/dist/document-DYH7tGnw.mjs.map +1 -0
- package/dist/{generate-_AmBlI4o.mjs → generate-BVfOLdwW.mjs} +3 -3
- package/dist/{generate-_AmBlI4o.mjs.map → generate-BVfOLdwW.mjs.map} +1 -1
- package/dist/generate.d.mts +1 -1
- package/dist/generate.mjs +1 -1
- package/dist/index.d.mts +12 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +5 -5
- package/dist/{parse-7SJ1sm-D.mjs → parse-Db2NGghB.mjs} +3 -28
- package/dist/parse-Db2NGghB.mjs.map +1 -0
- package/dist/parse.d.mts +1 -1
- package/dist/parse.mjs +1 -1
- package/dist/patch/index.d.mts +1 -1
- package/dist/patch/index.mjs +1 -1
- package/package.json +3 -3
- package/dist/context-CA7wUvmY.mjs.map +0 -1
- package/dist/core-properties-CR-T1Wqh.d.mts.map +0 -1
- package/dist/document-B_uvEH8b.mjs.map +0 -1
- package/dist/parse-7SJ1sm-D.mjs.map +0 -1
|
@@ -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, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
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, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
2690
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
3658
|
+
* Creates the end of a complex field.
|
|
2752
3659
|
*
|
|
2753
|
-
*
|
|
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
|
-
|
|
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
|
|
3119
|
-
if (cx.
|
|
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)
|
|
3135
|
-
else
|
|
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
|
|
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)
|
|
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
|
|
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
|
|
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
|
|
3611
|
-
|
|
3612
|
-
|
|
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 {
|
|
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-
|
|
6227
|
+
//# sourceMappingURL=document-DYH7tGnw.mjs.map
|