@office-open/docx 0.9.2 → 0.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- import { A as stringifyParagraphProperties, D as stringifyChildDispatch, E as tableDesc, F as parseDrawingRun, M as parseMathChildren, O as stringifyParagraphInline, Y as BorderStyle, at as Media, j as stringifyRunProperties, n as sectionPropertiesDesc, ot as createTransformation } from "./document-CeM-U6J3.mjs";
2
- import { Relationships, convertInchesToTwip, decimalNumber, derivePasswordHash, hexColorValue, toUint8Array, uCharHexNumber, uniqueId, uniqueNumericIdCreator, uniqueUuid } from "@office-open/core";
3
- import { attr, attrBool, attrNum, children, colorAttr, element, escapeXml, findChild, js2xml, textOf, xml2js } from "@office-open/xml";
1
+ import { A as stringifyParagraphProperties, D as stringifyChildDispatch, E as tableDesc, I as parseDrawingRun, M as stringifyRunPropertiesInner, N as parseMathChildren, O as stringifyParagraphInline, X as BorderStyle, j as stringifyRunProperties, lt as Media, n as sectionPropertiesDesc, tt as parseFormFieldData, ut as createTransformation } from "./document-B_uvEH8b.mjs";
2
+ import { Relationships, ThemeColor, convertInchesToTwip, decimalNumber, derivePasswordHash, hexColorValue, toUint8Array, uCharHexNumber, uniqueId, uniqueNumericIdCreator, uniqueUuid } from "@office-open/core";
3
+ import { attr, attrBool, attrNum, children, colorAttr, escapeXml, findChild, js2xml, textOf, xml2js } from "@office-open/xml";
4
4
  import { ChartCollection } from "@office-open/core/chart";
5
5
  import { SmartArtCollection } from "@office-open/core/smartart";
6
6
  //#region src/parts/paragraph/formatting/alignment.ts
@@ -74,6 +74,35 @@ const AlignmentType = {
74
74
  JUSTIFIED: "both"
75
75
  };
76
76
  //#endregion
77
+ //#region src/parts/paragraph/formatting/spacing.ts
78
+ /**
79
+ * Paragraph spacing module for WordprocessingML documents.
80
+ *
81
+ * This module provides spacing options for paragraphs including space before,
82
+ * space after, and line spacing.
83
+ *
84
+ * Reference: http://officeopenxml.com/WPspacing.php
85
+ *
86
+ * @module
87
+ */
88
+ /**
89
+ * Line spacing rule types.
90
+ *
91
+ * Specifies how the line height is calculated.
92
+ *
93
+ * @publicApi
94
+ */
95
+ const LineRuleType = {
96
+ /** Line spacing is at least the specified value */
97
+ AT_LEAST: "atLeast",
98
+ /** Line spacing is exactly the specified value */
99
+ EXACTLY: "exactly",
100
+ /** Line spacing is exactly the specified value (alias for EXACTLY) */
101
+ EXACT: "exact",
102
+ /** Line spacing is automatically determined based on content */
103
+ AUTO: "auto"
104
+ };
105
+ //#endregion
77
106
  //#region src/parts/paragraph/formatting/style.ts
78
107
  /**
79
108
  * Paragraph style module for WordprocessingML documents.
@@ -440,154 +469,6 @@ const RubyAlign = {
440
469
  RIGHT_VERTICAL: "rightVertical"
441
470
  };
442
471
  //#endregion
443
- //#region src/parts/paragraph/run/form-field.ts
444
- /**
445
- * Form field module for WordprocessingML documents.
446
- *
447
- * Form fields allow creating interactive controls (checkboxes, dropdown lists,
448
- * text inputs) within a document. Each form field is wrapped in a field code
449
- * region delimited by fldChar elements (begin/separate/end), with ffData
450
- * attached to the begin fldChar.
451
- *
452
- * Reference: ISO/IEC 29500-4, wml.xsd, CT_FFData, CT_FFCheckBox, CT_FFDDList, CT_FFTextInput
453
- *
454
- * @module
455
- */
456
- /**
457
- * Text input field type (ST_FFTextType).
458
- *
459
- * ## XSD Schema
460
- * ```xml
461
- * <xsd:simpleType name="ST_FFTextType">
462
- * <xsd:restriction base="xsd:string">
463
- * <xsd:enumeration value="regular"/>
464
- * <xsd:enumeration value="number"/>
465
- * <xsd:enumeration value="date"/>
466
- * <xsd:enumeration value="currentTime"/>
467
- * <xsd:enumeration value="currentDate"/>
468
- * <xsd:enumeration value="calculated"/>
469
- * </xsd:restriction>
470
- * </xsd:simpleType>
471
- * ```
472
- */
473
- const FormFieldTextType = {
474
- /** Regular text input */
475
- REGULAR: "regular",
476
- /** Numeric input */
477
- NUMBER: "number",
478
- /** Date input */
479
- DATE: "date",
480
- /** Current time */
481
- CURRENT_TIME: "currentTime",
482
- /** Current date */
483
- CURRENT_DATE: "currentDate",
484
- /** Calculated value */
485
- CALCULATED: "calculated"
486
- };
487
- /** Build a w:val-style element with a single attribute. */
488
- const valElement = (name, val) => `<${name} w:val="${val}"/>`;
489
- /**
490
- * Creates a help or status text element.
491
- */
492
- const createFormFieldText = (name, options) => `<${name} w:type="${options.type}" w:val="${options.value}"/>`;
493
- /**
494
- * Creates a checkbox form field element (w:checkBox).
495
- */
496
- const createCheckBox = (options) => {
497
- const children = [];
498
- if (options.size !== void 0) children.push(valElement("w:size", options.size));
499
- else if (options.sizeAuto !== void 0) children.push(`<w:sizeAuto/>`);
500
- if (options.default !== void 0) children.push(`<w:default/>`);
501
- if (options.checked !== void 0) children.push(`<w:checked/>`);
502
- return element("w:checkBox", void 0, children);
503
- };
504
- /**
505
- * Creates a dropdown list form field element (w:ddList).
506
- */
507
- const createDropDownList = (options) => {
508
- const children = [];
509
- if (options.result !== void 0) children.push(valElement("w:result", options.result));
510
- if (options.default !== void 0) children.push(valElement("w:default", options.default));
511
- for (const entry of options.entries) children.push(valElement("w:listEntry", entry));
512
- return element("w:ddList", void 0, children);
513
- };
514
- /**
515
- * Creates a text input form field element (w:textInput).
516
- */
517
- const createTextInput = (options) => {
518
- const children = [];
519
- if (options.type !== void 0) children.push(valElement("w:type", options.type));
520
- if (options.default !== void 0) children.push(valElement("w:default", options.default));
521
- if (options.maxLength !== void 0) children.push(valElement("w:maxLength", options.maxLength));
522
- if (options.format !== void 0) children.push(valElement("w:format", options.format));
523
- return element("w:textInput", void 0, children);
524
- };
525
- /**
526
- * Creates a form field data element (w:ffData).
527
- *
528
- * This element contains the definition for an interactive form field
529
- * (checkbox, dropdown list, or text input) within a document.
530
- *
531
- * ## XSD Schema
532
- * ```xml
533
- * <xsd:complexType name="CT_FFData">
534
- * <xsd:choice maxOccurs="unbounded">
535
- * <xsd:element name="name" type="CT_FFName"/>
536
- * <xsd:element name="label" type="CT_DecimalNumber"/>
537
- * <xsd:element name="tabIndex" type="CT_UnsignedDecimalNumber"/>
538
- * <xsd:element name="enabled" type="CT_OnOff"/>
539
- * <xsd:element name="calcOnExit" type="CT_OnOff"/>
540
- * <xsd:element name="entryMacro" type="CT_MacroName"/>
541
- * <xsd:element name="exitMacro" type="CT_MacroName"/>
542
- * <xsd:element name="helpText" type="CT_FFHelpText"/>
543
- * <xsd:element name="statusText" type="CT_FFStatusText"/>
544
- * <xsd:choice>
545
- * <xsd:element name="checkBox" type="CT_FFCheckBox"/>
546
- * <xsd:element name="ddList" type="CT_FFDDList"/>
547
- * <xsd:element name="textInput" type="CT_FFTextInput"/>
548
- * </xsd:choice>
549
- * </xsd:choice>
550
- * </xsd:complexType>
551
- * ```
552
- *
553
- * @example
554
- * ```typescript
555
- * // Checkbox
556
- * createFormFieldData({
557
- * name: "Check1",
558
- * checkBox: { checked: true, sizeAuto: true },
559
- * });
560
- *
561
- * // Dropdown
562
- * createFormFieldData({
563
- * name: "DropDown1",
564
- * dropDownList: { entries: ["Option A", "Option B", "Option C"], result: 0 },
565
- * });
566
- *
567
- * // Text input
568
- * createFormFieldData({
569
- * name: "Text1",
570
- * textInput: { type: "regular", default: "Enter text here" },
571
- * });
572
- * ```
573
- */
574
- const createFormFieldData = (options) => {
575
- const children = [];
576
- if (options.name !== void 0) children.push(valElement("w:name", options.name));
577
- if (options.label !== void 0) children.push(valElement("w:label", options.label));
578
- if (options.tabIndex !== void 0) children.push(valElement("w:tabIndex", options.tabIndex));
579
- if (options.enabled !== void 0) children.push(`<w:enabled/>`);
580
- if (options.calcOnExit !== void 0) children.push(`<w:calcOnExit/>`);
581
- if (options.entryMacro !== void 0) children.push(valElement("w:entryMacro", options.entryMacro));
582
- if (options.exitMacro !== void 0) children.push(valElement("w:exitMacro", options.exitMacro));
583
- if (options.helpText) children.push(createFormFieldText("w:helpText", options.helpText));
584
- if (options.statusText) children.push(createFormFieldText("w:statusText", options.statusText));
585
- if (options.checkBox) children.push(createCheckBox(options.checkBox));
586
- else if (options.dropDownList) children.push(createDropDownList(options.dropDownList));
587
- else if (options.textInput) children.push(createTextInput(options.textInput));
588
- return element("w:ffData", void 0, children);
589
- };
590
- //#endregion
591
472
  //#region src/parts/paragraph/run/proof-error.ts
592
473
  /**
593
474
  * Proof error types for WordprocessingML documents.
@@ -717,202 +598,658 @@ const TABLE_BORDERS_NONE = {
717
598
  top: NONE_BORDER
718
599
  };
719
600
  //#endregion
720
- //#region src/parts/numbering/level.ts
721
- /**
722
- * Number format types for list levels.
723
- *
724
- * Defines the various numbering formats available for list levels, including
725
- * decimal, roman numerals, letters, and various international formats.
726
- *
727
- * Reference: http://officeopenxml.com/WPnumbering-numFmt.php
728
- *
729
- * @publicApi
730
- */
731
- const LevelFormat = {
732
- /** Decimal numbering (1, 2, 3...). */
733
- DECIMAL: "decimal",
734
- /** Uppercase roman numerals (I, II, III...). */
735
- UPPER_ROMAN: "upperRoman",
736
- /** Lowercase roman numerals (i, ii, iii...). */
737
- LOWER_ROMAN: "lowerRoman",
738
- /** Uppercase letters (A, B, C...). */
739
- UPPER_LETTER: "upperLetter",
740
- /** Lowercase letters (a, b, c...). */
741
- LOWER_LETTER: "lowerLetter",
742
- /** Ordinal numbers (1st, 2nd, 3rd...). */
743
- ORDINAL: "ordinal",
744
- /** Cardinal text (one, two, three...). */
745
- CARDINAL_TEXT: "cardinalText",
746
- /** Ordinal text (first, second, third...). */
747
- ORDINAL_TEXT: "ordinalText",
748
- /** Hexadecimal numbering. */
749
- HEX: "hex",
750
- /** Chicago Manual of Style numbering. */
751
- CHICAGO: "chicago",
752
- /** Ideograph digital numbering. */
753
- IDEOGRAPH__DIGITAL: "ideographDigital",
754
- /** Japanese counting system. */
755
- JAPANESE_COUNTING: "japaneseCounting",
756
- /** Japanese aiueo ordering. */
757
- AIUEO: "aiueo",
758
- /** Japanese iroha ordering. */
759
- IROHA: "iroha",
760
- /** Full-width decimal numbering. */
761
- DECIMAL_FULL_WIDTH: "decimalFullWidth",
762
- /** Half-width decimal numbering. */
763
- DECIMAL_HALF_WIDTH: "decimalHalfWidth",
764
- /** Japanese legal numbering. */
765
- JAPANESE_LEGAL: "japaneseLegal",
766
- /** Japanese digital ten thousand numbering. */
767
- JAPANESE_DIGITAL_TEN_THOUSAND: "japaneseDigitalTenThousand",
768
- /** Decimal numbers enclosed in circles. */
769
- DECIMAL_ENCLOSED_CIRCLE: "decimalEnclosedCircle",
770
- /** Full-width decimal numbering variant 2. */
771
- DECIMAL_FULL_WIDTH2: "decimalFullWidth2",
772
- /** Full-width aiueo ordering. */
773
- AIUEO_FULL_WIDTH: "aiueoFullWidth",
774
- /** Full-width iroha ordering. */
775
- IROHA_FULL_WIDTH: "irohaFullWidth",
776
- /** Decimal with leading zeros. */
777
- DECIMAL_ZERO: "decimalZero",
778
- /** Bullet points. */
779
- BULLET: "bullet",
780
- /** Korean ganada ordering. */
781
- GANADA: "ganada",
782
- /** Korean chosung ordering. */
783
- CHOSUNG: "chosung",
784
- /** Decimal enclosed with fullstop. */
785
- DECIMAL_ENCLOSED_FULLSTOP: "decimalEnclosedFullstop",
786
- /** Decimal enclosed in parentheses. */
787
- DECIMAL_ENCLOSED_PARENTHESES: "decimalEnclosedParen",
788
- /** Decimal enclosed in circles (Chinese). */
789
- DECIMAL_ENCLOSED_CIRCLE_CHINESE: "decimalEnclosedCircleChinese",
790
- /** Ideograph enclosed in circles. */
791
- IDEOGRAPH_ENCLOSED_CIRCLE: "ideographEnclosedCircle",
792
- /** Traditional ideograph numbering. */
793
- IDEOGRAPH_TRADITIONAL: "ideographTraditional",
794
- /** Ideograph zodiac numbering. */
795
- IDEOGRAPH_ZODIAC: "ideographZodiac",
796
- /** Traditional ideograph zodiac numbering. */
797
- IDEOGRAPH_ZODIAC_TRADITIONAL: "ideographZodiacTraditional",
798
- /** Taiwanese counting system. */
799
- TAIWANESE_COUNTING: "taiwaneseCounting",
800
- /** Traditional ideograph legal numbering. */
801
- IDEOGRAPH_LEGAL_TRADITIONAL: "ideographLegalTraditional",
802
- /** Taiwanese counting thousand system. */
803
- TAIWANESE_COUNTING_THOUSAND: "taiwaneseCountingThousand",
804
- /** Taiwanese digital numbering. */
805
- TAIWANESE_DIGITAL: "taiwaneseDigital",
806
- /** Chinese counting system. */
807
- CHINESE_COUNTING: "chineseCounting",
808
- /** Simplified Chinese legal numbering. */
809
- CHINESE_LEGAL_SIMPLIFIED: "chineseLegalSimplified",
810
- /** Chinese counting thousand system. */
811
- CHINESE_COUNTING_THOUSAND: "chineseCountingThousand",
812
- /** Korean digital numbering. */
813
- KOREAN_DIGITAL: "koreanDigital",
814
- /** Korean counting system. */
815
- KOREAN_COUNTING: "koreanCounting",
816
- /** Korean legal numbering. */
817
- KOREAN_LEGAL: "koreanLegal",
818
- /** Korean digital numbering variant 2. */
819
- KOREAN_DIGITAL2: "koreanDigital2",
820
- /** Vietnamese counting system. */
821
- VIETNAMESE_COUNTING: "vietnameseCounting",
822
- /** Russian lowercase numbering. */
823
- RUSSIAN_LOWER: "russianLower",
824
- /** Russian uppercase numbering. */
825
- RUSSIAN_UPPER: "russianUpper",
826
- /** No numbering. */
827
- NONE: "none",
828
- /** Number enclosed in dashes. */
829
- NUMBER_IN_DASH: "numberInDash",
830
- /** Hebrew numbering variant 1. */
831
- HEBREW1: "hebrew1",
832
- /** Hebrew numbering variant 2. */
833
- HEBREW2: "hebrew2",
834
- /** Arabic alpha numbering. */
835
- ARABIC_ALPHA: "arabicAlpha",
836
- /** Arabic abjad numbering. */
837
- ARABIC_ABJAD: "arabicAbjad",
838
- /** Hindi vowels. */
839
- HINDI_VOWELS: "hindiVowels",
840
- /** Hindi consonants. */
841
- HINDI_CONSONANTS: "hindiConsonants",
842
- /** Hindi numbers. */
843
- HINDI_NUMBERS: "hindiNumbers",
844
- /** Hindi counting system. */
845
- HINDI_COUNTING: "hindiCounting",
846
- /** Thai letters. */
847
- THAI_LETTERS: "thaiLetters",
848
- /** Thai numbers. */
849
- THAI_NUMBERS: "thaiNumbers",
850
- /** Thai counting system. */
851
- THAI_COUNTING: "thaiCounting",
852
- /** Thai Baht text. */
853
- BAHT_TEXT: "bahtText",
854
- /** Dollar text. */
855
- DOLLAR_TEXT: "dollarText",
856
- /** Custom numbering format. */
857
- CUSTOM: "custom"
858
- };
601
+ //#region src/parts/paragraph/run/run-parse.ts
859
602
  /**
860
- * Suffix types for list levels.
603
+ * Run properties parser for DOCX documents.
861
604
  *
862
- * Defines what follows the numbering text (tab, space, or nothing).
605
+ * Parses w:rPr Element trees into RunPropertiesOptions objects.
863
606
  *
864
- * @publicApi
607
+ * @module
865
608
  */
866
- const LevelSuffix = {
867
- /** No separator after the numbering. */
868
- NOTHING: "nothing",
869
- /** Space character after the numbering. */
870
- SPACE: "space",
871
- /** Tab character after the numbering. */
872
- TAB: "tab"
873
- };
874
- //#endregion
875
- //#region src/parts/numbering/numbering.ts
876
609
  /**
877
- * Numbering module for WordprocessingML documents.
878
- *
879
- * Numbering provides support for numbered and bulleted lists.
880
- * Pure string serialization — no XmlComponent inheritance.
881
- *
882
- * Reference: http://officeopenxml.com/WPnumbering.php
883
- *
884
- * @module
610
+ * Parse a w:rPr element into RunPropertiesOptions.
885
611
  */
