@office-open/docx 0.9.3 → 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-DeKZoZem.mjs → context-CSBntKXD.mjs} +694 -1114
- package/dist/context-CSBntKXD.mjs.map +1 -0
- package/dist/{core-properties-D9dBbZtc.d.mts → core-properties-BMagGcpC.d.mts} +462 -423
- package/dist/core-properties-BMagGcpC.d.mts.map +1 -0
- package/dist/{document-D8HDkCHs.mjs → document-DYH7tGnw.mjs} +2259 -830
- package/dist/document-DYH7tGnw.mjs.map +1 -0
- package/dist/{generate-DjkvEWjY.mjs → generate-BVfOLdwW.mjs} +4 -4
- package/dist/generate-BVfOLdwW.mjs.map +1 -0
- package/dist/generate.d.mts +1 -1
- package/dist/generate.mjs +1 -1
- package/dist/index.d.mts +13 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +5 -34
- package/dist/index.mjs.map +1 -1
- package/dist/{parse-CR5VbXbs.mjs → parse-Db2NGghB.mjs} +17 -29
- 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-DeKZoZem.mjs.map +0 -1
- package/dist/core-properties-D9dBbZtc.d.mts.map +0 -1
- package/dist/document-D8HDkCHs.mjs.map +0 -1
- package/dist/generate-DjkvEWjY.mjs.map +0 -1
- package/dist/parse-CR5VbXbs.mjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { TargetModeType, 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";
|
|
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, 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,213 +632,1495 @@ const WidthType = {
|
|
|
632
632
|
PERCENTAGE: "pct"
|
|
633
633
|
};
|
|
634
634
|
//#endregion
|
|
635
|
-
//#region src/parts/
|
|
635
|
+
//#region src/parts/paragraph/run/run-parse.ts
|
|
636
636
|
/**
|
|
637
|
-
*
|
|
637
|
+
* Run properties parser for DOCX documents.
|
|
638
638
|
*
|
|
639
|
-
*
|
|
639
|
+
* Parses w:rPr Element trees into RunPropertiesOptions objects.
|
|
640
640
|
*
|
|
641
|
-
* @
|
|
641
|
+
* @module
|
|
642
642
|
*/
|
|
643
|
-
const TextWrappingType = {
|
|
644
|
-
NONE: 0,
|
|
645
|
-
SQUARE: 1,
|
|
646
|
-
TIGHT: 2,
|
|
647
|
-
TOP_AND_BOTTOM: 3,
|
|
648
|
-
THROUGH: 4
|
|
649
|
-
};
|
|
650
643
|
/**
|
|
651
|
-
*
|
|
652
|
-
*
|
|
653
|
-
* Specifies on which side(s) text can wrap around the drawing.
|
|
654
|
-
*
|
|
655
|
-
* Reference: http://officeopenxml.com/drwPicFloating-textWrap.php
|
|
656
|
-
*
|
|
657
|
-
* @publicApi
|
|
644
|
+
* Parse a w:rPr element into RunPropertiesOptions.
|
|
658
645
|
*/
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
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
|
+
}
|
|
671
822
|
/**
|
|
672
|
-
*
|
|
673
|
-
*
|
|
674
|
-
* This module provides tight text wrapping for floating drawings
|
|
675
|
-
* where text wraps closely around the image shape.
|
|
676
|
-
*
|
|
677
|
-
* Reference: http://officeopenxml.com/drwPicFloating-textWrap.php
|
|
678
|
-
*
|
|
679
|
-
* @module
|
|
823
|
+
* Parse a w:bdr element into BorderOptions.
|
|
680
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
|
+
}
|
|
681
841
|
/**
|
|
682
|
-
*
|
|
683
|
-
*
|
|
684
|
-
* Reference: http://officeopenxml.com/drwPicFloating-textWrap.php
|
|
685
|
-
*
|
|
686
|
-
* ## XSD Schema
|
|
687
|
-
* ```xml
|
|
688
|
-
* <xsd:complexType name="CT_WrapPath">
|
|
689
|
-
* <xsd:sequence>
|
|
690
|
-
* <xsd:element name="start" type="a:CT_Point2D" minOccurs="1" maxOccurs="1"/>
|
|
691
|
-
* <xsd:element name="lineTo" type="a:CT_Point2D" minOccurs="2" maxOccurs="unbounded"/>
|
|
692
|
-
* </xsd:sequence>
|
|
693
|
-
* <xsd:attribute name="edited" type="xsd:boolean" use="optional"/>
|
|
694
|
-
* </xsd:complexType>
|
|
695
|
-
* ```
|
|
842
|
+
* Parse a w:shd element into ShadingAttributesProperties.
|
|
696
843
|
*/
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
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
|
+
}
|
|
704
854
|
/**
|
|
705
|
-
*
|
|
706
|
-
*
|
|
707
|
-
* WrapTight causes text to wrap closely around the contours
|
|
708
|
-
* of the drawing rather than its rectangular bounding box.
|
|
709
|
-
* A default rectangular wrap polygon matching the image extent is generated.
|
|
710
|
-
*
|
|
711
|
-
* Reference: http://officeopenxml.com/drwPicFloating-textWrap.php
|
|
712
|
-
*
|
|
713
|
-
* ## XSD Schema
|
|
714
|
-
* ```xml
|
|
715
|
-
* <xsd:complexType name="CT_WrapTight">
|
|
716
|
-
* <xsd:sequence>
|
|
717
|
-
* <xsd:element name="wrapPolygon" type="CT_WrapPath" minOccurs="1" maxOccurs="1"/>
|
|
718
|
-
* </xsd:sequence>
|
|
719
|
-
* <xsd:attribute name="wrapText" type="ST_WrapText" use="required"/>
|
|
720
|
-
* <xsd:attribute name="distL" type="ST_WrapDistance"/>
|
|
721
|
-
* <xsd:attribute name="distR" type="ST_WrapDistance"/>
|
|
722
|
-
* </xsd:complexType>
|
|
723
|
-
* ```
|
|
855
|
+
* Parse a w:eastAsianLayout element into EastAsianLayoutOptions.
|
|
724
856
|
*/
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
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");
|
|
737
909
|
/**
|
|
738
|
-
*
|
|
739
|
-
*
|
|
740
|
-
* This module provides "through" text wrapping for floating drawings
|
|
741
|
-
* where text wraps through the image contours, filling any concave areas.
|
|
742
|
-
*
|
|
743
|
-
* Reference: http://officeopenxml.com/drwPicFloating-textWrap.php
|
|
744
|
-
*
|
|
745
|
-
* @module
|
|
910
|
+
* Parse a w:r element into run data.
|
|
911
|
+
* Returns { properties, children } where children are parsed run content items.
|
|
746
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
|
+
}
|
|
747
1020
|
/**
|
|
748
|
-
*
|
|
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.
|
|
749
1025
|
*
|
|
750
|
-
*
|
|
751
|
-
*
|
|
752
|
-
* ## XSD Schema
|
|
753
|
-
* ```xml
|
|
754
|
-
* <xsd:complexType name="CT_WrapPath">
|
|
755
|
-
* <xsd:sequence>
|
|
756
|
-
* <xsd:element name="start" type="a:CT_Point2D" minOccurs="1" maxOccurs="1"/>
|
|
757
|
-
* <xsd:element name="lineTo" type="a:CT_Point2D" minOccurs="2" maxOccurs="unbounded"/>
|
|
758
|
-
* </xsd:sequence>
|
|
759
|
-
* <xsd:attribute name="edited" type="xsd:boolean" use="optional"/>
|
|
760
|
-
* </xsd:complexType>
|
|
761
|
-
* ```
|
|
1026
|
+
* When empty run elements (tab, noBreakHyphen, date fields, etc.) are present,
|
|
1027
|
+
* uses children[] format to preserve them for round-trip fidelity.
|
|
762
1028
|
*/
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
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 }]
|
|
769
1046
|
]);
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
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
|
+
}
|
|
801
1090
|
//#endregion
|
|
802
|
-
//#region src/
|
|
1091
|
+
//#region src/parts/paragraph/stringify.ts
|
|
803
1092
|
/**
|
|
804
|
-
*
|
|
1093
|
+
* Direct XML string builders for paragraph and run properties.
|
|
805
1094
|
*
|
|
806
|
-
*
|
|
807
|
-
*
|
|
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.
|
|
808
1098
|
*
|
|
809
1099
|
* @module
|
|
810
1100
|
*/
|
|
811
|
-
/**
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
const
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
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
|
|
1917
|
+
//#region src/parts/drawing/text-wrap/text-wrapping.ts
|
|
1918
|
+
/**
|
|
1919
|
+
* Enumeration of text wrapping types for floating drawings.
|
|
1920
|
+
*
|
|
1921
|
+
* Reference: http://officeopenxml.com/drwPicFloating-textWrap.php
|
|
1922
|
+
*
|
|
1923
|
+
* @publicApi
|
|
1924
|
+
*/
|
|
1925
|
+
const TextWrappingType = {
|
|
1926
|
+
NONE: 0,
|
|
1927
|
+
SQUARE: 1,
|
|
1928
|
+
TIGHT: 2,
|
|
1929
|
+
TOP_AND_BOTTOM: 3,
|
|
1930
|
+
THROUGH: 4
|
|
1931
|
+
};
|
|
1932
|
+
/**
|
|
1933
|
+
* Enumeration of text wrapping sides for floating drawings.
|
|
1934
|
+
*
|
|
1935
|
+
* Specifies on which side(s) text can wrap around the drawing.
|
|
1936
|
+
*
|
|
1937
|
+
* Reference: http://officeopenxml.com/drwPicFloating-textWrap.php
|
|
1938
|
+
*
|
|
1939
|
+
* @publicApi
|
|
1940
|
+
*/
|
|
1941
|
+
const TextWrappingSide = {
|
|
1942
|
+
/** Text wraps on both sides of the drawing */
|
|
1943
|
+
BOTH_SIDES: "bothSides",
|
|
1944
|
+
/** Text wraps only on the left side */
|
|
1945
|
+
LEFT: "left",
|
|
1946
|
+
/** Text wraps only on the right side */
|
|
1947
|
+
RIGHT: "right",
|
|
1948
|
+
/** Text wraps on the side with more space */
|
|
1949
|
+
LARGEST: "largest"
|
|
1950
|
+
};
|
|
1951
|
+
//#endregion
|
|
1952
|
+
//#region src/parts/drawing/text-wrap/wrap-tight.ts
|
|
1953
|
+
/**
|
|
1954
|
+
* Wrap Tight module for DrawingML text wrapping.
|
|
1955
|
+
*
|
|
1956
|
+
* This module provides tight text wrapping for floating drawings
|
|
1957
|
+
* where text wraps closely around the image shape.
|
|
1958
|
+
*
|
|
1959
|
+
* Reference: http://officeopenxml.com/drwPicFloating-textWrap.php
|
|
1960
|
+
*
|
|
1961
|
+
* @module
|
|
1962
|
+
*/
|
|
1963
|
+
/**
|
|
1964
|
+
* Creates a default rectangular wrap polygon matching the image extent.
|
|
1965
|
+
*
|
|
1966
|
+
* Reference: http://officeopenxml.com/drwPicFloating-textWrap.php
|
|
1967
|
+
*
|
|
1968
|
+
* ## XSD Schema
|
|
1969
|
+
* ```xml
|
|
1970
|
+
* <xsd:complexType name="CT_WrapPath">
|
|
1971
|
+
* <xsd:sequence>
|
|
1972
|
+
* <xsd:element name="start" type="a:CT_Point2D" minOccurs="1" maxOccurs="1"/>
|
|
1973
|
+
* <xsd:element name="lineTo" type="a:CT_Point2D" minOccurs="2" maxOccurs="unbounded"/>
|
|
1974
|
+
* </xsd:sequence>
|
|
1975
|
+
* <xsd:attribute name="edited" type="xsd:boolean" use="optional"/>
|
|
1976
|
+
* </xsd:complexType>
|
|
1977
|
+
* ```
|
|
1978
|
+
*/
|
|
1979
|
+
const createWrapPolygon$1 = (cx, cy) => element("wp:wrapPolygon", { edited: "0" }, [
|
|
1980
|
+
`<wp:start x="0" y="0"/>`,
|
|
1981
|
+
`<wp:lineTo x="0" y="${-cy}"/>`,
|
|
1982
|
+
`<wp:lineTo x="${cx}" y="${-cy}"/>`,
|
|
1983
|
+
`<wp:lineTo x="${cx}" y="0"/>`,
|
|
1984
|
+
`<wp:lineTo x="0" y="0"/>`
|
|
1985
|
+
]);
|
|
1986
|
+
/**
|
|
1987
|
+
* Creates tight text wrapping for a floating drawing.
|
|
1988
|
+
*
|
|
1989
|
+
* WrapTight causes text to wrap closely around the contours
|
|
1990
|
+
* of the drawing rather than its rectangular bounding box.
|
|
1991
|
+
* A default rectangular wrap polygon matching the image extent is generated.
|
|
1992
|
+
*
|
|
1993
|
+
* Reference: http://officeopenxml.com/drwPicFloating-textWrap.php
|
|
1994
|
+
*
|
|
1995
|
+
* ## XSD Schema
|
|
1996
|
+
* ```xml
|
|
1997
|
+
* <xsd:complexType name="CT_WrapTight">
|
|
1998
|
+
* <xsd:sequence>
|
|
1999
|
+
* <xsd:element name="wrapPolygon" type="CT_WrapPath" minOccurs="1" maxOccurs="1"/>
|
|
2000
|
+
* </xsd:sequence>
|
|
2001
|
+
* <xsd:attribute name="wrapText" type="ST_WrapText" use="required"/>
|
|
2002
|
+
* <xsd:attribute name="distL" type="ST_WrapDistance"/>
|
|
2003
|
+
* <xsd:attribute name="distR" type="ST_WrapDistance"/>
|
|
2004
|
+
* </xsd:complexType>
|
|
2005
|
+
* ```
|
|
2006
|
+
*/
|
|
2007
|
+
const createWrapTight = (textWrapping, margins = {
|
|
2008
|
+
bottom: 0,
|
|
2009
|
+
left: 0,
|
|
2010
|
+
right: 0,
|
|
2011
|
+
top: 0
|
|
2012
|
+
}, extent) => element("wp:wrapTight", {
|
|
2013
|
+
distL: margins.left,
|
|
2014
|
+
distR: margins.right,
|
|
2015
|
+
wrapText: textWrapping.side || TextWrappingSide.BOTH_SIDES
|
|
2016
|
+
}, [createWrapPolygon$1(extent.x, extent.y)]);
|
|
2017
|
+
//#endregion
|
|
2018
|
+
//#region src/parts/drawing/text-wrap/wrap-through.ts
|
|
2019
|
+
/**
|
|
2020
|
+
* Wrap Through module for DrawingML text wrapping.
|
|
2021
|
+
*
|
|
2022
|
+
* This module provides "through" text wrapping for floating drawings
|
|
2023
|
+
* where text wraps through the image contours, filling any concave areas.
|
|
2024
|
+
*
|
|
2025
|
+
* Reference: http://officeopenxml.com/drwPicFloating-textWrap.php
|
|
2026
|
+
*
|
|
2027
|
+
* @module
|
|
2028
|
+
*/
|
|
2029
|
+
/**
|
|
2030
|
+
* Creates a default rectangular wrap polygon matching the image extent.
|
|
2031
|
+
*
|
|
2032
|
+
* Reference: http://officeopenxml.com/drwPicFloating-textWrap.php
|
|
2033
|
+
*
|
|
2034
|
+
* ## XSD Schema
|
|
2035
|
+
* ```xml
|
|
2036
|
+
* <xsd:complexType name="CT_WrapPath">
|
|
2037
|
+
* <xsd:sequence>
|
|
2038
|
+
* <xsd:element name="start" type="a:CT_Point2D" minOccurs="1" maxOccurs="1"/>
|
|
2039
|
+
* <xsd:element name="lineTo" type="a:CT_Point2D" minOccurs="2" maxOccurs="unbounded"/>
|
|
2040
|
+
* </xsd:sequence>
|
|
2041
|
+
* <xsd:attribute name="edited" type="xsd:boolean" use="optional"/>
|
|
2042
|
+
* </xsd:complexType>
|
|
2043
|
+
* ```
|
|
2044
|
+
*/
|
|
2045
|
+
const createWrapPolygon = (cx, cy) => element("wp:wrapPolygon", { edited: "0" }, [
|
|
2046
|
+
`<wp:start x="0" y="0"/>`,
|
|
2047
|
+
`<wp:lineTo x="0" y="${-cy}"/>`,
|
|
2048
|
+
`<wp:lineTo x="${cx}" y="${-cy}"/>`,
|
|
2049
|
+
`<wp:lineTo x="${cx}" y="0"/>`,
|
|
2050
|
+
`<wp:lineTo x="0" y="0"/>`
|
|
2051
|
+
]);
|
|
2052
|
+
/**
|
|
2053
|
+
* Creates "through" text wrapping for a floating drawing.
|
|
2054
|
+
*
|
|
2055
|
+
* WrapThrough is similar to WrapTight but allows text to wrap through
|
|
2056
|
+
* the concave portions of the drawing shape (e.g., the inside of the letter "O").
|
|
2057
|
+
* A default rectangular wrap polygon matching the image extent is generated.
|
|
2058
|
+
*
|
|
2059
|
+
* Reference: http://officeopenxml.com/drwPicFloating-textWrap.php
|
|
2060
|
+
*
|
|
2061
|
+
* ## XSD Schema
|
|
2062
|
+
* ```xml
|
|
2063
|
+
* <xsd:complexType name="CT_WrapThrough">
|
|
2064
|
+
* <xsd:sequence>
|
|
2065
|
+
* <xsd:element name="wrapPolygon" type="CT_WrapPath" minOccurs="1" maxOccurs="1"/>
|
|
2066
|
+
* </xsd:sequence>
|
|
2067
|
+
* <xsd:attribute name="wrapText" type="ST_WrapText" use="required"/>
|
|
2068
|
+
* <xsd:attribute name="distL" type="ST_WrapDistance"/>
|
|
2069
|
+
* <xsd:attribute name="distR" type="ST_WrapDistance"/>
|
|
2070
|
+
* </xsd:complexType>
|
|
2071
|
+
* ```
|
|
2072
|
+
*/
|
|
2073
|
+
const createWrapThrough = (textWrapping, margins = {
|
|
2074
|
+
bottom: 0,
|
|
2075
|
+
left: 0,
|
|
2076
|
+
right: 0,
|
|
2077
|
+
top: 0
|
|
2078
|
+
}, extent) => element("wp:wrapThrough", {
|
|
2079
|
+
distL: margins.left,
|
|
2080
|
+
distR: margins.right,
|
|
2081
|
+
wrapText: textWrapping.side || TextWrappingSide.BOTH_SIDES
|
|
2082
|
+
}, [createWrapPolygon(extent.x, extent.y)]);
|
|
2083
|
+
//#endregion
|
|
2084
|
+
//#region src/shared/constants.ts
|
|
2085
|
+
/**
|
|
2086
|
+
* Shared constants for WordprocessingML documents.
|
|
2087
|
+
*
|
|
2088
|
+
* Provides alignment, number format, and space type constants
|
|
2089
|
+
* used across multiple document components.
|
|
2090
|
+
*
|
|
2091
|
+
* @module
|
|
2092
|
+
*/
|
|
2093
|
+
/**
|
|
2094
|
+
* Horizontal alignment options for floating drawings.
|
|
2095
|
+
*
|
|
2096
|
+
* Reference: https://www.datypic.com/sc/ooxml/t-wp_ST_AlignH.html
|
|
2097
|
+
*
|
|
2098
|
+
* @publicApi
|
|
2099
|
+
*/
|
|
2100
|
+
const HorizontalPositionAlign = {
|
|
2101
|
+
CENTER: "center",
|
|
2102
|
+
INSIDE: "inside",
|
|
2103
|
+
LEFT: "left",
|
|
2104
|
+
OUTSIDE: "outside",
|
|
2105
|
+
RIGHT: "right"
|
|
2106
|
+
};
|
|
2107
|
+
/**
|
|
2108
|
+
* Vertical alignment options for floating drawings.
|
|
2109
|
+
*
|
|
2110
|
+
* Reference: https://www.datypic.com/sc/ooxml/t-wp_ST_AlignV.html
|
|
2111
|
+
*
|
|
2112
|
+
* @publicApi
|
|
2113
|
+
*/
|
|
2114
|
+
const VerticalPositionAlign = {
|
|
2115
|
+
BOTTOM: "bottom",
|
|
2116
|
+
CENTER: "center",
|
|
2117
|
+
INSIDE: "inside",
|
|
2118
|
+
OUTSIDE: "outside",
|
|
2119
|
+
TOP: "top"
|
|
2120
|
+
};
|
|
2121
|
+
/**
|
|
2122
|
+
* Number format types for page numbers and list numbering.
|
|
2123
|
+
*
|
|
842
2124
|
* Reference: http://officeopenxml.com/WPnumbering-numFmt.php
|
|
843
2125
|
*
|
|
844
2126
|
* @publicApi
|
|
@@ -1259,40 +2541,76 @@ function parseImageRun(el, ctx) {
|
|
|
1259
2541
|
}
|
|
1260
2542
|
if (anchor && !inline) {
|
|
1261
2543
|
const floating = {};
|
|
2544
|
+
const margins = {};
|
|
2545
|
+
const distT = attrNum(anchor, "distT");
|
|
2546
|
+
if (distT !== void 0) margins.top = distT;
|
|
2547
|
+
const distB = attrNum(anchor, "distB");
|
|
2548
|
+
if (distB !== void 0) margins.bottom = distB;
|
|
2549
|
+
const distL = attrNum(anchor, "distL");
|
|
2550
|
+
if (distL !== void 0) margins.left = distL;
|
|
2551
|
+
const distR = attrNum(anchor, "distR");
|
|
2552
|
+
if (distR !== void 0) margins.right = distR;
|
|
2553
|
+
if (Object.keys(margins).length > 0) floating.margins = margins;
|
|
1262
2554
|
const posH = findChild(anchor, "wp:positionH");
|
|
1263
2555
|
if (posH) {
|
|
1264
|
-
const
|
|
1265
|
-
|
|
1266
|
-
if (align) floating.horizontalPosition = { align: textOf(align) };
|
|
1267
|
-
else if (posOffset) {
|
|
1268
|
-
const val = Number(textOf(posOffset));
|
|
1269
|
-
if (!isNaN(val)) floating.horizontalPosition = { offset: val };
|
|
1270
|
-
}
|
|
2556
|
+
const hp = readPosition(posH);
|
|
2557
|
+
if (hp) floating.horizontalPosition = hp;
|
|
1271
2558
|
}
|
|
1272
2559
|
const posV = findChild(anchor, "wp:positionV");
|
|
1273
2560
|
if (posV) {
|
|
1274
|
-
const
|
|
1275
|
-
|
|
1276
|
-
if (align) floating.verticalPosition = { align: textOf(align) };
|
|
1277
|
-
else if (posOffset) {
|
|
1278
|
-
const val = Number(textOf(posOffset));
|
|
1279
|
-
if (!isNaN(val)) floating.verticalPosition = { offset: val };
|
|
1280
|
-
}
|
|
1281
|
-
}
|
|
1282
|
-
for (const wrapType of [
|
|
1283
|
-
"wrapSquare",
|
|
1284
|
-
"wrapTight",
|
|
1285
|
-
"wrapTopAndBottom",
|
|
1286
|
-
"wrapNone"
|
|
1287
|
-
]) if (findChild(anchor, `wp:${wrapType}`)) {
|
|
1288
|
-
floating.wrap = wrapType;
|
|
1289
|
-
break;
|
|
2561
|
+
const vp = readPosition(posV);
|
|
2562
|
+
if (vp) floating.verticalPosition = vp;
|
|
1290
2563
|
}
|
|
1291
|
-
|
|
2564
|
+
const wrap = readWrap(anchor);
|
|
2565
|
+
if (wrap) floating.wrap = wrap;
|
|
2566
|
+
const allowOverlap = attrBool(anchor, "allowOverlap");
|
|
2567
|
+
if (allowOverlap !== void 0) floating.allowOverlap = allowOverlap;
|
|
2568
|
+
const behindDoc = attrBool(anchor, "behindDoc");
|
|
2569
|
+
if (behindDoc !== void 0) floating.behindDocument = behindDoc;
|
|
2570
|
+
const locked = attrBool(anchor, "locked");
|
|
2571
|
+
if (locked !== void 0) floating.lockAnchor = locked;
|
|
2572
|
+
const layoutInCell = attrBool(anchor, "layoutInCell");
|
|
2573
|
+
if (layoutInCell !== void 0) floating.layoutInCell = layoutInCell;
|
|
2574
|
+
const relativeHeight = attrNum(anchor, "relativeHeight");
|
|
2575
|
+
if (relativeHeight !== void 0) floating.zIndex = relativeHeight;
|
|
1292
2576
|
if (Object.keys(floating).length > 0) imageOpts.floating = floating;
|
|
1293
2577
|
}
|
|
1294
2578
|
return { image: imageOpts };
|
|
1295
2579
|
}
|
|
2580
|
+
/** Map wp:positionH/V children + relativeFrom into a position-options object. */
|
|
2581
|
+
function readPosition(posEl) {
|
|
2582
|
+
const relative = attr(posEl, "relativeFrom");
|
|
2583
|
+
const alignEl = findChild(posEl, "wp:align");
|
|
2584
|
+
const posOffset = findChild(posEl, "wp:posOffset");
|
|
2585
|
+
const result = {};
|
|
2586
|
+
if (relative) result.relative = relative;
|
|
2587
|
+
if (alignEl) {
|
|
2588
|
+
const a = textOf(alignEl);
|
|
2589
|
+
if (a) result.align = a;
|
|
2590
|
+
} else if (posOffset) {
|
|
2591
|
+
const val = Number(textOf(posOffset));
|
|
2592
|
+
if (!isNaN(val)) result.offset = val;
|
|
2593
|
+
}
|
|
2594
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
2595
|
+
}
|
|
2596
|
+
/** Map the wp:anchor wrap child element into a TextWrapping ({ type, side? }). */
|
|
2597
|
+
function readWrap(anchor) {
|
|
2598
|
+
const WRAP_TYPE = [
|
|
2599
|
+
["wrapNone", TextWrappingType.NONE],
|
|
2600
|
+
["wrapSquare", TextWrappingType.SQUARE],
|
|
2601
|
+
["wrapTight", TextWrappingType.TIGHT],
|
|
2602
|
+
["wrapTopAndBottom", TextWrappingType.TOP_AND_BOTTOM],
|
|
2603
|
+
["wrapThrough", TextWrappingType.THROUGH]
|
|
2604
|
+
];
|
|
2605
|
+
for (const [name, type] of WRAP_TYPE) {
|
|
2606
|
+
const el = findChild(anchor, `wp:${name}`);
|
|
2607
|
+
if (!el) continue;
|
|
2608
|
+
const wrap = { type };
|
|
2609
|
+
const side = attr(el, "wrapText");
|
|
2610
|
+
if (side) wrap.side = side;
|
|
2611
|
+
return wrap;
|
|
2612
|
+
}
|
|
2613
|
+
}
|
|
1296
2614
|
function getDrawingExtent(el) {
|
|
1297
2615
|
const inline = findDeep(el, "wp:inline")[0];
|
|
1298
2616
|
const anchor = inline ? void 0 : findDeep(el, "wp:anchor")[0];
|
|
@@ -2149,577 +3467,200 @@ function parseMathFraction(el) {
|
|
|
2149
3467
|
denominator: parseMathArg(el, "m:den")
|
|
2150
3468
|
} };
|
|
2151
3469
|
}
|
|
2152
|
-
function parseMathRadical(el) {
|
|
2153
|
-
const degree = parseMathArg(el, "m:deg");
|
|
2154
|
-
return { radical: {
|
|
2155
|
-
children: parseMathArg(el, "m:e"),
|
|
2156
|
-
...degree.length > 0 ? { degree } : {}
|
|
2157
|
-
} };
|
|
2158
|
-
}
|
|
2159
|
-
function parseMathSuperScript(el) {
|
|
2160
|
-
return { superScript: {
|
|
2161
|
-
children: parseMathArg(el, "m:e"),
|
|
2162
|
-
superScript: parseMathArg(el, "m:sup")
|
|
2163
|
-
} };
|
|
2164
|
-
}
|
|
2165
|
-
function parseMathSubScript(el) {
|
|
2166
|
-
return { subScript: {
|
|
2167
|
-
children: parseMathArg(el, "m:e"),
|
|
2168
|
-
subScript: parseMathArg(el, "m:sub")
|
|
2169
|
-
} };
|
|
2170
|
-
}
|
|
2171
|
-
function parseMathSubSuperScript(el) {
|
|
2172
|
-
return { subSuperScript: {
|
|
2173
|
-
children: parseMathArg(el, "m:e"),
|
|
2174
|
-
subScript: parseMathArg(el, "m:sub"),
|
|
2175
|
-
superScript: parseMathArg(el, "m:sup")
|
|
2176
|
-
} };
|
|
2177
|
-
}
|
|
2178
|
-
function parseMathNAry(el) {
|
|
2179
|
-
const naryPr = findChild(el, "m:naryPr");
|
|
2180
|
-
const chrEl = naryPr ? findChild(naryPr, "m:chr") : void 0;
|
|
2181
|
-
const chrVal = chrEl ? attr(chrEl, "m:val") : void 0;
|
|
2182
|
-
const baseChildren = parseMathArg(el, "m:e");
|
|
2183
|
-
const sub = parseMathArg(el, "m:sub");
|
|
2184
|
-
const sup = parseMathArg(el, "m:sup");
|
|
2185
|
-
const common = {
|
|
2186
|
-
children: baseChildren,
|
|
2187
|
-
...sub.length > 0 ? { subScript: sub } : {},
|
|
2188
|
-
...sup.length > 0 ? { superScript: sup } : {}
|
|
2189
|
-
};
|
|
2190
|
-
if (chrVal === "∑") return { sum: common };
|
|
2191
|
-
return { integral: common };
|
|
2192
|
-
}
|
|
2193
|
-
function parseMathFunction(el) {
|
|
2194
|
-
return { function: {
|
|
2195
|
-
name: parseMathArg(el, "m:fName"),
|
|
2196
|
-
children: parseMathArg(el, "m:e")
|
|
2197
|
-
} };
|
|
2198
|
-
}
|
|
2199
|
-
function parseMathDelimiter(el) {
|
|
2200
|
-
const dPr = findChild(el, "m:dPr");
|
|
2201
|
-
const begChrEl = dPr ? findChild(dPr, "m:begChr") : void 0;
|
|
2202
|
-
const begChr = begChrEl ? attr(begChrEl, "m:val") : "(";
|
|
2203
|
-
const mathChildren = parseMathArg(el, "m:e");
|
|
2204
|
-
switch (begChr) {
|
|
2205
|
-
case "[": return { squareBrackets: mathChildren };
|
|
2206
|
-
case "{": return { curlyBrackets: mathChildren };
|
|
2207
|
-
case "<":
|
|
2208
|
-
case "⟨": return { angledBrackets: mathChildren };
|
|
2209
|
-
default: return { roundBrackets: mathChildren };
|
|
2210
|
-
}
|
|
2211
|
-
}
|
|
2212
|
-
function parseMathMatrix(el) {
|
|
2213
|
-
const rows = [];
|
|
2214
|
-
for (const mr of children(el, "m:mr")) rows.push(parseMathArg(mr, "m:e"));
|
|
2215
|
-
return { matrix: { rows } };
|
|
2216
|
-
}
|
|
2217
|
-
function parseMathAccent(el) {
|
|
2218
|
-
const accPr = findChild(el, "m:accPr");
|
|
2219
|
-
const chrEl = accPr ? findChild(accPr, "m:chr") : void 0;
|
|
2220
|
-
const accentChar = chrEl ? attr(chrEl, "m:val") : void 0;
|
|
2221
|
-
return { accent: {
|
|
3470
|
+
function parseMathRadical(el) {
|
|
3471
|
+
const degree = parseMathArg(el, "m:deg");
|
|
3472
|
+
return { radical: {
|
|
2222
3473
|
children: parseMathArg(el, "m:e"),
|
|
2223
|
-
...
|
|
3474
|
+
...degree.length > 0 ? { degree } : {}
|
|
2224
3475
|
} };
|
|
2225
3476
|
}
|
|
2226
|
-
function
|
|
2227
|
-
|
|
2228
|
-
const posEl = barPr ? findChild(barPr, "m:pos") : void 0;
|
|
2229
|
-
const pos = posEl ? attr(posEl, "m:val") : "top";
|
|
2230
|
-
return { bar: {
|
|
3477
|
+
function parseMathSuperScript(el) {
|
|
3478
|
+
return { superScript: {
|
|
2231
3479
|
children: parseMathArg(el, "m:e"),
|
|
2232
|
-
|
|
3480
|
+
superScript: parseMathArg(el, "m:sup")
|
|
2233
3481
|
} };
|
|
2234
3482
|
}
|
|
2235
|
-
function
|
|
2236
|
-
|
|
2237
|
-
for (const e of children(el, "m:e")) rows.push(parseMathChildren(e));
|
|
2238
|
-
return { eqArr: { rows } };
|
|
2239
|
-
}
|
|
2240
|
-
function parseMathLimitLower(el) {
|
|
2241
|
-
return { limitLower: {
|
|
3483
|
+
function parseMathSubScript(el) {
|
|
3484
|
+
return { subScript: {
|
|
2242
3485
|
children: parseMathArg(el, "m:e"),
|
|
2243
|
-
|
|
3486
|
+
subScript: parseMathArg(el, "m:sub")
|
|
2244
3487
|
} };
|
|
2245
3488
|
}
|
|
2246
|
-
function
|
|
2247
|
-
return {
|
|
3489
|
+
function parseMathSubSuperScript(el) {
|
|
3490
|
+
return { subSuperScript: {
|
|
2248
3491
|
children: parseMathArg(el, "m:e"),
|
|
2249
|
-
|
|
3492
|
+
subScript: parseMathArg(el, "m:sub"),
|
|
3493
|
+
superScript: parseMathArg(el, "m:sup")
|
|
2250
3494
|
} };
|
|
2251
3495
|
}
|
|
2252
|
-
function
|
|
2253
|
-
const
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
* Reference: http://officeopenxml.com/WPrun.php
|
|
2267
|
-
*
|
|
2268
|
-
* @module
|
|
2269
|
-
*/
|
|
2270
|
-
/**
|
|
2271
|
-
* Field character types that delimit field regions.
|
|
2272
|
-
*
|
|
2273
|
-
* @internal
|
|
2274
|
-
*/
|
|
2275
|
-
const FieldCharacterType = {
|
|
2276
|
-
BEGIN: "begin",
|
|
2277
|
-
END: "end",
|
|
2278
|
-
SEPARATE: "separate"
|
|
2279
|
-
};
|
|
2280
|
-
/**
|
|
2281
|
-
* Creates a field character element.
|
|
2282
|
-
*
|
|
2283
|
-
* ## XSD Schema
|
|
2284
|
-
* ```xml
|
|
2285
|
-
* <xsd:complexType name="CT_FldChar">
|
|
2286
|
-
* <xsd:sequence>
|
|
2287
|
-
* <xsd:element name="fldData" type="CT_Text" minOccurs="0"/>
|
|
2288
|
-
* <xsd:element name="ffData" type="CT_FFData" minOccurs="0"/>
|
|
2289
|
-
* <xsd:element name="numberingChange" type="CT_TrackChangeNumbering" minOccurs="0"/>
|
|
2290
|
-
* </xsd:sequence>
|
|
2291
|
-
* <xsd:attribute name="fldCharType" type="ST_FldCharType" use="required"/>
|
|
2292
|
-
* <xsd:attribute name="fldLock" type="s:ST_OnOff"/>
|
|
2293
|
-
* <xsd:attribute name="dirty" type="s:ST_OnOff"/>
|
|
2294
|
-
* </xsd:complexType>
|
|
2295
|
-
* ```
|
|
2296
|
-
* @internal
|
|
2297
|
-
*/
|
|
2298
|
-
const createFieldChar = (type, dirty, ffData, fldData, fieldLock) => {
|
|
2299
|
-
const children = [];
|
|
2300
|
-
if (fldData !== void 0) children.push(element("w:fldData", { "xml:space": "preserve" }, [fldData]));
|
|
2301
|
-
if (ffData) children.push(ffData);
|
|
2302
|
-
return element("w:fldChar", {
|
|
2303
|
-
"w:dirty": dirty,
|
|
2304
|
-
"w:fldLock": fieldLock,
|
|
2305
|
-
"w:fldCharType": type
|
|
2306
|
-
}, children.length > 0 ? children : void 0);
|
|
2307
|
-
};
|
|
2308
|
-
/**
|
|
2309
|
-
* Creates the beginning of a complex field.
|
|
2310
|
-
*
|
|
2311
|
-
* The Begin element marks the start of a field. A field consists of a begin character,
|
|
2312
|
-
* field instructions, an optional separate character, field result, and an end character.
|
|
2313
|
-
*
|
|
2314
|
-
* For form fields, pass `formField` to embed `w:ffData` within the begin `w:fldChar`.
|
|
2315
|
-
*
|
|
2316
|
-
* @param dirty - Whether the field should be recalculated
|
|
2317
|
-
* @param formField - Optional form field data to embed in the begin character
|
|
2318
|
-
*
|
|
2319
|
-
* @example
|
|
2320
|
-
* ```typescript
|
|
2321
|
-
* // Simple field begin
|
|
2322
|
-
* createBegin();
|
|
2323
|
-
*
|
|
2324
|
-
* // Form field (checkbox)
|
|
2325
|
-
* createBegin(false, {
|
|
2326
|
-
* name: "Check1",
|
|
2327
|
-
* checkBox: { checked: true, sizeAuto: true },
|
|
2328
|
-
* });
|
|
2329
|
-
* ```
|
|
2330
|
-
*/
|
|
2331
|
-
const createBegin = (dirty, formField, fieldLock) => createFieldChar(FieldCharacterType.BEGIN, dirty, formField ? createFormFieldData(formField) : void 0, void 0, fieldLock);
|
|
2332
|
-
/**
|
|
2333
|
-
* Creates the separator between field code and field result in a complex field.
|
|
2334
|
-
*
|
|
2335
|
-
* The Separate element divides the field code (instructions) from the field result
|
|
2336
|
-
* (the computed value).
|
|
2337
|
-
*/
|
|
2338
|
-
const createSeparate = (dirty) => createFieldChar(FieldCharacterType.SEPARATE, dirty);
|
|
2339
|
-
/**
|
|
2340
|
-
* Creates the end of a complex field.
|
|
2341
|
-
*
|
|
2342
|
-
* The End element marks the end of a field. Every field that begins with a Begin
|
|
2343
|
-
* element must be terminated with an End element.
|
|
2344
|
-
*/
|
|
2345
|
-
const createEnd = (dirty) => createFieldChar(FieldCharacterType.END, dirty);
|
|
2346
|
-
//#endregion
|
|
2347
|
-
//#region src/parts/paragraph/stringify.ts
|
|
2348
|
-
/**
|
|
2349
|
-
* Direct XML string builders for paragraph and run properties.
|
|
2350
|
-
*
|
|
2351
|
-
* Replaces `buildParagraphProperties() + xml()` and `buildRunProperties() + xml()`
|
|
2352
|
-
* with direct string concatenation — zero intermediate IXmlableObject allocation,
|
|
2353
|
-
* zero recursive xml() traversal. Follows PPTX/XLSX pattern.
|
|
2354
|
-
*
|
|
2355
|
-
* @module
|
|
2356
|
-
*/
|
|
2357
|
-
/** On/off: `<w:name/>` for true, `<w:name w:val="0"/>` for false */
|
|
2358
|
-
function onOff(name, val) {
|
|
2359
|
-
return val ? `<${name}/>` : `<${name} w:val="0"/>`;
|
|
2360
|
-
}
|
|
2361
|
-
/** Build attrs string from key-value pairs, skipping undefined */
|
|
2362
|
-
function attrParts(attrs) {
|
|
2363
|
-
const parts = [];
|
|
2364
|
-
for (const [key, val] of Object.entries(attrs)) if (val !== void 0) parts.push(`${key}="${val}"`);
|
|
2365
|
-
return parts.join(" ");
|
|
2366
|
-
}
|
|
2367
|
-
function borderStr(name, opts) {
|
|
2368
|
-
return `<${name} ${attrParts({
|
|
2369
|
-
"w:val": opts.style,
|
|
2370
|
-
"w:color": opts.color !== void 0 ? hexColorValue(opts.color) : void 0,
|
|
2371
|
-
"w:sz": opts.size !== void 0 ? eighthPointMeasureValue(opts.size) : void 0,
|
|
2372
|
-
"w:space": opts.space !== void 0 ? pointMeasureValue(opts.space) : void 0,
|
|
2373
|
-
"w:themeColor": opts.themeColor,
|
|
2374
|
-
"w:themeTint": opts.themeTint !== void 0 ? uCharHexNumber(opts.themeTint) : void 0,
|
|
2375
|
-
"w:themeShade": opts.themeShade !== void 0 ? uCharHexNumber(opts.themeShade) : void 0,
|
|
2376
|
-
"w:shadow": opts.shadow !== void 0 ? opts.shadow ? 1 : 0 : void 0,
|
|
2377
|
-
"w:frame": opts.frame !== void 0 ? opts.frame ? 1 : 0 : void 0
|
|
2378
|
-
})}/>`;
|
|
2379
|
-
}
|
|
2380
|
-
function shadingStr(opts) {
|
|
2381
|
-
return `<w:shd ${attrParts({
|
|
2382
|
-
"w:val": opts.type ?? "clear",
|
|
2383
|
-
"w:color": opts.color !== void 0 ? hexColorValue(opts.color) : void 0,
|
|
2384
|
-
"w:fill": opts.fill !== void 0 ? hexColorValue(opts.fill) : void 0,
|
|
2385
|
-
"w:themeColor": opts.themeColor,
|
|
2386
|
-
"w:themeTint": opts.themeTint !== void 0 ? uCharHexNumber(opts.themeTint) : void 0,
|
|
2387
|
-
"w:themeShade": opts.themeShade !== void 0 ? uCharHexNumber(opts.themeShade) : void 0,
|
|
2388
|
-
"w:themeFill": opts.themeFill,
|
|
2389
|
-
"w:themeFillTint": opts.themeFillTint !== void 0 ? uCharHexNumber(opts.themeFillTint) : void 0,
|
|
2390
|
-
"w:themeFillShade": opts.themeFillShade !== void 0 ? uCharHexNumber(opts.themeFillShade) : void 0
|
|
2391
|
-
})}/>`;
|
|
2392
|
-
}
|
|
2393
|
-
function spacingStr(opts) {
|
|
2394
|
-
return `<w:spacing ${attrParts({
|
|
2395
|
-
"w:after": opts.after,
|
|
2396
|
-
"w:afterAutospacing": opts.afterAutoSpacing !== void 0 ? opts.afterAutoSpacing ? 1 : 0 : void 0,
|
|
2397
|
-
"w:afterLines": opts.afterLines !== void 0 ? decimalNumber(opts.afterLines) : void 0,
|
|
2398
|
-
"w:before": opts.before,
|
|
2399
|
-
"w:beforeAutospacing": opts.beforeAutoSpacing !== void 0 ? opts.beforeAutoSpacing ? 1 : 0 : void 0,
|
|
2400
|
-
"w:beforeLines": opts.beforeLines !== void 0 ? decimalNumber(opts.beforeLines) : void 0,
|
|
2401
|
-
"w:line": opts.line,
|
|
2402
|
-
"w:lineRule": opts.lineRule
|
|
2403
|
-
})}/>`;
|
|
2404
|
-
}
|
|
2405
|
-
function indentStr(opts) {
|
|
2406
|
-
return `<w:ind ${attrParts({
|
|
2407
|
-
"w:start": opts.start !== void 0 ? signedTwipsMeasureValue(opts.start) : void 0,
|
|
2408
|
-
"w:startChars": opts.startChars !== void 0 ? decimalNumber(opts.startChars) : void 0,
|
|
2409
|
-
"w:end": opts.end !== void 0 ? signedTwipsMeasureValue(opts.end) : void 0,
|
|
2410
|
-
"w:endChars": opts.endChars !== void 0 ? decimalNumber(opts.endChars) : void 0,
|
|
2411
|
-
"w:left": opts.left !== void 0 ? signedTwipsMeasureValue(opts.left) : void 0,
|
|
2412
|
-
"w:leftChars": opts.leftChars !== void 0 ? decimalNumber(opts.leftChars) : void 0,
|
|
2413
|
-
"w:right": opts.right !== void 0 ? signedTwipsMeasureValue(opts.right) : void 0,
|
|
2414
|
-
"w:rightChars": opts.rightChars !== void 0 ? decimalNumber(opts.rightChars) : void 0,
|
|
2415
|
-
"w:hanging": opts.hanging !== void 0 ? twipsMeasureValue(opts.hanging) : void 0,
|
|
2416
|
-
"w:hangingChars": opts.hangingChars !== void 0 ? decimalNumber(opts.hangingChars) : void 0,
|
|
2417
|
-
"w:firstLine": opts.firstLine !== void 0 ? twipsMeasureValue(opts.firstLine) : void 0,
|
|
2418
|
-
"w:firstLineChars": opts.firstLineChars !== void 0 ? decimalNumber(opts.firstLineChars) : void 0
|
|
2419
|
-
})}/>`;
|
|
2420
|
-
}
|
|
2421
|
-
function tabStopsStr(defs) {
|
|
2422
|
-
return `<w:tabs>${defs.map(({ type, position, leader }) => {
|
|
2423
|
-
return `<w:tab ${attrParts({
|
|
2424
|
-
"w:val": type,
|
|
2425
|
-
"w:pos": position,
|
|
2426
|
-
"w:leader": leader
|
|
2427
|
-
})}/>`;
|
|
2428
|
-
}).join("")}</w:tabs>`;
|
|
2429
|
-
}
|
|
2430
|
-
function cnfStyleStr(opts) {
|
|
2431
|
-
return `<w:cnfStyle ${attrParts({
|
|
2432
|
-
"w:firstRow": opts.firstRow ? "1" : "0",
|
|
2433
|
-
"w:lastRow": opts.lastRow ? "1" : "0",
|
|
2434
|
-
"w:firstColumn": opts.firstColumn ? "1" : "0",
|
|
2435
|
-
"w:lastColumn": opts.lastColumn ? "1" : "0",
|
|
2436
|
-
"w:oddVBand": opts.oddVBand ? "1" : "0",
|
|
2437
|
-
"w:evenVBand": opts.evenVBand ? "1" : "0",
|
|
2438
|
-
"w:oddHBand": opts.oddHBand ? "1" : "0",
|
|
2439
|
-
"w:evenHBand": opts.evenHBand ? "1" : "0",
|
|
2440
|
-
"w:firstRowFirstColumn": opts.firstRowFirstColumn ? "1" : "0",
|
|
2441
|
-
"w:firstRowLastColumn": opts.firstRowLastColumn ? "1" : "0",
|
|
2442
|
-
"w:lastRowFirstColumn": opts.lastRowFirstColumn ? "1" : "0",
|
|
2443
|
-
"w:lastRowLastColumn": opts.lastRowLastColumn ? "1" : "0"
|
|
2444
|
-
})}/>`;
|
|
2445
|
-
}
|
|
2446
|
-
function framePrStr(opts) {
|
|
2447
|
-
const alignment = opts.alignment;
|
|
2448
|
-
const position = opts.position;
|
|
2449
|
-
return `<w:framePr ${attrParts({
|
|
2450
|
-
"w:xAlign": alignment?.x,
|
|
2451
|
-
"w:yAlign": alignment?.y,
|
|
2452
|
-
"w:hAnchor": opts.anchor?.horizontal,
|
|
2453
|
-
"w:anchorLock": opts.anchorLock,
|
|
2454
|
-
"w:vAnchor": opts.anchor?.vertical,
|
|
2455
|
-
"w:dropCap": opts.dropCap,
|
|
2456
|
-
"w:h": opts.height,
|
|
2457
|
-
"w:lines": opts.lines,
|
|
2458
|
-
"w:hRule": opts.rule,
|
|
2459
|
-
"w:hSpace": opts.space?.horizontal,
|
|
2460
|
-
"w:vSpace": opts.space?.vertical,
|
|
2461
|
-
"w:w": opts.width,
|
|
2462
|
-
"w:wrap": opts.wrap,
|
|
2463
|
-
"w:x": position?.x,
|
|
2464
|
-
"w:y": position?.y
|
|
2465
|
-
})}/>`;
|
|
3496
|
+
function parseMathNAry(el) {
|
|
3497
|
+
const naryPr = findChild(el, "m:naryPr");
|
|
3498
|
+
const chrEl = naryPr ? findChild(naryPr, "m:chr") : void 0;
|
|
3499
|
+
const chrVal = chrEl ? attr(chrEl, "m:val") : void 0;
|
|
3500
|
+
const baseChildren = parseMathArg(el, "m:e");
|
|
3501
|
+
const sub = parseMathArg(el, "m:sub");
|
|
3502
|
+
const sup = parseMathArg(el, "m:sup");
|
|
3503
|
+
const common = {
|
|
3504
|
+
children: baseChildren,
|
|
3505
|
+
...sub.length > 0 ? { subScript: sub } : {},
|
|
3506
|
+
...sup.length > 0 ? { superScript: sup } : {}
|
|
3507
|
+
};
|
|
3508
|
+
if (chrVal === "∑") return { sum: common };
|
|
3509
|
+
return { integral: common };
|
|
2466
3510
|
}
|
|
2467
|
-
function
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
3511
|
+
function parseMathFunction(el) {
|
|
3512
|
+
return { function: {
|
|
3513
|
+
name: parseMathArg(el, "m:fName"),
|
|
3514
|
+
children: parseMathArg(el, "m:e")
|
|
3515
|
+
} };
|
|
3516
|
+
}
|
|
3517
|
+
function parseMathDelimiter(el) {
|
|
3518
|
+
const dPr = findChild(el, "m:dPr");
|
|
3519
|
+
const begChrEl = dPr ? findChild(dPr, "m:begChr") : void 0;
|
|
3520
|
+
const begChr = begChrEl ? attr(begChrEl, "m:val") : "(";
|
|
3521
|
+
const mathChildren = parseMathArg(el, "m:e");
|
|
3522
|
+
switch (begChr) {
|
|
3523
|
+
case "[": return { squareBrackets: mathChildren };
|
|
3524
|
+
case "{": return { curlyBrackets: mathChildren };
|
|
3525
|
+
case "<":
|
|
3526
|
+
case "⟨": return { angledBrackets: mathChildren };
|
|
3527
|
+
default: return { roundBrackets: mathChildren };
|
|
2478
3528
|
}
|
|
2479
|
-
return `<w:numPr>${parts.join("")}</w:numPr>`;
|
|
2480
3529
|
}
|
|
2481
|
-
function
|
|
2482
|
-
|
|
2483
|
-
const
|
|
2484
|
-
return
|
|
2485
|
-
"w:val": opts.val !== void 0 ? hexColorValue(opts.val) : void 0,
|
|
2486
|
-
"w:themeColor": opts.themeColor,
|
|
2487
|
-
"w:themeTint": opts.themeTint !== void 0 ? uCharHexNumber(opts.themeTint) : void 0,
|
|
2488
|
-
"w:themeShade": opts.themeShade !== void 0 ? uCharHexNumber(opts.themeShade) : void 0
|
|
2489
|
-
})}/>`;
|
|
3530
|
+
function parseMathMatrix(el) {
|
|
3531
|
+
const rows = [];
|
|
3532
|
+
for (const mr of children(el, "m:mr")) rows.push(parseMathArg(mr, "m:e"));
|
|
3533
|
+
return { matrix: { rows } };
|
|
2490
3534
|
}
|
|
2491
|
-
function
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
"
|
|
2497
|
-
|
|
2498
|
-
}
|
|
2499
|
-
const attrs = nameOrAttrs;
|
|
2500
|
-
return `<w:rFonts ${attrParts({
|
|
2501
|
-
"w:ascii": attrs.ascii,
|
|
2502
|
-
"w:asciiTheme": attrs.asciiTheme,
|
|
2503
|
-
"w:cs": attrs.cs,
|
|
2504
|
-
"w:cstheme": attrs.cstheme,
|
|
2505
|
-
"w:eastAsia": attrs.eastAsia,
|
|
2506
|
-
"w:eastAsiaTheme": attrs.eastAsiaTheme,
|
|
2507
|
-
"w:hAnsi": attrs.hAnsi,
|
|
2508
|
-
"w:hAnsiTheme": attrs.hAnsiTheme,
|
|
2509
|
-
"w:hint": attrs.hint
|
|
2510
|
-
})}/>`;
|
|
3535
|
+
function parseMathAccent(el) {
|
|
3536
|
+
const accPr = findChild(el, "m:accPr");
|
|
3537
|
+
const chrEl = accPr ? findChild(accPr, "m:chr") : void 0;
|
|
3538
|
+
const accentChar = chrEl ? attr(chrEl, "m:val") : void 0;
|
|
3539
|
+
return { accent: {
|
|
3540
|
+
children: parseMathArg(el, "m:e"),
|
|
3541
|
+
...accentChar ? { accentCharacter: accentChar } : {}
|
|
3542
|
+
} };
|
|
2511
3543
|
}
|
|
2512
|
-
function
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
3544
|
+
function parseMathBar(el) {
|
|
3545
|
+
const barPr = findChild(el, "m:barPr");
|
|
3546
|
+
const posEl = barPr ? findChild(barPr, "m:pos") : void 0;
|
|
3547
|
+
const pos = posEl ? attr(posEl, "m:val") : "top";
|
|
3548
|
+
return { bar: {
|
|
3549
|
+
children: parseMathArg(el, "m:e"),
|
|
3550
|
+
type: pos ?? "top"
|
|
3551
|
+
} };
|
|
2517
3552
|
}
|
|
2518
|
-
function
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
"w:combineBrackets": opts.combineBrackets,
|
|
2523
|
-
"w:vert": opts.vert !== void 0 ? opts.vert ? 1 : 0 : void 0,
|
|
2524
|
-
"w:vertCompress": opts.vertCompress !== void 0 ? opts.vertCompress ? 1 : 0 : void 0
|
|
2525
|
-
})}/>`;
|
|
3553
|
+
function parseMathEqArr(el) {
|
|
3554
|
+
const rows = [];
|
|
3555
|
+
for (const e of children(el, "m:e")) rows.push(parseMathChildren(e));
|
|
3556
|
+
return { eqArr: { rows } };
|
|
2526
3557
|
}
|
|
2527
|
-
function
|
|
2528
|
-
return
|
|
2529
|
-
"
|
|
2530
|
-
"
|
|
2531
|
-
|
|
2532
|
-
|
|
3558
|
+
function parseMathLimitLower(el) {
|
|
3559
|
+
return { limitLower: {
|
|
3560
|
+
children: parseMathArg(el, "m:e"),
|
|
3561
|
+
limit: parseMathArg(el, "m:lim")
|
|
3562
|
+
} };
|
|
3563
|
+
}
|
|
3564
|
+
function parseMathLimitUpper(el) {
|
|
3565
|
+
return { limitUpper: {
|
|
3566
|
+
children: parseMathArg(el, "m:e"),
|
|
3567
|
+
limit: parseMathArg(el, "m:lim")
|
|
3568
|
+
} };
|
|
3569
|
+
}
|
|
3570
|
+
function parseMathArg(parent, childName) {
|
|
3571
|
+
const container = findChild(parent, childName);
|
|
3572
|
+
if (!container) return [];
|
|
3573
|
+
return parseMathChildren(container);
|
|
2533
3574
|
}
|
|
3575
|
+
//#endregion
|
|
3576
|
+
//#region src/parts/paragraph/run/field.ts
|
|
2534
3577
|
/**
|
|
2535
|
-
*
|
|
3578
|
+
* Field module for WordprocessingML documents.
|
|
2536
3579
|
*
|
|
2537
|
-
*
|
|
3580
|
+
* This module provides support for complex fields, which are regions of text
|
|
3581
|
+
* that can contain dynamic content such as page numbers, dates, or mail merge fields.
|
|
3582
|
+
* Fields are delimited by field character elements (begin, separate, end).
|
|
3583
|
+
*
|
|
3584
|
+
* Reference: http://officeopenxml.com/WPrun.php
|
|
3585
|
+
*
|
|
3586
|
+
* @module
|
|
2538
3587
|
*/
|
|
2539
|
-
function stringifyParagraphProperties(options) {
|
|
2540
|
-
const numberingReferences = [];
|
|
2541
|
-
if (!options) return {
|
|
2542
|
-
xml: void 0,
|
|
2543
|
-
numberingReferences
|
|
2544
|
-
};
|
|
2545
|
-
const parts = [];
|
|
2546
|
-
if (options.heading) parts.push(`<w:pStyle w:val="${escapeXml(options.heading)}"/>`);
|
|
2547
|
-
if (options.bullet) parts.push("<w:pStyle w:val=\"ListParagraph\"/>");
|
|
2548
|
-
if (options.numbering) {
|
|
2549
|
-
if (!options.style && !options.heading) {
|
|
2550
|
-
if (!options.numbering.custom) parts.push("<w:pStyle w:val=\"ListParagraph\"/>");
|
|
2551
|
-
}
|
|
2552
|
-
}
|
|
2553
|
-
if (options.style) parts.push(`<w:pStyle w:val="${escapeXml(options.style)}"/>`);
|
|
2554
|
-
if (options.keepNext !== void 0) parts.push(onOff("w:keepNext", options.keepNext));
|
|
2555
|
-
if (options.keepLines !== void 0) parts.push(onOff("w:keepLines", options.keepLines));
|
|
2556
|
-
if (options.pageBreakBefore) parts.push("<w:pageBreakBefore/>");
|
|
2557
|
-
if (options.frame) parts.push(framePrStr(options.frame));
|
|
2558
|
-
if (options.widowControl !== void 0) parts.push(onOff("w:widowControl", options.widowControl));
|
|
2559
|
-
if (options.bullet) parts.push(`<w:numPr><w:ilvl w:val="${Math.min(options.bullet.level, 9)}"/><w:numId w:val="1"/></w:numPr>`);
|
|
2560
|
-
if (options.numbering) {
|
|
2561
|
-
numberingReferences.push({
|
|
2562
|
-
instance: options.numbering.instance ?? 0,
|
|
2563
|
-
reference: options.numbering.reference
|
|
2564
|
-
});
|
|
2565
|
-
const numId = `${options.numbering.reference}-${options.numbering.instance ?? 0}`;
|
|
2566
|
-
parts.push(numPrStr(numId, options.numbering.level, options.numbering.numberingChange));
|
|
2567
|
-
} else if (options.numbering === false) parts.push(numPrStr(0, 0));
|
|
2568
|
-
if (options.border) {
|
|
2569
|
-
const bParts = [];
|
|
2570
|
-
if (options.border.top) bParts.push(borderStr("w:top", options.border.top));
|
|
2571
|
-
if (options.border.left) bParts.push(borderStr("w:left", options.border.left));
|
|
2572
|
-
if (options.border.bottom) bParts.push(borderStr("w:bottom", options.border.bottom));
|
|
2573
|
-
if (options.border.right) bParts.push(borderStr("w:right", options.border.right));
|
|
2574
|
-
if (options.border.between) bParts.push(borderStr("w:between", options.border.between));
|
|
2575
|
-
if (options.border.bar) bParts.push(borderStr("w:bar", options.border.bar));
|
|
2576
|
-
if (bParts.length) parts.push(`<w:pBdr>${bParts.join("")}</w:pBdr>`);
|
|
2577
|
-
}
|
|
2578
|
-
if (options.thematicBreak) parts.push(`<w:pBdr>${borderStr("w:bottom", {
|
|
2579
|
-
color: "auto",
|
|
2580
|
-
size: 6,
|
|
2581
|
-
space: 1,
|
|
2582
|
-
style: BorderStyle.SINGLE
|
|
2583
|
-
})}</w:pBdr>`);
|
|
2584
|
-
if (options.shading) parts.push(shadingStr(options.shading));
|
|
2585
|
-
if (options.wordWrap) parts.push("<w:wordWrap w:val=\"0\"/>");
|
|
2586
|
-
if (options.overflowPunctuation) parts.push(onOff("w:overflowPunct", options.overflowPunctuation));
|
|
2587
|
-
const tabDefs = [
|
|
2588
|
-
...options.rightTabStop !== void 0 ? [{
|
|
2589
|
-
position: options.rightTabStop,
|
|
2590
|
-
type: "right"
|
|
2591
|
-
}] : [],
|
|
2592
|
-
...options.tabStops ? options.tabStops : [],
|
|
2593
|
-
...options.leftTabStop !== void 0 ? [{
|
|
2594
|
-
position: options.leftTabStop,
|
|
2595
|
-
type: "left"
|
|
2596
|
-
}] : []
|
|
2597
|
-
];
|
|
2598
|
-
if (tabDefs.length > 0) parts.push(tabStopsStr(tabDefs));
|
|
2599
|
-
if (options.bidirectional !== void 0) parts.push(onOff("w:bidi", options.bidirectional));
|
|
2600
|
-
if (options.spacing) parts.push(spacingStr(options.spacing));
|
|
2601
|
-
if (options.indent) parts.push(indentStr(options.indent));
|
|
2602
|
-
if (options.contextualSpacing !== void 0) parts.push(onOff("w:contextualSpacing", options.contextualSpacing));
|
|
2603
|
-
if (options.alignment) parts.push(`<w:jc w:val="${options.alignment}"/>`);
|
|
2604
|
-
if (options.outlineLevel !== void 0) parts.push(`<w:outlineLvl w:val="${options.outlineLevel}"/>`);
|
|
2605
|
-
if (options.divId !== void 0) parts.push(`<w:divId w:val="${options.divId}"/>`);
|
|
2606
|
-
if (options.cnfStyle) parts.push(cnfStyleStr(options.cnfStyle));
|
|
2607
|
-
if (options.suppressLineNumbers !== void 0) parts.push(onOff("w:suppressLineNumbers", options.suppressLineNumbers));
|
|
2608
|
-
if (options.autoSpaceEastAsianText !== void 0) parts.push(onOff("w:autoSpaceDN", options.autoSpaceEastAsianText));
|
|
2609
|
-
if (options.suppressAutoHyphens !== void 0) parts.push(onOff("w:suppressAutoHyphens", options.suppressAutoHyphens));
|
|
2610
|
-
if (options.adjustRightInd !== void 0) parts.push(onOff("w:adjustRightInd", options.adjustRightInd));
|
|
2611
|
-
if (options.snapToGrid !== void 0) parts.push(onOff("w:snapToGrid", options.snapToGrid));
|
|
2612
|
-
if (options.mirrorIndents !== void 0) parts.push(onOff("w:mirrorIndents", options.mirrorIndents));
|
|
2613
|
-
if (options.kinsoku !== void 0) parts.push(onOff("w:kinsoku", options.kinsoku));
|
|
2614
|
-
if (options.topLinePunct !== void 0) parts.push(onOff("w:topLinePunct", options.topLinePunct));
|
|
2615
|
-
if (options.autoSpaceDE !== void 0) parts.push(onOff("w:autoSpaceDE", options.autoSpaceDE));
|
|
2616
|
-
if (options.textAlignment !== void 0) parts.push(`<w:textAlignment w:val="${options.textAlignment}"/>`);
|
|
2617
|
-
if (options.textboxTightWrap !== void 0) parts.push(`<w:textboxTightWrap w:val="${options.textboxTightWrap}"/>`);
|
|
2618
|
-
if (options.textDirection !== void 0) parts.push(`<w:textDirection w:val="${options.textDirection}"/>`);
|
|
2619
|
-
if (options.suppressOverlap !== void 0) parts.push(onOff("w:suppressOverlap", options.suppressOverlap));
|
|
2620
|
-
if (options.run) {
|
|
2621
|
-
const inner = stringifyRunPropertiesInner(options.run);
|
|
2622
|
-
if (inner !== void 0) {
|
|
2623
|
-
const extra = [];
|
|
2624
|
-
const runOpts = options.run;
|
|
2625
|
-
if (runOpts.insertion) {
|
|
2626
|
-
const { id, author, date } = runOpts.insertion;
|
|
2627
|
-
extra.push(`<w:ins w:id="${id}" w:author="${escapeXml(author)}" w:date="${date}"/>`);
|
|
2628
|
-
}
|
|
2629
|
-
if (runOpts.deletion) {
|
|
2630
|
-
const { id, author, date } = runOpts.deletion;
|
|
2631
|
-
extra.push(`<w:del w:id="${id}" w:author="${escapeXml(author)}" w:date="${date}"/>`);
|
|
2632
|
-
}
|
|
2633
|
-
const body = inner + extra.join("");
|
|
2634
|
-
parts.push(`<w:rPr>${body}</w:rPr>`);
|
|
2635
|
-
}
|
|
2636
|
-
}
|
|
2637
|
-
if (options.revision) {
|
|
2638
|
-
const rev = options.revision;
|
|
2639
|
-
const { author: _a, date: _d, id: _i, ...originalProps } = rev;
|
|
2640
|
-
const inner = stringifyParagraphProperties({
|
|
2641
|
-
...originalProps,
|
|
2642
|
-
includeIfEmpty: true
|
|
2643
|
-
});
|
|
2644
|
-
parts.push(`<w:pPrChange w:author="${escapeXml(rev.author)}" w:date="${rev.date}" w:id="${rev.id}">${inner.xml ?? "<w:pPr/>"}</w:pPrChange>`);
|
|
2645
|
-
}
|
|
2646
|
-
const body = parts.join("");
|
|
2647
|
-
return {
|
|
2648
|
-
xml: options.includeIfEmpty || body.length > 0 ? `<w:pPr>${body}</w:pPr>` : void 0,
|
|
2649
|
-
numberingReferences
|
|
2650
|
-
};
|
|
2651
|
-
}
|
|
2652
3588
|
/**
|
|
2653
|
-
*
|
|
2654
|
-
*
|
|
3589
|
+
* Field character types that delimit field regions.
|
|
3590
|
+
*
|
|
3591
|
+
* @internal
|
|
3592
|
+
*/
|
|
3593
|
+
const FieldCharacterType = {
|
|
3594
|
+
BEGIN: "begin",
|
|
3595
|
+
END: "end",
|
|
3596
|
+
SEPARATE: "separate"
|
|
3597
|
+
};
|
|
3598
|
+
/**
|
|
3599
|
+
* Creates a field character element.
|
|
3600
|
+
*
|
|
3601
|
+
* ## XSD Schema
|
|
3602
|
+
* ```xml
|
|
3603
|
+
* <xsd:complexType name="CT_FldChar">
|
|
3604
|
+
* <xsd:sequence>
|
|
3605
|
+
* <xsd:element name="fldData" type="CT_Text" minOccurs="0"/>
|
|
3606
|
+
* <xsd:element name="ffData" type="CT_FFData" minOccurs="0"/>
|
|
3607
|
+
* <xsd:element name="numberingChange" type="CT_TrackChangeNumbering" minOccurs="0"/>
|
|
3608
|
+
* </xsd:sequence>
|
|
3609
|
+
* <xsd:attribute name="fldCharType" type="ST_FldCharType" use="required"/>
|
|
3610
|
+
* <xsd:attribute name="fldLock" type="s:ST_OnOff"/>
|
|
3611
|
+
* <xsd:attribute name="dirty" type="s:ST_OnOff"/>
|
|
3612
|
+
* </xsd:complexType>
|
|
3613
|
+
* ```
|
|
3614
|
+
* @internal
|
|
2655
3615
|
*/
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
if (
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
if ((opts.italicComplexScript === void 0 && opts.italic !== void 0 || opts.italicComplexScript) !== void 0) parts.push(onOff("w:iCs", opts.italicComplexScript ?? opts.italic));
|
|
2667
|
-
if (opts.smallCaps !== void 0) parts.push(onOff("w:smallCaps", opts.smallCaps));
|
|
2668
|
-
else if (opts.allCaps !== void 0) parts.push(onOff("w:caps", opts.allCaps));
|
|
2669
|
-
if (opts.strike !== void 0) parts.push(onOff("w:strike", opts.strike));
|
|
2670
|
-
if (opts.doubleStrike !== void 0) parts.push(onOff("w:dstrike", opts.doubleStrike));
|
|
2671
|
-
if (opts.emboss !== void 0) parts.push(onOff("w:emboss", opts.emboss));
|
|
2672
|
-
if (opts.imprint !== void 0) parts.push(onOff("w:imprint", opts.imprint));
|
|
2673
|
-
if (opts.outline !== void 0) parts.push(onOff("w:outline", opts.outline));
|
|
2674
|
-
if (opts.shadow !== void 0) parts.push(onOff("w:shadow", opts.shadow));
|
|
2675
|
-
if (opts.webHidden !== void 0) parts.push(onOff("w:webHidden", opts.webHidden));
|
|
2676
|
-
if (opts.noProof !== void 0) parts.push(onOff("w:noProof", opts.noProof));
|
|
2677
|
-
if (opts.snapToGrid !== void 0) parts.push(onOff("w:snapToGrid", opts.snapToGrid));
|
|
2678
|
-
if (opts.vanish) parts.push(onOff("w:vanish", opts.vanish));
|
|
2679
|
-
if (opts.color) parts.push(colorStr(opts.color));
|
|
2680
|
-
if (opts.characterSpacing) parts.push(`<w:spacing w:val="${signedTwipsMeasureValue(opts.characterSpacing)}"/>`);
|
|
2681
|
-
if (opts.scale !== void 0) parts.push(`<w:w w:val="${opts.scale}"/>`);
|
|
2682
|
-
if (opts.kern) parts.push(`<w:kern w:val="${hpsMeasureValue(opts.kern)}"/>`);
|
|
2683
|
-
if (opts.position) parts.push(`<w:position w:val="${opts.position}"/>`);
|
|
2684
|
-
if (opts.size !== void 0) parts.push(`<w:sz w:val="${hpsMeasureValue(opts.size * 2)}"/>`);
|
|
2685
|
-
const szCs = opts.sizeComplexScript === void 0 || opts.sizeComplexScript === true ? opts.size : opts.sizeComplexScript;
|
|
2686
|
-
if (szCs) parts.push(`<w:szCs w:val="${hpsMeasureValue(szCs * 2)}"/>`);
|
|
2687
|
-
if (opts.highlight) parts.push(`<w:highlight w:val="${opts.highlight}"/>`);
|
|
2688
|
-
if (opts.highlightComplexScript === true) {
|
|
2689
|
-
if (opts.highlight) parts.push(`<w:highlightCs w:val="${opts.highlight}"/>`);
|
|
2690
|
-
} else if (opts.highlightComplexScript !== void 0 && opts.highlightComplexScript !== false) parts.push(`<w:highlightCs w:val="${opts.highlightComplexScript}"/>`);
|
|
2691
|
-
if (opts.underline) parts.push(underlineStr(opts.underline.type, opts.underline.color));
|
|
2692
|
-
if (opts.effect) parts.push(`<w:effect w:val="${opts.effect}"/>`);
|
|
2693
|
-
if (opts.border) parts.push(borderStr("w:bdr", opts.border));
|
|
2694
|
-
if (opts.shading) parts.push(shadingStr(opts.shading));
|
|
2695
|
-
if (opts.subScript) parts.push("<w:vertAlign w:val=\"subscript\"/>");
|
|
2696
|
-
if (opts.superScript) parts.push("<w:vertAlign w:val=\"superscript\"/>");
|
|
2697
|
-
if (opts.rightToLeft !== void 0) parts.push(onOff("w:rtl", opts.rightToLeft));
|
|
2698
|
-
if (opts.emphasisMark) parts.push(`<w:em w:val="${opts.emphasisMark.type ?? "dot"}"/>`);
|
|
2699
|
-
if (opts.language) parts.push(languageStr(opts.language));
|
|
2700
|
-
if (opts.specVanish) parts.push("<w:specVanish/>");
|
|
2701
|
-
if (opts.math) parts.push(onOff("w:oMath", opts.math));
|
|
2702
|
-
if (opts.fitText !== void 0) parts.push(`<w:fitText w:val="${opts.fitText}"/>`);
|
|
2703
|
-
if (opts.complexScript !== void 0) parts.push(onOff("w:cs", opts.complexScript));
|
|
2704
|
-
if (opts.eastAsianLayout) parts.push(eastAsianLayoutStr(opts.eastAsianLayout));
|
|
2705
|
-
if (opts.contentPartRId) parts.push(`<w:contentPart r:id="${opts.contentPartRId}"/>`);
|
|
2706
|
-
if (opts.revision) {
|
|
2707
|
-
const rev = opts.revision;
|
|
2708
|
-
const { author: _a, date: _d, id: _i, ...originalProps } = rev;
|
|
2709
|
-
const inner = stringifyRunPropertiesInner(originalProps);
|
|
2710
|
-
parts.push(`<w:rPrChange w:author="${escapeXml(rev.author)}" w:date="${rev.date}" w:id="${rev.id}"><w:rPr>${inner ?? ""}</w:rPr></w:rPrChange>`);
|
|
2711
|
-
}
|
|
2712
|
-
return parts.length > 0 ? parts.join("") : void 0;
|
|
2713
|
-
}
|
|
3616
|
+
const createFieldChar = (type, dirty, ffData, fldData, fieldLock) => {
|
|
3617
|
+
const children = [];
|
|
3618
|
+
if (fldData !== void 0) children.push(element("w:fldData", { "xml:space": "preserve" }, [fldData]));
|
|
3619
|
+
if (ffData) children.push(ffData);
|
|
3620
|
+
return element("w:fldChar", {
|
|
3621
|
+
"w:dirty": dirty,
|
|
3622
|
+
"w:fldLock": fieldLock,
|
|
3623
|
+
"w:fldCharType": type
|
|
3624
|
+
}, children.length > 0 ? children : void 0);
|
|
3625
|
+
};
|
|
2714
3626
|
/**
|
|
2715
|
-
*
|
|
3627
|
+
* Creates the beginning of a complex field.
|
|
2716
3628
|
*
|
|
2717
|
-
*
|
|
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
|
+
* ```
|
|
2718
3648
|
*/
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
3649
|
+
const createBegin = (dirty, formField, fieldLock) => createFieldChar(FieldCharacterType.BEGIN, dirty, formField ? createFormFieldData(formField) : void 0, void 0, fieldLock);
|
|
3650
|
+
/**
|
|
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).
|
|
3655
|
+
*/
|
|
3656
|
+
const createSeparate = (dirty) => createFieldChar(FieldCharacterType.SEPARATE, dirty);
|
|
3657
|
+
/**
|
|
3658
|
+
* Creates the end of a complex field.
|
|
3659
|
+
*
|
|
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.
|
|
3662
|
+
*/
|
|
3663
|
+
const createEnd = (dirty) => createFieldChar(FieldCharacterType.END, dirty);
|
|
2723
3664
|
//#endregion
|
|
2724
3665
|
//#region src/parts/inline.ts
|
|
2725
3666
|
/**
|
|
@@ -3032,6 +3973,11 @@ function stringifyChildDispatch(child, ctx) {
|
|
|
3032
3973
|
if (sf.cachedValue !== void 0) return `<w:fldSimple w:instr="${escapeXml(sf.instruction)}"><w:r><w:t>${escapeXml(sf.cachedValue)}</w:t></w:r></w:fldSimple>`;
|
|
3033
3974
|
return `<w:fldSimple w:instr="${escapeXml(sf.instruction)}"/>`;
|
|
3034
3975
|
}
|
|
3976
|
+
if ("complexField" in child) {
|
|
3977
|
+
const cf = child.complexField;
|
|
3978
|
+
const resultXml = cf.result !== void 0 ? `<w:r><w:fldChar w:fldCharType="separate"/></w:r><w:r><w:t xml:space="preserve">${escapeXml(cf.result)}</w:t></w:r>` : "";
|
|
3979
|
+
return `<w:r><w:fldChar w:fldCharType="begin"/></w:r><w:r><w:instrText xml:space="preserve">${escapeXml(cf.instruction)}</w:instrText></w:r>` + resultXml + "<w:r><w:fldChar w:fldCharType=\"end\"/></w:r>";
|
|
3980
|
+
}
|
|
3035
3981
|
if ("seqIdentifier" in child) {
|
|
3036
3982
|
const id = child.seqIdentifier;
|
|
3037
3983
|
return `<w:r><w:fldChar w:fldCharType="begin"/><w:instrText xml:space="preserve"> SEQ ${escapeXml(id)} </w:instrText><w:fldChar w:fldCharType="separate"/><w:fldChar w:fldCharType="end"/></w:r>`;
|
|
@@ -3074,26 +4020,30 @@ function stringifyChildDispatch(child, ctx) {
|
|
|
3074
4020
|
}
|
|
3075
4021
|
if ("customXml" in child) {
|
|
3076
4022
|
const cx = child.customXml;
|
|
3077
|
-
const
|
|
3078
|
-
if (cx.
|
|
3079
|
-
const parts = [];
|
|
3080
|
-
if (cx.customXmlPr) {
|
|
3081
|
-
const prParts = [];
|
|
3082
|
-
if (cx.customXmlPr.placeholder) prParts.push(`<w:placeholder w:val="${escapeXml(cx.customXmlPr.placeholder)}"/>`);
|
|
3083
|
-
if (cx.customXmlPr.attrs?.length) for (const a of cx.customXmlPr.attrs) {
|
|
3084
|
-
const aa = [`w:name="${escapeXml(a.name)}"`, `w:val="${escapeXml(a.val)}"`];
|
|
3085
|
-
if (a.uri) aa.push(`w:uri="${escapeXml(a.uri)}"`);
|
|
3086
|
-
prParts.push(`<w:attr ${aa.join(" ")}/>`);
|
|
3087
|
-
}
|
|
3088
|
-
if (prParts.length) parts.push(`<w:customXmlPr>${prParts.join("")}</w:customXmlPr>`);
|
|
3089
|
-
}
|
|
3090
|
-
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));
|
|
3091
4025
|
else {
|
|
3092
4026
|
const jr = stringifyChildDispatch(c, ctx);
|
|
3093
|
-
if (jr !== void 0)
|
|
3094
|
-
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("");
|
|
3095
4045
|
}
|
|
3096
|
-
return
|
|
4046
|
+
return stringifySdtShell(s.properties, s.endProperties, contentXml);
|
|
3097
4047
|
}
|
|
3098
4048
|
}
|
|
3099
4049
|
/** Serialize children of Dir/Bdo containers. */
|
|
@@ -3134,6 +4084,151 @@ function stringifyParagraphInline(opts, ctx) {
|
|
|
3134
4084
|
return body ? `<w:p>${body}</w:p>` : "<w:p/>";
|
|
3135
4085
|
}
|
|
3136
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
|
|
3137
4232
|
//#region src/parts/table/stringify.ts
|
|
3138
4233
|
/**
|
|
3139
4234
|
* Direct XML string builders for table properties.
|
|
@@ -3178,20 +4273,15 @@ function cellMarginStr(tag, opts) {
|
|
|
3178
4273
|
const inner = cellMarginChildrenStr(opts);
|
|
3179
4274
|
return inner ? `<${tag}>${inner}</${tag}>` : void 0;
|
|
3180
4275
|
}
|
|
3181
|
-
const DEFAULT_BORDER = {
|
|
3182
|
-
color: "auto",
|
|
3183
|
-
size: 4,
|
|
3184
|
-
style: BorderStyle.SINGLE
|
|
3185
|
-
};
|
|
3186
4276
|
function tableBordersStr(opts) {
|
|
3187
4277
|
const parts = [];
|
|
3188
|
-
parts.push(borderStr("w:top", opts.top
|
|
3189
|
-
parts.push(borderStr("w:left", opts.left
|
|
3190
|
-
parts.push(borderStr("w:bottom", opts.bottom
|
|
3191
|
-
parts.push(borderStr("w:right", opts.right
|
|
3192
|
-
parts.push(borderStr("w:insideH", opts.insideHorizontal
|
|
3193
|
-
parts.push(borderStr("w:insideV", opts.insideVertical
|
|
3194
|
-
return `<w:tblBorders>${parts.join("")}</w:tblBorders
|
|
4278
|
+
if (opts.top) parts.push(borderStr("w:top", opts.top));
|
|
4279
|
+
if (opts.left) parts.push(borderStr("w:left", opts.left));
|
|
4280
|
+
if (opts.bottom) parts.push(borderStr("w:bottom", opts.bottom));
|
|
4281
|
+
if (opts.right) parts.push(borderStr("w:right", opts.right));
|
|
4282
|
+
if (opts.insideHorizontal) parts.push(borderStr("w:insideH", opts.insideHorizontal));
|
|
4283
|
+
if (opts.insideVertical) parts.push(borderStr("w:insideV", opts.insideVertical));
|
|
4284
|
+
return parts.length > 0 ? `<w:tblBorders>${parts.join("")}</w:tblBorders>` : void 0;
|
|
3195
4285
|
}
|
|
3196
4286
|
function cellBordersStr(opts) {
|
|
3197
4287
|
const parts = [];
|
|
@@ -3276,7 +4366,10 @@ function stringifyTablePropertiesInner(options) {
|
|
|
3276
4366
|
if (options.width) parts.push(tableWidthStr("w:tblW", options.width));
|
|
3277
4367
|
if (options.alignment) parts.push(`<w:jc w:val="${options.alignment}"/>`);
|
|
3278
4368
|
if (options.indent) parts.push(tableWidthStr("w:tblInd", options.indent));
|
|
3279
|
-
if (options.borders)
|
|
4369
|
+
if (options.borders) {
|
|
4370
|
+
const bs = tableBordersStr(options.borders);
|
|
4371
|
+
if (bs) parts.push(bs);
|
|
4372
|
+
}
|
|
3280
4373
|
if (options.shading) parts.push(shadingStr(options.shading));
|
|
3281
4374
|
if (options.layout) parts.push(`<w:tblLayout w:type="${options.layout}"/>`);
|
|
3282
4375
|
if (options.cellMargin) {
|
|
@@ -3400,7 +4493,10 @@ function stringifyTablePropertyExceptions(options) {
|
|
|
3400
4493
|
if (options.alignment) parts.push(`<w:jc w:val="${options.alignment}"/>`);
|
|
3401
4494
|
if (options.cellSpacing) parts.push(cellSpacingStr(options.cellSpacing));
|
|
3402
4495
|
if (options.indent) parts.push(tableWidthStr("w:tblInd", options.indent));
|
|
3403
|
-
if (options.borders)
|
|
4496
|
+
if (options.borders) {
|
|
4497
|
+
const bs = tableBordersStr(options.borders);
|
|
4498
|
+
if (bs) parts.push(bs);
|
|
4499
|
+
}
|
|
3404
4500
|
if (options.shading) parts.push(shadingStr(options.shading));
|
|
3405
4501
|
if (options.layout) parts.push(`<w:tblLayout w:type="${options.layout}"/>`);
|
|
3406
4502
|
if (options.cellMargin) {
|
|
@@ -3422,6 +4518,27 @@ function stringifyTablePropertyExceptions(options) {
|
|
|
3422
4518
|
}
|
|
3423
4519
|
//#endregion
|
|
3424
4520
|
//#region src/parts/table/descriptor.ts
|
|
4521
|
+
/**
|
|
4522
|
+
* Table (w:tbl) descriptor for DOCX.
|
|
4523
|
+
*
|
|
4524
|
+
* Stringifies pure JSON TableOptions into XML using direct string
|
|
4525
|
+
* concatenation — zero IXmlableObject, zero xml(), zero BaseXmlComponent.
|
|
4526
|
+
*
|
|
4527
|
+
* @module
|
|
4528
|
+
*/
|
|
4529
|
+
const BORDER_STYLES = Object.values(BorderStyle);
|
|
4530
|
+
const THEME_COLORS = Object.values(ThemeColor);
|
|
4531
|
+
/** Parse track-change attributes (id/author/date) from w:ins/w:del/w:cellIns/w:cellDel. */
|
|
4532
|
+
function parseChangeAttrs(el) {
|
|
4533
|
+
const change = {};
|
|
4534
|
+
const id = attrNum(el, "w:id");
|
|
4535
|
+
if (id !== void 0) change.id = id;
|
|
4536
|
+
const author = attr(el, "w:author");
|
|
4537
|
+
if (author) change.author = author;
|
|
4538
|
+
const date = attr(el, "w:date");
|
|
4539
|
+
if (date) change.date = date;
|
|
4540
|
+
return change;
|
|
4541
|
+
}
|
|
3425
4542
|
function buildTableGridXml(widths, revision) {
|
|
3426
4543
|
const cols = widths.map((w) => `<w:gridCol w:w="${w}"/>`).join("");
|
|
3427
4544
|
if (revision) {
|
|
@@ -3463,7 +4580,15 @@ function stringifyTableRow(row, ctx, extraCells) {
|
|
|
3463
4580
|
const trPr = stringifyTableRowProperties(row);
|
|
3464
4581
|
if (trPr) parts.push(trPr);
|
|
3465
4582
|
const prefixCount = parts.length;
|
|
3466
|
-
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));
|
|
3467
4592
|
if (extraCells && extraCells.length > 0) for (const { cell, columnIndex } of extraCells) {
|
|
3468
4593
|
const insertIdx = findInsertIndex(row.cells, columnIndex, prefixCount);
|
|
3469
4594
|
parts.splice(insertIdx, 0, stringifyTableCell(cell, ctx));
|
|
@@ -3477,10 +4602,20 @@ function stringifyTableRow(row, ctx, extraCells) {
|
|
|
3477
4602
|
const body = parts.join("");
|
|
3478
4603
|
return body ? `<w:tr${attr}>${body}</w:tr>` : attr ? `<w:tr${attr}/>` : "<w:tr/>";
|
|
3479
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
|
+
}
|
|
3480
4613
|
function findInsertIndex(cells, columnIndex, prefixCount) {
|
|
3481
4614
|
let colIdx = 0;
|
|
3482
4615
|
for (let i = 0; i < cells.length; i++) {
|
|
3483
|
-
const
|
|
4616
|
+
const c = cells[i];
|
|
4617
|
+
if (!isPlainCell(c)) continue;
|
|
4618
|
+
const { columnSpan } = getCellSpans(c);
|
|
3484
4619
|
colIdx += columnSpan;
|
|
3485
4620
|
if (colIdx > columnIndex) return i + prefixCount;
|
|
3486
4621
|
}
|
|
@@ -3492,9 +4627,12 @@ function findInsertIndex(cells, columnIndex, prefixCount) {
|
|
|
3492
4627
|
function computeVerticalMergeCells(rows) {
|
|
3493
4628
|
const extraMap = /* @__PURE__ */ new Map();
|
|
3494
4629
|
for (let ri = 0; ri < rows.length - 1; ri++) {
|
|
3495
|
-
const
|
|
4630
|
+
const row = rows[ri];
|
|
4631
|
+
if (!isPlainRow(row)) continue;
|
|
4632
|
+
const cells = row.cells;
|
|
3496
4633
|
let colIdx = 0;
|
|
3497
4634
|
for (const cell of cells) {
|
|
4635
|
+
if (!isPlainCell(cell)) continue;
|
|
3498
4636
|
const typedCell = cell;
|
|
3499
4637
|
const { columnSpan, rowSpan } = getCellSpans(typedCell);
|
|
3500
4638
|
if (rowSpan > 1) {
|
|
@@ -3520,9 +4658,9 @@ const tableDesc = {
|
|
|
3520
4658
|
kind: "custom",
|
|
3521
4659
|
stringify(opts, ctx) {
|
|
3522
4660
|
const parts = [];
|
|
3523
|
-
const
|
|
4661
|
+
const tblPrOpts = {
|
|
3524
4662
|
alignment: opts.alignment,
|
|
3525
|
-
borders: opts.borders
|
|
4663
|
+
borders: opts.borders,
|
|
3526
4664
|
caption: opts.caption,
|
|
3527
4665
|
cellMargin: opts.margins,
|
|
3528
4666
|
cellSpacing: opts.cellSpacing,
|
|
@@ -3536,16 +4674,27 @@ const tableDesc = {
|
|
|
3536
4674
|
styleRowBandSize: opts.styleRowBandSize,
|
|
3537
4675
|
tableLook: opts.tableLook,
|
|
3538
4676
|
visuallyRightToLeft: opts.visuallyRightToLeft,
|
|
3539
|
-
width: opts.width
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
4677
|
+
width: opts.width,
|
|
4678
|
+
includeIfEmpty: true
|
|
4679
|
+
};
|
|
4680
|
+
parts.push(stringifyTableProperties(tblPrOpts));
|
|
4681
|
+
const columnWidths = opts.columnWidths ?? Array(Math.max(1, ...opts.rows.map((r) => isPlainRow(r) ? r.cells.length : 0))).fill(100);
|
|
3543
4682
|
parts.push(buildTableGridXml(columnWidths, opts.columnWidthsRevision));
|
|
3544
4683
|
const extraCells = computeVerticalMergeCells(opts.rows);
|
|
3545
4684
|
for (let ri = 0; ri < opts.rows.length; ri++) {
|
|
3546
|
-
const
|
|
3547
|
-
|
|
3548
|
-
|
|
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
|
+
}
|
|
3549
4698
|
}
|
|
3550
4699
|
return `<w:tbl>${parts.join("")}</w:tbl>`;
|
|
3551
4700
|
},
|
|
@@ -3588,28 +4737,38 @@ function parseTablePropertiesEl(el) {
|
|
|
3588
4737
|
}
|
|
3589
4738
|
const tblBorders = findChild(el, "w:tblBorders");
|
|
3590
4739
|
if (tblBorders) {
|
|
4740
|
+
const SIDE_KEYS = [
|
|
4741
|
+
["top", "top"],
|
|
4742
|
+
["left", "left"],
|
|
4743
|
+
["bottom", "bottom"],
|
|
4744
|
+
["right", "right"],
|
|
4745
|
+
["insideH", "insideHorizontal"],
|
|
4746
|
+
["insideV", "insideVertical"]
|
|
4747
|
+
];
|
|
3591
4748
|
const borders = {};
|
|
3592
|
-
for (const
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
"
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
"
|
|
3599
|
-
|
|
3600
|
-
const
|
|
3601
|
-
if (
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
4749
|
+
for (const [xmlSide, key] of SIDE_KEYS) {
|
|
4750
|
+
const sideEl = findChild(tblBorders, `w:${xmlSide}`);
|
|
4751
|
+
if (!sideEl) continue;
|
|
4752
|
+
const style = attr(sideEl, "w:val");
|
|
4753
|
+
if (!style || !BORDER_STYLES.includes(style)) continue;
|
|
4754
|
+
const sideOpts = { style };
|
|
4755
|
+
const color = attr(sideEl, "w:color");
|
|
4756
|
+
if (color) sideOpts.color = color;
|
|
4757
|
+
const size = attrNum(sideEl, "w:sz");
|
|
4758
|
+
if (size !== void 0) sideOpts.size = size;
|
|
4759
|
+
const space = attrNum(sideEl, "w:space");
|
|
4760
|
+
if (space !== void 0) sideOpts.space = space;
|
|
4761
|
+
const themeColor = attr(sideEl, "w:themeColor");
|
|
4762
|
+
if (themeColor && THEME_COLORS.includes(themeColor)) sideOpts.themeColor = themeColor;
|
|
4763
|
+
const themeTint = attr(sideEl, "w:themeTint");
|
|
4764
|
+
if (themeTint) sideOpts.themeTint = themeTint;
|
|
4765
|
+
const themeShade = attr(sideEl, "w:themeShade");
|
|
4766
|
+
if (themeShade) sideOpts.themeShade = themeShade;
|
|
4767
|
+
const shadow = attrBool(sideEl, "w:shadow");
|
|
4768
|
+
if (shadow !== void 0) sideOpts.shadow = shadow;
|
|
4769
|
+
const frame = attrBool(sideEl, "w:frame");
|
|
4770
|
+
if (frame !== void 0) sideOpts.frame = frame;
|
|
4771
|
+
borders[key] = sideOpts;
|
|
3613
4772
|
}
|
|
3614
4773
|
if (Object.keys(borders).length > 0) opts.borders = borders;
|
|
3615
4774
|
}
|
|
@@ -3684,6 +4843,45 @@ function parseTablePropertiesEl(el) {
|
|
|
3684
4843
|
...type ? { type } : {}
|
|
3685
4844
|
};
|
|
3686
4845
|
}
|
|
4846
|
+
const bidiVisual = findChild(el, "w:bidiVisual");
|
|
4847
|
+
if (bidiVisual) opts.visuallyRightToLeft = attrBool(bidiVisual, "w:val") ?? true;
|
|
4848
|
+
const tblStyleRowBandSize = findChild(el, "w:tblStyleRowBandSize");
|
|
4849
|
+
if (tblStyleRowBandSize) {
|
|
4850
|
+
const val = attrNum(tblStyleRowBandSize, "w:val");
|
|
4851
|
+
if (val !== void 0) opts.styleRowBandSize = val;
|
|
4852
|
+
}
|
|
4853
|
+
const tblStyleColBandSize = findChild(el, "w:tblStyleColBandSize");
|
|
4854
|
+
if (tblStyleColBandSize) {
|
|
4855
|
+
const val = attrNum(tblStyleColBandSize, "w:val");
|
|
4856
|
+
if (val !== void 0) opts.styleColBandSize = val;
|
|
4857
|
+
}
|
|
4858
|
+
const tblCaption = findChild(el, "w:tblCaption");
|
|
4859
|
+
if (tblCaption) {
|
|
4860
|
+
const val = attr(tblCaption, "w:val");
|
|
4861
|
+
if (val) opts.caption = val;
|
|
4862
|
+
}
|
|
4863
|
+
const tblCellSpacing = findChild(el, "w:tblCellSpacing");
|
|
4864
|
+
if (tblCellSpacing) {
|
|
4865
|
+
const type = attr(tblCellSpacing, "w:type");
|
|
4866
|
+
const w = attrNum(tblCellSpacing, "w:w");
|
|
4867
|
+
if (w !== void 0) opts.cellSpacing = {
|
|
4868
|
+
value: w,
|
|
4869
|
+
...type ? { type } : {}
|
|
4870
|
+
};
|
|
4871
|
+
}
|
|
4872
|
+
const tblPrChange = findChild(el, "w:tblPrChange");
|
|
4873
|
+
if (tblPrChange) {
|
|
4874
|
+
const rev = {};
|
|
4875
|
+
const author = attr(tblPrChange, "w:author");
|
|
4876
|
+
if (author) rev.author = author;
|
|
4877
|
+
const date = attr(tblPrChange, "w:date");
|
|
4878
|
+
if (date) rev.date = date;
|
|
4879
|
+
const id = attrNum(tblPrChange, "w:id");
|
|
4880
|
+
if (id !== void 0) rev.id = id;
|
|
4881
|
+
const innerTblPr = findChild(tblPrChange, "w:tblPr");
|
|
4882
|
+
if (innerTblPr) Object.assign(rev, parseTablePropertiesEl(innerTblPr));
|
|
4883
|
+
if (Object.keys(rev).length > 0) opts.revision = rev;
|
|
4884
|
+
}
|
|
3687
4885
|
return opts;
|
|
3688
4886
|
}
|
|
3689
4887
|
function parseColumnWidthsEl(el) {
|
|
@@ -3707,10 +4905,105 @@ function parseTableRowPropertiesEl(el) {
|
|
|
3707
4905
|
rule: rule ?? "atLeast"
|
|
3708
4906
|
};
|
|
3709
4907
|
}
|
|
4908
|
+
const cnfStyle = findChild(el, "w:cnfStyle");
|
|
4909
|
+
if (cnfStyle) {
|
|
4910
|
+
const val = attr(cnfStyle, "w:val");
|
|
4911
|
+
if (val) {
|
|
4912
|
+
const cnf = { val };
|
|
4913
|
+
const changed = attrBool(cnfStyle, "w:changed");
|
|
4914
|
+
if (changed !== void 0) cnf.changed = changed;
|
|
4915
|
+
opts.cnfStyle = cnf;
|
|
4916
|
+
}
|
|
4917
|
+
}
|
|
4918
|
+
const divId = findChild(el, "w:divId");
|
|
4919
|
+
if (divId) {
|
|
4920
|
+
const val = attrNum(divId, "w:val");
|
|
4921
|
+
if (val !== void 0) opts.divId = val;
|
|
4922
|
+
}
|
|
4923
|
+
const gridBefore = findChild(el, "w:gridBefore");
|
|
4924
|
+
if (gridBefore) {
|
|
4925
|
+
const val = attrNum(gridBefore, "w:val");
|
|
4926
|
+
if (val !== void 0) opts.gridBefore = val;
|
|
4927
|
+
}
|
|
4928
|
+
const gridAfter = findChild(el, "w:gridAfter");
|
|
4929
|
+
if (gridAfter) {
|
|
4930
|
+
const val = attrNum(gridAfter, "w:val");
|
|
4931
|
+
if (val !== void 0) opts.gridAfter = val;
|
|
4932
|
+
}
|
|
4933
|
+
const wBefore = findChild(el, "w:wBefore");
|
|
4934
|
+
if (wBefore) {
|
|
4935
|
+
const rawSize = attr(wBefore, "w:w");
|
|
4936
|
+
const type = attr(wBefore, "w:type");
|
|
4937
|
+
const size = type === "pct" ? rawSize : attrNum(wBefore, "w:w");
|
|
4938
|
+
if (size !== void 0) opts.widthBefore = {
|
|
4939
|
+
size,
|
|
4940
|
+
...type ? { type } : {}
|
|
4941
|
+
};
|
|
4942
|
+
}
|
|
4943
|
+
const wAfter = findChild(el, "w:wAfter");
|
|
4944
|
+
if (wAfter) {
|
|
4945
|
+
const rawSize = attr(wAfter, "w:w");
|
|
4946
|
+
const type = attr(wAfter, "w:type");
|
|
4947
|
+
const size = type === "pct" ? rawSize : attrNum(wAfter, "w:w");
|
|
4948
|
+
if (size !== void 0) opts.widthAfter = {
|
|
4949
|
+
size,
|
|
4950
|
+
...type ? { type } : {}
|
|
4951
|
+
};
|
|
4952
|
+
}
|
|
4953
|
+
const jc = findChild(el, "w:jc");
|
|
4954
|
+
if (jc) {
|
|
4955
|
+
const val = attr(jc, "w:val");
|
|
4956
|
+
if (val) opts.rowAlignment = val;
|
|
4957
|
+
}
|
|
4958
|
+
const hidden = findChild(el, "w:hidden");
|
|
4959
|
+
if (hidden) opts.hidden = attrBool(hidden, "w:val") ?? true;
|
|
4960
|
+
const tblCellSpacing = findChild(el, "w:tblCellSpacing");
|
|
4961
|
+
if (tblCellSpacing) {
|
|
4962
|
+
const type = attr(tblCellSpacing, "w:type");
|
|
4963
|
+
const w = attrNum(tblCellSpacing, "w:w");
|
|
4964
|
+
if (w !== void 0) opts.cellSpacing = {
|
|
4965
|
+
value: w,
|
|
4966
|
+
...type ? { type } : {}
|
|
4967
|
+
};
|
|
4968
|
+
}
|
|
4969
|
+
const ins = findChild(el, "w:ins");
|
|
4970
|
+
if (ins) opts.insertion = parseChangeAttrs(ins);
|
|
4971
|
+
const del = findChild(el, "w:del");
|
|
4972
|
+
if (del) opts.deletion = parseChangeAttrs(del);
|
|
4973
|
+
const trPrChange = findChild(el, "w:trPrChange");
|
|
4974
|
+
if (trPrChange) {
|
|
4975
|
+
const rev = {};
|
|
4976
|
+
const author = attr(trPrChange, "w:author");
|
|
4977
|
+
if (author) rev.author = author;
|
|
4978
|
+
const date = attr(trPrChange, "w:date");
|
|
4979
|
+
if (date) rev.date = date;
|
|
4980
|
+
const id = attrNum(trPrChange, "w:id");
|
|
4981
|
+
if (id !== void 0) rev.id = id;
|
|
4982
|
+
const innerTrPr = findChild(trPrChange, "w:trPr");
|
|
4983
|
+
if (innerTrPr) Object.assign(rev, parseTableRowPropertiesEl(innerTrPr));
|
|
4984
|
+
if (Object.keys(rev).length > 0) opts.revision = rev;
|
|
4985
|
+
}
|
|
3710
4986
|
const tblHeader = findChild(el, "w:tblHeader");
|
|
3711
4987
|
if (tblHeader) opts.tableHeader = attrBool(tblHeader, "w:val") ?? true;
|
|
3712
4988
|
const cantSplit = findChild(el, "w:cantSplit");
|
|
3713
4989
|
if (cantSplit) opts.cantSplit = attrBool(cantSplit, "w:val") ?? true;
|
|
4990
|
+
const tblLook = findChild(el, "w:tblLook");
|
|
4991
|
+
if (tblLook) {
|
|
4992
|
+
const look = {};
|
|
4993
|
+
const firstRow = attrBool(tblLook, "w:firstRow");
|
|
4994
|
+
if (firstRow !== void 0) look.firstRow = firstRow;
|
|
4995
|
+
const lastRow = attrBool(tblLook, "w:lastRow");
|
|
4996
|
+
if (lastRow !== void 0) look.lastRow = lastRow;
|
|
4997
|
+
const firstColumn = attrBool(tblLook, "w:firstColumn");
|
|
4998
|
+
if (firstColumn !== void 0) look.firstColumn = firstColumn;
|
|
4999
|
+
const lastColumn = attrBool(tblLook, "w:lastColumn");
|
|
5000
|
+
if (lastColumn !== void 0) look.lastColumn = lastColumn;
|
|
5001
|
+
const noHBand = attrBool(tblLook, "w:noHBand");
|
|
5002
|
+
if (noHBand !== void 0) look.noHBand = noHBand;
|
|
5003
|
+
const noVBand = attrBool(tblLook, "w:noVBand");
|
|
5004
|
+
if (noVBand !== void 0) look.noVBand = noVBand;
|
|
5005
|
+
if (Object.keys(look).length > 0) opts.tableLook = look;
|
|
5006
|
+
}
|
|
3714
5007
|
return opts;
|
|
3715
5008
|
}
|
|
3716
5009
|
function parseTableCellPropertiesEl(el) {
|
|
@@ -3750,13 +5043,17 @@ function parseTableCellPropertiesEl(el) {
|
|
|
3750
5043
|
const tcBorders = findChild(el, "w:tcBorders");
|
|
3751
5044
|
if (tcBorders) {
|
|
3752
5045
|
const borders = {};
|
|
3753
|
-
for (const
|
|
3754
|
-
"top",
|
|
3755
|
-
"
|
|
3756
|
-
"left",
|
|
3757
|
-
"
|
|
5046
|
+
for (const [xmlSide, key] of [
|
|
5047
|
+
["top", "top"],
|
|
5048
|
+
["start", "start"],
|
|
5049
|
+
["left", "left"],
|
|
5050
|
+
["bottom", "bottom"],
|
|
5051
|
+
["end", "end"],
|
|
5052
|
+
["right", "right"],
|
|
5053
|
+
["tl2br", "topLeftToBottomRight"],
|
|
5054
|
+
["tr2bl", "topRightToBottomLeft"]
|
|
3758
5055
|
]) {
|
|
3759
|
-
const sideEl = findChild(tcBorders, `w:${
|
|
5056
|
+
const sideEl = findChild(tcBorders, `w:${xmlSide}`);
|
|
3760
5057
|
if (sideEl) {
|
|
3761
5058
|
const b = {};
|
|
3762
5059
|
const val = attr(sideEl, "w:val");
|
|
@@ -3765,12 +5062,13 @@ function parseTableCellPropertiesEl(el) {
|
|
|
3765
5062
|
if (color) b.color = color;
|
|
3766
5063
|
const sz = attrNum(sideEl, "w:sz");
|
|
3767
5064
|
if (sz !== void 0) b.size = sz;
|
|
3768
|
-
borders[
|
|
5065
|
+
borders[key] = b;
|
|
3769
5066
|
}
|
|
3770
5067
|
}
|
|
3771
5068
|
if (Object.keys(borders).length > 0) opts.borders = borders;
|
|
3772
5069
|
}
|
|
3773
|
-
|
|
5070
|
+
const noWrap = findChild(el, "w:noWrap");
|
|
5071
|
+
if (noWrap) opts.noWrap = attrBool(noWrap, "w:val") ?? true;
|
|
3774
5072
|
const tcMar = findChild(el, "w:tcMar");
|
|
3775
5073
|
if (tcMar) {
|
|
3776
5074
|
const margins = {};
|
|
@@ -3799,6 +5097,48 @@ function parseTableCellPropertiesEl(el) {
|
|
|
3799
5097
|
const val = attr(textDirection, "w:val");
|
|
3800
5098
|
if (val) opts.textDirection = val;
|
|
3801
5099
|
}
|
|
5100
|
+
const hMerge = findChild(el, "w:hMerge");
|
|
5101
|
+
if (hMerge) opts.horizontalMerge = attr(hMerge, "w:val") === "restart" ? "restart" : "continue";
|
|
5102
|
+
const tcFitText = findChild(el, "w:tcFitText");
|
|
5103
|
+
if (tcFitText) opts.fitText = attrBool(tcFitText, "w:val") ?? true;
|
|
5104
|
+
const hideMark = findChild(el, "w:hideMark");
|
|
5105
|
+
if (hideMark) opts.hideMark = attrBool(hideMark, "w:val") ?? true;
|
|
5106
|
+
const headersEl = findChild(el, "w:headers");
|
|
5107
|
+
if (headersEl) {
|
|
5108
|
+
const headerVals = [];
|
|
5109
|
+
for (const h of headersEl.elements ?? []) {
|
|
5110
|
+
if (h.name !== "w:header") continue;
|
|
5111
|
+
const val = attr(h, "w:val");
|
|
5112
|
+
if (val) headerVals.push(val);
|
|
5113
|
+
}
|
|
5114
|
+
if (headerVals.length > 0) opts.headers = headerVals;
|
|
5115
|
+
}
|
|
5116
|
+
const cellIns = findChild(el, "w:cellIns");
|
|
5117
|
+
if (cellIns) opts.insertion = parseChangeAttrs(cellIns);
|
|
5118
|
+
const cellDel = findChild(el, "w:cellDel");
|
|
5119
|
+
if (cellDel) opts.deletion = parseChangeAttrs(cellDel);
|
|
5120
|
+
const tcPrChange = findChild(el, "w:tcPrChange");
|
|
5121
|
+
if (tcPrChange) {
|
|
5122
|
+
const rev = {};
|
|
5123
|
+
const author = attr(tcPrChange, "w:author");
|
|
5124
|
+
if (author) rev.author = author;
|
|
5125
|
+
const date = attr(tcPrChange, "w:date");
|
|
5126
|
+
if (date) rev.date = date;
|
|
5127
|
+
const id = attrNum(tcPrChange, "w:id");
|
|
5128
|
+
if (id !== void 0) rev.id = id;
|
|
5129
|
+
const innerTcPr = findChild(tcPrChange, "w:tcPr");
|
|
5130
|
+
if (innerTcPr) Object.assign(rev, parseTableCellPropertiesEl(innerTcPr));
|
|
5131
|
+
if (Object.keys(rev).length > 0) opts.revision = rev;
|
|
5132
|
+
}
|
|
5133
|
+
const cellMerge = findChild(el, "w:cellMerge");
|
|
5134
|
+
if (cellMerge) {
|
|
5135
|
+
const cm = parseChangeAttrs(cellMerge);
|
|
5136
|
+
const vMerge = attr(cellMerge, "w:vMerge");
|
|
5137
|
+
if (vMerge) cm.verticalMerge = xsdVerticalMergeRev.from(vMerge);
|
|
5138
|
+
const vMergeOrig = attr(cellMerge, "w:vMergeOrig");
|
|
5139
|
+
if (vMergeOrig) cm.verticalMergeOriginal = xsdVerticalMergeRev.from(vMergeOrig);
|
|
5140
|
+
if (Object.keys(cm).length > 0) opts.cellMerge = cm;
|
|
5141
|
+
}
|
|
3802
5142
|
return opts;
|
|
3803
5143
|
}
|
|
3804
5144
|
function parseTableCellEl(el, ctx) {
|
|
@@ -3821,8 +5161,45 @@ function parseTableRowEl(el, ctx) {
|
|
|
3821
5161
|
const opts = {};
|
|
3822
5162
|
const trPr = findChild(el, "w:trPr");
|
|
3823
5163
|
if (trPr) Object.assign(opts, parseTableRowPropertiesEl(trPr));
|
|
5164
|
+
for (const [attrName, optKey] of [
|
|
5165
|
+
["w:rsidRPr", "rsidRPr"],
|
|
5166
|
+
["w:rsidR", "rsidR"],
|
|
5167
|
+
["w:rsidDel", "rsidDel"],
|
|
5168
|
+
["w:rsidTr", "rsidTr"]
|
|
5169
|
+
]) {
|
|
5170
|
+
const val = attr(el, attrName);
|
|
5171
|
+
if (val) opts[optKey] = val;
|
|
5172
|
+
}
|
|
3824
5173
|
const childCells = [];
|
|
3825
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
|
+
}
|
|
3826
5203
|
opts.cells = childCells;
|
|
3827
5204
|
return opts;
|
|
3828
5205
|
}
|
|
@@ -3834,6 +5211,34 @@ function parseTableEl(el, ctx) {
|
|
|
3834
5211
|
if (colWidths.length > 0) opts.columnWidths = colWidths;
|
|
3835
5212
|
const rows = [];
|
|
3836
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
|
+
}
|
|
3837
5242
|
opts.rows = rows;
|
|
3838
5243
|
return opts;
|
|
3839
5244
|
}
|
|
@@ -4402,6 +5807,10 @@ const createHeaderFooterReference = (type, options) => `<${type} r:id="rId${opti
|
|
|
4402
5807
|
*
|
|
4403
5808
|
* @module
|
|
4404
5809
|
*/
|
|
5810
|
+
/** Valid page-number @w:fmt values (ST_NumberFormat). */
|
|
5811
|
+
const PAGE_NUMBER_FORMATS = Object.values(NumberFormat);
|
|
5812
|
+
/** Valid page-number @w:chapSep values (ST_ChapterSep). */
|
|
5813
|
+
const PAGE_NUMBER_SEPARATORS = Object.values(PageNumberSeparator);
|
|
4405
5814
|
function stringifyBorderXml(tag, opts) {
|
|
4406
5815
|
const attrs = [];
|
|
4407
5816
|
if (opts.style !== void 0) attrs.push(`w:val="${opts.style}"`);
|
|
@@ -4516,14 +5925,14 @@ function stringifySectionPropertiesInner(opts) {
|
|
|
4516
5925
|
const parts = [];
|
|
4517
5926
|
appendHeaderFooterRefs(parts, "w:headerReference", opts.headerWrapperGroup);
|
|
4518
5927
|
appendHeaderFooterRefs(parts, "w:footerReference", opts.footerWrapperGroup);
|
|
4519
|
-
const { size: { width = sectionPageSizeDefaults.WIDTH, height = sectionPageSizeDefaults.HEIGHT, orientation = sectionPageSizeDefaults.ORIENTATION } = {}, margin: { top = sectionMarginDefaults.TOP, right = sectionMarginDefaults.RIGHT, bottom = sectionMarginDefaults.BOTTOM, left = sectionMarginDefaults.LEFT, header = sectionMarginDefaults.HEADER, footer = sectionMarginDefaults.FOOTER, gutter = sectionMarginDefaults.GUTTER } = {}, pageNumbers = {}, borders, textDirection } = opts.page ?? {};
|
|
5928
|
+
const { size: { width = sectionPageSizeDefaults.WIDTH, height = sectionPageSizeDefaults.HEIGHT, orientation = sectionPageSizeDefaults.ORIENTATION, code } = {}, margin: { top = sectionMarginDefaults.TOP, right = sectionMarginDefaults.RIGHT, bottom = sectionMarginDefaults.BOTTOM, left = sectionMarginDefaults.LEFT, header = sectionMarginDefaults.HEADER, footer = sectionMarginDefaults.FOOTER, gutter = sectionMarginDefaults.GUTTER } = {}, pageNumbers = {}, borders, textDirection } = opts.page ?? {};
|
|
4520
5929
|
const { linePitch = 312, charSpace = 0, type: gridType = "lines" } = opts.grid ?? {};
|
|
4521
5930
|
if (opts.footnotePr) parts.push(footnotePrXml("w:footnotePr", opts.footnotePr));
|
|
4522
5931
|
if (opts.endnotePr) parts.push(footnotePrXml("w:endnotePr", opts.endnotePr));
|
|
4523
5932
|
if (opts.type) parts.push(sectionTypeXml(opts.type));
|
|
4524
5933
|
const pgW = orientation === "landscape" ? convertToTwip(height) : width;
|
|
4525
5934
|
const pgH = orientation === "landscape" ? convertToTwip(width) : height;
|
|
4526
|
-
parts.push(pageSizeXml(pgW, pgH, orientation));
|
|
5935
|
+
parts.push(pageSizeXml(pgW, pgH, orientation, code));
|
|
4527
5936
|
parts.push(pageMarginXml(top, right, bottom, left, header, footer, gutter));
|
|
4528
5937
|
if (borders) parts.push(pageBordersXml(borders));
|
|
4529
5938
|
if (opts.lineNumbers) parts.push(lineNumberXml(opts.lineNumbers));
|
|
@@ -4605,6 +6014,8 @@ function parseSectionPropertiesEl(el) {
|
|
|
4605
6014
|
if (h !== void 0) size.height = h;
|
|
4606
6015
|
}
|
|
4607
6016
|
if (orient) size.orientation = orient;
|
|
6017
|
+
const code = attrNum(pgSz, "w:code");
|
|
6018
|
+
if (code !== void 0) size.code = code;
|
|
4608
6019
|
if (Object.keys(size).length > 0) page.size = size;
|
|
4609
6020
|
const pgMar = findChild(el, "w:pgMar");
|
|
4610
6021
|
if (pgMar) {
|
|
@@ -4629,7 +6040,11 @@ function parseSectionPropertiesEl(el) {
|
|
|
4629
6040
|
const start = attrNum(pgNumType, "w:start");
|
|
4630
6041
|
if (start !== void 0) pageNumbers.start = start;
|
|
4631
6042
|
const fmt = attr(pgNumType, "w:fmt");
|
|
4632
|
-
if (fmt) pageNumbers.formatType = fmt;
|
|
6043
|
+
if (fmt && PAGE_NUMBER_FORMATS.includes(fmt)) pageNumbers.formatType = fmt;
|
|
6044
|
+
const chapSep = attr(pgNumType, "w:chapSep");
|
|
6045
|
+
if (chapSep && PAGE_NUMBER_SEPARATORS.includes(chapSep)) pageNumbers.separator = chapSep;
|
|
6046
|
+
const chapStyle = attrNum(pgNumType, "w:chapStyle");
|
|
6047
|
+
if (chapStyle !== void 0) pageNumbers.chapStyle = chapStyle;
|
|
4633
6048
|
if (Object.keys(pageNumbers).length > 0) page.pageNumbers = pageNumbers;
|
|
4634
6049
|
}
|
|
4635
6050
|
if (Object.keys(page).length > 0) opts.page = page;
|
|
@@ -4641,7 +6056,21 @@ function parseSectionPropertiesEl(el) {
|
|
|
4641
6056
|
if (count !== void 0) column.count = count;
|
|
4642
6057
|
const space = attrNum(cols, "w:space");
|
|
4643
6058
|
if (space !== void 0) column.space = space;
|
|
4644
|
-
|
|
6059
|
+
const separate = attrBool(cols, "w:sep");
|
|
6060
|
+
if (separate !== void 0) column.separate = separate;
|
|
6061
|
+
const equalWidth = attrBool(cols, "w:equalWidth");
|
|
6062
|
+
if (equalWidth !== void 0) column.equalWidth = equalWidth;
|
|
6063
|
+
const colChildren = [];
|
|
6064
|
+
for (const colEl of cols.elements ?? []) {
|
|
6065
|
+
if (colEl.name !== "w:col") continue;
|
|
6066
|
+
const width = attrNum(colEl, "w:w");
|
|
6067
|
+
if (width === void 0) continue;
|
|
6068
|
+
const colAttr = { width };
|
|
6069
|
+
const colSpace = attrNum(colEl, "w:space");
|
|
6070
|
+
if (colSpace !== void 0) colAttr.space = colSpace;
|
|
6071
|
+
colChildren.push(colAttr);
|
|
6072
|
+
}
|
|
6073
|
+
if (colChildren.length > 0) column.children = colChildren;
|
|
4645
6074
|
if (Object.keys(column).length > 0) opts.column = column;
|
|
4646
6075
|
}
|
|
4647
6076
|
const type = findChild(el, "w:type");
|
|
@@ -4793,6 +6222,6 @@ function parseNotePropertiesEl(el) {
|
|
|
4793
6222
|
return opts;
|
|
4794
6223
|
}
|
|
4795
6224
|
//#endregion
|
|
4796
|
-
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 };
|
|
4797
6226
|
|
|
4798
|
-
//# sourceMappingURL=document-
|
|
6227
|
+
//# sourceMappingURL=document-DYH7tGnw.mjs.map
|