@office-open/docx 0.9.3 → 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,5 +1,5 @@
1
- import { A as stringifyParagraphProperties, D as stringifyChildDispatch, E as tableDesc, F as parseDrawingRun, M as parseMathChildren, O as stringifyParagraphInline, Y as BorderStyle, ct as Media, et as parseFormFieldData, j as stringifyRunProperties, lt as createTransformation, n as sectionPropertiesDesc } from "./document-D8HDkCHs.mjs";
2
- import { Relationships, convertInchesToTwip, decimalNumber, derivePasswordHash, hexColorValue, toUint8Array, uCharHexNumber, uniqueId, uniqueNumericIdCreator, uniqueUuid } from "@office-open/core";
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
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";
@@ -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.
@@ -569,518 +598,16 @@ const TABLE_BORDERS_NONE = {
569
598
  top: NONE_BORDER
570
599
  };
571
600
  //#endregion
572
- //#region src/parts/numbering/level.ts
573
- /**
574
- * Number format types for list levels.
575
- *
576
- * Defines the various numbering formats available for list levels, including
577
- * decimal, roman numerals, letters, and various international formats.
578
- *
579
- * Reference: http://officeopenxml.com/WPnumbering-numFmt.php
580
- *
581
- * @publicApi
582
- */
583
- const LevelFormat = {
584
- /** Decimal numbering (1, 2, 3...). */
585
- DECIMAL: "decimal",
586
- /** Uppercase roman numerals (I, II, III...). */
587
- UPPER_ROMAN: "upperRoman",
588
- /** Lowercase roman numerals (i, ii, iii...). */
589
- LOWER_ROMAN: "lowerRoman",
590
- /** Uppercase letters (A, B, C...). */
591
- UPPER_LETTER: "upperLetter",
592
- /** Lowercase letters (a, b, c...). */
593
- LOWER_LETTER: "lowerLetter",
594
- /** Ordinal numbers (1st, 2nd, 3rd...). */
595
- ORDINAL: "ordinal",
596
- /** Cardinal text (one, two, three...). */
597
- CARDINAL_TEXT: "cardinalText",
598
- /** Ordinal text (first, second, third...). */
599
- ORDINAL_TEXT: "ordinalText",
600
- /** Hexadecimal numbering. */
601
- HEX: "hex",
602
- /** Chicago Manual of Style numbering. */
603
- CHICAGO: "chicago",
604
- /** Ideograph digital numbering. */
605
- IDEOGRAPH__DIGITAL: "ideographDigital",
606
- /** Japanese counting system. */
607
- JAPANESE_COUNTING: "japaneseCounting",
608
- /** Japanese aiueo ordering. */
609
- AIUEO: "aiueo",
610
- /** Japanese iroha ordering. */
611
- IROHA: "iroha",
612
- /** Full-width decimal numbering. */
613
- DECIMAL_FULL_WIDTH: "decimalFullWidth",
614
- /** Half-width decimal numbering. */
615
- DECIMAL_HALF_WIDTH: "decimalHalfWidth",
616
- /** Japanese legal numbering. */
617
- JAPANESE_LEGAL: "japaneseLegal",
618
- /** Japanese digital ten thousand numbering. */
619
- JAPANESE_DIGITAL_TEN_THOUSAND: "japaneseDigitalTenThousand",
620
- /** Decimal numbers enclosed in circles. */
621
- DECIMAL_ENCLOSED_CIRCLE: "decimalEnclosedCircle",
622
- /** Full-width decimal numbering variant 2. */
623
- DECIMAL_FULL_WIDTH2: "decimalFullWidth2",
624
- /** Full-width aiueo ordering. */
625
- AIUEO_FULL_WIDTH: "aiueoFullWidth",
626
- /** Full-width iroha ordering. */
627
- IROHA_FULL_WIDTH: "irohaFullWidth",
628
- /** Decimal with leading zeros. */
629
- DECIMAL_ZERO: "decimalZero",
630
- /** Bullet points. */
631
- BULLET: "bullet",
632
- /** Korean ganada ordering. */
633
- GANADA: "ganada",
634
- /** Korean chosung ordering. */
635
- CHOSUNG: "chosung",
636
- /** Decimal enclosed with fullstop. */
637
- DECIMAL_ENCLOSED_FULLSTOP: "decimalEnclosedFullstop",
638
- /** Decimal enclosed in parentheses. */
639
- DECIMAL_ENCLOSED_PARENTHESES: "decimalEnclosedParen",
640
- /** Decimal enclosed in circles (Chinese). */
641
- DECIMAL_ENCLOSED_CIRCLE_CHINESE: "decimalEnclosedCircleChinese",
642
- /** Ideograph enclosed in circles. */
643
- IDEOGRAPH_ENCLOSED_CIRCLE: "ideographEnclosedCircle",
644
- /** Traditional ideograph numbering. */
645
- IDEOGRAPH_TRADITIONAL: "ideographTraditional",
646
- /** Ideograph zodiac numbering. */
647
- IDEOGRAPH_ZODIAC: "ideographZodiac",
648
- /** Traditional ideograph zodiac numbering. */
649
- IDEOGRAPH_ZODIAC_TRADITIONAL: "ideographZodiacTraditional",
650
- /** Taiwanese counting system. */
651
- TAIWANESE_COUNTING: "taiwaneseCounting",
652
- /** Traditional ideograph legal numbering. */
653
- IDEOGRAPH_LEGAL_TRADITIONAL: "ideographLegalTraditional",
654
- /** Taiwanese counting thousand system. */
655
- TAIWANESE_COUNTING_THOUSAND: "taiwaneseCountingThousand",
656
- /** Taiwanese digital numbering. */
657
- TAIWANESE_DIGITAL: "taiwaneseDigital",
658
- /** Chinese counting system. */
659
- CHINESE_COUNTING: "chineseCounting",
660
- /** Simplified Chinese legal numbering. */
661
- CHINESE_LEGAL_SIMPLIFIED: "chineseLegalSimplified",
662
- /** Chinese counting thousand system. */
663
- CHINESE_COUNTING_THOUSAND: "chineseCountingThousand",
664
- /** Korean digital numbering. */
665
- KOREAN_DIGITAL: "koreanDigital",
666
- /** Korean counting system. */
667
- KOREAN_COUNTING: "koreanCounting",
668
- /** Korean legal numbering. */
669
- KOREAN_LEGAL: "koreanLegal",
670
- /** Korean digital numbering variant 2. */
671
- KOREAN_DIGITAL2: "koreanDigital2",
672
- /** Vietnamese counting system. */
673
- VIETNAMESE_COUNTING: "vietnameseCounting",
674
- /** Russian lowercase numbering. */
675
- RUSSIAN_LOWER: "russianLower",
676
- /** Russian uppercase numbering. */
677
- RUSSIAN_UPPER: "russianUpper",
678
- /** No numbering. */
679
- NONE: "none",
680
- /** Number enclosed in dashes. */
681
- NUMBER_IN_DASH: "numberInDash",
682
- /** Hebrew numbering variant 1. */
683
- HEBREW1: "hebrew1",
684
- /** Hebrew numbering variant 2. */
685
- HEBREW2: "hebrew2",
686
- /** Arabic alpha numbering. */
687
- ARABIC_ALPHA: "arabicAlpha",
688
- /** Arabic abjad numbering. */
689
- ARABIC_ABJAD: "arabicAbjad",
690
- /** Hindi vowels. */
691
- HINDI_VOWELS: "hindiVowels",
692
- /** Hindi consonants. */
693
- HINDI_CONSONANTS: "hindiConsonants",
694
- /** Hindi numbers. */
695
- HINDI_NUMBERS: "hindiNumbers",
696
- /** Hindi counting system. */
697
- HINDI_COUNTING: "hindiCounting",
698
- /** Thai letters. */
699
- THAI_LETTERS: "thaiLetters",
700
- /** Thai numbers. */
701
- THAI_NUMBERS: "thaiNumbers",
702
- /** Thai counting system. */
703
- THAI_COUNTING: "thaiCounting",
704
- /** Thai Baht text. */
705
- BAHT_TEXT: "bahtText",
706
- /** Dollar text. */
707
- DOLLAR_TEXT: "dollarText",
708
- /** Custom numbering format. */
709
- CUSTOM: "custom"
710
- };
601
+ //#region src/parts/paragraph/run/run-parse.ts
711
602
  /**
712
- * Suffix types for list levels.
603
+ * Run properties parser for DOCX documents.
713
604
  *
714
- * Defines what follows the numbering text (tab, space, or nothing).
605
+ * Parses w:rPr Element trees into RunPropertiesOptions objects.
715
606
  *
716
- * @publicApi
607
+ * @module
717
608
  */