886
- /** Namespace attributes for w:numbering (pre-computed constant). */
887
- const NUMBERING_ATTRS = "xmlns:wpc=\"http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" xmlns:o=\"urn:schemas-microsoft-com:office:office\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:wp14=\"http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" xmlns:w10=\"urn:schemas-microsoft-com:office:word\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:w14=\"http://schemas.microsoft.com/office/word/2010/wordml\" xmlns:w15=\"http://schemas.microsoft.com/office/word/2012/wordml\" xmlns:wpg=\"http://schemas.microsoft.com/office/word/2010/wordprocessingGroup\" xmlns:wpi=\"http://schemas.microsoft.com/office/word/2010/wordprocessingInk\" xmlns:wne=\"http://schemas.microsoft.com/office/word/2006/wordml\" xmlns:wps=\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\" mc:Ignorable=\"w14 w15 wp14\"";
888
- /** Default bullet levels (9 levels: 0-8). */
889
- const DEFAULT_BULLET_LEVELS = [
890
- {
891
- alignment: AlignmentType.LEFT,
892
- format: LevelFormat.BULLET,
893
- level: 0,
894
- style: { paragraph: { indent: {
895
- hanging: convertInchesToTwip(.25),
896
- left: convertInchesToTwip(.5)
897
- } } },
898
- text: "●"
899
- },
900
- {
901
- alignment: AlignmentType.LEFT,
902
- format: LevelFormat.BULLET,
903
- level: 1,
904
- style: { paragraph: { indent: {
905
- hanging: convertInchesToTwip(.25),
906
- left: convertInchesToTwip(1)
907
- } } },
908
- text: "○"
909
- },
910
- {
911
- alignment: AlignmentType.LEFT,
912
- format: LevelFormat.BULLET,
913
- level: 2,
914
- style: { paragraph: { indent: {
915
- hanging: convertInchesToTwip(.25),
612
+ function parseRunProperties(el) {
613
+ const opts = {};
614
+ const rStyle = findChild(el, "w:rStyle");
615
+ if (rStyle) opts.style = attr(rStyle, "w:val");
616
+ const font = findChild(el, "w:rFonts");
617
+ if (font) {
618
+ const ascii = attr(font, "w:ascii");
619
+ const eastAsia = attr(font, "w:eastAsia");
620
+ const hAnsi = attr(font, "w:hAnsi");
621
+ const cs = attr(font, "w:cs");
622
+ const hint = attr(font, "w:hint");
623
+ if (ascii && !eastAsia && !hAnsi && !cs) opts.font = hint ? {
624
+ name: ascii,
625
+ hint
626
+ } : ascii;
627
+ else {
628
+ const fontObj = {};
629
+ if (ascii) fontObj.ascii = ascii;
630
+ if (eastAsia) fontObj.eastAsia = eastAsia;
631
+ if (hAnsi) fontObj.hAnsi = hAnsi;
632
+ if (cs) fontObj.cs = cs;
633
+ if (hint) fontObj.hint = hint;
634
+ opts.font = fontObj;
635
+ }
636
+ }
637
+ const bold = findChild(el, "w:b");
638
+ if (bold) opts.bold = attrBool(bold, "w:val") ?? true;
639
+ const boldCs = findChild(el, "w:bCs");
640
+ if (boldCs) opts.boldComplexScript = attrBool(boldCs, "w:val") ?? true;
641
+ const italic = findChild(el, "w:i");
642
+ if (italic) opts.italic = attrBool(italic, "w:val") ?? true;
643
+ const italicCs = findChild(el, "w:iCs");
644
+ if (italicCs) opts.italicComplexScript = attrBool(italicCs, "w:val") ?? true;
645
+ const underline = findChild(el, "w:u");
646
+ if (underline) {
647
+ const ul = {};
648
+ const uType = attr(underline, "w:val");
649
+ if (uType) ul.type = uType;
650
+ const uColor = colorAttr(underline, "w:color");
651
+ if (uColor) ul.color = uColor;
652
+ opts.underline = ul;
653
+ }
654
+ for (const [name, optKey] of [
655
+ ["w:strike", "strike"],
656
+ ["w:dstrike", "doubleStrike"],
657
+ ["w:outline", "outline"],
658
+ ["w:shadow", "shadow"],
659
+ ["w:emboss", "emboss"],
660
+ ["w:imprint", "imprint"],
661
+ ["w:vanish", "vanish"],
662
+ ["w:webHidden", "webHidden"],
663
+ ["w:noProof", "noProof"],
664
+ ["w:snapToGrid", "snapToGrid"],
665
+ ["w:smallCaps", "smallCaps"],
666
+ ["w:caps", "allCaps"],
667
+ ["w:rtl", "rightToLeft"],
668
+ ["w:cs", "complexScript"],
669
+ ["w:specVanish", "specVanish"],
670
+ ["w:oMath", "math"]
671
+ ]) {
672
+ const child = findChild(el, name);
673
+ if (child) opts[optKey] = attrBool(child, "w:val") ?? true;
674
+ }
675
+ const color = findChild(el, "w:color");
676
+ if (color) {
677
+ const c = colorAttr(color, "w:val");
678
+ const themeColor = attr(color, "w:themeColor");
679
+ const themeTint = attr(color, "w:themeTint");
680
+ const themeShade = attr(color, "w:themeShade");
681
+ if (themeColor || themeTint || themeShade) {
682
+ const colorObj = {};
683
+ if (c) colorObj.val = c;
684
+ if (themeColor) colorObj.themeColor = themeColor;
685
+ if (themeTint) colorObj.themeTint = themeTint;
686
+ if (themeShade) colorObj.themeShade = themeShade;
687
+ opts.color = colorObj;
688
+ } else if (c) opts.color = c;
689
+ }
690
+ const sz = findChild(el, "w:sz");
691
+ if (sz) {
692
+ const halfPts = attrNum(sz, "w:val");
693
+ if (halfPts !== void 0) opts.size = halfPts / 2;
694
+ }
695
+ const szCs = findChild(el, "w:szCs");
696
+ if (szCs) {
697
+ const halfPts = attrNum(szCs, "w:val");
698
+ if (halfPts !== void 0) opts.sizeComplexScript = halfPts / 2;
699
+ }
700
+ const highlight = findChild(el, "w:highlight");
701
+ if (highlight) {
702
+ const val = attr(highlight, "w:val");
703
+ if (val) opts.highlight = val;
704
+ }
705
+ const highlightCs = findChild(el, "w:highlightCs");
706
+ if (highlightCs) {
707
+ const val = attr(highlightCs, "w:val");
708
+ if (val) opts.highlightComplexScript = val;
709
+ }
710
+ const vertAlign = findChild(el, "w:vertAlign");
711
+ if (vertAlign) {
712
+ const val = attr(vertAlign, "w:val");
713
+ if (val === "subscript") opts.subScript = true;
714
+ else if (val === "superscript") opts.superScript = true;
715
+ }
716
+ const effect = findChild(el, "w:effect");
717
+ if (effect) {
718
+ const val = attr(effect, "w:val");
719
+ if (val) opts.effect = val;
720
+ }
721
+ const emphasisMark = findChild(el, "w:em");
722
+ if (emphasisMark) {
723
+ const val = attr(emphasisMark, "w:val");
724
+ if (val) opts.emphasisMark = { type: val };
725
+ }
726
+ const spacing = findChild(el, "w:spacing");
727
+ if (spacing) {
728
+ const val = attrNum(spacing, "w:val");
729
+ if (val !== void 0) opts.characterSpacing = val;
730
+ }
731
+ const scale = findChild(el, "w:w");
732
+ if (scale) {
733
+ const val = attrNum(scale, "w:val");
734
+ if (val !== void 0) opts.scale = val;
735
+ }
736
+ const kern = findChild(el, "w:kern");
737
+ if (kern) {
738
+ const val = attrNum(kern, "w:val");
739
+ if (val !== void 0) opts.kern = val;
740
+ }
741
+ const position = findChild(el, "w:position");
742
+ if (position) {
743
+ const val = attr(position, "w:val");
744
+ if (val !== void 0) opts.position = val;
745
+ }
746
+ const fitText = findChild(el, "w:fitText");
747
+ if (fitText) {
748
+ const val = attrNum(fitText, "w:val");
749
+ if (val !== void 0) opts.fitText = val;
750
+ }
751
+ const lang = findChild(el, "w:lang");
752
+ if (lang) {
753
+ const langObj = {};
754
+ const val = attr(lang, "w:val");
755
+ if (val) langObj.value = val;
756
+ const eastAsia = attr(lang, "w:eastAsia");
757
+ if (eastAsia) langObj.eastAsia = eastAsia;
758
+ const bidi = attr(lang, "w:bidi");
759
+ if (bidi) langObj.bidirectional = bidi;
760
+ if (Object.keys(langObj).length > 0) opts.language = langObj;
761
+ }
762
+ const bdr = findChild(el, "w:bdr");
763
+ if (bdr) opts.border = parseBorder(bdr);
764
+ const shd = findChild(el, "w:shd");
765
+ if (shd) opts.shading = parseShading(shd);
766
+ const eastAsianLayout = findChild(el, "w:eastAsianLayout");
767
+ if (eastAsianLayout) opts.eastAsianLayout = parseEastAsianLayout(eastAsianLayout);
768
+ const contentPart = findChild(el, "w:contentPart");
769
+ if (contentPart) {
770
+ const rId = attr(contentPart, "r:id");
771
+ if (rId) opts.contentPartRId = rId;
772
+ }
773
+ const rPrChange = findChild(el, "w:rPrChange");
774
+ if (rPrChange) {
775
+ const rev = {};
776
+ const author = attr(rPrChange, "w:author");
777
+ if (author) rev.author = author;
778
+ const date = attr(rPrChange, "w:date");
779
+ if (date) rev.date = date;
780
+ const id = attrNum(rPrChange, "w:id");
781
+ if (id !== void 0) rev.id = id;
782
+ const innerRPr = findChild(rPrChange, "w:rPr");
783
+ if (innerRPr) Object.assign(rev, parseRunProperties(innerRPr));
784
+ if (Object.keys(rev).length > 0) opts.revision = rev;
785
+ }
786
+ return opts;
787
+ }
788
+ /**
789
+ * Parse a w:bdr element into BorderOptions.
790
+ */
791
+ function parseBorder(el) {
792
+ const opts = {};
793
+ const style = attr(el, "w:val");
794
+ if (style) opts.style = style;
795
+ const color = colorAttr(el, "w:color");
796
+ if (color) opts.color = color;
797
+ const size = attrNum(el, "w:sz");
798
+ if (size !== void 0) opts.size = size;
799
+ const space = attrNum(el, "w:space");
800
+ if (space !== void 0) opts.space = space;
801
+ const shadow = attrBool(el, "w:shadow");
802
+ if (shadow !== void 0) opts.shadow = shadow;
803
+ const frame = attrBool(el, "w:frame");
804
+ if (frame !== void 0) opts.frame = frame;
805
+ return opts;
806
+ }
807
+ /**
808
+ * Parse a w:shd element into ShadingAttributesProperties.
809
+ */
810
+ function parseShading(el) {
811
+ const opts = {};
812
+ const fill = colorAttr(el, "w:fill");
813
+ if (fill) opts.fill = fill;
814
+ const color = colorAttr(el, "w:color");
815
+ if (color) opts.color = color;
816
+ const type = attr(el, "w:val");
817
+ if (type) opts.type = type;
818
+ return opts;
819
+ }
820
+ /**
821
+ * Parse a w:eastAsianLayout element into EastAsianLayoutOptions.
822
+ */
823
+ function parseEastAsianLayout(el) {
824
+ const opts = {};
825
+ const id = attrNum(el, "w:id");
826
+ if (id !== void 0) opts.id = id;
827
+ const combine = attrBool(el, "w:combine");
828
+ if (combine !== void 0) opts.combine = combine;
829
+ const combineBrackets = attr(el, "w:combineBrackets");
830
+ if (combineBrackets) opts.combineBrackets = combineBrackets;
831
+ const vert = attrBool(el, "w:vert");
832
+ if (vert !== void 0) opts.vert = vert;
833
+ const vertCompress = attrBool(el, "w:vertCompress");
834
+ if (vertCompress !== void 0) opts.vertCompress = vertCompress;
835
+ return opts;
836
+ }
837
+ /** Matches w:br[@w:type="page"] → PageBreak */
838
+ const PARSED_PAGE_BREAK = Symbol("PageBreak");
839
+ /** Matches w:br (line break) */
840
+ const PARSED_LINE_BREAK = Symbol("LineBreak");
841
+ /** Matches w:tab */
842
+ const PARSED_TAB = Symbol("Tab");
843
+ /** Matches w:cr */
844
+ const PARSED_CR = Symbol("CarriageReturn");
845
+ /** Matches w:noBreakHyphen */
846
+ const PARSED_NO_BREAK_HYPHEN = Symbol("NoBreakHyphen");
847
+ /** Matches w:softHyphen */
848
+ const PARSED_SOFT_HYPHEN = Symbol("SoftHyphen");
849
+ /** Matches w:footnoteRef — auto-generated by Footnote class */
850
+ const PARSED_FOOTNOTE_REF = Symbol("FootnoteRef");
851
+ /** Matches w:br[@w:type="column"] */
852
+ const PARSED_COLUMN_BREAK = Symbol("ColumnBreak");
853
+ /** Matches w:dayShort */
854
+ const PARSED_DAY_SHORT = Symbol("DayShort");
855
+ /** Matches w:monthShort */
856
+ const PARSED_MONTH_SHORT = Symbol("MonthShort");
857
+ /** Matches w:yearShort */
858
+ const PARSED_YEAR_SHORT = Symbol("YearShort");
859
+ /** Matches w:dayLong */
860
+ const PARSED_DAY_LONG = Symbol("DayLong");
861
+ /** Matches w:monthLong */
862
+ const PARSED_MONTH_LONG = Symbol("MonthLong");
863
+ /** Matches w:yearLong */
864
+ const PARSED_YEAR_LONG = Symbol("YearLong");
865
+ /** Matches w:annotationRef */
866
+ const PARSED_ANNOTATION_REF = Symbol("AnnotationRef");
867
+ /** Matches w:separator */
868
+ const PARSED_SEPARATOR = Symbol("Separator");
869
+ /** Matches w:continuationSeparator */
870
+ const PARSED_CONTINUATION_SEPARATOR = Symbol("ContinuationSeparator");
871
+ /** Matches w:pgNum */
872
+ const PARSED_PG_NUM = Symbol("PgNum");
873
+ /** Matches w:lastRenderedPageBreak */
874
+ const PARSED_LAST_RENDERED_PAGE_BREAK = Symbol("LastRenderedPageBreak");
875
+ /**
876
+ * Parse a w:r element into run data.
877
+ * Returns { properties, children } where children are parsed run content items.
878
+ */
879
+ function parseRun(el, _ctx) {
880
+ const rPr = findChild(el, "w:rPr");
881
+ const properties = rPr ? parseRunProperties(rPr) : void 0;
882
+ const children = [];
883
+ for (const child of el.elements ?? []) switch (child.name) {
884
+ case "w:rPr": break;
885
+ case "w:t": {
886
+ const preserveSpace = attrBool(child, "xml:space");
887
+ let text = textOf(child);
888
+ if (preserveSpace && text) {}
889
+ children.push(text);
890
+ break;
891
+ }
892
+ case "w:delText": {
893
+ const text = textOf(child);
894
+ if (text) children.push(text);
895
+ break;
896
+ }
897
+ case "w:br": {
898
+ const brType = attr(child, "w:type");
899
+ if (brType === "page") children.push(PARSED_PAGE_BREAK);
900
+ else if (brType === "column") children.push(PARSED_COLUMN_BREAK);
901
+ else children.push(PARSED_LINE_BREAK);
902
+ break;
903
+ }
904
+ case "w:tab":
905
+ children.push(PARSED_TAB);
906
+ break;
907
+ case "w:cr":
908
+ children.push(PARSED_CR);
909
+ break;
910
+ case "w:noBreakHyphen":
911
+ children.push(PARSED_NO_BREAK_HYPHEN);
912
+ break;
913
+ case "w:softHyphen":
914
+ children.push(PARSED_SOFT_HYPHEN);
915
+ break;
916
+ case "w:commentReference": {
917
+ const id = attrNum(child, "w:id");
918
+ if (id !== void 0) children.push({ commentReference: id });
919
+ break;
920
+ }
921
+ case "w:drawing":
922
+ case "w:pict": break;
923
+ case "w:sym": {
924
+ const charVal = attr(child, "w:char");
925
+ const fontVal = attr(child, "w:font");
926
+ if (charVal) children.push({ symbolRun: {
927
+ char: charVal,
928
+ symbolfont: fontVal ?? "Wingdings"
929
+ } });
930
+ break;
931
+ }
932
+ case "w:footnoteReference": {
933
+ const id = attrNum(child, "w:id");
934
+ if (id !== void 0) children.push({ footnoteReference: id });
935
+ break;
936
+ }
937
+ case "w:endnoteReference": {
938
+ const id = attrNum(child, "w:id");
939
+ if (id !== void 0) children.push({ endnoteReference: id });
940
+ break;
941
+ }
942
+ case "w:footnoteRef":
943
+ case "w:endnoteRef":
944
+ children.push(PARSED_FOOTNOTE_REF);
945
+ break;
946
+ case "w:dayShort":
947
+ children.push(PARSED_DAY_SHORT);
948
+ break;
949
+ case "w:monthShort":
950
+ children.push(PARSED_MONTH_SHORT);
951
+ break;
952
+ case "w:yearShort":
953
+ children.push(PARSED_YEAR_SHORT);
954
+ break;
955
+ case "w:dayLong":
956
+ children.push(PARSED_DAY_LONG);
957
+ break;
958
+ case "w:monthLong":
959
+ children.push(PARSED_MONTH_LONG);
960
+ break;
961
+ case "w:yearLong":
962
+ children.push(PARSED_YEAR_LONG);
963
+ break;
964
+ case "w:annotationRef":
965
+ children.push(PARSED_ANNOTATION_REF);
966
+ break;
967
+ case "w:separator":
968
+ children.push(PARSED_SEPARATOR);
969
+ break;
970
+ case "w:continuationSeparator":
971
+ children.push(PARSED_CONTINUATION_SEPARATOR);
972
+ break;
973
+ case "w:pgNum":
974
+ children.push(PARSED_PG_NUM);
975
+ break;
976
+ case "w:lastRenderedPageBreak":
977
+ children.push(PARSED_LAST_RENDERED_PAGE_BREAK);
978
+ break;
979
+ default: break;
980
+ }
981
+ return {
982
+ properties,
983
+ children
984
+ };
985
+ }
986
+ /**
987
+ * Convert parsed run data into an RunOptions suitable for the Document constructor.
988
+ * Simplifies the parsed children into text + break format.
989
+ * If the run contains only a commentReference, returns { commentReference: id } instead.
990
+ * If the run only contains footnoteRef/endnoteRef (auto-generated), returns empty options.
991
+ *
992
+ * When empty run elements (tab, noBreakHyphen, date fields, etc.) are present,
993
+ * uses children[] format to preserve them for round-trip fidelity.
994
+ */
995
+ /** Mapping from parse symbols to RunOptions child objects for empty elements. */
996
+ const SYMBOL_TO_CHILD = new Map([
997
+ [PARSED_TAB, { tab: true }],
998
+ [PARSED_CR, { carriageReturn: true }],
999
+ [PARSED_NO_BREAK_HYPHEN, { noBreakHyphen: true }],
1000
+ [PARSED_SOFT_HYPHEN, { softHyphen: true }],
1001
+ [PARSED_DAY_SHORT, { dayShort: true }],
1002
+ [PARSED_MONTH_SHORT, { monthShort: true }],
1003
+ [PARSED_YEAR_SHORT, { yearShort: true }],
1004
+ [PARSED_DAY_LONG, { dayLong: true }],
1005
+ [PARSED_MONTH_LONG, { monthLong: true }],
1006
+ [PARSED_YEAR_LONG, { yearLong: true }],
1007
+ [PARSED_ANNOTATION_REF, { annotationRef: true }],
1008
+ [PARSED_SEPARATOR, { separator: true }],
1009
+ [PARSED_CONTINUATION_SEPARATOR, { continuationSeparator: true }],
1010
+ [PARSED_PG_NUM, { pgNum: true }],
1011
+ [PARSED_LAST_RENDERED_PAGE_BREAK, { lastRenderedPageBreak: true }]
1012
+ ]);
1013
+ function parsedRunToOptions(parsed) {
1014
+ const contentChildren = parsed.children.filter((c) => c !== PARSED_FOOTNOTE_REF);
1015
+ if (contentChildren.length === 0 && parsed.children.some((c) => c === PARSED_FOOTNOTE_REF)) return null;
1016
+ const opts = { ...parsed.properties };
1017
+ const isRefChild = (c) => typeof c === "object" && c !== null && ("commentReference" in c || "footnoteReference" in c || "endnoteReference" in c);
1018
+ const refChildren = contentChildren.filter(isRefChild);
1019
+ const nonRefChildren = contentChildren.filter((c) => !isRefChild(c));
1020
+ if (refChildren.length > 0 && nonRefChildren.length === 0) return refChildren[0];
1021
+ const symbolIdx = nonRefChildren.findIndex((c) => typeof c === "object" && c !== null && "symbolRun" in c);
1022
+ if (symbolIdx >= 0 && nonRefChildren.length === 1 && !parsed.properties) return nonRefChildren[symbolIdx];
1023
+ const textParts = [];
1024
+ let breakCount = 0;
1025
+ let hasPageBreak = false;
1026
+ let hasColumnBreak = false;
1027
+ const extraChildren = [];
1028
+ for (const child of nonRefChildren) if (typeof child === "string") textParts.push(child);
1029
+ else if (child === PARSED_LINE_BREAK) breakCount++;
1030
+ else if (child === PARSED_PAGE_BREAK) hasPageBreak = true;
1031
+ else if (child === PARSED_COLUMN_BREAK) hasColumnBreak = true;
1032
+ else {
1033
+ const mapped = SYMBOL_TO_CHILD.get(child);
1034
+ if (mapped) extraChildren.push(mapped);
1035
+ }
1036
+ if (extraChildren.length > 0) {
1037
+ const children = [];
1038
+ for (const child of nonRefChildren) if (typeof child === "string") children.push(child);
1039
+ else if (child === PARSED_LINE_BREAK) children.push({ break: 1 });
1040
+ else if (child === PARSED_PAGE_BREAK) children.push({ pageBreak: true });
1041
+ else if (child === PARSED_COLUMN_BREAK) children.push({ columnBreak: true });
1042
+ else {
1043
+ const mapped = SYMBOL_TO_CHILD.get(child);
1044
+ if (mapped) children.push(mapped);
1045
+ }
1046
+ opts.children = children;
1047
+ } else {
1048
+ if (textParts.length > 0) opts.text = textParts.join("");
1049
+ if (breakCount > 0) opts.break = breakCount;
1050
+ if (hasPageBreak) opts.pageBreak = true;
1051
+ if (hasColumnBreak) opts.columnBreak = true;
1052
+ }
1053
+ if (Object.keys(opts).length === 0 && textParts.length === 0 && breakCount === 0 && !hasPageBreak && !hasColumnBreak && extraChildren.length === 0) return null;
1054
+ return opts;
1055
+ }
1056
+ //#endregion
1057
+ //#region src/parts/numbering/level.ts
1058
+ /**
1059
+ * Number format types for list levels.
1060
+ *
1061
+ * Defines the various numbering formats available for list levels, including
1062
+ * decimal, roman numerals, letters, and various international formats.
1063
+ *
1064
+ * Reference: http://officeopenxml.com/WPnumbering-numFmt.php
1065
+ *
1066
+ * @publicApi
1067
+ */
1068
+ const LevelFormat = {
1069
+ /** Decimal numbering (1, 2, 3...). */
1070
+ DECIMAL: "decimal",
1071
+ /** Uppercase roman numerals (I, II, III...). */
1072
+ UPPER_ROMAN: "upperRoman",
1073
+ /** Lowercase roman numerals (i, ii, iii...). */
1074
+ LOWER_ROMAN: "lowerRoman",
1075
+ /** Uppercase letters (A, B, C...). */
1076
+ UPPER_LETTER: "upperLetter",
1077
+ /** Lowercase letters (a, b, c...). */
1078
+ LOWER_LETTER: "lowerLetter",
1079
+ /** Ordinal numbers (1st, 2nd, 3rd...). */
1080
+ ORDINAL: "ordinal",
1081
+ /** Cardinal text (one, two, three...). */
1082
+ CARDINAL_TEXT: "cardinalText",
1083
+ /** Ordinal text (first, second, third...). */
1084
+ ORDINAL_TEXT: "ordinalText",
1085
+ /** Hexadecimal numbering. */
1086
+ HEX: "hex",
1087
+ /** Chicago Manual of Style numbering. */
1088
+ CHICAGO: "chicago",
1089
+ /** Ideograph digital numbering. */
1090
+ IDEOGRAPH__DIGITAL: "ideographDigital",
1091
+ /** Japanese counting system. */
1092
+ JAPANESE_COUNTING: "japaneseCounting",
1093
+ /** Japanese aiueo ordering. */
1094
+ AIUEO: "aiueo",
1095
+ /** Japanese iroha ordering. */
1096
+ IROHA: "iroha",
1097
+ /** Full-width decimal numbering. */
1098
+ DECIMAL_FULL_WIDTH: "decimalFullWidth",
1099
+ /** Half-width decimal numbering. */
1100
+ DECIMAL_HALF_WIDTH: "decimalHalfWidth",
1101
+ /** Japanese legal numbering. */
1102
+ JAPANESE_LEGAL: "japaneseLegal",
1103
+ /** Japanese digital ten thousand numbering. */
1104
+ JAPANESE_DIGITAL_TEN_THOUSAND: "japaneseDigitalTenThousand",
1105
+ /** Decimal numbers enclosed in circles. */
1106
+ DECIMAL_ENCLOSED_CIRCLE: "decimalEnclosedCircle",
1107
+ /** Full-width decimal numbering variant 2. */
1108
+ DECIMAL_FULL_WIDTH2: "decimalFullWidth2",
1109
+ /** Full-width aiueo ordering. */
1110
+ AIUEO_FULL_WIDTH: "aiueoFullWidth",
1111
+ /** Full-width iroha ordering. */
1112
+ IROHA_FULL_WIDTH: "irohaFullWidth",
1113
+ /** Decimal with leading zeros. */
1114
+ DECIMAL_ZERO: "decimalZero",
1115
+ /** Bullet points. */
1116
+ BULLET: "bullet",
1117
+ /** Korean ganada ordering. */
1118
+ GANADA: "ganada",
1119
+ /** Korean chosung ordering. */
1120
+ CHOSUNG: "chosung",
1121
+ /** Decimal enclosed with fullstop. */
1122
+ DECIMAL_ENCLOSED_FULLSTOP: "decimalEnclosedFullstop",
1123
+ /** Decimal enclosed in parentheses. */
1124
+ DECIMAL_ENCLOSED_PARENTHESES: "decimalEnclosedParen",
1125
+ /** Decimal enclosed in circles (Chinese). */
1126
+ DECIMAL_ENCLOSED_CIRCLE_CHINESE: "decimalEnclosedCircleChinese",
1127
+ /** Ideograph enclosed in circles. */
1128
+ IDEOGRAPH_ENCLOSED_CIRCLE: "ideographEnclosedCircle",
1129
+ /** Traditional ideograph numbering. */
1130
+ IDEOGRAPH_TRADITIONAL: "ideographTraditional",
1131
+ /** Ideograph zodiac numbering. */
1132
+ IDEOGRAPH_ZODIAC: "ideographZodiac",
1133
+ /** Traditional ideograph zodiac numbering. */
1134
+ IDEOGRAPH_ZODIAC_TRADITIONAL: "ideographZodiacTraditional",
1135
+ /** Taiwanese counting system. */
1136
+ TAIWANESE_COUNTING: "taiwaneseCounting",
1137
+ /** Traditional ideograph legal numbering. */
1138
+ IDEOGRAPH_LEGAL_TRADITIONAL: "ideographLegalTraditional",
1139
+ /** Taiwanese counting thousand system. */
1140
+ TAIWANESE_COUNTING_THOUSAND: "taiwaneseCountingThousand",
1141
+ /** Taiwanese digital numbering. */
1142
+ TAIWANESE_DIGITAL: "taiwaneseDigital",
1143
+ /** Chinese counting system. */
1144
+ CHINESE_COUNTING: "chineseCounting",
1145
+ /** Simplified Chinese legal numbering. */
1146
+ CHINESE_LEGAL_SIMPLIFIED: "chineseLegalSimplified",
1147
+ /** Chinese counting thousand system. */
1148
+ CHINESE_COUNTING_THOUSAND: "chineseCountingThousand",
1149
+ /** Korean digital numbering. */
1150
+ KOREAN_DIGITAL: "koreanDigital",
1151
+ /** Korean counting system. */
1152
+ KOREAN_COUNTING: "koreanCounting",
1153
+ /** Korean legal numbering. */
1154
+ KOREAN_LEGAL: "koreanLegal",
1155
+ /** Korean digital numbering variant 2. */
1156
+ KOREAN_DIGITAL2: "koreanDigital2",
1157
+ /** Vietnamese counting system. */
1158
+ VIETNAMESE_COUNTING: "vietnameseCounting",
1159
+ /** Russian lowercase numbering. */
1160
+ RUSSIAN_LOWER: "russianLower",
1161
+ /** Russian uppercase numbering. */
1162
+ RUSSIAN_UPPER: "russianUpper",
1163
+ /** No numbering. */
1164
+ NONE: "none",
1165
+ /** Number enclosed in dashes. */
1166
+ NUMBER_IN_DASH: "numberInDash",
1167
+ /** Hebrew numbering variant 1. */
1168
+ HEBREW1: "hebrew1",
1169
+ /** Hebrew numbering variant 2. */
1170
+ HEBREW2: "hebrew2",
1171
+ /** Arabic alpha numbering. */
1172
+ ARABIC_ALPHA: "arabicAlpha",
1173
+ /** Arabic abjad numbering. */
1174
+ ARABIC_ABJAD: "arabicAbjad",
1175
+ /** Hindi vowels. */
1176
+ HINDI_VOWELS: "hindiVowels",
1177
+ /** Hindi consonants. */
1178
+ HINDI_CONSONANTS: "hindiConsonants",
1179
+ /** Hindi numbers. */
1180
+ HINDI_NUMBERS: "hindiNumbers",
1181
+ /** Hindi counting system. */
1182
+ HINDI_COUNTING: "hindiCounting",
1183
+ /** Thai letters. */
1184
+ THAI_LETTERS: "thaiLetters",
1185
+ /** Thai numbers. */
1186
+ THAI_NUMBERS: "thaiNumbers",
1187
+ /** Thai counting system. */
1188
+ THAI_COUNTING: "thaiCounting",
1189
+ /** Thai Baht text. */
1190
+ BAHT_TEXT: "bahtText",
1191
+ /** Dollar text. */
1192
+ DOLLAR_TEXT: "dollarText",
1193
+ /** Custom numbering format. */
1194
+ CUSTOM: "custom"
1195
+ };
1196
+ /**
1197
+ * Suffix types for list levels.
1198
+ *
1199
+ * Defines what follows the numbering text (tab, space, or nothing).
1200
+ *
1201
+ * @publicApi
1202
+ */
1203
+ const LevelSuffix = {
1204
+ /** No separator after the numbering. */
1205
+ NOTHING: "nothing",
1206
+ /** Space character after the numbering. */
1207
+ SPACE: "space",
1208
+ /** Tab character after the numbering. */
1209
+ TAB: "tab"
1210
+ };
1211
+ //#endregion
1212
+ //#region src/parts/numbering/numbering.ts
1213
+ /**
1214
+ * Numbering module for WordprocessingML documents.
1215
+ *
1216
+ * Numbering provides support for numbered and bulleted lists.
1217
+ * Pure string serialization — no XmlComponent inheritance.
1218
+ *
1219
+ * Reference: http://officeopenxml.com/WPnumbering.php
1220
+ *
1221
+ * @module
1222
+ */
1223
+ /** Namespace attributes for w:numbering (pre-computed constant). */
1224
+ const NUMBERING_ATTRS = "xmlns:wpc=\"http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" xmlns:o=\"urn:schemas-microsoft-com:office:office\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:wp14=\"http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" xmlns:w10=\"urn:schemas-microsoft-com:office:word\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:w14=\"http://schemas.microsoft.com/office/word/2010/wordml\" xmlns:w15=\"http://schemas.microsoft.com/office/word/2012/wordml\" xmlns:wpg=\"http://schemas.microsoft.com/office/word/2010/wordprocessingGroup\" xmlns:wpi=\"http://schemas.microsoft.com/office/word/2010/wordprocessingInk\" xmlns:wne=\"http://schemas.microsoft.com/office/word/2006/wordml\" xmlns:wps=\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\" mc:Ignorable=\"w14 w15 wp14\"";
1225
+ /** Default bullet levels (9 levels: 0-8). */
1226
+ const DEFAULT_BULLET_LEVELS = [
1227
+ {
1228
+ alignment: AlignmentType.LEFT,
1229
+ format: LevelFormat.BULLET,
1230
+ level: 0,
1231
+ style: { paragraph: { indent: {
1232
+ hanging: convertInchesToTwip(.25),
1233
+ left: convertInchesToTwip(.5)
1234
+ } } },
1235
+ text: "●"
1236
+ },
1237
+ {
1238
+ alignment: AlignmentType.LEFT,
1239
+ format: LevelFormat.BULLET,
1240
+ level: 1,
1241
+ style: { paragraph: { indent: {
1242
+ hanging: convertInchesToTwip(.25),
1243
+ left: convertInchesToTwip(1)
1244
+ } } },
1245
+ text: "○"
1246
+ },
1247
+ {
1248
+ alignment: AlignmentType.LEFT,
1249
+ format: LevelFormat.BULLET,
1250
+ level: 2,
1251
+ style: { paragraph: { indent: {
1252
+ hanging: convertInchesToTwip(.25),
916
1253
  left: 2160
917
1254
  } } },
918
1255
  text: "■"
@@ -976,656 +1313,243 @@ const DEFAULT_BULLET_LEVELS = [
976
1313
  left: 6480
977
1314
  } } },
978
1315
  text: "●"
979
- }
980
- ];
981
- /**
982
- * Numbering definitions for a WordprocessingML document.
983
- *
984
- * Pure data accumulator — no XmlComponent inheritance.
985
- * Serializes via `serialize()` producing a complete XML part.
986
- */
987
- var Numbering = class {
988
- abstractNumberingData = /* @__PURE__ */ new Map();
989
- concreteNumberingData = /* @__PURE__ */ new Map();
990
- referenceConfigMap = /* @__PURE__ */ new Map();
991
- abstractNumUniqueNumericId = uniqueNumericIdCreator();
992
- concreteNumUniqueNumericId = uniqueNumericIdCreator(1);
993
- _numIdMacAtCleanup;
994
- _numPicBullets;
995
- constructor(options) {
996
- this._numIdMacAtCleanup = options.numIdMacAtCleanup;
997
- this._numPicBullets = options.numPicBullets;
998
- const defaultAbstractId = this.abstractNumUniqueNumericId();
999
- this.abstractNumberingData.set("default-bullet-numbering", {
1000
- id: defaultAbstractId,
1001
- levels: DEFAULT_BULLET_LEVELS
1002
- });
1003
- this.concreteNumberingData.set("default-bullet-numbering", {
1004
- abstractNumId: defaultAbstractId,
1005
- instance: 0,
1006
- numId: 1,
1007
- overrideLevels: [{
1008
- num: 0,
1009
- start: 1
1010
- }],
1011
- reference: "default-bullet-numbering"
1012
- });
1013
- for (const con of options.config) {
1014
- this.abstractNumberingData.set(con.reference, {
1015
- id: this.abstractNumUniqueNumericId(),
1016
- levels: con.levels
1017
- });
1018
- this.referenceConfigMap.set(con.reference, con.levels);
1019
- }
1020
- }
1021
- /** Serialize to word/numbering.xml content (with XML declaration). */
1022
- serialize() {
1023
- const parts = [];
1024
- parts.push(`<w:numbering ${NUMBERING_ATTRS}>`);
1025
- if (this._numPicBullets) for (const bullet of this._numPicBullets) if (bullet.pict) parts.push(`<w:numPicBullet w:numPicBulletId="${bullet.numPicBulletId}">${bullet.pict}</w:numPicBullet>`);
1026
- else parts.push(`<w:numPicBullet w:numPicBulletId="${bullet.numPicBulletId}"/>`);
1027
- for (const an of this.abstractNumberingData.values()) parts.push(stringifyAbstractNumbering(an.id, an.levels, an.extraOptions));
1028
- for (const cn of this.concreteNumberingData.values()) parts.push(stringifyConcreteNumbering(cn));
1029
- if (this._numIdMacAtCleanup !== void 0) parts.push(`<w:numIdMacAtCleanup w:val="${decimalNumber(this._numIdMacAtCleanup)}"/>`);
1030
- parts.push("</w:numbering>");
1031
- return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + parts.join("");
1032
- }
1033
- /**
1034
- * Creates a concrete numbering instance from an abstract numbering definition.
1035
- */
1036
- createConcreteNumberingInstance(reference, instance) {
1037
- const abstractNumbering = this.abstractNumberingData.get(reference);
1038
- if (!abstractNumbering) return;
1039
- const fullReference = `${reference}-${instance}`;
1040
- if (this.concreteNumberingData.has(fullReference)) return;
1041
- const referenceConfigLevels = this.referenceConfigMap.get(reference);
1042
- const firstLevelStartNumber = referenceConfigLevels && referenceConfigLevels[0].start;
1043
- this.concreteNumberingData.set(fullReference, {
1044
- abstractNumId: abstractNumbering.id,
1045
- instance,
1046
- numId: this.concreteNumUniqueNumericId(),
1047
- overrideLevels: [typeof firstLevelStartNumber === "number" && Number.isInteger(firstLevelStartNumber) ? {
1048
- num: 0,
1049
- start: firstLevelStartNumber
1050
- } : {
1051
- num: 0,
1052
- start: 1
1053
- }],
1054
- reference
1055
- });
1056
- }
1057
- /** Gets all concrete numbering instances. */
1058
- get concreteNumbering() {
1059
- return [...this.concreteNumberingData.values()];
1060
- }
1061
- /** Gets all reference configurations. */
1062
- get referenceConfig() {
1063
- return [...this.referenceConfigMap.values()];
1064
- }
1065
- };
1066
- function stringifyAbstractNumbering(id, levels, extraOptions) {
1067
- const parts = [];
1068
- parts.push(`<w:abstractNum w:abstractNumId="${decimalNumber(id)}" w15:restartNumberingAfterBreak="0">`);
1069
- if (extraOptions?.nsid !== void 0) parts.push(`<w:nsid w:val="${extraOptions.nsid}"/>`);
1070
- parts.push(`<w:multiLevelType w:val="hybridMultilevel"/>`);
1071
- if (extraOptions?.tmpl !== void 0) parts.push(`<w:tmpl w:val="${extraOptions.tmpl}"/>`);
1072
- if (extraOptions?.name !== void 0) parts.push(`<w:name w:val="${extraOptions.name}"/>`);
1073
- if (extraOptions?.styleLink !== void 0) parts.push(`<w:styleLink w:val="${extraOptions.styleLink}"/>`);
1074
- if (extraOptions?.numStyleLink !== void 0) parts.push(`<w:numStyleLink w:val="${extraOptions.numStyleLink}"/>`);
1075
- for (const level of levels) parts.push(stringifyLevel(level));
1076
- parts.push("</w:abstractNum>");
1077
- return parts.join("");
1078
- }
1079
- function stringifyConcreteNumbering(cn) {
1080
- const parts = [];
1081
- parts.push(`<w:num w:numId="${decimalNumber(cn.numId)}">`);
1082
- parts.push(`<w:abstractNumId w:val="${decimalNumber(cn.abstractNumId)}"/>`);
1083
- if (cn.overrideLevels) for (const level of cn.overrideLevels) if (level.start !== void 0) parts.push(`<w:lvlOverride w:ilvl="${level.num}"><w:startOverride w:val="${level.start}"/></w:lvlOverride>`);
1084
- else parts.push(`<w:lvlOverride w:ilvl="${level.num}"/>`);
1085
- parts.push("</w:num>");
1086
- return parts.join("");
1087
- }
1088
- function stringifyLevel(opts) {
1089
- const children = [];
1090
- children.push(`<w:start w:val="${decimalNumber(opts.start ?? 1)}"/>`);
1091
- if (opts.format) children.push(`<w:numFmt w:val="${opts.format}"/>`);
1092
- if (opts.lvlRestart !== void 0) children.push(`<w:lvlRestart w:val="${decimalNumber(opts.lvlRestart)}"/>`);
1093
- if (opts.suffix) children.push(`<w:suff w:val="${opts.suffix}"/>`);
1094
- if (opts.isLegalNumberingStyle) children.push("<w:isLgl/>");
1095
- if (opts.text) children.push(`<w:lvlText w:val="${opts.text}"/>`);
1096
- if (opts.lvlPicBulletId !== void 0) children.push(`<w:lvlPicBulletId w:val="${decimalNumber(opts.lvlPicBulletId)}"/>`);
1097
- if (opts.legacy !== void 0) {
1098
- const legacyAttrs = [];
1099
- if (opts.legacy.space !== void 0) legacyAttrs.push(`w:legacySpace="${opts.legacy.space}"`);
1100
- if (opts.legacy.indent !== void 0) legacyAttrs.push(`w:legacyIndent="${opts.legacy.indent}"`);
1101
- children.push(`<w:legacy ${legacyAttrs.join(" ")}/>`);
1102
- }
1103
- children.push(`<w:lvlJc w:val="${opts.alignment ?? AlignmentType.START}"/>`);
1104
- const pPrXml = stringifyParagraphProperties(opts.style && opts.style.paragraph).xml;
1105
- const rPrXml = stringifyRunProperties(opts.style && opts.style.run);
1106
- if (pPrXml) children.push(pPrXml);
1107
- if (rPrXml) children.push(rPrXml);
1108
- const lvlAttrs = [`w:ilvl="${decimalNumber(Math.min(opts.level, 9))}"`, `w15:tentative="1"`];
1109
- if (opts.templateCode !== void 0) lvlAttrs.push(`w:tplc="${opts.templateCode}"`);
1110
- if (opts.tentative !== void 0) lvlAttrs.push(`w:tentative="${opts.tentative ? 1 : 0}"`);
1111
- return `<w:lvl ${lvlAttrs.join(" ")}>${children.join("")}</w:lvl>`;
1112
- }
1113
- /**
1114
- * Parse w:numbering element into NumberingOptions.
1115
- */
1116
- function parseNumberingDefinitions(el) {
1117
- const abstractNums = /* @__PURE__ */ new Map();
1118
- for (const child of el.elements ?? []) {
1119
- if (child.name !== "w:abstractNum") continue;
1120
- const id = attr(child, "w:abstractNumId");
1121
- if (id !== void 0) abstractNums.set(id, child);
1122
- }
1123
- const numToAbstract = /* @__PURE__ */ new Map();
1124
- for (const child of el.elements ?? []) {
1125
- if (child.name !== "w:num") continue;
1126
- const numId = attr(child, "w:numId");
1127
- const abstractRef = findChild(child, "w:abstractNumId");
1128
- const abstractId = abstractRef ? attr(abstractRef, "w:val") : void 0;
1129
- if (numId !== void 0 && abstractId !== void 0) numToAbstract.set(numId, abstractId);
1130
- }
1131
- const configs = [];
1132
- for (const [numId, abstractId] of numToAbstract) {
1133
- const abstractEl = abstractNums.get(abstractId);
1134
- if (!abstractEl) continue;
1135
- const levels = [];
1136
- for (const child of abstractEl.elements ?? []) {
1137
- if (child.name !== "w:lvl") continue;
1138
- const levelOpts = parseLevelEl(child);
1139
- if (levelOpts) levels.push(levelOpts);
1140
- }
1141
- if (levels.length > 0 && levels.every((l) => l.format === LevelFormat.BULLET)) continue;
1142
- if (levels.length > 0) configs.push({
1143
- reference: `list_${numId}`,
1144
- levels
1145
- });
1146
- }
1147
- if (configs.length === 0) return void 0;
1148
- return { config: configs };
1149
- }
1150
- function parseLevelEl(el) {
1151
- const opts = {};
1152
- const level = attrNum(el, "w:ilvl");
1153
- if (level !== void 0) opts.level = level;
1154
- const start = findChild(el, "w:start");
1155
- if (start) {
1156
- const val = attrNum(start, "w:val");
1157
- if (val !== void 0) opts.start = val;
1158
- }
1159
- const numFmt = findChild(el, "w:numFmt");
1160
- if (numFmt) {
1161
- const val = attr(numFmt, "w:val");
1162
- if (val) opts.format = val;
1163
- }
1164
- const lvlText = findChild(el, "w:lvlText");
1165
- if (lvlText) {
1166
- const val = attr(lvlText, "w:val");
1167
- if (val) opts.text = val;
1168
- }
1169
- const lvlJc = findChild(el, "w:lvlJc");
1170
- if (lvlJc) {
1171
- const val = attr(lvlJc, "w:val");
1172
- if (val) opts.alignment = val;
1173
- }
1174
- const suff = findChild(el, "w:suff");
1175
- if (suff) {
1176
- const val = attr(suff, "w:val");
1177
- if (val) opts.suffix = val;
1178
- }
1179
- if (findChild(el, "w:isLgl")) opts.isLegalNumberingStyle = true;
1180
- const rPr = findChild(el, "w:rPr");
1181
- if (rPr) {
1182
- const style = {};
1183
- const sz = findChild(rPr, "w:sz");
1184
- if (sz) {
1185
- const val = attrNum(sz, "w:val");
1186
- if (val !== void 0) {
1187
- if (!style.run) style.run = {};
1188
- style.run.size = val;
1189
- }
1190
- }
1191
- const rFonts = findChild(rPr, "w:rFonts");
1192
- if (rFonts) {
1193
- const ascii = attr(rFonts, "w:ascii");
1194
- if (ascii) {
1195
- if (!style.run) style.run = {};
1196
- style.run.font = ascii;
1197
- }
1198
- }
1199
- if (Object.keys(style).length > 0) opts.style = style;
1200
- }
1201
- const pPr = findChild(el, "w:pPr");
1202
- if (pPr) {
1203
- const style = opts.style ?? {};
1204
- const paraStyle = {};
1205
- const ind = findChild(pPr, "w:ind");
1206
- if (ind) {
1207
- const indent = {};
1208
- const left = attrNum(ind, "w:left");
1209
- if (left !== void 0) indent.left = left;
1210
- const hanging = attrNum(ind, "w:hanging");
1211
- if (hanging !== void 0) indent.hanging = hanging;
1212
- if (Object.keys(indent).length > 0) paraStyle.indent = indent;
1213
- }
1214
- if (Object.keys(paraStyle).length > 0) {
1215
- style.paragraph = paraStyle;
1216
- opts.style = style;
1217
- }
1218
- }
1219
- return Object.keys(opts).length > 0 ? opts : void 0;
1220
- }
1221
- //#endregion
1222
- //#region src/parts/paragraph/run/run-parse.ts
1316
+ }
1317
+ ];
1223
1318
  /**
1224
- * Run properties parser for DOCX documents.
1225
- *
1226
- * Parses w:rPr Element trees into RunPropertiesOptions objects.
1319
+ * Numbering definitions for a WordprocessingML document.
1227
1320
  *
1228
- * @module
1229
- */
1230
- /**
1231
- * Parse a w:rPr element into RunPropertiesOptions.
1321
+ * Pure data accumulator — no XmlComponent inheritance.
1322
+ * Serializes via `serialize()` producing a complete XML part.
1232
1323
  */
1233
- function parseRunProperties(el) {
1234
- const opts = {};
1235
- const rStyle = findChild(el, "w:rStyle");
1236
- if (rStyle) opts.style = attr(rStyle, "w:val");
1237
- const font = findChild(el, "w:rFonts");
1238
- if (font) {
1239
- const ascii = attr(font, "w:ascii");
1240
- const eastAsia = attr(font, "w:eastAsia");
1241
- const hAnsi = attr(font, "w:hAnsi");
1242
- const cs = attr(font, "w:cs");
1243
- const hint = attr(font, "w:hint");
1244
- if (ascii && !eastAsia && !hAnsi && !cs) opts.font = hint ? {
1245
- name: ascii,
1246
- hint
1247
- } : ascii;
1248
- else {
1249
- const fontObj = {};
1250
- if (ascii) fontObj.ascii = ascii;
1251
- if (eastAsia) fontObj.eastAsia = eastAsia;
1252
- if (hAnsi) fontObj.hAnsi = hAnsi;
1253
- if (cs) fontObj.cs = cs;
1254
- if (hint) fontObj.hint = hint;
1255
- opts.font = fontObj;
1324
+ var Numbering = class {
1325
+ abstractNumberingData = /* @__PURE__ */ new Map();
1326
+ concreteNumberingData = /* @__PURE__ */ new Map();
1327
+ referenceConfigMap = /* @__PURE__ */ new Map();
1328
+ abstractNumUniqueNumericId = uniqueNumericIdCreator();
1329
+ concreteNumUniqueNumericId = uniqueNumericIdCreator(1);
1330
+ _numIdMacAtCleanup;
1331
+ _numPicBullets;
1332
+ constructor(options) {
1333
+ this._numIdMacAtCleanup = options.numIdMacAtCleanup;
1334
+ this._numPicBullets = options.numPicBullets;
1335
+ const defaultAbstractId = this.abstractNumUniqueNumericId();
1336
+ this.abstractNumberingData.set("default-bullet-numbering", {
1337
+ id: defaultAbstractId,
1338
+ levels: DEFAULT_BULLET_LEVELS
1339
+ });
1340
+ this.concreteNumberingData.set("default-bullet-numbering", {
1341
+ abstractNumId: defaultAbstractId,
1342
+ instance: 0,
1343
+ numId: 1,
1344
+ overrideLevels: [{
1345
+ num: 0,
1346
+ start: 1
1347
+ }],
1348
+ reference: "default-bullet-numbering"
1349
+ });
1350
+ for (const con of options.config) {
1351
+ this.abstractNumberingData.set(con.reference, {
1352
+ id: this.abstractNumUniqueNumericId(),
1353
+ levels: con.levels
1354
+ });
1355
+ this.referenceConfigMap.set(con.reference, con.levels);
1256
1356
  }
1257
1357
  }
1258
- const bold = findChild(el, "w:b");
1259
- if (bold) opts.bold = attrBool(bold, "w:val") ?? true;
1260
- const boldCs = findChild(el, "w:bCs");
1261
- if (boldCs) opts.boldComplexScript = attrBool(boldCs, "w:val") ?? true;
1262
- const italic = findChild(el, "w:i");
1263
- if (italic) opts.italic = attrBool(italic, "w:val") ?? true;
1264
- const italicCs = findChild(el, "w:iCs");
1265
- if (italicCs) opts.italicComplexScript = attrBool(italicCs, "w:val") ?? true;
1266
- const underline = findChild(el, "w:u");
1267
- if (underline) {
1268
- const ul = {};
1269
- const uType = attr(underline, "w:val");
1270
- if (uType) ul.type = uType;
1271
- const uColor = colorAttr(underline, "w:color");
1272
- if (uColor) ul.color = uColor;
1273
- opts.underline = ul;
1274
- }
1275
- for (const [name, optKey] of [
1276
- ["w:strike", "strike"],
1277
- ["w:dstrike", "doubleStrike"],
1278
- ["w:outline", "outline"],
1279
- ["w:shadow", "shadow"],
1280
- ["w:emboss", "emboss"],
1281
- ["w:imprint", "imprint"],
1282
- ["w:vanish", "vanish"],
1283
- ["w:webHidden", "webHidden"],
1284
- ["w:noProof", "noProof"],
1285
- ["w:snapToGrid", "snapToGrid"],
1286
- ["w:smallCaps", "smallCaps"],
1287
- ["w:caps", "allCaps"],
1288
- ["w:rtl", "rightToLeft"],
1289
- ["w:cs", "complexScript"],
1290
- ["w:specVanish", "specVanish"],
1291
- ["w:math", "math"]
1292
- ]) {
1293
- const child = findChild(el, name);
1294
- if (child) opts[optKey] = attrBool(child, "w:val") ?? true;
1295
- }
1296
- const color = findChild(el, "w:color");
1297
- if (color) {
1298
- const c = colorAttr(color, "w:val");
1299
- if (c) opts.color = c;
1300
- }
1301
- const sz = findChild(el, "w:sz");
1302
- if (sz) {
1303
- const halfPts = attrNum(sz, "w:val");
1304
- if (halfPts !== void 0) opts.size = halfPts / 2;
1305
- }
1306
- const szCs = findChild(el, "w:szCs");
1307
- if (szCs) {
1308
- const halfPts = attrNum(szCs, "w:val");
1309
- if (halfPts !== void 0) opts.sizeComplexScript = halfPts / 2;
1310
- }
1311
- const highlight = findChild(el, "w:highlight");
1312
- if (highlight) {
1313
- const val = attr(highlight, "w:val");
1314
- if (val) opts.highlight = val;
1315
- }
1316
- const highlightCs = findChild(el, "w:highlightCs");
1317
- if (highlightCs) {
1318
- const val = attr(highlightCs, "w:val");
1319
- if (val) opts.highlightComplexScript = val;
1320
- }
1321
- const vertAlign = findChild(el, "w:vertAlign");
1322
- if (vertAlign) {
1323
- const val = attr(vertAlign, "w:val");
1324
- if (val === "subscript") opts.subScript = true;
1325
- else if (val === "superscript") opts.superScript = true;
1326
- }
1327
- const effect = findChild(el, "w:effect");
1328
- if (effect) {
1329
- const val = attr(effect, "w:val");
1330
- if (val) opts.effect = val;
1331
- }
1332
- const emphasisMark = findChild(el, "w:em");
1333
- if (emphasisMark) {
1334
- const val = attr(emphasisMark, "w:val");
1335
- if (val) opts.emphasisMark = { type: val };
1336
- }
1337
- const spacing = findChild(el, "w:spacing");
1338
- if (spacing) {
1339
- const val = attrNum(spacing, "w:val");
1340
- if (val !== void 0) opts.characterSpacing = val;
1341
- }
1342
- const scale = findChild(el, "w:w");
1343
- if (scale) {
1344
- const val = attrNum(scale, "w:val");
1345
- if (val !== void 0) opts.scale = val;
1346
- }
1347
- const kern = findChild(el, "w:kern");
1348
- if (kern) {
1349
- const val = attrNum(kern, "w:val");
1350
- if (val !== void 0) opts.kern = val;
1358
+ /** Serialize to word/numbering.xml content (with XML declaration). */
1359
+ serialize() {
1360
+ const parts = [];
1361
+ parts.push(`<w:numbering ${NUMBERING_ATTRS}>`);
1362
+ if (this._numPicBullets) for (const bullet of this._numPicBullets) if (bullet.pict) parts.push(`<w:numPicBullet w:numPicBulletId="${bullet.numPicBulletId}">${bullet.pict}</w:numPicBullet>`);
1363
+ else parts.push(`<w:numPicBullet w:numPicBulletId="${bullet.numPicBulletId}"/>`);
1364
+ for (const an of this.abstractNumberingData.values()) parts.push(stringifyAbstractNumbering(an.id, an.levels, an.extraOptions));
1365
+ for (const cn of this.concreteNumberingData.values()) parts.push(stringifyConcreteNumbering(cn));
1366
+ if (this._numIdMacAtCleanup !== void 0) parts.push(`<w:numIdMacAtCleanup w:val="${decimalNumber(this._numIdMacAtCleanup)}"/>`);
1367
+ parts.push("</w:numbering>");
1368
+ return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + parts.join("");
1351
1369
  }
1352
- const position = findChild(el, "w:position");
1353
- if (position) {
1354
- const val = attr(position, "w:val");
1355
- if (val !== void 0) opts.position = val;
1370
+ /**
1371
+ * Creates a concrete numbering instance from an abstract numbering definition.
1372
+ */
1373
+ createConcreteNumberingInstance(reference, instance) {
1374
+ const abstractNumbering = this.abstractNumberingData.get(reference);
1375
+ if (!abstractNumbering) return;
1376
+ const fullReference = `${reference}-${instance}`;
1377
+ if (this.concreteNumberingData.has(fullReference)) return;
1378
+ const referenceConfigLevels = this.referenceConfigMap.get(reference);
1379
+ const firstLevelStartNumber = referenceConfigLevels && referenceConfigLevels[0].start;
1380
+ this.concreteNumberingData.set(fullReference, {
1381
+ abstractNumId: abstractNumbering.id,
1382
+ instance,
1383
+ numId: this.concreteNumUniqueNumericId(),
1384
+ overrideLevels: [typeof firstLevelStartNumber === "number" && Number.isInteger(firstLevelStartNumber) ? {
1385
+ num: 0,
1386
+ start: firstLevelStartNumber
1387
+ } : {
1388
+ num: 0,
1389
+ start: 1
1390
+ }],
1391
+ reference
1392
+ });
1356
1393
  }
1357
- const fitText = findChild(el, "w:fitText");
1358
- if (fitText) {
1359
- const val = attrNum(fitText, "w:val");
1360
- if (val !== void 0) opts.fitText = val;
1394
+ /** Gets all concrete numbering instances. */
1395
+ get concreteNumbering() {
1396
+ return [...this.concreteNumberingData.values()];
1361
1397
  }
1362
- const lang = findChild(el, "w:lang");
1363
- if (lang) {
1364
- const langObj = {};
1365
- const val = attr(lang, "w:val");
1366
- if (val) langObj.val = val;
1367
- const eastAsia = attr(lang, "w:eastAsia");
1368
- if (eastAsia) langObj.eastAsia = eastAsia;
1369
- const bidi = attr(lang, "w:bidi");
1370
- if (bidi) langObj.bidi = bidi;
1371
- if (Object.keys(langObj).length > 0) opts.language = langObj;
1398
+ /** Gets all reference configurations. */
1399
+ get referenceConfig() {
1400
+ return [...this.referenceConfigMap.values()];
1372
1401
  }
1373
- const bdr = findChild(el, "w:bdr");
1374
- if (bdr) opts.border = parseBorder(bdr);
1375
- const shd = findChild(el, "w:shd");
1376
- if (shd) opts.shading = parseShading(shd);
1377
- return opts;
1378
- }
1379
- /**
1380
- * Parse a w:bdr element into BorderOptions.
1381
- */
1382
- function parseBorder(el) {
1383
- const opts = {};
1384
- const style = attr(el, "w:val");
1385
- if (style) opts.style = style;
1386
- const color = colorAttr(el, "w:color");
1387
- if (color) opts.color = color;
1388
- const size = attrNum(el, "w:sz");
1389
- if (size !== void 0) opts.size = size;
1390
- const space = attrNum(el, "w:space");
1391
- if (space !== void 0) opts.space = space;
1392
- const shadow = attrBool(el, "w:shadow");
1393
- if (shadow !== void 0) opts.shadow = shadow;
1394
- const frame = attrBool(el, "w:frame");
1395
- if (frame !== void 0) opts.frame = frame;
1396
- return opts;
1397
- }
1398
- /**
1399
- * Parse a w:shd element into ShadingAttributesProperties.
1400
- */
1401
- function parseShading(el) {
1402
- const opts = {};
1403
- const fill = colorAttr(el, "w:fill");
1404
- if (fill) opts.fill = fill;
1405
- const color = colorAttr(el, "w:color");
1406
- if (color) opts.color = color;
1407
- const type = attr(el, "w:val");
1408
- if (type) opts.type = type;
1409
- return opts;
1402
+ };
1403
+ function stringifyAbstractNumbering(id, levels, extraOptions) {
1404
+ const parts = [];
1405
+ parts.push(`<w:abstractNum w:abstractNumId="${decimalNumber(id)}" w15:restartNumberingAfterBreak="0">`);
1406
+ if (extraOptions?.nsid !== void 0) parts.push(`<w:nsid w:val="${extraOptions.nsid}"/>`);
1407
+ parts.push(`<w:multiLevelType w:val="hybridMultilevel"/>`);
1408
+ if (extraOptions?.tmpl !== void 0) parts.push(`<w:tmpl w:val="${extraOptions.tmpl}"/>`);
1409
+ if (extraOptions?.name !== void 0) parts.push(`<w:name w:val="${extraOptions.name}"/>`);
1410
+ if (extraOptions?.styleLink !== void 0) parts.push(`<w:styleLink w:val="${extraOptions.styleLink}"/>`);
1411
+ if (extraOptions?.numStyleLink !== void 0) parts.push(`<w:numStyleLink w:val="${extraOptions.numStyleLink}"/>`);
1412
+ for (const level of levels) parts.push(stringifyLevel(level));
1413
+ parts.push("</w:abstractNum>");
1414
+ return parts.join("");
1410
1415
  }
1411
- /** Matches w:br[@w:type="page"] → PageBreak */
1412
- const PARSED_PAGE_BREAK = Symbol("PageBreak");
1413
- /** Matches w:br (line break) */
1414
- const PARSED_LINE_BREAK = Symbol("LineBreak");
1415
- /** Matches w:tab */
1416
- const PARSED_TAB = Symbol("Tab");
1417
- /** Matches w:cr */
1418
- const PARSED_CR = Symbol("CarriageReturn");
1419
- /** Matches w:noBreakHyphen */
1420
- const PARSED_NO_BREAK_HYPHEN = Symbol("NoBreakHyphen");
1421
- /** Matches w:softHyphen */
1422
- const PARSED_SOFT_HYPHEN = Symbol("SoftHyphen");
1423
- /** Matches w:footnoteRef — auto-generated by Footnote class */
1424
- const PARSED_FOOTNOTE_REF = Symbol("FootnoteRef");
1425
- /** Matches w:br[@w:type="column"] */
1426
- const PARSED_COLUMN_BREAK = Symbol("ColumnBreak");
1427
- /** Matches w:dayShort */
1428
- const PARSED_DAY_SHORT = Symbol("DayShort");
1429
- /** Matches w:monthShort */
1430
- const PARSED_MONTH_SHORT = Symbol("MonthShort");
1431
- /** Matches w:yearShort */
1432
- const PARSED_YEAR_SHORT = Symbol("YearShort");
1433
- /** Matches w:dayLong */
1434
- const PARSED_DAY_LONG = Symbol("DayLong");
1435
- /** Matches w:monthLong */
1436
- const PARSED_MONTH_LONG = Symbol("MonthLong");
1437
- /** Matches w:yearLong */
1438
- const PARSED_YEAR_LONG = Symbol("YearLong");
1439
- /** Matches w:annotationRef */
1440
- const PARSED_ANNOTATION_REF = Symbol("AnnotationRef");
1441
- /** Matches w:separator */
1442
- const PARSED_SEPARATOR = Symbol("Separator");
1443
- /** Matches w:continuationSeparator */
1444
- const PARSED_CONTINUATION_SEPARATOR = Symbol("ContinuationSeparator");
1445
- /** Matches w:pgNum */
1446
- const PARSED_PG_NUM = Symbol("PgNum");
1447
- /** Matches w:lastRenderedPageBreak */
1448
- const PARSED_LAST_RENDERED_PAGE_BREAK = Symbol("LastRenderedPageBreak");
1449
- /**
1450
- * Parse a w:r element into run data.
1451
- * Returns { properties, children } where children are parsed run content items.
1452
- */
1453
- function parseRun(el, _ctx) {
1454
- const rPr = findChild(el, "w:rPr");
1455
- const properties = rPr ? parseRunProperties(rPr) : void 0;
1416
+ function stringifyConcreteNumbering(cn) {
1417
+ const parts = [];
1418
+ parts.push(`<w:num w:numId="${decimalNumber(cn.numId)}">`);
1419
+ parts.push(`<w:abstractNumId w:val="${decimalNumber(cn.abstractNumId)}"/>`);
1420
+ if (cn.overrideLevels) for (const level of cn.overrideLevels) if (level.start !== void 0) parts.push(`<w:lvlOverride w:ilvl="${level.num}"><w:startOverride w:val="${level.start}"/></w:lvlOverride>`);
1421
+ else parts.push(`<w:lvlOverride w:ilvl="${level.num}"/>`);
1422
+ parts.push("</w:num>");
1423
+ return parts.join("");
1424
+ }
1425
+ function stringifyLevel(opts) {
1456
1426
  const children = [];
1457
- for (const child of el.elements ?? []) switch (child.name) {
1458
- case "w:rPr": break;
1459
- case "w:t": {
1460
- const preserveSpace = attrBool(child, "xml:space");
1461
- let text = textOf(child);
1462
- if (preserveSpace && text) {}
1463
- children.push(text);
1464
- break;
1465
- }
1466
- case "w:delText": {
1467
- const text = textOf(child);
1468
- if (text) children.push(text);
1469
- break;
1470
- }
1471
- case "w:br": {
1472
- const brType = attr(child, "w:type");
1473
- if (brType === "page") children.push(PARSED_PAGE_BREAK);
1474
- else if (brType === "column") children.push(PARSED_COLUMN_BREAK);
1475
- else children.push(PARSED_LINE_BREAK);
1476
- break;
1477
- }
1478
- case "w:tab":
1479
- children.push(PARSED_TAB);
1480
- break;
1481
- case "w:cr":
1482
- children.push(PARSED_CR);
1483
- break;
1484
- case "w:noBreakHyphen":
1485
- children.push(PARSED_NO_BREAK_HYPHEN);
1486
- break;
1487
- case "w:softHyphen":
1488
- children.push(PARSED_SOFT_HYPHEN);
1489
- break;
1490
- case "w:commentReference": {
1491
- const id = attrNum(child, "w:id");
1492
- if (id !== void 0) children.push({ commentReference: id });
1493
- break;
1494
- }
1495
- case "w:drawing":
1496
- case "w:pict": break;
1497
- case "w:sym": {
1498
- const charVal = attr(child, "w:char");
1499
- const fontVal = attr(child, "w:font");
1500
- if (charVal) children.push({ symbolRun: {
1501
- char: charVal,
1502
- symbolfont: fontVal ?? "Wingdings"
1503
- } });
1504
- break;
1505
- }
1506
- case "w:footnoteReference": {
1507
- const id = attrNum(child, "w:id");
1508
- if (id !== void 0) children.push({ footnoteReference: id });
1509
- break;
1510
- }
1511
- case "w:endnoteReference": {
1512
- const id = attrNum(child, "w:id");
1513
- if (id !== void 0) children.push({ endnoteReference: id });
1514
- break;
1515
- }
1516
- case "w:footnoteRef":
1517
- case "w:endnoteRef":
1518
- children.push(PARSED_FOOTNOTE_REF);
1519
- break;
1520
- case "w:dayShort":
1521
- children.push(PARSED_DAY_SHORT);
1522
- break;
1523
- case "w:monthShort":
1524
- children.push(PARSED_MONTH_SHORT);
1525
- break;
1526
- case "w:yearShort":
1527
- children.push(PARSED_YEAR_SHORT);
1528
- break;
1529
- case "w:dayLong":
1530
- children.push(PARSED_DAY_LONG);
1531
- break;
1532
- case "w:monthLong":
1533
- children.push(PARSED_MONTH_LONG);
1534
- break;
1535
- case "w:yearLong":
1536
- children.push(PARSED_YEAR_LONG);
1537
- break;
1538
- case "w:annotationRef":
1539
- children.push(PARSED_ANNOTATION_REF);
1540
- break;
1541
- case "w:separator":
1542
- children.push(PARSED_SEPARATOR);
1543
- break;
1544
- case "w:continuationSeparator":
1545
- children.push(PARSED_CONTINUATION_SEPARATOR);
1546
- break;
1547
- case "w:pgNum":
1548
- children.push(PARSED_PG_NUM);
1549
- break;
1550
- case "w:lastRenderedPageBreak":
1551
- children.push(PARSED_LAST_RENDERED_PAGE_BREAK);
1552
- break;
1553
- default: break;
1427
+ children.push(`<w:start w:val="${decimalNumber(opts.start ?? 1)}"/>`);
1428
+ if (opts.format) children.push(`<w:numFmt w:val="${opts.format}"/>`);
1429
+ if (opts.lvlRestart !== void 0) children.push(`<w:lvlRestart w:val="${decimalNumber(opts.lvlRestart)}"/>`);
1430
+ if (opts.suffix) children.push(`<w:suff w:val="${opts.suffix}"/>`);
1431
+ if (opts.isLegalNumberingStyle) children.push("<w:isLgl/>");
1432
+ if (opts.text) children.push(`<w:lvlText w:val="${opts.text}"/>`);
1433
+ if (opts.lvlPicBulletId !== void 0) children.push(`<w:lvlPicBulletId w:val="${decimalNumber(opts.lvlPicBulletId)}"/>`);
1434
+ if (opts.legacy !== void 0) {
1435
+ const legacyAttrs = [];
1436
+ if (opts.legacy.space !== void 0) legacyAttrs.push(`w:legacySpace="${opts.legacy.space}"`);
1437
+ if (opts.legacy.indent !== void 0) legacyAttrs.push(`w:legacyIndent="${opts.legacy.indent}"`);
1438
+ children.push(`<w:legacy ${legacyAttrs.join(" ")}/>`);
1554
1439
  }
1555
- return {
1556
- properties,
1557
- children
1558
- };
1440
+ children.push(`<w:lvlJc w:val="${opts.alignment ?? AlignmentType.START}"/>`);
1441
+ const pPrXml = stringifyParagraphProperties(opts.style && opts.style.paragraph).xml;
1442
+ const rPrXml = stringifyRunProperties(opts.style && opts.style.run);
1443
+ if (pPrXml) children.push(pPrXml);
1444
+ if (rPrXml) children.push(rPrXml);
1445
+ const lvlAttrs = [`w:ilvl="${decimalNumber(Math.min(opts.level, 9))}"`, `w15:tentative="1"`];
1446
+ if (opts.templateCode !== void 0) lvlAttrs.push(`w:tplc="${opts.templateCode}"`);
1447
+ if (opts.tentative !== void 0) lvlAttrs.push(`w:tentative="${opts.tentative ? 1 : 0}"`);
1448
+ return `<w:lvl ${lvlAttrs.join(" ")}>${children.join("")}</w:lvl>`;
1559
1449
  }
1560
1450
  /**
1561
- * Convert parsed run data into an RunOptions suitable for the Document constructor.
1562
- * Simplifies the parsed children into text + break format.
1563
- * If the run contains only a commentReference, returns { commentReference: id } instead.
1564
- * If the run only contains footnoteRef/endnoteRef (auto-generated), returns empty options.
1565
- *
1566
- * When empty run elements (tab, noBreakHyphen, date fields, etc.) are present,
1567
- * uses children[] format to preserve them for round-trip fidelity.
1451
+ * Parse w:numbering element into NumberingOptions.
1568
1452
  */
1569
- /** Mapping from parse symbols to RunOptions child objects for empty elements. */
1570
- const SYMBOL_TO_CHILD = new Map([
1571
- [PARSED_TAB, { tab: true }],
1572
- [PARSED_CR, { carriageReturn: true }],
1573
- [PARSED_NO_BREAK_HYPHEN, { noBreakHyphen: true }],
1574
- [PARSED_SOFT_HYPHEN, { softHyphen: true }],
1575
- [PARSED_DAY_SHORT, { dayShort: true }],
1576
- [PARSED_MONTH_SHORT, { monthShort: true }],
1577
- [PARSED_YEAR_SHORT, { yearShort: true }],
1578
- [PARSED_DAY_LONG, { dayLong: true }],
1579
- [PARSED_MONTH_LONG, { monthLong: true }],
1580
- [PARSED_YEAR_LONG, { yearLong: true }],
1581
- [PARSED_ANNOTATION_REF, { annotationRef: true }],
1582
- [PARSED_SEPARATOR, { separator: true }],
1583
- [PARSED_CONTINUATION_SEPARATOR, { continuationSeparator: true }],
1584
- [PARSED_PG_NUM, { pgNum: true }],
1585
- [PARSED_LAST_RENDERED_PAGE_BREAK, { lastRenderedPageBreak: true }]
1586
- ]);
1587
- function parsedRunToOptions(parsed) {
1588
- const contentChildren = parsed.children.filter((c) => c !== PARSED_FOOTNOTE_REF);
1589
- if (contentChildren.length === 0 && parsed.children.some((c) => c === PARSED_FOOTNOTE_REF)) return null;
1590
- const opts = { ...parsed.properties };
1591
- const isRefChild = (c) => typeof c === "object" && c !== null && ("commentReference" in c || "footnoteReference" in c || "endnoteReference" in c);
1592
- const refChildren = contentChildren.filter(isRefChild);
1593
- const nonRefChildren = contentChildren.filter((c) => !isRefChild(c));
1594
- if (refChildren.length > 0 && nonRefChildren.length === 0) return refChildren[0];
1595
- const symbolIdx = nonRefChildren.findIndex((c) => typeof c === "object" && c !== null && "symbolRun" in c);
1596
- if (symbolIdx >= 0 && nonRefChildren.length === 1 && !parsed.properties) return nonRefChildren[symbolIdx];
1597
- const textParts = [];
1598
- let breakCount = 0;
1599
- let hasPageBreak = false;
1600
- let hasColumnBreak = false;
1601
- const extraChildren = [];
1602
- for (const child of nonRefChildren) if (typeof child === "string") textParts.push(child);
1603
- else if (child === PARSED_LINE_BREAK) breakCount++;
1604
- else if (child === PARSED_PAGE_BREAK) hasPageBreak = true;
1605
- else if (child === PARSED_COLUMN_BREAK) hasColumnBreak = true;
1606
- else {
1607
- const mapped = SYMBOL_TO_CHILD.get(child);
1608
- if (mapped) extraChildren.push(mapped);
1453
+ function parseNumberingDefinitions(el, parseParagraphProperties, ctx) {
1454
+ const abstractNums = /* @__PURE__ */ new Map();
1455
+ for (const child of el.elements ?? []) {
1456
+ if (child.name !== "w:abstractNum") continue;
1457
+ const id = attr(child, "w:abstractNumId");
1458
+ if (id !== void 0) abstractNums.set(id, child);
1609
1459
  }
1610
- if (extraChildren.length > 0) {
1611
- const children = [];
1612
- for (const child of nonRefChildren) if (typeof child === "string") children.push(child);
1613
- else if (child === PARSED_LINE_BREAK) children.push({ break: 1 });
1614
- else if (child === PARSED_PAGE_BREAK) children.push({ pageBreak: true });
1615
- else if (child === PARSED_COLUMN_BREAK) children.push({ columnBreak: true });
1616
- else {
1617
- const mapped = SYMBOL_TO_CHILD.get(child);
1618
- if (mapped) children.push(mapped);
1460
+ const numToAbstract = /* @__PURE__ */ new Map();
1461
+ for (const child of el.elements ?? []) {
1462
+ if (child.name !== "w:num") continue;
1463
+ const numId = attr(child, "w:numId");
1464
+ const abstractRef = findChild(child, "w:abstractNumId");
1465
+ const abstractId = abstractRef ? attr(abstractRef, "w:val") : void 0;
1466
+ if (numId !== void 0 && abstractId !== void 0) numToAbstract.set(numId, abstractId);
1467
+ }
1468
+ const configs = [];
1469
+ for (const [numId, abstractId] of numToAbstract) {
1470
+ const abstractEl = abstractNums.get(abstractId);
1471
+ if (!abstractEl) continue;
1472
+ const levels = [];
1473
+ for (const child of abstractEl.elements ?? []) {
1474
+ if (child.name !== "w:lvl") continue;
1475
+ const levelOpts = parseLevelEl(child, parseParagraphProperties, ctx);
1476
+ if (levelOpts) levels.push(levelOpts);
1619
1477
  }
1620
- opts.children = children;
1621
- } else {
1622
- if (textParts.length > 0) opts.text = textParts.join("");
1623
- if (breakCount > 0) opts.break = breakCount;
1624
- if (hasPageBreak) opts.pageBreak = true;
1625
- if (hasColumnBreak) opts.columnBreak = true;
1478
+ if (levels.length > 0 && levels.every((l) => l.format === LevelFormat.BULLET)) continue;
1479
+ if (levels.length > 0) configs.push({
1480
+ reference: `list_${numId}`,
1481
+ levels
1482
+ });
1626
1483
  }
1627
- if (Object.keys(opts).length === 0 && textParts.length === 0 && breakCount === 0 && !hasPageBreak && !hasColumnBreak && extraChildren.length === 0) return null;
1628
- return opts;
1484
+ if (configs.length === 0) return void 0;
1485
+ return { config: configs };
1486
+ }
1487
+ function parseLevelEl(el, parseParagraphProperties, ctx) {
1488
+ const opts = {};
1489
+ const level = attrNum(el, "w:ilvl");
1490
+ if (level !== void 0) opts.level = level;
1491
+ const start = findChild(el, "w:start");
1492
+ if (start) {
1493
+ const val = attrNum(start, "w:val");
1494
+ if (val !== void 0) opts.start = val;
1495
+ }
1496
+ const lvlRestart = findChild(el, "w:lvlRestart");
1497
+ if (lvlRestart) {
1498
+ const val = attrNum(lvlRestart, "w:val");
1499
+ if (val !== void 0) opts.lvlRestart = val;
1500
+ }
1501
+ const numFmt = findChild(el, "w:numFmt");
1502
+ if (numFmt) {
1503
+ const val = attr(numFmt, "w:val");
1504
+ if (val) opts.format = val;
1505
+ }
1506
+ const suff = findChild(el, "w:suff");
1507
+ if (suff) {
1508
+ const val = attr(suff, "w:val");
1509
+ if (val) opts.suffix = val;
1510
+ }
1511
+ if (findChild(el, "w:isLgl")) opts.isLegalNumberingStyle = true;
1512
+ const lvlText = findChild(el, "w:lvlText");
1513
+ if (lvlText) {
1514
+ const val = attr(lvlText, "w:val");
1515
+ if (val) opts.text = val;
1516
+ }
1517
+ const lvlPicBulletId = findChild(el, "w:lvlPicBulletId");
1518
+ if (lvlPicBulletId) {
1519
+ const val = attrNum(lvlPicBulletId, "w:val");
1520
+ if (val !== void 0) opts.lvlPicBulletId = val;
1521
+ }
1522
+ const legacyEl = findChild(el, "w:legacy");
1523
+ if (legacyEl) {
1524
+ const legacy = {};
1525
+ const space = attrNum(legacyEl, "w:legacySpace");
1526
+ if (space !== void 0) legacy.space = space;
1527
+ const indent = attrNum(legacyEl, "w:legacyIndent");
1528
+ if (indent !== void 0) legacy.indent = indent;
1529
+ if (Object.keys(legacy).length > 0) opts.legacy = legacy;
1530
+ }
1531
+ const lvlJc = findChild(el, "w:lvlJc");
1532
+ if (lvlJc) {
1533
+ const val = attr(lvlJc, "w:val");
1534
+ if (val) opts.alignment = val;
1535
+ }
1536
+ const tplc = attr(el, "w:tplc");
1537
+ if (tplc) opts.templateCode = tplc;
1538
+ const tentative = attrBool(el, "w:tentative");
1539
+ if (tentative !== void 0) opts.tentative = tentative;
1540
+ const style = {};
1541
+ const rPr = findChild(el, "w:rPr");
1542
+ if (rPr) {
1543
+ const runOpts = parseRunProperties(rPr);
1544
+ if (Object.keys(runOpts).length > 0) style.run = runOpts;
1545
+ }
1546
+ const pPr = findChild(el, "w:pPr");
1547
+ if (pPr) {
1548
+ const paraOpts = parseParagraphProperties(pPr, ctx);
1549
+ if (Object.keys(paraOpts).length > 0) style.paragraph = paraOpts;
1550
+ }
1551
+ if (Object.keys(style).length > 0) opts.style = style;
1552
+ return Object.keys(opts).length > 0 ? opts : void 0;
1629
1553
  }
1630
1554
  //#endregion
1631
1555
  //#region src/parts/styles/factory.ts
@@ -2034,7 +1958,7 @@ function buildNumberingCache(numberingEl) {
2034
1958
  return cache;
2035
1959
  }
2036
1960
  /**
2037
- * Parse w:styles element into StylesOptions-like structure.
1961
+ * Parse w:styles element into StylesOptions.
2038
1962
  *
2039
1963
  * Skips built-in styles that DefaultStylesFactory already generates,
2040
1964
  * keeping only user-defined custom styles for round-trip fidelity.
@@ -2044,13 +1968,12 @@ function parseStyleDefinitions(el, parseParagraphProperties, ctx) {
2044
1968
  const paragraphStyles = [];
2045
1969
  const characterStyles = [];
2046
1970
  for (const child of el.elements ?? []) if (child.name === "w:docDefaults") {
2047
- const defOpts = parseDocDefaults(child);
1971
+ const defOpts = parseDocDefaults(child, parseParagraphProperties, ctx);
2048
1972
  if (defOpts) opts.default = defOpts;
2049
1973
  } else if (child.name === "w:style") {
2050
1974
  const styleOpts = parseStyleElement(child, parseParagraphProperties, ctx);
2051
- if (!styleOpts) continue;
2052
- const styleId = styleOpts.id;
2053
- if (styleId && BUILTIN_STYLE_IDS.has(styleId)) continue;
1975
+ if (!styleOpts?._type || !styleOpts.id) continue;
1976
+ if (BUILTIN_STYLE_IDS.has(styleOpts.id)) continue;
2054
1977
  const type = styleOpts._type;
2055
1978
  delete styleOpts._type;
2056
1979
  if (type === "paragraph") paragraphStyles.push(styleOpts);
@@ -2060,38 +1983,25 @@ function parseStyleDefinitions(el, parseParagraphProperties, ctx) {
2060
1983
  if (characterStyles.length > 0) opts.characterStyles = characterStyles;
2061
1984
  return Object.keys(opts).length > 0 ? opts : void 0;
2062
1985
  }
2063
- function parseDocDefaults(el) {
2064
- const result = {};
2065
- const docDefaults = {};
1986
+ function parseDocDefaults(el, parseParagraphProperties, ctx) {
1987
+ const document = {};
2066
1988
  const rPrDefault = findChild(el, "w:rPrDefault");
2067
1989
  if (rPrDefault) {
2068
1990
  const rPr = findChild(rPrDefault, "w:rPr");
2069
1991
  if (rPr) {
2070
1992
  const runDefaults = parseRunProperties(rPr);
2071
- if (Object.keys(runDefaults).length > 0) docDefaults.run = runDefaults;
1993
+ if (Object.keys(runDefaults).length > 0) document.run = runDefaults;
2072
1994
  }
2073
1995
  }
2074
1996
  const pPrDefault = findChild(el, "w:pPrDefault");
2075
1997
  if (pPrDefault) {
2076
1998
  const pPr = findChild(pPrDefault, "w:pPr");
2077
1999
  if (pPr) {
2078
- const paraDefaults = {};
2079
- const spacing = findChild(pPr, "w:spacing");
2080
- if (spacing) {
2081
- const sp = {};
2082
- const before = attrNum(spacing, "w:before");
2083
- if (before !== void 0) sp.before = before;
2084
- const after = attrNum(spacing, "w:after");
2085
- if (after !== void 0) sp.after = after;
2086
- const line = attrNum(spacing, "w:line");
2087
- if (line !== void 0) sp.line = line;
2088
- if (Object.keys(sp).length > 0) paraDefaults.spacing = sp;
2089
- }
2090
- if (Object.keys(paraDefaults).length > 0) docDefaults.paragraph = paraDefaults;
2000
+ const paraDefaults = parseParagraphProperties(pPr, ctx);
2001
+ if (Object.keys(paraDefaults).length > 0) document.paragraph = paraDefaults;
2091
2002
  }
2092
2003
  }
2093
- if (Object.keys(docDefaults).length > 0) result.document = docDefaults;
2094
- return Object.keys(result).length > 0 ? result : void 0;
2004
+ return Object.keys(document).length > 0 ? { document } : void 0;
2095
2005
  }
2096
2006
  function parseStyleElement(el, parseParagraphProperties, ctx) {
2097
2007
  const opts = {};
@@ -2195,6 +2105,14 @@ function compatSetting(name, val) {
2195
2105
  function maybeDerive(password, hashValue) {
2196
2106
  return password !== void 0 && hashValue === void 0 ? derivePasswordHash(password) : void 0;
2197
2107
  }
2108
+ /** Valid w:documentProtection/@w:edit values (ST_DocProtect). */
2109
+ const DOC_PROTECT_EDITS = [
2110
+ "none",
2111
+ "readOnly",
2112
+ "comments",
2113
+ "trackedChanges",
2114
+ "forms"
2115
+ ];
2198
2116
  function stringifyDocProtect(opts) {
2199
2117
  const derived = maybeDerive(opts.password, opts.hashValue);
2200
2118
  const attrs = { "w:enforcement": "1" };
@@ -2540,7 +2458,7 @@ const settingsDesc = {
2540
2458
  p.push(onOff("w:autoFormatOverride", opts.autoFormatOverride));
2541
2459
  p.push(onOff("w:styleLockTheme", opts.styleLockTheme));
2542
2460
  p.push(onOff("w:styleLockQFSet", opts.styleLockQFSet));
2543
- p.push(numVal("w:defaultTabStop", opts.defaultTabStop ?? 420));
2461
+ if (opts.defaultTabStop !== void 0) p.push(numVal("w:defaultTabStop", opts.defaultTabStop));
2544
2462
  p.push(onOff("w:autoHyphenation", opts.hyphenation?.autoHyphenation));
2545
2463
  p.push(numVal("w:consecutiveHyphenLimit", opts.hyphenation?.consecutiveHyphenLimit));
2546
2464
  p.push(numVal("w:hyphenationZone", opts.hyphenation?.hyphenationZone));
@@ -2561,7 +2479,7 @@ const settingsDesc = {
2561
2479
  p.push(numVal("w:drawingGridVerticalOrigin", opts.drawingGridVerticalOrigin));
2562
2480
  p.push(onOff("w:doNotUseMarginsForDrawingGridOrigin", opts.doNotUseMarginsForDrawingGridOrigin));
2563
2481
  p.push(onOff("w:doNotShadeFormData", opts.doNotShadeFormData));
2564
- p.push(strVal("w:characterSpacingControl", opts.characterSpacingControl ?? "compressPunctuation"));
2482
+ if (opts.characterSpacingControl !== void 0) p.push(strVal("w:characterSpacingControl", opts.characterSpacingControl));
2565
2483
  p.push(onOff("w:noPunctuationKerning", opts.noPunctuationKerning));
2566
2484
  p.push(onOff("w:printTwoOnOne", opts.printTwoOnOne));
2567
2485
  p.push(onOff("w:strictFirstAndLastChars", opts.strictFirstAndLastChars));
@@ -2598,20 +2516,11 @@ const settingsDesc = {
2598
2516
  if (opts.hdrShapeDefaults !== void 0) p.push("<w:hdrShapeDefaults/>");
2599
2517
  if (opts.footnotePr !== void 0) p.push(stringifyFootnotePr(opts.footnotePr));
2600
2518
  if (opts.endnotePr !== void 0) p.push(stringifyEndnotePr(opts.endnotePr));
2601
- p.push(stringifyCompatibility({
2519
+ const compatXml = stringifyCompatibility({
2602
2520
  ...opts.compatibility,
2603
- version: opts.compatibility?.version ?? opts.compatibilityModeVersion ?? 15,
2604
- spaceForUnderline: opts.compatibility?.spaceForUnderline ?? true,
2605
- balanceSingleByteDoubleByteWidth: opts.compatibility?.balanceSingleByteDoubleByteWidth ?? true,
2606
- doNotLeaveBackslashAlone: opts.compatibility?.doNotLeaveBackslashAlone ?? true,
2607
- underlineTrailingSpaces: opts.compatibility?.underlineTrailingSpaces ?? true,
2608
- doNotExpandShiftReturn: opts.compatibility?.doNotExpandShiftReturn ?? true,
2609
- adjustLineHeightInTable: opts.compatibility?.adjustLineHeightInTable ?? true,
2610
- useFELayout: opts.compatibility?.useFELayout ?? true,
2611
- overrideTableStyleFontSizeAndJustification: opts.compatibility?.overrideTableStyleFontSizeAndJustification ?? true,
2612
- enableOpenTypeFeatures: opts.compatibility?.enableOpenTypeFeatures ?? true,
2613
- doNotFlipMirrorIndents: opts.compatibility?.doNotFlipMirrorIndents ?? true
2614
- }));
2521
+ version: opts.compatibility?.version ?? opts.compatibilityModeVersion
2522
+ });
2523
+ if (compatXml) p.push(compatXml);
2615
2524
  if (opts.docVars?.length) {
2616
2525
  const vars = opts.docVars.map((v) => attrEl("w:docVar", {
2617
2526
  "w:name": v.name,
@@ -2669,14 +2578,16 @@ const settingsDesc = {
2669
2578
  const val = attr(tabStopEl, "w:val");
2670
2579
  if (val) opts.defaultTabStop = parseInt(val, 10);
2671
2580
  }
2672
- if (findChild(el, "w:trackRevisions")) {
2581
+ const trackRevEl = findChild(el, "w:trackRevisions");
2582
+ if (trackRevEl) {
2673
2583
  const features = opts.features ?? {};
2674
- features.trackRevisions = true;
2584
+ features.trackRevisions = attrBool(trackRevEl, "w:val") ?? true;
2675
2585
  opts.features = features;
2676
2586
  }
2677
- if (findChild(el, "w:updateFields")) {
2587
+ const updateFieldsEl = findChild(el, "w:updateFields");
2588
+ if (updateFieldsEl) {
2678
2589
  const features = opts.features ?? {};
2679
- features.updateFields = true;
2590
+ features.updateFields = attrBool(updateFieldsEl, "w:val") ?? true;
2680
2591
  opts.features = features;
2681
2592
  }
2682
2593
  const compatEl = findChild(el, "w:compat");
@@ -2833,7 +2744,7 @@ const settingsDesc = {
2833
2744
  if (docProtEl) {
2834
2745
  const prot = {};
2835
2746
  const edit = attr(docProtEl, "w:edit");
2836
- if (edit) prot.edit = edit;
2747
+ if (edit && DOC_PROTECT_EDITS.includes(edit)) prot.edit = edit;
2837
2748
  if (attr(docProtEl, "w:enforcement") !== void 0) {
2838
2749
  const hash = attr(docProtEl, "w:hash");
2839
2750
  if (hash) prot.hash = hash;
@@ -2860,10 +2771,16 @@ const settingsDesc = {
2860
2771
  const formatting = attr(docProtEl, "w:formatting");
2861
2772
  if (formatting !== void 0) prot.formatting = formatting === "1" || formatting === "true";
2862
2773
  }
2863
- if (Object.keys(prot).length > 0) opts.documentProtection = prot;
2774
+ if (Object.keys(prot).length > 0) {
2775
+ const features = opts.features ?? {};
2776
+ features.documentProtection = prot;
2777
+ opts.features = features;
2778
+ }
2864
2779
  }
2865
- if (findChild(el, "w:doNotTrackMoves")) opts.doNotTrackMoves = true;
2866
- if (findChild(el, "w:doNotTrackFormatting")) opts.doNotTrackFormatting = true;
2780
+ const noMovesEl = findChild(el, "w:doNotTrackMoves");
2781
+ if (noMovesEl) opts.doNotTrackMoves = attrBool(noMovesEl, "w:val") ?? true;
2782
+ const noFmtEl = findChild(el, "w:doNotTrackFormatting");
2783
+ if (noFmtEl) opts.doNotTrackFormatting = attrBool(noFmtEl, "w:val") ?? true;
2867
2784
  return opts;
2868
2785
  }
2869
2786
  };
@@ -3001,6 +2918,19 @@ function parseTocFieldInstruction(instruction, opts) {
3001
2918
  if (switches["o"]) opts.headingStyleRange = switches["o"];
3002
2919
  if (switches["p"]) opts.entryAndPageNumberSeparator = switches["p"];
3003
2920
  if (switches["s"]) opts.seqFieldIdentifierForPrefix = switches["s"];
2921
+ if (switches["t"]) {
2922
+ const parts = switches["t"].split(",");
2923
+ const stylesWithLevels = [];
2924
+ for (let i = 0; i + 1 < parts.length; i += 2) {
2925
+ const styleName = parts[i];
2926
+ const level = parseInt(parts[i + 1], 10);
2927
+ if (styleName && !Number.isNaN(level)) stylesWithLevels.push({
2928
+ styleName,
2929
+ level
2930
+ });
2931
+ }
2932
+ if (stylesWithLevels.length > 0) opts.stylesWithLevels = stylesWithLevels;
2933
+ }
3004
2934
  if ("u" in switches) opts.useAppliedParagraphOutlineLevel = true;
3005
2935
  if ("w" in switches) opts.preserveTabInEntries = true;
3006
2936
  if ("x" in switches) opts.preserveNewLineInEntries = true;
@@ -3365,6 +3295,22 @@ const HEADING_MAP = {
3365
3295
  Heading6: HeadingLevel.HEADING_6,
3366
3296
  Title: HeadingLevel.TITLE
3367
3297
  };
3298
+ /** Valid w:spacing/@w:lineRule values (ST_LineSpacingRule). */
3299
+ const LINE_RULES = Object.values(LineRuleType);
3300
+ /** Valid border @w:val values (ST_Border). */
3301
+ const BORDER_STYLES = Object.values(BorderStyle);
3302
+ /** Valid border @w:themeColor values (ST_ThemeColor). */
3303
+ const THEME_COLORS = Object.values(ThemeColor);
3304
+ /**
3305
+ * Reverse of inline.ts's deleted-page-number field map: maps a w:delInstrText
3306
+ * field code to the PageNumber placeholder a deletion run uses on the stringify
3307
+ * side, so deleted page-number fields round-trip instead of being dropped.
3308
+ */
3309
+ const DELETED_PAGE_FIELD = {
3310
+ PAGE: "CURRENT",
3311
+ NUMPAGES: "TOTAL_PAGES",
3312
+ SECTIONPAGES: "TOTAL_PAGES_IN_SECTION"
3313
+ };
3368
3314
  /**
3369
3315
  * Parse w:pPr element into paragraph properties (without children).
3370
3316
  */
@@ -3391,11 +3337,15 @@ function parseParagraphProperties(el, ctx) {
3391
3337
  const line = attrNum(spacing, "w:line");
3392
3338
  if (line !== void 0) sp.line = line;
3393
3339
  const lineRule = attr(spacing, "w:lineRule");
3394
- if (lineRule) sp.lineRule = lineRule;
3395
- const beforeAuto = attrBool(spacing, "w:beforeAutospacing") ?? attrBool(spacing, "w:beforeLines");
3396
- if (beforeAuto !== void 0) sp.beforeAutoSpacing = beforeAuto;
3397
- const afterAuto = attrBool(spacing, "w:afterAutospacing") ?? attrBool(spacing, "w:afterLines");
3398
- if (afterAuto !== void 0) sp.afterAutoSpacing = afterAuto;
3340
+ if (lineRule && LINE_RULES.includes(lineRule)) sp.lineRule = lineRule;
3341
+ const beforeAutoSpacing = attrBool(spacing, "w:beforeAutospacing");
3342
+ if (beforeAutoSpacing !== void 0) sp.beforeAutoSpacing = beforeAutoSpacing;
3343
+ const afterAutoSpacing = attrBool(spacing, "w:afterAutospacing");
3344
+ if (afterAutoSpacing !== void 0) sp.afterAutoSpacing = afterAutoSpacing;
3345
+ const beforeLines = attrNum(spacing, "w:beforeLines");
3346
+ if (beforeLines !== void 0) sp.beforeLines = beforeLines;
3347
+ const afterLines = attrNum(spacing, "w:afterLines");
3348
+ if (afterLines !== void 0) sp.afterLines = afterLines;
3399
3349
  if (Object.keys(sp).length > 0) opts.spacing = sp;
3400
3350
  }
3401
3351
  const ind = findChild(el, "w:ind");
@@ -3403,16 +3353,28 @@ function parseParagraphProperties(el, ctx) {
3403
3353
  const indentObj = {};
3404
3354
  const left = attrNum(ind, "w:left");
3405
3355
  if (left !== void 0) indentObj.left = left;
3356
+ const leftChars = attrNum(ind, "w:leftChars");
3357
+ if (leftChars !== void 0) indentObj.leftChars = leftChars;
3406
3358
  const right = attrNum(ind, "w:right");
3407
3359
  if (right !== void 0) indentObj.right = right;
3360
+ const rightChars = attrNum(ind, "w:rightChars");
3361
+ if (rightChars !== void 0) indentObj.rightChars = rightChars;
3408
3362
  const start = attrNum(ind, "w:start");
3409
3363
  if (start !== void 0) indentObj.start = start;
3364
+ const startChars = attrNum(ind, "w:startChars");
3365
+ if (startChars !== void 0) indentObj.startChars = startChars;
3410
3366
  const end = attrNum(ind, "w:end");
3411
3367
  if (end !== void 0) indentObj.end = end;
3368
+ const endChars = attrNum(ind, "w:endChars");
3369
+ if (endChars !== void 0) indentObj.endChars = endChars;
3412
3370
  const hanging = attrNum(ind, "w:hanging");
3413
3371
  if (hanging !== void 0) indentObj.hanging = hanging;
3372
+ const hangingChars = attrNum(ind, "w:hangingChars");
3373
+ if (hangingChars !== void 0) indentObj.hangingChars = hangingChars;
3414
3374
  const firstLine = attrNum(ind, "w:firstLine");
3415
3375
  if (firstLine !== void 0) indentObj.firstLine = firstLine;
3376
+ const firstLineChars = attrNum(ind, "w:firstLineChars");
3377
+ if (firstLineChars !== void 0) indentObj.firstLineChars = firstLineChars;
3416
3378
  if (Object.keys(indentObj).length > 0) opts.indent = indentObj;
3417
3379
  }
3418
3380
  const numPr = findChild(el, "w:numPr");
@@ -3473,6 +3435,7 @@ function parseParagraphProperties(el, ctx) {
3473
3435
  ["w:kinsoku", "kinsoku"],
3474
3436
  ["w:topLinePunct", "topLinePunct"],
3475
3437
  ["w:autoSpaceDE", "autoSpaceDE"],
3438
+ ["w:autoSpaceDN", "autoSpaceEastAsianText"],
3476
3439
  ["w:overflowPunct", "overflowPunctuation"],
3477
3440
  ["w:suppressOverlap", "suppressOverlap"]
3478
3441
  ]) {
@@ -3486,21 +3449,32 @@ function parseParagraphProperties(el, ctx) {
3486
3449
  "top",
3487
3450
  "bottom",
3488
3451
  "left",
3489
- "right"
3452
+ "right",
3453
+ "between",
3454
+ "bar"
3490
3455
  ]) {
3491
3456
  const sideEl = findChild(pBdr, `w:${side}`);
3492
- if (sideEl) {
3493
- const sideOpts = {};
3494
- const style = attr(sideEl, "w:val");
3495
- if (style) sideOpts.style = style;
3496
- const color = attr(sideEl, "w:color");
3497
- if (color) sideOpts.color = color;
3498
- const size = attrNum(sideEl, "w:sz");
3499
- if (size !== void 0) sideOpts.size = size;
3500
- const space = attrNum(sideEl, "w:space");
3501
- if (space !== void 0) sideOpts.space = space;
3502
- border[side] = sideOpts;
3503
- }
3457
+ if (!sideEl) continue;
3458
+ const style = attr(sideEl, "w:val");
3459
+ if (!style || !BORDER_STYLES.includes(style)) continue;
3460
+ const sideOpts = { style };
3461
+ const color = attr(sideEl, "w:color");
3462
+ if (color) sideOpts.color = color;
3463
+ const size = attrNum(sideEl, "w:sz");
3464
+ if (size !== void 0) sideOpts.size = size;
3465
+ const space = attrNum(sideEl, "w:space");
3466
+ if (space !== void 0) sideOpts.space = space;
3467
+ const themeColor = attr(sideEl, "w:themeColor");
3468
+ if (themeColor && THEME_COLORS.includes(themeColor)) sideOpts.themeColor = themeColor;
3469
+ const themeTint = attr(sideEl, "w:themeTint");
3470
+ if (themeTint) sideOpts.themeTint = themeTint;
3471
+ const themeShade = attr(sideEl, "w:themeShade");
3472
+ if (themeShade) sideOpts.themeShade = themeShade;
3473
+ const shadow = attrBool(sideEl, "w:shadow");
3474
+ if (shadow !== void 0) sideOpts.shadow = shadow;
3475
+ const frame = attrBool(sideEl, "w:frame");
3476
+ if (frame !== void 0) sideOpts.frame = frame;
3477
+ border[side] = sideOpts;
3504
3478
  }
3505
3479
  if (Object.keys(border).length > 0) opts.border = border;
3506
3480
  }
@@ -3545,6 +3519,24 @@ function parseParagraphProperties(el, ctx) {
3545
3519
  const val = attr(framePr, attrName);
3546
3520
  if (val !== void 0) frame[optName] = val;
3547
3521
  }
3522
+ const xAlign = attr(framePr, "w:xAlign");
3523
+ const yAlign = attr(framePr, "w:yAlign");
3524
+ if (xAlign || yAlign) {
3525
+ const alignment = {};
3526
+ if (xAlign) alignment.x = xAlign;
3527
+ if (yAlign) alignment.y = yAlign;
3528
+ frame.alignment = alignment;
3529
+ }
3530
+ const hAnchor = attr(framePr, "w:hAnchor");
3531
+ const vAnchor = attr(framePr, "w:vAnchor");
3532
+ if (hAnchor || vAnchor) {
3533
+ const anchor = {};
3534
+ if (hAnchor) anchor.horizontal = hAnchor;
3535
+ if (vAnchor) anchor.vertical = vAnchor;
3536
+ frame.anchor = anchor;
3537
+ }
3538
+ const anchorLock = attrBool(framePr, "w:anchorLock");
3539
+ if (anchorLock !== void 0) frame.anchorLock = anchorLock;
3548
3540
  const w = attrNum(framePr, "w:w");
3549
3541
  if (w !== void 0) frame.width = w;
3550
3542
  const h = attrNum(framePr, "w:h");
@@ -3554,6 +3546,136 @@ function parseParagraphProperties(el, ctx) {
3554
3546
  return opts;
3555
3547
  }
3556
3548
  /**
3549
+ * Concatenate `<w:t>` text in a run element.
3550
+ *
3551
+ * Used to capture a textInput form field's current value from the result run
3552
+ * (the runs between the `separate` and `end` fldChars). Only `<w:t>` is read —
3553
+ * `<w:tab>`/`<w:br>` in results are ignored as rare for user-entered text.
3554
+ */
3555
+ function collectRunText(el) {
3556
+ let text = "";
3557
+ for (const c of el.elements ?? []) if (c.name === "w:t") text += textOf(c);
3558
+ return text;
3559
+ }
3560
+ /** Concatenate `<w:t>` text across all `<w:r>` children of a container (rt/rubyBase). */
3561
+ function collectRunsText(el) {
3562
+ let text = "";
3563
+ for (const r of el.elements ?? []) if (r.name === "w:r") text += collectRunText(r);
3564
+ return text;
3565
+ }
3566
+ /**
3567
+ * Parse the inline children of a smartTag/customXml container (recursive).
3568
+ *
3569
+ * Handles runs and nested smartTag/customXml. Form fields, hyperlinks and
3570
+ * other paragraph-level constructs are rare inside these containers and are
3571
+ * not handled here.
3572
+ */
3573
+ function parseContainerChildren(el, ctx) {
3574
+ const children = [];
3575
+ for (const sub of el.elements ?? []) switch (sub.name) {
3576
+ case "w:r": {
3577
+ const runOpts = parsedRunToOptions(parseRun(sub, ctx));
3578
+ if (runOpts !== null) children.push(runOpts);
3579
+ break;
3580
+ }
3581
+ case "w:smartTag":
3582
+ children.push({ smartTag: parseSmartTagInline(sub, ctx) });
3583
+ break;
3584
+ case "w:customXml":
3585
+ children.push({ customXml: parseCustomXmlInline(sub, ctx) });
3586
+ break;
3587
+ default: break;
3588
+ }
3589
+ return children;
3590
+ }
3591
+ /** Parse a w:smartTag element into its ParagraphChild form. */
3592
+ function parseSmartTagInline(el, ctx) {
3593
+ const st = {};
3594
+ const element = attr(el, "w:element");
3595
+ if (element) st.element = element;
3596
+ const uri = attr(el, "w:uri");
3597
+ if (uri) st.uri = uri;
3598
+ const pr = findChild(el, "w:smartTagPr");
3599
+ if (pr) {
3600
+ const props = [];
3601
+ for (const a of pr.elements ?? []) {
3602
+ if (a.name !== "w:attr") continue;
3603
+ const prop = {
3604
+ name: attr(a, "w:name") ?? "",
3605
+ val: attr(a, "w:val") ?? ""
3606
+ };
3607
+ const auri = attr(a, "w:uri");
3608
+ if (auri) prop.uri = auri;
3609
+ props.push(prop);
3610
+ }
3611
+ if (props.length > 0) st.properties = props;
3612
+ }
3613
+ const content = parseContainerChildren(el, ctx);
3614
+ if (content.length > 0) st.children = content;
3615
+ return st;
3616
+ }
3617
+ /** Parse an inline w:customXml element into its ParagraphChild form. */
3618
+ function parseCustomXmlInline(el, ctx) {
3619
+ const cx = {};
3620
+ const element = attr(el, "w:element");
3621
+ if (element) cx.element = element;
3622
+ const uri = attr(el, "w:uri");
3623
+ if (uri) cx.uri = uri;
3624
+ const pr = findChild(el, "w:customXmlPr");
3625
+ if (pr) {
3626
+ const cxPr = {};
3627
+ const placeholder = findChild(pr, "w:placeholder");
3628
+ if (placeholder) {
3629
+ const pval = attr(placeholder, "w:val");
3630
+ if (pval) cxPr.placeholder = pval;
3631
+ }
3632
+ const attrsList = [];
3633
+ for (const a of pr.elements ?? []) {
3634
+ if (a.name !== "w:attr") continue;
3635
+ const name = attr(a, "w:name");
3636
+ const val = attr(a, "w:val");
3637
+ if (name && val) {
3638
+ const ao = {
3639
+ name,
3640
+ val
3641
+ };
3642
+ const auri = attr(a, "w:uri");
3643
+ if (auri) ao.uri = auri;
3644
+ attrsList.push(ao);
3645
+ }
3646
+ }
3647
+ if (attrsList.length > 0) cxPr.attrs = attrsList;
3648
+ if (cxPr.placeholder !== void 0 || cxPr.attrs !== void 0) cx.customXmlPr = cxPr;
3649
+ }
3650
+ const content = parseContainerChildren(el, ctx);
3651
+ if (content.length > 0) cx.children = content;
3652
+ return cx;
3653
+ }
3654
+ /** Parse a move-revision range start (w:moveFromRangeStart / w:moveToRangeStart). */
3655
+ function parseMoveRangeStart(el) {
3656
+ const id = attrNum(el, "w:id");
3657
+ if (id === void 0) return null;
3658
+ const m = { id };
3659
+ const name = attr(el, "w:name");
3660
+ if (name !== void 0) m.name = name;
3661
+ const author = attr(el, "w:author");
3662
+ if (author !== void 0) m.author = author;
3663
+ const date = attr(el, "w:date");
3664
+ if (date !== void 0) m.date = date;
3665
+ return m;
3666
+ }
3667
+ /** Parse a customXml range start (Ins/Del/MoveFrom/MoveTo). */
3668
+ function parseCustomXmlRangeStart(el) {
3669
+ const id = attrNum(el, "w:id");
3670
+ if (id === void 0) return null;
3671
+ const m = { id };
3672
+ const author = attr(el, "w:author");
3673
+ if (author !== void 0) m.author = author;
3674
+ const date = attr(el, "w:date");
3675
+ if (date !== void 0) m.date = date;
3676
+ return m;
3677
+ }
3678
+ /**
3557
3679
  * Parse a w:p element into ParagraphOptions.
3558
3680
  */
3559
3681
  function parseParagraph(el, ctx) {
@@ -3561,9 +3683,57 @@ function parseParagraph(el, ctx) {
3561
3683
  const pPr = findChild(el, "w:pPr");
3562
3684
  if (pPr) Object.assign(opts, parseParagraphProperties(pPr, ctx));
3563
3685
  const childList = [];
3686
+ let fieldKind = null;
3687
+ let pendingFormField = null;
3688
+ let pendingInstruction = "";
3689
+ let pendingResult = "";
3690
+ let collectingResult = false;
3564
3691
  for (const child of el.elements ?? []) switch (child.name) {
3565
3692
  case "w:pPr": break;
3566
3693
  case "w:r": {
3694
+ const fldCharEl = findChild(child, "w:fldChar");
3695
+ if (fldCharEl) {
3696
+ const fctype = attr(fldCharEl, "w:fldCharType");
3697
+ if (fctype === "begin") {
3698
+ const ffDataEl = findChild(fldCharEl, "w:ffData");
3699
+ if (ffDataEl) {
3700
+ fieldKind = "form";
3701
+ pendingFormField = parseFormFieldData(ffDataEl);
3702
+ } else {
3703
+ fieldKind = "complex";
3704
+ pendingInstruction = "";
3705
+ pendingResult = "";
3706
+ }
3707
+ collectingResult = false;
3708
+ } else if (fctype === "separate") collectingResult = true;
3709
+ else if (fctype === "end" && fieldKind) {
3710
+ if (fieldKind === "form" && pendingFormField) childList.push({ formField: pendingFormField });
3711
+ else if (fieldKind === "complex") {
3712
+ const cf = { instruction: pendingInstruction };
3713
+ if (pendingResult) cf.result = pendingResult;
3714
+ childList.push({ complexField: cf });
3715
+ }
3716
+ fieldKind = null;
3717
+ pendingFormField = null;
3718
+ collectingResult = false;
3719
+ }
3720
+ break;
3721
+ }
3722
+ if (fieldKind) {
3723
+ if (fieldKind === "complex") if (collectingResult) pendingResult += collectRunText(child);
3724
+ else {
3725
+ const instrEl = findChild(child, "w:instrText");
3726
+ if (instrEl) pendingInstruction += textOf(instrEl);
3727
+ }
3728
+ else if (collectingResult && pendingFormField?.textInput) {
3729
+ const text = collectRunText(child);
3730
+ if (text) {
3731
+ const ti = pendingFormField.textInput;
3732
+ ti.value = (ti.value ?? "") + text;
3733
+ }
3734
+ }
3735
+ break;
3736
+ }
3567
3737
  const drawingEl = findChild(child, "w:drawing");
3568
3738
  if (drawingEl) {
3569
3739
  const drawingChild = parseDrawingRun(drawingEl, ctx);
@@ -3646,6 +3816,24 @@ function parseParagraph(el, ctx) {
3646
3816
  break;
3647
3817
  }
3648
3818
  case "w:del": {
3819
+ let delFieldPlaceholder;
3820
+ for (const sub of child.elements ?? []) {
3821
+ if (sub.name !== "w:r") continue;
3822
+ const delInstrEl = findChild(sub, "w:delInstrText");
3823
+ if (delInstrEl) {
3824
+ delFieldPlaceholder = DELETED_PAGE_FIELD[(textOf(delInstrEl) ?? "").trim()];
3825
+ if (delFieldPlaceholder) break;
3826
+ }
3827
+ }
3828
+ if (delFieldPlaceholder) {
3829
+ childList.push({ deletion: {
3830
+ id: attrNum(child, "w:id") ?? 0,
3831
+ author: attr(child, "w:author") ?? "",
3832
+ date: attr(child, "w:date") ?? "",
3833
+ children: [delFieldPlaceholder]
3834
+ } });
3835
+ break;
3836
+ }
3649
3837
  const delRun = findChild(child, "w:r");
3650
3838
  if (delRun) {
3651
3839
  const runOpts = parsedRunToOptions(parseRun(delRun, ctx));
@@ -3658,6 +3846,208 @@ function parseParagraph(el, ctx) {
3658
3846
  }
3659
3847
  break;
3660
3848
  }
3849
+ case "w:moveFrom": {
3850
+ const runEl = findChild(child, "w:r");
3851
+ if (runEl) {
3852
+ const runOpts = parsedRunToOptions(parseRun(runEl, ctx));
3853
+ if (runOpts !== null && typeof runOpts === "object" && !("commentReference" in runOpts)) childList.push({ movedFrom: {
3854
+ id: attrNum(child, "w:id") ?? 0,
3855
+ author: attr(child, "w:author") ?? "",
3856
+ date: attr(child, "w:date") ?? "",
3857
+ ...runOpts
3858
+ } });
3859
+ }
3860
+ break;
3861
+ }
3862
+ case "w:moveTo": {
3863
+ const runEl = findChild(child, "w:r");
3864
+ if (runEl) {
3865
+ const runOpts = parsedRunToOptions(parseRun(runEl, ctx));
3866
+ if (runOpts !== null && typeof runOpts === "object" && !("commentReference" in runOpts)) childList.push({ movedTo: {
3867
+ id: attrNum(child, "w:id") ?? 0,
3868
+ author: attr(child, "w:author") ?? "",
3869
+ date: attr(child, "w:date") ?? "",
3870
+ ...runOpts
3871
+ } });
3872
+ }
3873
+ break;
3874
+ }
3875
+ case "w:fldSimple": {
3876
+ const instruction = attr(child, "w:instr");
3877
+ if (instruction) {
3878
+ const sf = { instruction };
3879
+ let cachedValue = "";
3880
+ for (const sub of child.elements ?? []) if (sub.name === "w:r") cachedValue += collectRunText(sub);
3881
+ if (cachedValue) sf.cachedValue = cachedValue;
3882
+ childList.push({ simpleField: sf });
3883
+ }
3884
+ break;
3885
+ }
3886
+ case "w:smartTag": {
3887
+ const st = parseSmartTagInline(child, ctx);
3888
+ if (st.element) childList.push({ smartTag: st });
3889
+ break;
3890
+ }
3891
+ case "w:customXml": {
3892
+ const cx = parseCustomXmlInline(child, ctx);
3893
+ if (cx.element) childList.push({ customXml: cx });
3894
+ break;
3895
+ }
3896
+ case "w:dir": {
3897
+ const val = attr(child, "w:val");
3898
+ if (val) {
3899
+ const dir = { val };
3900
+ const content = parseContainerChildren(child, ctx);
3901
+ if (content.length > 0) dir.children = content;
3902
+ childList.push({ dir });
3903
+ }
3904
+ break;
3905
+ }
3906
+ case "w:bdo": {
3907
+ const val = attr(child, "w:val");
3908
+ if (val) {
3909
+ const bdo = { val };
3910
+ const content = parseContainerChildren(child, ctx);
3911
+ if (content.length > 0) bdo.children = content;
3912
+ childList.push({ bdo });
3913
+ }
3914
+ break;
3915
+ }
3916
+ case "w:ruby": {
3917
+ const ruby = {};
3918
+ const pr = findChild(child, "w:rubyPr");
3919
+ if (pr) {
3920
+ const alignEl = findChild(pr, "w:rubyAlign");
3921
+ if (alignEl) {
3922
+ const v = attr(alignEl, "w:val");
3923
+ if (v) ruby.alignment = v;
3924
+ }
3925
+ const hpsEl = findChild(pr, "w:hps");
3926
+ if (hpsEl) {
3927
+ const v = attrNum(hpsEl, "w:val");
3928
+ if (v !== void 0) ruby.fontSize = v / 2;
3929
+ }
3930
+ const hpsRaiseEl = findChild(pr, "w:hpsRaise");
3931
+ if (hpsRaiseEl) {
3932
+ const v = attrNum(hpsRaiseEl, "w:val");
3933
+ if (v !== void 0) ruby.raise = v / 2;
3934
+ }
3935
+ const hpsBaseEl = findChild(pr, "w:hpsBaseText");
3936
+ if (hpsBaseEl) {
3937
+ const v = attrNum(hpsBaseEl, "w:val");
3938
+ if (v !== void 0) ruby.baseFontSize = v / 2;
3939
+ }
3940
+ const lidEl = findChild(pr, "w:lid");
3941
+ if (lidEl) {
3942
+ const v = attr(lidEl, "w:val");
3943
+ if (v) ruby.languageId = v;
3944
+ }
3945
+ if (findChild(pr, "w:dirty")) ruby.dirty = true;
3946
+ }
3947
+ const rt = findChild(child, "w:rt");
3948
+ if (rt) ruby.text = collectRunsText(rt);
3949
+ const rubyBase = findChild(child, "w:rubyBase");
3950
+ if (rubyBase) ruby.base = collectRunsText(rubyBase);
3951
+ if (ruby.text !== void 0 && ruby.base !== void 0) childList.push({ ruby });
3952
+ break;
3953
+ }
3954
+ case "w:proofErr": {
3955
+ const type = attr(child, "w:type");
3956
+ if (type) childList.push({ proofErr: type });
3957
+ break;
3958
+ }
3959
+ case "w:ptab": {
3960
+ const alignment = attr(child, "w:alignment");
3961
+ const leader = attr(child, "w:leader");
3962
+ const relativeTo = attr(child, "w:relativeTo");
3963
+ if (alignment !== void 0 && leader !== void 0 && relativeTo !== void 0) childList.push({ positionalTab: {
3964
+ alignment,
3965
+ leader,
3966
+ relativeTo
3967
+ } });
3968
+ break;
3969
+ }
3970
+ case "w:permStart": {
3971
+ const id = attr(child, "w:id");
3972
+ if (id !== void 0) {
3973
+ const ps = { id };
3974
+ const ed = attr(child, "w:ed");
3975
+ if (ed !== void 0) ps.ed = ed;
3976
+ const editGroup = attr(child, "w:edGrp");
3977
+ if (editGroup !== void 0) ps.editGroup = editGroup;
3978
+ const colFirst = attrNum(child, "w:colFirst");
3979
+ if (colFirst !== void 0) ps.colFirst = colFirst;
3980
+ const colLast = attrNum(child, "w:colLast");
3981
+ if (colLast !== void 0) ps.colLast = colLast;
3982
+ childList.push({ permStart: ps });
3983
+ }
3984
+ break;
3985
+ }
3986
+ case "w:permEnd": {
3987
+ const id = attr(child, "w:id");
3988
+ if (id !== void 0) childList.push({ permEnd: id });
3989
+ break;
3990
+ }
3991
+ case "w:moveFromRangeStart": {
3992
+ const m = parseMoveRangeStart(child);
3993
+ if (m) childList.push({ moveFromRangeStart: m });
3994
+ break;
3995
+ }
3996
+ case "w:moveFromRangeEnd": {
3997
+ const id = attrNum(child, "w:id");
3998
+ if (id !== void 0) childList.push({ moveFromRangeEnd: id });
3999
+ break;
4000
+ }
4001
+ case "w:moveToRangeStart": {
4002
+ const m = parseMoveRangeStart(child);
4003
+ if (m) childList.push({ moveToRangeStart: m });
4004
+ break;
4005
+ }
4006
+ case "w:moveToRangeEnd": {
4007
+ const id = attrNum(child, "w:id");
4008
+ if (id !== void 0) childList.push({ moveToRangeEnd: id });
4009
+ break;
4010
+ }
4011
+ case "w:customXmlInsRangeStart": {
4012
+ const m = parseCustomXmlRangeStart(child);
4013
+ if (m) childList.push({ customXmlInsRangeStart: m });
4014
+ break;
4015
+ }
4016
+ case "w:customXmlInsRangeEnd": {
4017
+ const id = attrNum(child, "w:id");
4018
+ if (id !== void 0) childList.push({ customXmlInsRangeEnd: id });
4019
+ break;
4020
+ }
4021
+ case "w:customXmlDelRangeStart": {
4022
+ const m = parseCustomXmlRangeStart(child);
4023
+ if (m) childList.push({ customXmlDelRangeStart: m });
4024
+ break;
4025
+ }
4026
+ case "w:customXmlDelRangeEnd": {
4027
+ const id = attrNum(child, "w:id");
4028
+ if (id !== void 0) childList.push({ customXmlDelRangeEnd: id });
4029
+ break;
4030
+ }
4031
+ case "w:customXmlMoveFromRangeStart": {
4032
+ const m = parseCustomXmlRangeStart(child);
4033
+ if (m) childList.push({ customXmlMoveFromRangeStart: m });
4034
+ break;
4035
+ }
4036
+ case "w:customXmlMoveFromRangeEnd": {
4037
+ const id = attrNum(child, "w:id");
4038
+ if (id !== void 0) childList.push({ customXmlMoveFromRangeEnd: id });
4039
+ break;
4040
+ }
4041
+ case "w:customXmlMoveToRangeStart": {
4042
+ const m = parseCustomXmlRangeStart(child);
4043
+ if (m) childList.push({ customXmlMoveToRangeStart: m });
4044
+ break;
4045
+ }
4046
+ case "w:customXmlMoveToRangeEnd": {
4047
+ const id = attrNum(child, "w:id");
4048
+ if (id !== void 0) childList.push({ customXmlMoveToRangeEnd: id });
4049
+ break;
4050
+ }
3661
4051
  default: break;
3662
4052
  }
3663
4053
  if (childList.length > 0) {
@@ -3873,6 +4263,22 @@ function parseSdtProperties(el) {
3873
4263
  if (gallery) opts.docPartList.gallery = attr(gallery, "w:val");
3874
4264
  const category = findChild(dp, "w:docPartCategory");
3875
4265
  if (category) opts.docPartList.category = attr(category, "w:val");
4266
+ } else if (findChild(el, "w14:checkbox")) {
4267
+ const cb = findChild(el, "w14:checkbox");
4268
+ const cbObj = {};
4269
+ const checked = findChild(cb, "w14:checked");
4270
+ if (checked) cbObj.checked = attrBool(checked, "w14:val") ?? true;
4271
+ const checkedState = findChild(cb, "w14:checkedState");
4272
+ if (checkedState) cbObj.checkedState = {
4273
+ val: attr(checkedState, "w14:val") ?? "",
4274
+ font: attr(checkedState, "w14:font")
4275
+ };
4276
+ const uncheckedState = findChild(cb, "w14:uncheckedState");
4277
+ if (uncheckedState) cbObj.uncheckedState = {
4278
+ val: attr(uncheckedState, "w14:val") ?? "",
4279
+ font: attr(uncheckedState, "w14:font")
4280
+ };
4281
+ opts.checkbox = cbObj;
3876
4282
  }
3877
4283
  return opts;
3878
4284
  }
@@ -4714,6 +5120,28 @@ function sdtDocPartXml(name, options) {
4714
5120
  function onOffAttr(name, val) {
4715
5121
  return val ? `<${name}/>` : `<${name} w:val="0"/>`;
4716
5122
  }
5123
+ const W14_NS = "xmlns:w14=\"http://schemas.microsoft.com/office/word/2010/wordml\"";
5124
+ /** Default symbol font for checkbox content controls (CT_SdtCheckboxSymbol). */
5125
+ const CHECKBOX_FONT = "MS Gothic";
5126
+ const DEFAULT_CHECKED = {
5127
+ val: "2612",
5128
+ font: CHECKBOX_FONT
5129
+ };
5130
+ const DEFAULT_UNCHECKED = {
5131
+ val: "2610",
5132
+ font: CHECKBOX_FONT
5133
+ };
5134
+ /**
5135
+ * Build a w14:checkbox element (Word 2010+ content control checkbox).
5136
+ *
5137
+ * Lives in the w14 extension namespace; emitted with an inline xmlns:w14 so it
5138
+ * is valid wherever w:sdtPr appears. validate.ts tolerates the w14 namespace.
5139
+ */
5140
+ function sdtCheckboxXml(opts) {
5141
+ const checked = opts.checkedState ?? DEFAULT_CHECKED;
5142
+ const unchecked = opts.uncheckedState ?? DEFAULT_UNCHECKED;
5143
+ 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>`;
5144
+ }
4717
5145
  function stringifySdtPr(opts) {
4718
5146
  const parts = [];
4719
5147
  if (opts.alias !== void 0) parts.push(`<w:alias w:val="${escapeXml$1(opts.alias)}"/>`);
@@ -4740,6 +5168,7 @@ function stringifySdtPr(opts) {
4740
5168
  } else if (opts.citation) parts.push("<w:citation/>");
4741
5169
  else if (opts.group) parts.push("<w:group/>");
4742
5170
  else if (opts.bibliography) parts.push("<w:bibliography/>");
5171
+ else if (opts.checkbox) parts.push(sdtCheckboxXml(opts.checkbox));
4743
5172
  return parts.length ? `<w:sdtPr>${parts.join("")}</w:sdtPr>` : "<w:sdtPr/>";
4744
5173
  }
4745
5174
  /** Parse w:sdtPr element into SdtPropertiesOptions. */
@@ -4843,6 +5272,23 @@ function parseSdtPr(el) {
4843
5272
  else if (findChild(el, "w:citation")) opts.citation = true;
4844
5273
  else if (findChild(el, "w:group")) opts.group = true;
4845
5274
  else if (findChild(el, "w:bibliography")) opts.bibliography = true;
5275
+ else if (findChild(el, "w14:checkbox")) {
5276
+ const cb = findChild(el, "w14:checkbox");
5277
+ const cbObj = {};
5278
+ const checked = findChild(cb, "w14:checked");
5279
+ if (checked) cbObj.checked = attrBool(checked, "w14:val") ?? true;
5280
+ const checkedState = findChild(cb, "w14:checkedState");
5281
+ if (checkedState) cbObj.checkedState = {
5282
+ val: attr(checkedState, "w14:val") ?? "",
5283
+ font: attr(checkedState, "w14:font")
5284
+ };
5285
+ const uncheckedState = findChild(cb, "w14:uncheckedState");
5286
+ if (uncheckedState) cbObj.uncheckedState = {
5287
+ val: attr(uncheckedState, "w14:val") ?? "",
5288
+ font: attr(uncheckedState, "w14:font")
5289
+ };
5290
+ opts.checkbox = cbObj;
5291
+ }
4846
5292
  return opts;
4847
5293
  }
4848
5294
  /** Parse w:customXmlPr element into CustomXmlPrOptions. */
@@ -4888,8 +5334,15 @@ const sdtBlockDesc = {
4888
5334
  stringify(opts, ctx) {
4889
5335
  const parts = ["<w:sdt>"];
4890
5336
  parts.push(stringifySdtPr(opts.properties));
4891
- parts.push("<w:sdtEndPr/>");
4892
- if (opts.children && opts.children.length > 0) {
5337
+ const endPrInner = opts.endProperties ? stringifyRunPropertiesInner(opts.endProperties) : void 0;
5338
+ parts.push(endPrInner ? `<w:sdtEndPr>${endPrInner}</w:sdtEndPr>` : "<w:sdtEndPr/>");
5339
+ if (opts.properties.checkbox) {
5340
+ const cb = opts.properties.checkbox;
5341
+ const symbol = cb.checked ?? false ? cb.checkedState ?? DEFAULT_CHECKED : cb.uncheckedState ?? DEFAULT_UNCHECKED;
5342
+ const font = escapeXml$1(symbol.font ?? CHECKBOX_FONT);
5343
+ const char = escapeXml$1(String.fromCodePoint(parseInt(symbol.val, 16)));
5344
+ parts.push(`<w:sdtContent><w:p><w:r><w:rPr><w:rFonts w:ascii="${font}" w:hAnsi="${font}"/></w:rPr><w:t>${char}</w:t></w:r></w:p></w:sdtContent>`);
5345
+ } else if (opts.children && opts.children.length > 0) {
4893
5346
  const contentParts = [];
4894
5347
  for (const child of opts.children) contentParts.push(ctx.stringifyChild(child, ctx));
4895
5348
  const contentBody = contentParts.join("");
@@ -4902,6 +5355,9 @@ const sdtBlockDesc = {
4902
5355
  const dctx = ctx;
4903
5356
  const sdtPr = findChild(el, "w:sdtPr");
4904
5357
  const properties = sdtPr ? parseSdtPr(sdtPr) : {};
5358
+ let endProperties;
5359
+ const sdtEndPr = findChild(el, "w:sdtEndPr");
5360
+ if (sdtEndPr) endProperties = parseRunProperties(sdtEndPr);
4905
5361
  const sdtContent = findChild(el, "w:sdtContent");
4906
5362
  let childList;
4907
5363
  if (sdtContent && sdtContent.elements?.length) {
@@ -4910,7 +5366,8 @@ const sdtBlockDesc = {
4910
5366
  }
4911
5367
  return {
4912
5368
  properties,
4913
- children: childList
5369
+ children: childList,
5370
+ endProperties
4914
5371
  };
4915
5372
  }
4916
5373
  };
@@ -5037,6 +5494,114 @@ const customPropertiesDesc = {
5037
5494
  }
5038
5495
  };
5039
5496
  //#endregion
5497
+ //#region src/parts/app-properties.ts
5498
+ const appPropertiesDesc = {
5499
+ kind: "custom",
5500
+ stringify(opts, _ctx) {
5501
+ const p = ["<Properties xmlns=\"http://schemas.openxmlformats.org/officeDocument/2006/extended-properties\" xmlns:vt=\"http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes\">"];
5502
+ if (opts.template !== void 0) p.push(`<Template>${escapeXml(opts.template)}</Template>`);
5503
+ if (opts.manager !== void 0) p.push(`<Manager>${escapeXml(opts.manager)}</Manager>`);
5504
+ if (opts.company !== void 0) p.push(`<Company>${escapeXml(opts.company)}</Company>`);
5505
+ if (opts.pages !== void 0) p.push(`<Pages>${opts.pages}</Pages>`);
5506
+ if (opts.words !== void 0) p.push(`<Words>${opts.words}</Words>`);
5507
+ if (opts.characters !== void 0) p.push(`<Characters>${opts.characters}</Characters>`);
5508
+ if (opts.lines !== void 0) p.push(`<Lines>${opts.lines}</Lines>`);
5509
+ if (opts.paragraphs !== void 0) p.push(`<Paragraphs>${opts.paragraphs}</Paragraphs>`);
5510
+ if (opts.slides !== void 0) p.push(`<Slides>${opts.slides}</Slides>`);
5511
+ if (opts.notes !== void 0) p.push(`<Notes>${opts.notes}</Notes>`);
5512
+ if (opts.totalTime !== void 0) p.push(`<TotalTime>${opts.totalTime}</TotalTime>`);
5513
+ if (opts.hiddenSlides !== void 0) p.push(`<HiddenSlides>${opts.hiddenSlides}</HiddenSlides>`);
5514
+ if (opts.mmClips !== void 0) p.push(`<MMClips>${opts.mmClips}</MMClips>`);
5515
+ if (opts.scaleCrop !== void 0) p.push(`<ScaleCrop>${opts.scaleCrop ? 1 : 0}</ScaleCrop>`);
5516
+ if (opts.linksUpToDate !== void 0) p.push(`<LinksUpToDate>${opts.linksUpToDate ? 1 : 0}</LinksUpToDate>`);
5517
+ if (opts.charactersWithSpaces !== void 0) p.push(`<CharactersWithSpaces>${opts.charactersWithSpaces}</CharactersWithSpaces>`);
5518
+ if (opts.sharedDoc !== void 0) p.push(`<SharedDoc>${opts.sharedDoc ? 1 : 0}</SharedDoc>`);
5519
+ if (opts.hyperlinkBase !== void 0) p.push(`<HyperlinkBase>${escapeXml(opts.hyperlinkBase)}</HyperlinkBase>`);
5520
+ if (opts.hyperlinksChanged !== void 0) p.push(`<HyperlinksChanged>${opts.hyperlinksChanged ? 1 : 0}</HyperlinksChanged>`);
5521
+ if (opts.application !== void 0) p.push(`<Application>${escapeXml(opts.application)}</Application>`);
5522
+ if (opts.appVersion !== void 0) p.push(`<AppVersion>${escapeXml(opts.appVersion)}</AppVersion>`);
5523
+ if (opts.docSecurity !== void 0) p.push(`<DocSecurity>${opts.docSecurity}</DocSecurity>`);
5524
+ p.push("</Properties>");
5525
+ return p.join("");
5526
+ },
5527
+ parse(el, _ctx) {
5528
+ const result = {};
5529
+ for (const child of el.elements ?? []) {
5530
+ if (typeof child.name !== "string") continue;
5531
+ const text = child.elements?.[0]?.text;
5532
+ switch (child.name) {
5533
+ case "Template":
5534
+ if (typeof text === "string") result.template = text;
5535
+ break;
5536
+ case "Manager":
5537
+ if (typeof text === "string") result.manager = text;
5538
+ break;
5539
+ case "Company":
5540
+ if (typeof text === "string") result.company = text;
5541
+ break;
5542
+ case "Pages":
5543
+ if (typeof text === "string") result.pages = Number(text);
5544
+ break;
5545
+ case "Words":
5546
+ if (typeof text === "string") result.words = Number(text);
5547
+ break;
5548
+ case "Characters":
5549
+ if (typeof text === "string") result.characters = Number(text);
5550
+ break;
5551
+ case "Lines":
5552
+ if (typeof text === "string") result.lines = Number(text);
5553
+ break;
5554
+ case "Paragraphs":
5555
+ if (typeof text === "string") result.paragraphs = Number(text);
5556
+ break;
5557
+ case "Slides":
5558
+ if (typeof text === "string") result.slides = Number(text);
5559
+ break;
5560
+ case "Notes":
5561
+ if (typeof text === "string") result.notes = Number(text);
5562
+ break;
5563
+ case "TotalTime":
5564
+ if (typeof text === "string") result.totalTime = Number(text);
5565
+ break;
5566
+ case "HiddenSlides":
5567
+ if (typeof text === "string") result.hiddenSlides = Number(text);
5568
+ break;
5569
+ case "MMClips":
5570
+ if (typeof text === "string") result.mmClips = Number(text);
5571
+ break;
5572
+ case "ScaleCrop":
5573
+ if (typeof text === "string") result.scaleCrop = text === "1" || text === "true";
5574
+ break;
5575
+ case "LinksUpToDate":
5576
+ if (typeof text === "string") result.linksUpToDate = text === "1" || text === "true";
5577
+ break;
5578
+ case "CharactersWithSpaces":
5579
+ if (typeof text === "string") result.charactersWithSpaces = Number(text);
5580
+ break;
5581
+ case "SharedDoc":
5582
+ if (typeof text === "string") result.sharedDoc = text === "1" || text === "true";
5583
+ break;
5584
+ case "HyperlinkBase":
5585
+ if (typeof text === "string") result.hyperlinkBase = text;
5586
+ break;
5587
+ case "HyperlinksChanged":
5588
+ if (typeof text === "string") result.hyperlinksChanged = text === "1" || text === "true";
5589
+ break;
5590
+ case "Application":
5591
+ if (typeof text === "string") result.application = text;
5592
+ break;
5593
+ case "AppVersion":
5594
+ if (typeof text === "string") result.appVersion = text;
5595
+ break;
5596
+ case "DocSecurity":
5597
+ if (typeof text === "string") result.docSecurity = Number(text);
5598
+ break;
5599
+ }
5600
+ }
5601
+ return result;
5602
+ }
5603
+ };
5604
+ //#endregion
5040
5605
  //#region src/parts/web-settings.ts
5041
5606
  /**
5042
5607
  * Screen size types for web settings target.
@@ -5579,6 +6144,6 @@ var DocxReadContext = class {
5579
6144
  }
5580
6145
  };
5581
6146
  //#endregion
5582
- export { RelativeVerticalPosition as $, footnotesDesc as A, settingsDesc as B, fontTableDesc as C, EditGroupType as D, AltChunkCollection as E, stringifyTableOfContents as F, Numbering as G, buildNumberingCache as H, parseToc as I, LevelSuffix as J, parseNumberingDefinitions as K, SdtDateMappingType as L, parseParagraphProperties as M, stringifyBodyChild as N, parseSdtBlock as O, stringifyDocumentXml as P, RelativeHorizontalPosition as Q, SdtLock as R, bibliographyDesc as S, SubDocCollection as T, buildStyleCache as U, Styles as V, parseStyleDefinitions as W, TableLayoutType as X, TABLE_BORDERS_NONE as Y, OverlapType as Z, commentsDesc as _, AlignmentType as _t, framesetXml as a, PositionalTabAlignment as at, DocPartType as b, corePropertiesDesc as c, EmphasisMarkType as ct, sdtBlockDesc as d, HighlightColor as dt, TableAnchorType as et, setBodyParseChild as f, TextEffect as ft, contentTypesDesc as g, HeadingLevel as gt, buildContentTypes as h, TextboxTightWrapType as ht, frameXml as i, RubyAlign as it, parseParagraph as j, endnotesDesc as k, altChunkDesc as l, UnderlineType as lt, relationshipsDesc as m, TextAlignmentType as mt, DocxWriteContext as n, FormFieldTextType as nt, webSettingsDesc as o, PositionalTabLeader as ot, subDocDesc as p, PageNumber as pt, LevelFormat as q, TargetScreenSize as r, createFormFieldData as rt, customPropertiesDesc as s, PositionalTabRelativeTo as st, DocxReadContext as t, ProofErrorType as tt, customXmlBlockDesc as u, createImageData as ut, DocPartBehavior as v, CharacterSet as w, glossaryDesc as x, DocPartGallery as y, StyleLevel as z };
6147
+ export { RelativeHorizontalPosition as $, endnotesDesc as A, StyleLevel as B, bibliographyDesc as C, AltChunkCollection as D, SubDocCollection as E, stringifyDocumentXml as F, parseStyleDefinitions as G, Styles as H, stringifyTableOfContents as I, LevelFormat as J, Numbering as K, parseToc as L, parseParagraph as M, parseParagraphProperties as N, EditGroupType as O, stringifyBodyChild as P, OverlapType as Q, SdtDateMappingType as R, glossaryDesc as S, CharacterSet as T, buildNumberingCache as U, settingsDesc as V, buildStyleCache as W, TABLE_BORDERS_NONE as X, LevelSuffix as Y, TableLayoutType as Z, contentTypesDesc as _, AlignmentType as _t, framesetXml as a, PositionalTabLeader as at, DocPartGallery as b, customPropertiesDesc as c, UnderlineType as ct, customXmlBlockDesc as d, TextEffect as dt, RelativeVerticalPosition as et, sdtBlockDesc as f, PageNumber as ft, buildContentTypes as g, LineRuleType as gt, relationshipsDesc as h, HeadingLevel as ht, frameXml as i, PositionalTabAlignment as it, footnotesDesc as j, parseSdtBlock as k, corePropertiesDesc as l, createImageData as lt, subDocDesc as m, TextboxTightWrapType as mt, DocxWriteContext as n, ProofErrorType as nt, webSettingsDesc as o, PositionalTabRelativeTo as ot, setBodyParseChild as p, TextAlignmentType as pt, parseNumberingDefinitions as q, TargetScreenSize as r, RubyAlign as rt, appPropertiesDesc as s, EmphasisMarkType as st, DocxReadContext as t, TableAnchorType as tt, altChunkDesc as u, HighlightColor as ut, commentsDesc as v, fontTableDesc as w, DocPartType as x, DocPartBehavior as y, SdtLock as z };
5583
6148
 
5584
- //# sourceMappingURL=context-CERMOUn0.mjs.map
6149
+ //# sourceMappingURL=context-CA7wUvmY.mjs.map