718
- const LevelSuffix = {
719
- /** No separator after the numbering. */
720
- NOTHING: "nothing",
721
- /** Space character after the numbering. */
722
- SPACE: "space",
723
- /** Tab character after the numbering. */
724
- TAB: "tab"
725
- };
726
- //#endregion
727
- //#region src/parts/numbering/numbering.ts
728
609
  /**
729
- * Numbering module for WordprocessingML documents.
730
- *
731
- * Numbering provides support for numbered and bulleted lists.
732
- * Pure string serialization — no XmlComponent inheritance.
733
- *
734
- * Reference: http://officeopenxml.com/WPnumbering.php
735
- *
736
- * @module
737
- */
738
- /** Namespace attributes for w:numbering (pre-computed constant). */
739
- 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\"";
740
- /** Default bullet levels (9 levels: 0-8). */
741
- const DEFAULT_BULLET_LEVELS = [
742
- {
743
- alignment: AlignmentType.LEFT,
744
- format: LevelFormat.BULLET,
745
- level: 0,
746
- style: { paragraph: { indent: {
747
- hanging: convertInchesToTwip(.25),
748
- left: convertInchesToTwip(.5)
749
- } } },
750
- text: "●"
751
- },
752
- {
753
- alignment: AlignmentType.LEFT,
754
- format: LevelFormat.BULLET,
755
- level: 1,
756
- style: { paragraph: { indent: {
757
- hanging: convertInchesToTwip(.25),
758
- left: convertInchesToTwip(1)
759
- } } },
760
- text: "○"
761
- },
762
- {
763
- alignment: AlignmentType.LEFT,
764
- format: LevelFormat.BULLET,
765
- level: 2,
766
- style: { paragraph: { indent: {
767
- hanging: convertInchesToTwip(.25),
768
- left: 2160
769
- } } },
770
- text: "■"
771
- },
772
- {
773
- alignment: AlignmentType.LEFT,
774
- format: LevelFormat.BULLET,
775
- level: 3,
776
- style: { paragraph: { indent: {
777
- hanging: convertInchesToTwip(.25),
778
- left: 2880
779
- } } },
780
- text: "●"
781
- },
782
- {
783
- alignment: AlignmentType.LEFT,
784
- format: LevelFormat.BULLET,
785
- level: 4,
786
- style: { paragraph: { indent: {
787
- hanging: convertInchesToTwip(.25),
788
- left: 3600
789
- } } },
790
- text: "○"
791
- },
792
- {
793
- alignment: AlignmentType.LEFT,
794
- format: LevelFormat.BULLET,
795
- level: 5,
796
- style: { paragraph: { indent: {
797
- hanging: convertInchesToTwip(.25),
798
- left: 4320
799
- } } },
800
- text: "■"
801
- },
802
- {
803
- alignment: AlignmentType.LEFT,
804
- format: LevelFormat.BULLET,
805
- level: 6,
806
- style: { paragraph: { indent: {
807
- hanging: convertInchesToTwip(.25),
808
- left: 5040
809
- } } },
810
- text: "●"
811
- },
812
- {
813
- alignment: AlignmentType.LEFT,
814
- format: LevelFormat.BULLET,
815
- level: 7,
816
- style: { paragraph: { indent: {
817
- hanging: convertInchesToTwip(.25),
818
- left: 5760
819
- } } },
820
- text: "●"
821
- },
822
- {
823
- alignment: AlignmentType.LEFT,
824
- format: LevelFormat.BULLET,
825
- level: 8,
826
- style: { paragraph: { indent: {
827
- hanging: convertInchesToTwip(.25),
828
- left: 6480
829
- } } },
830
- text: "●"
831
- }
832
- ];
833
- /**
834
- * Numbering definitions for a WordprocessingML document.
835
- *
836
- * Pure data accumulator — no XmlComponent inheritance.
837
- * Serializes via `serialize()` producing a complete XML part.
838
- */
839
- var Numbering = class {
840
- abstractNumberingData = /* @__PURE__ */ new Map();
841
- concreteNumberingData = /* @__PURE__ */ new Map();
842
- referenceConfigMap = /* @__PURE__ */ new Map();
843
- abstractNumUniqueNumericId = uniqueNumericIdCreator();
844
- concreteNumUniqueNumericId = uniqueNumericIdCreator(1);
845
- _numIdMacAtCleanup;
846
- _numPicBullets;
847
- constructor(options) {
848
- this._numIdMacAtCleanup = options.numIdMacAtCleanup;
849
- this._numPicBullets = options.numPicBullets;
850
- const defaultAbstractId = this.abstractNumUniqueNumericId();
851
- this.abstractNumberingData.set("default-bullet-numbering", {
852
- id: defaultAbstractId,
853
- levels: DEFAULT_BULLET_LEVELS
854
- });
855
- this.concreteNumberingData.set("default-bullet-numbering", {
856
- abstractNumId: defaultAbstractId,
857
- instance: 0,
858
- numId: 1,
859
- overrideLevels: [{
860
- num: 0,
861
- start: 1
862
- }],
863
- reference: "default-bullet-numbering"
864
- });
865
- for (const con of options.config) {
866
- this.abstractNumberingData.set(con.reference, {
867
- id: this.abstractNumUniqueNumericId(),
868
- levels: con.levels
869
- });
870
- this.referenceConfigMap.set(con.reference, con.levels);
871
- }
872
- }
873
- /** Serialize to word/numbering.xml content (with XML declaration). */
874
- serialize() {
875
- const parts = [];
876
- parts.push(`<w:numbering ${NUMBERING_ATTRS}>`);
877
- if (this._numPicBullets) for (const bullet of this._numPicBullets) if (bullet.pict) parts.push(`<w:numPicBullet w:numPicBulletId="${bullet.numPicBulletId}">${bullet.pict}</w:numPicBullet>`);
878
- else parts.push(`<w:numPicBullet w:numPicBulletId="${bullet.numPicBulletId}"/>`);
879
- for (const an of this.abstractNumberingData.values()) parts.push(stringifyAbstractNumbering(an.id, an.levels, an.extraOptions));
880
- for (const cn of this.concreteNumberingData.values()) parts.push(stringifyConcreteNumbering(cn));
881
- if (this._numIdMacAtCleanup !== void 0) parts.push(`<w:numIdMacAtCleanup w:val="${decimalNumber(this._numIdMacAtCleanup)}"/>`);
882
- parts.push("</w:numbering>");
883
- return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + parts.join("");
884
- }
885
- /**
886
- * Creates a concrete numbering instance from an abstract numbering definition.
887
- */
888
- createConcreteNumberingInstance(reference, instance) {
889
- const abstractNumbering = this.abstractNumberingData.get(reference);
890
- if (!abstractNumbering) return;
891
- const fullReference = `${reference}-${instance}`;
892
- if (this.concreteNumberingData.has(fullReference)) return;
893
- const referenceConfigLevels = this.referenceConfigMap.get(reference);
894
- const firstLevelStartNumber = referenceConfigLevels && referenceConfigLevels[0].start;
895
- this.concreteNumberingData.set(fullReference, {
896
- abstractNumId: abstractNumbering.id,
897
- instance,
898
- numId: this.concreteNumUniqueNumericId(),
899
- overrideLevels: [typeof firstLevelStartNumber === "number" && Number.isInteger(firstLevelStartNumber) ? {
900
- num: 0,
901
- start: firstLevelStartNumber
902
- } : {
903
- num: 0,
904
- start: 1
905
- }],
906
- reference
907
- });
908
- }
909
- /** Gets all concrete numbering instances. */
910
- get concreteNumbering() {
911
- return [...this.concreteNumberingData.values()];
912
- }
913
- /** Gets all reference configurations. */
914
- get referenceConfig() {
915
- return [...this.referenceConfigMap.values()];
916
- }
917
- };
918
- function stringifyAbstractNumbering(id, levels, extraOptions) {
919
- const parts = [];
920
- parts.push(`<w:abstractNum w:abstractNumId="${decimalNumber(id)}" w15:restartNumberingAfterBreak="0">`);
921
- if (extraOptions?.nsid !== void 0) parts.push(`<w:nsid w:val="${extraOptions.nsid}"/>`);
922
- parts.push(`<w:multiLevelType w:val="hybridMultilevel"/>`);
923
- if (extraOptions?.tmpl !== void 0) parts.push(`<w:tmpl w:val="${extraOptions.tmpl}"/>`);
924
- if (extraOptions?.name !== void 0) parts.push(`<w:name w:val="${extraOptions.name}"/>`);
925
- if (extraOptions?.styleLink !== void 0) parts.push(`<w:styleLink w:val="${extraOptions.styleLink}"/>`);
926
- if (extraOptions?.numStyleLink !== void 0) parts.push(`<w:numStyleLink w:val="${extraOptions.numStyleLink}"/>`);
927
- for (const level of levels) parts.push(stringifyLevel(level));
928
- parts.push("</w:abstractNum>");
929
- return parts.join("");
930
- }
931
- function stringifyConcreteNumbering(cn) {
932
- const parts = [];
933
- parts.push(`<w:num w:numId="${decimalNumber(cn.numId)}">`);
934
- parts.push(`<w:abstractNumId w:val="${decimalNumber(cn.abstractNumId)}"/>`);
935
- 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>`);
936
- else parts.push(`<w:lvlOverride w:ilvl="${level.num}"/>`);
937
- parts.push("</w:num>");
938
- return parts.join("");
939
- }
940
- function stringifyLevel(opts) {
941
- const children = [];
942
- children.push(`<w:start w:val="${decimalNumber(opts.start ?? 1)}"/>`);
943
- if (opts.format) children.push(`<w:numFmt w:val="${opts.format}"/>`);
944
- if (opts.lvlRestart !== void 0) children.push(`<w:lvlRestart w:val="${decimalNumber(opts.lvlRestart)}"/>`);
945
- if (opts.suffix) children.push(`<w:suff w:val="${opts.suffix}"/>`);
946
- if (opts.isLegalNumberingStyle) children.push("<w:isLgl/>");
947
- if (opts.text) children.push(`<w:lvlText w:val="${opts.text}"/>`);
948
- if (opts.lvlPicBulletId !== void 0) children.push(`<w:lvlPicBulletId w:val="${decimalNumber(opts.lvlPicBulletId)}"/>`);
949
- if (opts.legacy !== void 0) {
950
- const legacyAttrs = [];
951
- if (opts.legacy.space !== void 0) legacyAttrs.push(`w:legacySpace="${opts.legacy.space}"`);
952
- if (opts.legacy.indent !== void 0) legacyAttrs.push(`w:legacyIndent="${opts.legacy.indent}"`);
953
- children.push(`<w:legacy ${legacyAttrs.join(" ")}/>`);
954
- }
955
- children.push(`<w:lvlJc w:val="${opts.alignment ?? AlignmentType.START}"/>`);
956
- const pPrXml = stringifyParagraphProperties(opts.style && opts.style.paragraph).xml;
957
- const rPrXml = stringifyRunProperties(opts.style && opts.style.run);
958
- if (pPrXml) children.push(pPrXml);
959
- if (rPrXml) children.push(rPrXml);
960
- const lvlAttrs = [`w:ilvl="${decimalNumber(Math.min(opts.level, 9))}"`, `w15:tentative="1"`];
961
- if (opts.templateCode !== void 0) lvlAttrs.push(`w:tplc="${opts.templateCode}"`);
962
- if (opts.tentative !== void 0) lvlAttrs.push(`w:tentative="${opts.tentative ? 1 : 0}"`);
963
- return `<w:lvl ${lvlAttrs.join(" ")}>${children.join("")}</w:lvl>`;
964
- }
965
- /**
966
- * Parse w:numbering element into NumberingOptions.
967
- */
968
- function parseNumberingDefinitions(el) {
969
- const abstractNums = /* @__PURE__ */ new Map();
970
- for (const child of el.elements ?? []) {
971
- if (child.name !== "w:abstractNum") continue;
972
- const id = attr(child, "w:abstractNumId");
973
- if (id !== void 0) abstractNums.set(id, child);
974
- }
975
- const numToAbstract = /* @__PURE__ */ new Map();
976
- for (const child of el.elements ?? []) {
977
- if (child.name !== "w:num") continue;
978
- const numId = attr(child, "w:numId");
979
- const abstractRef = findChild(child, "w:abstractNumId");
980
- const abstractId = abstractRef ? attr(abstractRef, "w:val") : void 0;
981
- if (numId !== void 0 && abstractId !== void 0) numToAbstract.set(numId, abstractId);
982
- }
983
- const configs = [];
984
- for (const [numId, abstractId] of numToAbstract) {
985
- const abstractEl = abstractNums.get(abstractId);
986
- if (!abstractEl) continue;
987
- const levels = [];
988
- for (const child of abstractEl.elements ?? []) {
989
- if (child.name !== "w:lvl") continue;
990
- const levelOpts = parseLevelEl(child);
991
- if (levelOpts) levels.push(levelOpts);
992
- }
993
- if (levels.length > 0 && levels.every((l) => l.format === LevelFormat.BULLET)) continue;
994
- if (levels.length > 0) configs.push({
995
- reference: `list_${numId}`,
996
- levels
997
- });
998
- }
999
- if (configs.length === 0) return void 0;
1000
- return { config: configs };
1001
- }
1002
- function parseLevelEl(el) {
1003
- const opts = {};
1004
- const level = attrNum(el, "w:ilvl");
1005
- if (level !== void 0) opts.level = level;
1006
- const start = findChild(el, "w:start");
1007
- if (start) {
1008
- const val = attrNum(start, "w:val");
1009
- if (val !== void 0) opts.start = val;
1010
- }
1011
- const numFmt = findChild(el, "w:numFmt");
1012
- if (numFmt) {
1013
- const val = attr(numFmt, "w:val");
1014
- if (val) opts.format = val;
1015
- }
1016
- const lvlText = findChild(el, "w:lvlText");
1017
- if (lvlText) {
1018
- const val = attr(lvlText, "w:val");
1019
- if (val) opts.text = val;
1020
- }
1021
- const lvlJc = findChild(el, "w:lvlJc");
1022
- if (lvlJc) {
1023
- const val = attr(lvlJc, "w:val");
1024
- if (val) opts.alignment = val;
1025
- }
1026
- const suff = findChild(el, "w:suff");
1027
- if (suff) {
1028
- const val = attr(suff, "w:val");
1029
- if (val) opts.suffix = val;
1030
- }
1031
- if (findChild(el, "w:isLgl")) opts.isLegalNumberingStyle = true;
1032
- const rPr = findChild(el, "w:rPr");
1033
- if (rPr) {
1034
- const style = {};
1035
- const sz = findChild(rPr, "w:sz");
1036
- if (sz) {
1037
- const val = attrNum(sz, "w:val");
1038
- if (val !== void 0) {
1039
- if (!style.run) style.run = {};
1040
- style.run.size = val;
1041
- }
1042
- }
1043
- const rFonts = findChild(rPr, "w:rFonts");
1044
- if (rFonts) {
1045
- const ascii = attr(rFonts, "w:ascii");
1046
- if (ascii) {
1047
- if (!style.run) style.run = {};
1048
- style.run.font = ascii;
1049
- }
1050
- }
1051
- if (Object.keys(style).length > 0) opts.style = style;
1052
- }
1053
- const pPr = findChild(el, "w:pPr");
1054
- if (pPr) {
1055
- const style = opts.style ?? {};
1056
- const paraStyle = {};
1057
- const ind = findChild(pPr, "w:ind");
1058
- if (ind) {
1059
- const indent = {};
1060
- const left = attrNum(ind, "w:left");
1061
- if (left !== void 0) indent.left = left;
1062
- const hanging = attrNum(ind, "w:hanging");
1063
- if (hanging !== void 0) indent.hanging = hanging;
1064
- if (Object.keys(indent).length > 0) paraStyle.indent = indent;
1065
- }
1066
- if (Object.keys(paraStyle).length > 0) {
1067
- style.paragraph = paraStyle;
1068
- opts.style = style;
1069
- }
1070
- }
1071
- return Object.keys(opts).length > 0 ? opts : void 0;
1072
- }
1073
- //#endregion
1074
- //#region src/parts/paragraph/run/run-parse.ts
1075
- /**
1076
- * Run properties parser for DOCX documents.
1077
- *
1078
- * Parses w:rPr Element trees into RunPropertiesOptions objects.
1079
- *
1080
- * @module
1081
- */
1082
- /**
1083
- * Parse a w:rPr element into RunPropertiesOptions.
610
+ * Parse a w:rPr element into RunPropertiesOptions.
1084
611
  */
1085
612
  function parseRunProperties(el) {
1086
613
  const opts = {};
@@ -1140,7 +667,7 @@ function parseRunProperties(el) {
1140
667
  ["w:rtl", "rightToLeft"],
1141
668
  ["w:cs", "complexScript"],
1142
669
  ["w:specVanish", "specVanish"],
1143
- ["w:math", "math"]
670
+ ["w:oMath", "math"]
1144
671
  ]) {
1145
672
  const child = findChild(el, name);
1146
673
  if (child) opts[optKey] = attrBool(child, "w:val") ?? true;
@@ -1148,7 +675,17 @@ function parseRunProperties(el) {
1148
675
  const color = findChild(el, "w:color");
1149
676
  if (color) {
1150
677
  const c = colorAttr(color, "w:val");
1151
- if (c) opts.color = c;
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;
1152
689
  }
1153
690
  const sz = findChild(el, "w:sz");
1154
691
  if (sz) {
@@ -1215,17 +752,37 @@ function parseRunProperties(el) {
1215
752
  if (lang) {
1216
753
  const langObj = {};
1217
754
  const val = attr(lang, "w:val");
1218
- if (val) langObj.val = val;
755
+ if (val) langObj.value = val;
1219
756
  const eastAsia = attr(lang, "w:eastAsia");
1220
757
  if (eastAsia) langObj.eastAsia = eastAsia;
1221
758
  const bidi = attr(lang, "w:bidi");
1222
- if (bidi) langObj.bidi = bidi;
759
+ if (bidi) langObj.bidirectional = bidi;
1223
760
  if (Object.keys(langObj).length > 0) opts.language = langObj;
1224
761
  }
1225
762
  const bdr = findChild(el, "w:bdr");
1226
763
  if (bdr) opts.border = parseBorder(bdr);
1227
764
  const shd = findChild(el, "w:shd");
1228
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
+ }
1229
786
  return opts;
1230
787
  }
1231
788
  /**
@@ -1260,6 +817,23 @@ function parseShading(el) {
1260
817
  if (type) opts.type = type;
1261
818
  return opts;
1262
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
+ }
1263
837
  /** Matches w:br[@w:type="page"] → PageBreak */
1264
838
  const PARSED_PAGE_BREAK = Symbol("PageBreak");
1265
839
  /** Matches w:br (line break) */
@@ -1459,25 +1033,523 @@ function parsedRunToOptions(parsed) {
1459
1033
  const mapped = SYMBOL_TO_CHILD.get(child);
1460
1034
  if (mapped) extraChildren.push(mapped);
1461
1035
  }
1462
- if (extraChildren.length > 0) {
1463
- const children = [];
1464
- for (const child of nonRefChildren) if (typeof child === "string") children.push(child);
1465
- else if (child === PARSED_LINE_BREAK) children.push({ break: 1 });
1466
- else if (child === PARSED_PAGE_BREAK) children.push({ pageBreak: true });
1467
- else if (child === PARSED_COLUMN_BREAK) children.push({ columnBreak: true });
1468
- else {
1469
- const mapped = SYMBOL_TO_CHILD.get(child);
1470
- if (mapped) children.push(mapped);
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),
1253
+ left: 2160
1254
+ } } },
1255
+ text: "■"
1256
+ },
1257
+ {
1258
+ alignment: AlignmentType.LEFT,
1259
+ format: LevelFormat.BULLET,
1260
+ level: 3,
1261
+ style: { paragraph: { indent: {
1262
+ hanging: convertInchesToTwip(.25),
1263
+ left: 2880
1264
+ } } },
1265
+ text: "●"
1266
+ },
1267
+ {
1268
+ alignment: AlignmentType.LEFT,
1269
+ format: LevelFormat.BULLET,
1270
+ level: 4,
1271
+ style: { paragraph: { indent: {
1272
+ hanging: convertInchesToTwip(.25),
1273
+ left: 3600
1274
+ } } },
1275
+ text: "○"
1276
+ },
1277
+ {
1278
+ alignment: AlignmentType.LEFT,
1279
+ format: LevelFormat.BULLET,
1280
+ level: 5,
1281
+ style: { paragraph: { indent: {
1282
+ hanging: convertInchesToTwip(.25),
1283
+ left: 4320
1284
+ } } },
1285
+ text: "■"
1286
+ },
1287
+ {
1288
+ alignment: AlignmentType.LEFT,
1289
+ format: LevelFormat.BULLET,
1290
+ level: 6,
1291
+ style: { paragraph: { indent: {
1292
+ hanging: convertInchesToTwip(.25),
1293
+ left: 5040
1294
+ } } },
1295
+ text: "●"
1296
+ },
1297
+ {
1298
+ alignment: AlignmentType.LEFT,
1299
+ format: LevelFormat.BULLET,
1300
+ level: 7,
1301
+ style: { paragraph: { indent: {
1302
+ hanging: convertInchesToTwip(.25),
1303
+ left: 5760
1304
+ } } },
1305
+ text: "●"
1306
+ },
1307
+ {
1308
+ alignment: AlignmentType.LEFT,
1309
+ format: LevelFormat.BULLET,
1310
+ level: 8,
1311
+ style: { paragraph: { indent: {
1312
+ hanging: convertInchesToTwip(.25),
1313
+ left: 6480
1314
+ } } },
1315
+ text: "●"
1316
+ }
1317
+ ];
1318
+ /**
1319
+ * Numbering definitions for a WordprocessingML document.
1320
+ *
1321
+ * Pure data accumulator — no XmlComponent inheritance.
1322
+ * Serializes via `serialize()` producing a complete XML part.
1323
+ */
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);
1356
+ }
1357
+ }
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("");
1369
+ }
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
+ });
1393
+ }
1394
+ /** Gets all concrete numbering instances. */
1395
+ get concreteNumbering() {
1396
+ return [...this.concreteNumberingData.values()];
1397
+ }
1398
+ /** Gets all reference configurations. */
1399
+ get referenceConfig() {
1400
+ return [...this.referenceConfigMap.values()];
1401
+ }
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("");
1415
+ }
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) {
1426
+ const children = [];
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(" ")}/>`);
1439
+ }
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>`;
1449
+ }
1450
+ /**
1451
+ * Parse w:numbering element into NumberingOptions.
1452
+ */
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);
1459
+ }
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);
1471
1477
  }
1472
- opts.children = children;
1473
- } else {
1474
- if (textParts.length > 0) opts.text = textParts.join("");
1475
- if (breakCount > 0) opts.break = breakCount;
1476
- if (hasPageBreak) opts.pageBreak = true;
1477
- 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
+ });
1478
1483
  }
1479
- if (Object.keys(opts).length === 0 && textParts.length === 0 && breakCount === 0 && !hasPageBreak && !hasColumnBreak && extraChildren.length === 0) return null;
1480
- 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;
1481
1553
  }
1482
1554
  //#endregion
1483
1555
  //#region src/parts/styles/factory.ts
@@ -1886,7 +1958,7 @@ function buildNumberingCache(numberingEl) {
1886
1958
  return cache;
1887
1959
  }
1888
1960
  /**
1889
- * Parse w:styles element into StylesOptions-like structure.
1961
+ * Parse w:styles element into StylesOptions.
1890
1962
  *
1891
1963
  * Skips built-in styles that DefaultStylesFactory already generates,
1892
1964
  * keeping only user-defined custom styles for round-trip fidelity.
@@ -1896,13 +1968,12 @@ function parseStyleDefinitions(el, parseParagraphProperties, ctx) {
1896
1968
  const paragraphStyles = [];
1897
1969
  const characterStyles = [];
1898
1970
  for (const child of el.elements ?? []) if (child.name === "w:docDefaults") {
1899
- const defOpts = parseDocDefaults(child);
1971
+ const defOpts = parseDocDefaults(child, parseParagraphProperties, ctx);
1900
1972
  if (defOpts) opts.default = defOpts;
1901
1973
  } else if (child.name === "w:style") {
1902
1974
  const styleOpts = parseStyleElement(child, parseParagraphProperties, ctx);
1903
- if (!styleOpts) continue;
1904
- const styleId = styleOpts.id;
1905
- if (styleId && BUILTIN_STYLE_IDS.has(styleId)) continue;
1975
+ if (!styleOpts?._type || !styleOpts.id) continue;
1976
+ if (BUILTIN_STYLE_IDS.has(styleOpts.id)) continue;
1906
1977
  const type = styleOpts._type;
1907
1978
  delete styleOpts._type;
1908
1979
  if (type === "paragraph") paragraphStyles.push(styleOpts);
@@ -1912,38 +1983,25 @@ function parseStyleDefinitions(el, parseParagraphProperties, ctx) {
1912
1983
  if (characterStyles.length > 0) opts.characterStyles = characterStyles;
1913
1984
  return Object.keys(opts).length > 0 ? opts : void 0;
1914
1985
  }
1915
- function parseDocDefaults(el) {
1916
- const result = {};
1917
- const docDefaults = {};
1986
+ function parseDocDefaults(el, parseParagraphProperties, ctx) {
1987
+ const document = {};
1918
1988
  const rPrDefault = findChild(el, "w:rPrDefault");
1919
1989
  if (rPrDefault) {
1920
1990
  const rPr = findChild(rPrDefault, "w:rPr");
1921
1991
  if (rPr) {
1922
1992
  const runDefaults = parseRunProperties(rPr);
1923
- if (Object.keys(runDefaults).length > 0) docDefaults.run = runDefaults;
1993
+ if (Object.keys(runDefaults).length > 0) document.run = runDefaults;
1924
1994
  }
1925
1995
  }
1926
1996
  const pPrDefault = findChild(el, "w:pPrDefault");
1927
1997
  if (pPrDefault) {
1928
1998
  const pPr = findChild(pPrDefault, "w:pPr");
1929
1999
  if (pPr) {
1930
- const paraDefaults = {};
1931
- const spacing = findChild(pPr, "w:spacing");
1932
- if (spacing) {
1933
- const sp = {};
1934
- const before = attrNum(spacing, "w:before");
1935
- if (before !== void 0) sp.before = before;
1936
- const after = attrNum(spacing, "w:after");
1937
- if (after !== void 0) sp.after = after;
1938
- const line = attrNum(spacing, "w:line");
1939
- if (line !== void 0) sp.line = line;
1940
- if (Object.keys(sp).length > 0) paraDefaults.spacing = sp;
1941
- }
1942
- 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;
1943
2002
  }
1944
2003
  }
1945
- if (Object.keys(docDefaults).length > 0) result.document = docDefaults;
1946
- return Object.keys(result).length > 0 ? result : void 0;
2004
+ return Object.keys(document).length > 0 ? { document } : void 0;
1947
2005
  }
1948
2006
  function parseStyleElement(el, parseParagraphProperties, ctx) {
1949
2007
  const opts = {};
@@ -2047,6 +2105,14 @@ function compatSetting(name, val) {
2047
2105
  function maybeDerive(password, hashValue) {
2048
2106
  return password !== void 0 && hashValue === void 0 ? derivePasswordHash(password) : void 0;
2049
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
+ ];
2050
2116
  function stringifyDocProtect(opts) {
2051
2117
  const derived = maybeDerive(opts.password, opts.hashValue);
2052
2118
  const attrs = { "w:enforcement": "1" };
@@ -2392,7 +2458,7 @@ const settingsDesc = {
2392
2458
  p.push(onOff("w:autoFormatOverride", opts.autoFormatOverride));
2393
2459
  p.push(onOff("w:styleLockTheme", opts.styleLockTheme));
2394
2460
  p.push(onOff("w:styleLockQFSet", opts.styleLockQFSet));
2395
- p.push(numVal("w:defaultTabStop", opts.defaultTabStop ?? 420));
2461
+ if (opts.defaultTabStop !== void 0) p.push(numVal("w:defaultTabStop", opts.defaultTabStop));
2396
2462
  p.push(onOff("w:autoHyphenation", opts.hyphenation?.autoHyphenation));
2397
2463
  p.push(numVal("w:consecutiveHyphenLimit", opts.hyphenation?.consecutiveHyphenLimit));
2398
2464
  p.push(numVal("w:hyphenationZone", opts.hyphenation?.hyphenationZone));
@@ -2413,7 +2479,7 @@ const settingsDesc = {
2413
2479
  p.push(numVal("w:drawingGridVerticalOrigin", opts.drawingGridVerticalOrigin));
2414
2480
  p.push(onOff("w:doNotUseMarginsForDrawingGridOrigin", opts.doNotUseMarginsForDrawingGridOrigin));
2415
2481
  p.push(onOff("w:doNotShadeFormData", opts.doNotShadeFormData));
2416
- p.push(strVal("w:characterSpacingControl", opts.characterSpacingControl ?? "compressPunctuation"));
2482
+ if (opts.characterSpacingControl !== void 0) p.push(strVal("w:characterSpacingControl", opts.characterSpacingControl));
2417
2483
  p.push(onOff("w:noPunctuationKerning", opts.noPunctuationKerning));
2418
2484
  p.push(onOff("w:printTwoOnOne", opts.printTwoOnOne));
2419
2485
  p.push(onOff("w:strictFirstAndLastChars", opts.strictFirstAndLastChars));
@@ -2450,20 +2516,11 @@ const settingsDesc = {
2450
2516
  if (opts.hdrShapeDefaults !== void 0) p.push("<w:hdrShapeDefaults/>");
2451
2517
  if (opts.footnotePr !== void 0) p.push(stringifyFootnotePr(opts.footnotePr));
2452
2518
  if (opts.endnotePr !== void 0) p.push(stringifyEndnotePr(opts.endnotePr));
2453
- p.push(stringifyCompatibility({
2519
+ const compatXml = stringifyCompatibility({
2454
2520
  ...opts.compatibility,
2455
- version: opts.compatibility?.version ?? opts.compatibilityModeVersion ?? 15,
2456
- spaceForUnderline: opts.compatibility?.spaceForUnderline ?? true,
2457
- balanceSingleByteDoubleByteWidth: opts.compatibility?.balanceSingleByteDoubleByteWidth ?? true,
2458
- doNotLeaveBackslashAlone: opts.compatibility?.doNotLeaveBackslashAlone ?? true,
2459
- underlineTrailingSpaces: opts.compatibility?.underlineTrailingSpaces ?? true,
2460
- doNotExpandShiftReturn: opts.compatibility?.doNotExpandShiftReturn ?? true,
2461
- adjustLineHeightInTable: opts.compatibility?.adjustLineHeightInTable ?? true,
2462
- useFELayout: opts.compatibility?.useFELayout ?? true,
2463
- overrideTableStyleFontSizeAndJustification: opts.compatibility?.overrideTableStyleFontSizeAndJustification ?? true,
2464
- enableOpenTypeFeatures: opts.compatibility?.enableOpenTypeFeatures ?? true,
2465
- doNotFlipMirrorIndents: opts.compatibility?.doNotFlipMirrorIndents ?? true
2466
- }));
2521
+ version: opts.compatibility?.version ?? opts.compatibilityModeVersion
2522
+ });
2523
+ if (compatXml) p.push(compatXml);
2467
2524
  if (opts.docVars?.length) {
2468
2525
  const vars = opts.docVars.map((v) => attrEl("w:docVar", {
2469
2526
  "w:name": v.name,
@@ -2521,14 +2578,16 @@ const settingsDesc = {
2521
2578
  const val = attr(tabStopEl, "w:val");
2522
2579
  if (val) opts.defaultTabStop = parseInt(val, 10);
2523
2580
  }
2524
- if (findChild(el, "w:trackRevisions")) {
2581
+ const trackRevEl = findChild(el, "w:trackRevisions");
2582
+ if (trackRevEl) {
2525
2583
  const features = opts.features ?? {};
2526
- features.trackRevisions = true;
2584
+ features.trackRevisions = attrBool(trackRevEl, "w:val") ?? true;
2527
2585
  opts.features = features;
2528
2586
  }
2529
- if (findChild(el, "w:updateFields")) {
2587
+ const updateFieldsEl = findChild(el, "w:updateFields");
2588
+ if (updateFieldsEl) {
2530
2589
  const features = opts.features ?? {};
2531
- features.updateFields = true;
2590
+ features.updateFields = attrBool(updateFieldsEl, "w:val") ?? true;
2532
2591
  opts.features = features;
2533
2592
  }
2534
2593
  const compatEl = findChild(el, "w:compat");
@@ -2685,7 +2744,7 @@ const settingsDesc = {
2685
2744
  if (docProtEl) {
2686
2745
  const prot = {};
2687
2746
  const edit = attr(docProtEl, "w:edit");
2688
- if (edit) prot.edit = edit;
2747
+ if (edit && DOC_PROTECT_EDITS.includes(edit)) prot.edit = edit;
2689
2748
  if (attr(docProtEl, "w:enforcement") !== void 0) {
2690
2749
  const hash = attr(docProtEl, "w:hash");
2691
2750
  if (hash) prot.hash = hash;
@@ -2712,10 +2771,16 @@ const settingsDesc = {
2712
2771
  const formatting = attr(docProtEl, "w:formatting");
2713
2772
  if (formatting !== void 0) prot.formatting = formatting === "1" || formatting === "true";
2714
2773
  }
2715
- 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
+ }
2716
2779
  }
2717
- if (findChild(el, "w:doNotTrackMoves")) opts.doNotTrackMoves = true;
2718
- 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;
2719
2784
  return opts;
2720
2785
  }
2721
2786
  };
@@ -2853,6 +2918,19 @@ function parseTocFieldInstruction(instruction, opts) {
2853
2918
  if (switches["o"]) opts.headingStyleRange = switches["o"];
2854
2919
  if (switches["p"]) opts.entryAndPageNumberSeparator = switches["p"];
2855
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
+ }
2856
2934
  if ("u" in switches) opts.useAppliedParagraphOutlineLevel = true;
2857
2935
  if ("w" in switches) opts.preserveTabInEntries = true;
2858
2936
  if ("x" in switches) opts.preserveNewLineInEntries = true;
@@ -3217,6 +3295,22 @@ const HEADING_MAP = {
3217
3295
  Heading6: HeadingLevel.HEADING_6,
3218
3296
  Title: HeadingLevel.TITLE
3219
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
+ };
3220
3314
  /**
3221
3315
  * Parse w:pPr element into paragraph properties (without children).
3222
3316
  */
@@ -3243,11 +3337,15 @@ function parseParagraphProperties(el, ctx) {
3243
3337
  const line = attrNum(spacing, "w:line");
3244
3338
  if (line !== void 0) sp.line = line;
3245
3339
  const lineRule = attr(spacing, "w:lineRule");
3246
- if (lineRule) sp.lineRule = lineRule;
3247
- const beforeAuto = attrBool(spacing, "w:beforeAutospacing") ?? attrBool(spacing, "w:beforeLines");
3248
- if (beforeAuto !== void 0) sp.beforeAutoSpacing = beforeAuto;
3249
- const afterAuto = attrBool(spacing, "w:afterAutospacing") ?? attrBool(spacing, "w:afterLines");
3250
- 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;
3251
3349
  if (Object.keys(sp).length > 0) opts.spacing = sp;
3252
3350
  }
3253
3351
  const ind = findChild(el, "w:ind");
@@ -3255,16 +3353,28 @@ function parseParagraphProperties(el, ctx) {
3255
3353
  const indentObj = {};
3256
3354
  const left = attrNum(ind, "w:left");
3257
3355
  if (left !== void 0) indentObj.left = left;
3356
+ const leftChars = attrNum(ind, "w:leftChars");
3357
+ if (leftChars !== void 0) indentObj.leftChars = leftChars;
3258
3358
  const right = attrNum(ind, "w:right");
3259
3359
  if (right !== void 0) indentObj.right = right;
3360
+ const rightChars = attrNum(ind, "w:rightChars");
3361
+ if (rightChars !== void 0) indentObj.rightChars = rightChars;
3260
3362
  const start = attrNum(ind, "w:start");
3261
3363
  if (start !== void 0) indentObj.start = start;
3364
+ const startChars = attrNum(ind, "w:startChars");
3365
+ if (startChars !== void 0) indentObj.startChars = startChars;
3262
3366
  const end = attrNum(ind, "w:end");
3263
3367
  if (end !== void 0) indentObj.end = end;
3368
+ const endChars = attrNum(ind, "w:endChars");
3369
+ if (endChars !== void 0) indentObj.endChars = endChars;
3264
3370
  const hanging = attrNum(ind, "w:hanging");
3265
3371
  if (hanging !== void 0) indentObj.hanging = hanging;
3372
+ const hangingChars = attrNum(ind, "w:hangingChars");
3373
+ if (hangingChars !== void 0) indentObj.hangingChars = hangingChars;
3266
3374
  const firstLine = attrNum(ind, "w:firstLine");
3267
3375
  if (firstLine !== void 0) indentObj.firstLine = firstLine;
3376
+ const firstLineChars = attrNum(ind, "w:firstLineChars");
3377
+ if (firstLineChars !== void 0) indentObj.firstLineChars = firstLineChars;
3268
3378
  if (Object.keys(indentObj).length > 0) opts.indent = indentObj;
3269
3379
  }
3270
3380
  const numPr = findChild(el, "w:numPr");
@@ -3325,6 +3435,7 @@ function parseParagraphProperties(el, ctx) {
3325
3435
  ["w:kinsoku", "kinsoku"],
3326
3436
  ["w:topLinePunct", "topLinePunct"],
3327
3437
  ["w:autoSpaceDE", "autoSpaceDE"],
3438
+ ["w:autoSpaceDN", "autoSpaceEastAsianText"],
3328
3439
  ["w:overflowPunct", "overflowPunctuation"],
3329
3440
  ["w:suppressOverlap", "suppressOverlap"]
3330
3441
  ]) {
@@ -3338,21 +3449,32 @@ function parseParagraphProperties(el, ctx) {
3338
3449
  "top",
3339
3450
  "bottom",
3340
3451
  "left",
3341
- "right"
3452
+ "right",
3453
+ "between",
3454
+ "bar"
3342
3455
  ]) {
3343
3456
  const sideEl = findChild(pBdr, `w:${side}`);
3344
- if (sideEl) {
3345
- const sideOpts = {};
3346
- const style = attr(sideEl, "w:val");
3347
- if (style) sideOpts.style = style;
3348
- const color = attr(sideEl, "w:color");
3349
- if (color) sideOpts.color = color;
3350
- const size = attrNum(sideEl, "w:sz");
3351
- if (size !== void 0) sideOpts.size = size;
3352
- const space = attrNum(sideEl, "w:space");
3353
- if (space !== void 0) sideOpts.space = space;
3354
- border[side] = sideOpts;
3355
- }
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;
3356
3478
  }
3357
3479
  if (Object.keys(border).length > 0) opts.border = border;
3358
3480
  }
@@ -3397,6 +3519,24 @@ function parseParagraphProperties(el, ctx) {
3397
3519
  const val = attr(framePr, attrName);
3398
3520
  if (val !== void 0) frame[optName] = val;
3399
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;
3400
3540
  const w = attrNum(framePr, "w:w");
3401
3541
  if (w !== void 0) frame.width = w;
3402
3542
  const h = attrNum(framePr, "w:h");
@@ -3417,6 +3557,124 @@ function collectRunText(el) {
3417
3557
  for (const c of el.elements ?? []) if (c.name === "w:t") text += textOf(c);
3418
3558
  return text;
3419
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
+ }
3420
3678
  /**
3421
3679
  * Parse a w:p element into ParagraphOptions.
3422
3680
  */
@@ -3425,7 +3683,10 @@ function parseParagraph(el, ctx) {
3425
3683
  const pPr = findChild(el, "w:pPr");
3426
3684
  if (pPr) Object.assign(opts, parseParagraphProperties(pPr, ctx));
3427
3685
  const childList = [];
3686
+ let fieldKind = null;
3428
3687
  let pendingFormField = null;
3688
+ let pendingInstruction = "";
3689
+ let pendingResult = "";
3429
3690
  let collectingResult = false;
3430
3691
  for (const child of el.elements ?? []) switch (child.name) {
3431
3692
  case "w:pPr": break;
@@ -3435,17 +3696,36 @@ function parseParagraph(el, ctx) {
3435
3696
  const fctype = attr(fldCharEl, "w:fldCharType");
3436
3697
  if (fctype === "begin") {
3437
3698
  const ffDataEl = findChild(fldCharEl, "w:ffData");
3438
- if (ffDataEl) pendingFormField = parseFormFieldData(ffDataEl);
3699
+ if (ffDataEl) {
3700
+ fieldKind = "form";
3701
+ pendingFormField = parseFormFieldData(ffDataEl);
3702
+ } else {
3703
+ fieldKind = "complex";
3704
+ pendingInstruction = "";
3705
+ pendingResult = "";
3706
+ }
3707
+ collectingResult = false;
3439
3708
  } else if (fctype === "separate") collectingResult = true;
3440
- else if (fctype === "end" && pendingFormField) {
3441
- childList.push({ formField: pendingFormField });
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;
3442
3717
  pendingFormField = null;
3443
3718
  collectingResult = false;
3444
3719
  }
3445
3720
  break;
3446
3721
  }
3447
- if (pendingFormField) {
3448
- if (collectingResult && pendingFormField.textInput) {
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) {
3449
3729
  const text = collectRunText(child);
3450
3730
  if (text) {
3451
3731
  const ti = pendingFormField.textInput;
@@ -3536,6 +3816,24 @@ function parseParagraph(el, ctx) {
3536
3816
  break;
3537
3817
  }
3538
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
+ }
3539
3837
  const delRun = findChild(child, "w:r");
3540
3838
  if (delRun) {
3541
3839
  const runOpts = parsedRunToOptions(parseRun(delRun, ctx));
@@ -3548,6 +3846,208 @@ function parseParagraph(el, ctx) {
3548
3846
  }
3549
3847
  break;
3550
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
+ }
3551
4051
  default: break;
3552
4052
  }
3553
4053
  if (childList.length > 0) {
@@ -4834,7 +5334,8 @@ const sdtBlockDesc = {
4834
5334
  stringify(opts, ctx) {
4835
5335
  const parts = ["<w:sdt>"];
4836
5336
  parts.push(stringifySdtPr(opts.properties));
4837
- parts.push("<w:sdtEndPr/>");
5337
+ const endPrInner = opts.endProperties ? stringifyRunPropertiesInner(opts.endProperties) : void 0;
5338
+ parts.push(endPrInner ? `<w:sdtEndPr>${endPrInner}</w:sdtEndPr>` : "<w:sdtEndPr/>");
4838
5339
  if (opts.properties.checkbox) {
4839
5340
  const cb = opts.properties.checkbox;
4840
5341
  const symbol = cb.checked ?? false ? cb.checkedState ?? DEFAULT_CHECKED : cb.uncheckedState ?? DEFAULT_UNCHECKED;
@@ -4854,6 +5355,9 @@ const sdtBlockDesc = {
4854
5355
  const dctx = ctx;
4855
5356
  const sdtPr = findChild(el, "w:sdtPr");
4856
5357
  const properties = sdtPr ? parseSdtPr(sdtPr) : {};
5358
+ let endProperties;
5359
+ const sdtEndPr = findChild(el, "w:sdtEndPr");
5360
+ if (sdtEndPr) endProperties = parseRunProperties(sdtEndPr);
4857
5361
  const sdtContent = findChild(el, "w:sdtContent");
4858
5362
  let childList;
4859
5363
  if (sdtContent && sdtContent.elements?.length) {
@@ -4862,7 +5366,8 @@ const sdtBlockDesc = {
4862
5366
  }
4863
5367
  return {
4864
5368
  properties,
4865
- children: childList
5369
+ children: childList,
5370
+ endProperties
4866
5371
  };
4867
5372
  }
4868
5373
  };
@@ -4989,6 +5494,114 @@ const customPropertiesDesc = {
4989
5494
  }
4990
5495
  };
4991
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
4992
5605
  //#region src/parts/web-settings.ts
4993
5606
  /**
4994
5607
  * Screen size types for web settings target.
@@ -5531,6 +6144,6 @@ var DocxReadContext = class {
5531
6144
  }
5532
6145
  };
5533
6146
  //#endregion
5534
- 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 _, framesetXml as a, PositionalTabRelativeTo as at, DocPartType as b, corePropertiesDesc as c, createImageData as ct, sdtBlockDesc as d, PageNumber as dt, TableAnchorType as et, setBodyParseChild as f, TextAlignmentType as ft, contentTypesDesc as g, buildContentTypes as h, AlignmentType as ht, frameXml as i, PositionalTabLeader as it, parseParagraph as j, endnotesDesc as k, altChunkDesc as l, HighlightColor as lt, relationshipsDesc as m, HeadingLevel as mt, DocxWriteContext as n, RubyAlign as nt, webSettingsDesc as o, EmphasisMarkType as ot, subDocDesc as p, TextboxTightWrapType as pt, LevelFormat as q, TargetScreenSize as r, PositionalTabAlignment as rt, customPropertiesDesc as s, UnderlineType as st, DocxReadContext as t, ProofErrorType as tt, customXmlBlockDesc as u, TextEffect 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 };
5535
6148
 
5536
- //# sourceMappingURL=context-DeKZoZem.mjs.map
6149
+ //# sourceMappingURL=context-CA7wUvmY.mjs.map