@office-open/docx 0.9.0 → 0.9.2

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,4 +1,4 @@
1
- import { A as stringifyParagraphProperties, D as stringifyJsonChild, E as tableDesc, F as parseDrawingRun, M as parseMathChildren, O as stringifyParagraphInline, Y as BorderStyle, at as Media, j as stringifyRunProperties, n as sectionPropertiesDesc, ot as createTransformation } from "./document-CWr8C_OX.mjs";
1
+ import { A as stringifyParagraphProperties, D as stringifyChildDispatch, E as tableDesc, F as parseDrawingRun, M as parseMathChildren, O as stringifyParagraphInline, Y as BorderStyle, at as Media, j as stringifyRunProperties, n as sectionPropertiesDesc, ot as createTransformation } from "./document-CeM-U6J3.mjs";
2
2
  import { Relationships, convertInchesToTwip, decimalNumber, derivePasswordHash, hexColorValue, toUint8Array, uCharHexNumber, uniqueId, uniqueNumericIdCreator, uniqueUuid } from "@office-open/core";
3
3
  import { attr, attrBool, attrNum, children, colorAttr, element, escapeXml, findChild, js2xml, textOf, xml2js } from "@office-open/xml";
4
4
  import { ChartCollection } from "@office-open/core/chart";
@@ -2710,6 +2710,160 @@ const settingsDesc = {
2710
2710
  if (findChild(el, "w:embedTrueTypeFonts")) opts.embedTrueTypeFonts = true;
2711
2711
  if (findChild(el, "w:embedSystemFonts")) opts.embedSystemFonts = true;
2712
2712
  if (findChild(el, "w:saveSubsetFonts")) opts.saveSubsetFonts = true;
2713
+ if (findChild(el, "w:removePersonalInformation")) opts.removePersonalInformation = true;
2714
+ if (findChild(el, "w:removeDateAndTime")) opts.removeDateAndTime = true;
2715
+ if (findChild(el, "w:hideSpellingErrors")) opts.hideSpellingErrors = true;
2716
+ if (findChild(el, "w:hideGrammaticalErrors")) opts.hideGrammaticalErrors = true;
2717
+ if (findChild(el, "w:mirrorMargins")) opts.mirrorMargins = true;
2718
+ if (findChild(el, "w:saveFormsData")) opts.saveFormsData = true;
2719
+ if (findChild(el, "w:alignBordersAndEdges")) opts.alignBordersAndEdges = true;
2720
+ if (findChild(el, "w:bordersDoNotSurroundHeader")) opts.bordersDoNotSurroundHeader = true;
2721
+ if (findChild(el, "w:bordersDoNotSurroundFooter")) opts.bordersDoNotSurroundFooter = true;
2722
+ if (findChild(el, "w:gutterAtTop")) opts.gutterAtTop = true;
2723
+ if (findChild(el, "w:formsDesign")) opts.formsDesign = true;
2724
+ if (findChild(el, "w:linkStyles")) opts.linkStyles = true;
2725
+ if (findChild(el, "w:autoHyphenation")) {
2726
+ const hyphenation = opts.hyphenation ?? {};
2727
+ hyphenation.autoHyphenation = true;
2728
+ opts.hyphenation = hyphenation;
2729
+ }
2730
+ if (findChild(el, "w:doNotHyphenateCaps")) {
2731
+ const hyphenation = opts.hyphenation ?? {};
2732
+ hyphenation.doNotHyphenateCaps = true;
2733
+ opts.hyphenation = hyphenation;
2734
+ }
2735
+ const consHyphEl = findChild(el, "w:consecutiveHyphenLimit");
2736
+ if (consHyphEl) {
2737
+ const val = attr(consHyphEl, "w:val");
2738
+ if (val) {
2739
+ const hyphenation = opts.hyphenation ?? {};
2740
+ hyphenation.consecutiveHyphenLimit = parseInt(val, 10);
2741
+ opts.hyphenation = hyphenation;
2742
+ }
2743
+ }
2744
+ const hyphZoneEl = findChild(el, "w:hyphenationZone");
2745
+ if (hyphZoneEl) {
2746
+ const val = attr(hyphZoneEl, "w:val");
2747
+ if (val) {
2748
+ const hyphenation = opts.hyphenation ?? {};
2749
+ hyphenation.hyphenationZone = parseInt(val, 10);
2750
+ opts.hyphenation = hyphenation;
2751
+ }
2752
+ }
2753
+ const attachedTplEl = findChild(el, "w:attachedTemplate");
2754
+ if (attachedTplEl) {
2755
+ const val = attr(attachedTplEl, "r:id");
2756
+ if (val) opts.attachedTemplate = val;
2757
+ }
2758
+ const spsmEl = findChild(el, "w:stylePaneSortMethod");
2759
+ if (spsmEl) {
2760
+ const val = attr(spsmEl, "w:val");
2761
+ if (val) opts.stylePaneSortMethod = val;
2762
+ }
2763
+ const docTypeEl = findChild(el, "w:documentType");
2764
+ if (docTypeEl) {
2765
+ const val = attr(docTypeEl, "w:val");
2766
+ if (val) opts.documentType = val;
2767
+ }
2768
+ const defTblStyleEl = findChild(el, "w:defaultTableStyle");
2769
+ if (defTblStyleEl) {
2770
+ const val = attr(defTblStyleEl, "w:val");
2771
+ if (val) opts.defaultTableStyle = val;
2772
+ }
2773
+ const spffEl = findChild(el, "w:stylePaneFormatFilter");
2774
+ if (spffEl) {
2775
+ const filter = {};
2776
+ for (const [prop, xmlKey] of [
2777
+ ["allStyles", "w:allStyles"],
2778
+ ["customStyles", "w:customStyles"],
2779
+ ["stylesInUse", "w:stylesInUse"],
2780
+ ["headingStyles", "w:headingStyles"],
2781
+ ["numberingStyles", "w:numberingStyles"],
2782
+ ["tableStyles", "w:tableStyles"],
2783
+ ["directFormattingOnRuns", "w:directFormattingOnRuns"],
2784
+ ["directFormattingOnParagraphs", "w:directFormattingOnParagraphs"],
2785
+ ["directFormattingOnNumbering", "w:directFormattingOnNumbering"],
2786
+ ["directFormattingOnTables", "w:directFormattingOnTables"],
2787
+ ["clearFormatting", "w:clearFormatting"],
2788
+ ["top3HeadingStyles", "w:top3HeadingStyles"],
2789
+ ["visibleStyles", "w:visibleStyles"],
2790
+ ["alternateStyleNames", "w:alternateStyleNames"]
2791
+ ]) {
2792
+ const v = attr(spffEl, xmlKey);
2793
+ if (v !== void 0) filter[prop] = v !== "0" && v !== "false" && v !== "off";
2794
+ }
2795
+ if (Object.keys(filter).length > 0) opts.stylePaneFormatFilter = filter;
2796
+ }
2797
+ const catEl = findChild(el, "w:clickAndTypeStyle");
2798
+ if (catEl) {
2799
+ const val = attr(catEl, "w:val");
2800
+ if (val) opts.clickAndTypeStyle = val;
2801
+ }
2802
+ const awsList = [];
2803
+ for (const child of el.elements ?? []) {
2804
+ if (child.name !== "w:activeWritingStyle") continue;
2805
+ const entry = {};
2806
+ const lang = attr(child, "w:lang");
2807
+ if (lang) entry.lang = lang;
2808
+ const vendorID = attr(child, "w:vendorID");
2809
+ if (vendorID) entry.vendorID = vendorID;
2810
+ const dllVersion = attr(child, "w:dllVersion");
2811
+ if (dllVersion) entry.dllVersion = dllVersion;
2812
+ const nlCheck = attr(child, "w:nlCheck");
2813
+ if (nlCheck !== void 0) entry.nlCheck = nlCheck !== "0" && nlCheck !== "false";
2814
+ const checkStyle = attr(child, "w:checkStyle");
2815
+ if (checkStyle !== void 0) entry.checkStyle = checkStyle !== "0" && checkStyle !== "false";
2816
+ const appCheck = attr(child, "w:appCheck");
2817
+ if (appCheck) entry.appCheck = appCheck;
2818
+ const appName = attr(child, "w:appName");
2819
+ if (appName) entry.appName = appName;
2820
+ if (Object.keys(entry).length > 0) awsList.push(entry);
2821
+ }
2822
+ if (awsList.length > 0) opts.activeWritingStyle = awsList;
2823
+ const proofEl = findChild(el, "w:proofState");
2824
+ if (proofEl) {
2825
+ const proof = {};
2826
+ const spelling = attr(proofEl, "w:spelling");
2827
+ if (spelling) proof.spelling = spelling;
2828
+ const grammar = attr(proofEl, "w:grammar");
2829
+ if (grammar) proof.grammar = grammar;
2830
+ if (Object.keys(proof).length > 0) opts.proofState = proof;
2831
+ }
2832
+ const docProtEl = findChild(el, "w:documentProtection");
2833
+ if (docProtEl) {
2834
+ const prot = {};
2835
+ const edit = attr(docProtEl, "w:edit");
2836
+ if (edit) prot.edit = edit;
2837
+ if (attr(docProtEl, "w:enforcement") !== void 0) {
2838
+ const hash = attr(docProtEl, "w:hash");
2839
+ if (hash) prot.hash = hash;
2840
+ const salt = attr(docProtEl, "w:salt");
2841
+ if (salt) prot.salt = salt;
2842
+ const cryptProviderType = attr(docProtEl, "w:cryptProviderType");
2843
+ if (cryptProviderType) prot.cryptoProviderType = cryptProviderType;
2844
+ const cryptAlgorithmClass = attr(docProtEl, "w:cryptAlgorithmClass");
2845
+ if (cryptAlgorithmClass) prot.cryptoAlgorithmClass = cryptAlgorithmClass;
2846
+ const cryptAlgorithmType = attr(docProtEl, "w:cryptAlgorithmType");
2847
+ if (cryptAlgorithmType) prot.cryptoAlgorithmType = cryptAlgorithmType;
2848
+ const cryptAlgorithmSid = attr(docProtEl, "w:cryptAlgorithmSid");
2849
+ if (cryptAlgorithmSid) prot.cryptoAlgorithmSid = parseInt(cryptAlgorithmSid, 10);
2850
+ const cryptSpinCount = attr(docProtEl, "w:cryptSpinCount");
2851
+ if (cryptSpinCount) prot.cryptoSpinCount = parseInt(cryptSpinCount, 10);
2852
+ const hashValue = attr(docProtEl, "w:hashValue");
2853
+ if (hashValue) prot.hashValue = hashValue;
2854
+ const saltValue = attr(docProtEl, "w:saltValue");
2855
+ if (saltValue) prot.saltValue = saltValue;
2856
+ const spinCount = attr(docProtEl, "w:spinCount");
2857
+ if (spinCount) prot.spinCount = parseInt(spinCount, 10);
2858
+ const algorithmName = attr(docProtEl, "w:algorithmName");
2859
+ if (algorithmName) prot.algorithmName = algorithmName;
2860
+ const formatting = attr(docProtEl, "w:formatting");
2861
+ if (formatting !== void 0) prot.formatting = formatting === "1" || formatting === "true";
2862
+ }
2863
+ if (Object.keys(prot).length > 0) opts.documentProtection = prot;
2864
+ }
2865
+ if (findChild(el, "w:doNotTrackMoves")) opts.doNotTrackMoves = true;
2866
+ if (findChild(el, "w:doNotTrackFormatting")) opts.doNotTrackFormatting = true;
2713
2867
  return opts;
2714
2868
  }
2715
2869
  };
@@ -2926,250 +3080,864 @@ function stringifyTableOfContents(alias = "Table of Contents", options = {}) {
2926
3080
  return `<w:sdt>${`<w:sdtPr><w:alias${alias ? ` w:val="${escapeXml(alias)}"` : ""}/><w:docPartObj><w:docPartGallery w:val="Table of Contents"/></w:docPartObj></w:sdtPr>`}${`<w:sdtContent><w:p><w:r><w:rPr><w:rFonts w:asciiTheme="majorHAnsi" w:cstheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cs="Times New Roman"/></w:rPr><w:fldChar w:fldCharType="begin" w:dirty="1"/></w:r><w:r><w:instrText xml:space="preserve"> ${instr} </w:instrText></w:r><w:r><w:fldChar w:fldCharType="separate"/></w:r></w:p><w:p><w:r><w:fldChar w:fldCharType="end"/></w:r></w:p></w:sdtContent>`}</w:sdt>`;
2927
3081
  }
2928
3082
  //#endregion
2929
- //#region src/parts/footnotes/descriptor.ts
2930
- const NS$2 = "xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\" 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:v=\"urn:schemas-microsoft-com:vml\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:w10=\"urn:schemas-microsoft-com:office:word\" xmlns:w14=\"http://schemas.microsoft.com/office/word/2010/wordml\" xmlns:w15=\"http://schemas.microsoft.com/office/word/2012/wordml\" xmlns:wne=\"http://schemas.openxmlformats.org/office/word/2006/wordml\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" xmlns:wp14=\"http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing\" xmlns:wpc=\"http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas\" xmlns:wpg=\"http://schemas.microsoft.com/office/word/2010/wordprocessingGroup\" xmlns:wpi=\"http://schemas.microsoft.com/office/word/2010/wordprocessingInk\" xmlns:wps=\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\"";
2931
- /** XML for the footnoteRef run — auto-injected at start of first paragraph. */
2932
- const FOOTNOTE_REF_RUN = "<w:r><w:rPr><w:rStyle w:val=\"FootnoteReference\"/></w:rPr><w:footnoteRef/></w:r>";
2933
- /** Separator footnote (id=-1). */
2934
- const SEPARATOR_FOOTNOTE = "<w:footnote w:type=\"separator\" w:id=\"-1\"><w:p><w:pPr><w:spacing w:after=\"0\" w:line=\"240\" w:lineRule=\"auto\"/></w:pPr><w:r><w:separator/></w:r></w:p></w:footnote>";
2935
- /** Continuation separator footnote (id=0). */
2936
- const CONTINUATION_SEPARATOR_FOOTNOTE = "<w:footnote w:type=\"continuationSeparator\" w:id=\"0\"><w:p><w:pPr><w:spacing w:after=\"0\" w:line=\"240\" w:lineRule=\"auto\"/></w:pPr><w:r><w:continuationSeparator/></w:r></w:p></w:footnote>";
2937
- const footnotesDesc = {
2938
- kind: "custom",
2939
- stringify(data, ctx) {
2940
- const parts = [
2941
- `<w:footnotes ${NS$2} mc:Ignorable="w14 w15 wp14">`,
2942
- SEPARATOR_FOOTNOTE,
2943
- CONTINUATION_SEPARATOR_FOOTNOTE
2944
- ];
2945
- for (const [id, paragraphs] of data.notes) {
2946
- parts.push(`<w:footnote w:id="${id}">`);
2947
- for (let i = 0; i < paragraphs.length; i++) {
2948
- const pXml = stringifyParagraphInline(paragraphs[i], ctx);
2949
- if (i === 0) {
2950
- const openIdx = pXml.indexOf(">");
2951
- if (openIdx !== -1) parts.push(pXml.slice(0, openIdx + 1) + FOOTNOTE_REF_RUN + pXml.slice(openIdx + 1));
2952
- else parts.push(pXml);
2953
- } else parts.push(pXml);
2954
- }
2955
- parts.push("</w:footnote>");
2956
- }
2957
- parts.push("</w:footnotes>");
2958
- return parts.join("");
2959
- },
2960
- parse(_el, _ctx) {
2961
- return {};
3083
+ //#region src/parts/fonts/font-wrapper.ts
3084
+ /**
3085
+ * Wrapper class for managing embedded font relationships.
3086
+ *
3087
+ * Each font is assigned a unique key for obfuscation.
3088
+ * The actual font table XML is generated by `fontTableDesc.stringify()`.
3089
+ *
3090
+ * @example
3091
+ * ```typescript
3092
+ * const fontWrapper = new FontWrapper([
3093
+ * { name: "CustomFont", data: fontBuffer }
3094
+ * ]);
3095
+ * ```
3096
+ */
3097
+ var FontWrapper = class {
3098
+ options;
3099
+ relationships;
3100
+ fontOptionsWithKey = [];
3101
+ constructor(options) {
3102
+ this.options = options;
3103
+ this.fontOptionsWithKey = options.map((o) => ({
3104
+ ...o,
3105
+ fontKey: uniqueUuid()
3106
+ }));
3107
+ this.relationships = new Relationships();
3108
+ for (let i = 0; i < options.length; i++) this.relationships.addRelationship(i + 1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/font", `fonts/${options[i].name}.odttf`);
2962
3109
  }
2963
3110
  };
2964
3111
  //#endregion
2965
- //#region src/parts/endnotes/descriptor.ts
2966
- const NS$1 = "xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\" 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:v=\"urn:schemas-microsoft-com:vml\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:w10=\"urn:schemas-microsoft-com:office:word\" xmlns:w14=\"http://schemas.microsoft.com/office/word/2010/wordml\" xmlns:w15=\"http://schemas.microsoft.com/office/word/2012/wordml\" xmlns:wne=\"http://schemas.openxmlformats.org/office/word/2006/wordml\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" xmlns:wp14=\"http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing\" xmlns:wpc=\"http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas\" xmlns:wpg=\"http://schemas.microsoft.com/office/word/2010/wordprocessingGroup\" xmlns:wpi=\"http://schemas.microsoft.com/office/word/2010/wordprocessingInk\" xmlns:wps=\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\"";
2967
- /** XML for the endnoteRef run auto-injected at start of first paragraph. */
2968
- const ENDNOTE_REF_RUN = "<w:r><w:rPr><w:rStyle w:val=\"EndnoteReference\"/></w:rPr><w:endnoteRef/></w:r>";
2969
- /** Separator endnote (id=-1). */
2970
- const SEPARATOR_ENDNOTE = "<w:endnote w:type=\"separator\" w:id=\"-1\"><w:p><w:pPr><w:spacing w:after=\"0\" w:line=\"240\" w:lineRule=\"auto\"/></w:pPr><w:r><w:separator/></w:r></w:p></w:endnote>";
2971
- /** Continuation separator endnote (id=0). */
2972
- const CONTINUATION_SEPARATOR_ENDNOTE = "<w:endnote w:type=\"continuationSeparator\" w:id=\"0\"><w:p><w:pPr><w:spacing w:after=\"0\" w:line=\"240\" w:lineRule=\"auto\"/></w:pPr><w:r><w:continuationSeparator/></w:r></w:p></w:endnote>";
2973
- const endnotesDesc = {
2974
- kind: "custom",
2975
- stringify(data, ctx) {
2976
- const parts = [
2977
- `<w:endnotes ${NS$1} mc:Ignorable="w14 w15 wp14">`,
2978
- SEPARATOR_ENDNOTE,
2979
- CONTINUATION_SEPARATOR_ENDNOTE
2980
- ];
2981
- for (const [id, paragraphs] of data.notes) {
2982
- parts.push(`<w:endnote w:id="${id}">`);
2983
- for (let i = 0; i < paragraphs.length; i++) {
2984
- const pXml = stringifyParagraphInline(paragraphs[i], ctx);
2985
- if (i === 0) {
2986
- const openIdx = pXml.indexOf(">");
2987
- if (openIdx !== -1) parts.push(pXml.slice(0, openIdx + 1) + ENDNOTE_REF_RUN + pXml.slice(openIdx + 1));
2988
- else parts.push(pXml);
2989
- } else parts.push(pXml);
2990
- }
2991
- parts.push("</w:endnote>");
2992
- }
2993
- parts.push("</w:endnotes>");
2994
- return parts.join("");
2995
- },
2996
- parse(_el, _ctx) {
2997
- return {};
2998
- }
3112
+ //#region src/parts/textbox/shape/shape.ts
3113
+ /**
3114
+ * Maps VmlShapeStyle property names to their corresponding CSS-style property names.
3115
+ * Used internally for converting TypeScript-friendly property names to VML style attributes.
3116
+ */
3117
+ const styleToKeyMap = {
3118
+ flip: "flip",
3119
+ height: "height",
3120
+ left: "left",
3121
+ marginBottom: "margin-bottom",
3122
+ marginLeft: "margin-left",
3123
+ marginRight: "margin-right",
3124
+ marginTop: "margin-top",
3125
+ position: "position",
3126
+ positionHorizontal: "mso-position-horizontal",
3127
+ positionHorizontalRelative: "mso-position-horizontal-relative",
3128
+ positionVertical: "mso-position-vertical",
3129
+ positionVerticalRelative: "mso-position-vertical-relative",
3130
+ rotation: "rotation",
3131
+ top: "top",
3132
+ visibility: "visibility",
3133
+ width: "width",
3134
+ wrapDistanceBottom: "mso-wrap-distance-bottom",
3135
+ wrapDistanceLeft: "mso-wrap-distance-left",
3136
+ wrapDistanceRight: "mso-wrap-distance-right",
3137
+ wrapDistanceTop: "mso-wrap-distance-top",
3138
+ wrapEdited: "mso-wrap-edited",
3139
+ wrapStyle: "mso-wrap-style",
3140
+ zIndex: "z-index"
2999
3141
  };
3000
3142
  //#endregion
3001
- //#region src/parts/sdt/sdt-parse.ts
3143
+ //#region src/body.ts
3002
3144
  /**
3003
- * Structured Document Tag parser for DOCX documents.
3145
+ * Body-level stringification for DOCX documents.
3004
3146
  *
3005
- * Parses w:sdt elements into SdtPropertiesOptions + children.
3147
+ * Converts pure JSON options to XML strings for document body content.
3148
+ * Pure string concatenation — zero IXmlableObject, zero BaseXmlComponent.
3006
3149
  *
3007
3150
  * @module
3008
3151
  */
3009
3152
  /**
3010
- * Parse w:sdtPr element into SdtPropertiesOptions.
3153
+ * Mapping from empty child property name to self-closing XML element.
3154
+ *
3155
+ * These are single-key objects like `{ noBreakHyphen: true }` that map to
3156
+ * self-closing XML elements with no attributes.
3157
+ *
3158
+ * XSD reference: EG_RunInnerContent group in wml.xsd.
3011
3159
  */
3012
- function parseSdtProperties(el) {
3013
- const opts = {};
3014
- const alias = findChild(el, "w:alias");
3015
- if (alias) opts.alias = attr(alias, "w:val");
3016
- const tag = findChild(el, "w:tag");
3017
- if (tag) {
3018
- const val = attr(tag, "w:val");
3019
- if (val) opts.tag = val;
3020
- }
3021
- const id = findChild(el, "w:id");
3022
- if (id) {
3023
- const val = attrNum(id, "w:val");
3024
- if (val !== void 0) opts.id = val;
3025
- }
3026
- const lock = findChild(el, "w:lock");
3027
- if (lock) {
3028
- const val = attr(lock, "w:val");
3029
- if (val) opts.lock = val;
3030
- }
3031
- const temporary = findChild(el, "w:temporary");
3032
- if (temporary) opts.temporary = attrBool(temporary, "w:val") ?? true;
3033
- const showingPlcHdr = findChild(el, "w:showingPlcHdr");
3034
- if (showingPlcHdr) opts.showingPlaceholder = attrBool(showingPlcHdr, "w:val") ?? true;
3035
- const label = findChild(el, "w:label");
3036
- if (label) {
3037
- const val = attrNum(label, "w:val");
3038
- if (val !== void 0) opts.label = val;
3039
- }
3040
- const tabIndex = findChild(el, "w:tabIndex");
3041
- if (tabIndex) {
3042
- const val = attrNum(tabIndex, "w:val");
3043
- if (val !== void 0) opts.tabIndex = val;
3160
+ const EMPTY_RUN_ELEMENTS = {
3161
+ noBreakHyphen: "<w:noBreakHyphen/>",
3162
+ softHyphen: "<w:softHyphen/>",
3163
+ dayShort: "<w:dayShort/>",
3164
+ monthShort: "<w:monthShort/>",
3165
+ yearShort: "<w:yearShort/>",
3166
+ dayLong: "<w:dayLong/>",
3167
+ monthLong: "<w:monthLong/>",
3168
+ yearLong: "<w:yearLong/>",
3169
+ annotationRef: "<w:annotationRef/>",
3170
+ footnoteRef: "<w:footnoteRef/>",
3171
+ endnoteRef: "<w:endnoteRef/>",
3172
+ separator: "<w:separator/>",
3173
+ continuationSeparator: "<w:continuationSeparator/>",
3174
+ pgNum: "<w:pgNum/>",
3175
+ carriageReturn: "<w:cr/>",
3176
+ lastRenderedPageBreak: "<w:lastRenderedPageBreak/>"
3177
+ };
3178
+ /**
3179
+ * Stringify a run (w:r) from pure JSON options.
3180
+ *
3181
+ * Handles text, children, breaks, and run properties.
3182
+ */
3183
+ function stringifyRun(opts, ctx) {
3184
+ const parts = [];
3185
+ let commentRefStyle = false;
3186
+ if (opts.children) {
3187
+ for (const child of opts.children) if (typeof child === "object" && child !== null && "commentReference" in child) {
3188
+ commentRefStyle = true;
3189
+ break;
3190
+ }
3044
3191
  }
3045
- const dataBinding = findChild(el, "w:dataBinding");
3046
- if (dataBinding) opts.dataBinding = {
3047
- xpath: attr(dataBinding, "w:xpath") ?? "",
3048
- storeItemID: attr(dataBinding, "w:storeItemID") ?? "",
3049
- prefixMappings: attr(dataBinding, "w:prefixMappings")
3050
- };
3051
- if (findChild(el, "w:equation")) opts.equation = true;
3052
- else if (findChild(el, "w:comboBox")) {
3053
- const comboBox = findChild(el, "w:comboBox");
3054
- const items = [];
3055
- for (const li of children(comboBox, "w:listItem")) items.push({
3056
- displayText: attr(li, "w:displayText"),
3057
- value: attr(li, "w:value")
3058
- });
3059
- opts.comboBox = {
3060
- items: items.length > 0 ? items : void 0,
3061
- lastValue: attr(comboBox, "w:lastValue")
3062
- };
3063
- } else if (findChild(el, "w:date")) {
3064
- const date = findChild(el, "w:date");
3065
- const dateOpts = {};
3066
- const dateFormat = findChild(date, "w:dateFormat");
3067
- if (dateFormat) dateOpts.dateFormat = textOf(dateFormat);
3068
- const lid = findChild(date, "w:lid");
3069
- if (lid) dateOpts.languageId = textOf(lid);
3070
- const storeMapped = findChild(date, "w:storeMappedDataAs");
3071
- if (storeMapped) dateOpts.storeMappedDataAs = attr(storeMapped, "w:val");
3072
- const calendar = findChild(date, "w:calendar");
3073
- if (calendar) dateOpts.calendar = attr(calendar, "w:val");
3074
- const fullDate = attr(date, "w:fullDate");
3075
- if (fullDate) dateOpts.fullDate = fullDate;
3076
- opts.date = dateOpts;
3077
- } else if (findChild(el, "w:dropDownList")) {
3078
- const ddl = findChild(el, "w:dropDownList");
3079
- const items = [];
3080
- for (const li of children(ddl, "w:listItem")) items.push({
3081
- displayText: attr(li, "w:displayText"),
3082
- value: attr(li, "w:value")
3083
- });
3084
- opts.dropDownList = {
3085
- items: items.length > 0 ? items : void 0,
3086
- lastValue: attr(ddl, "w:lastValue")
3087
- };
3088
- } else if (findChild(el, "w:picture")) opts.picture = true;
3089
- else if (findChild(el, "w:richText")) opts.richText = true;
3090
- else if (findChild(el, "w:text")) opts.text = { multiLine: attrBool(findChild(el, "w:text"), "w:multiLine") };
3091
- else if (findChild(el, "w:citation")) opts.citation = true;
3092
- else if (findChild(el, "w:group")) opts.group = true;
3093
- else if (findChild(el, "w:bibliography")) opts.bibliography = true;
3094
- else if (findChild(el, "w:docPartObj")) {
3095
- const dp = findChild(el, "w:docPartObj");
3096
- opts.docPartObj = {};
3097
- const gallery = findChild(dp, "w:docPartGallery");
3098
- if (gallery) opts.docPartObj.gallery = attr(gallery, "w:val");
3099
- const category = findChild(dp, "w:docPartCategory");
3100
- if (category) opts.docPartObj.category = attr(category, "w:val");
3101
- } else if (findChild(el, "w:docPartList")) {
3102
- const dp = findChild(el, "w:docPartList");
3103
- opts.docPartList = {};
3104
- const gallery = findChild(dp, "w:docPartGallery");
3105
- if (gallery) opts.docPartList.gallery = attr(gallery, "w:val");
3106
- const category = findChild(dp, "w:docPartCategory");
3107
- if (category) opts.docPartList.category = attr(category, "w:val");
3108
- }
3109
- return opts;
3192
+ const rPr = stringifyRunProperties(commentRefStyle ? {
3193
+ ...opts,
3194
+ style: "CommentReference"
3195
+ } : opts);
3196
+ if (rPr) parts.push(rPr);
3197
+ if (opts.break) for (let i = 0; i < opts.break; i++) parts.push("<w:br/>");
3198
+ if (opts.children) {
3199
+ for (const child of opts.children) if (typeof child === "string") parts.push(`<w:t xml:space="preserve">${escapeXml(child)}</w:t>`);
3200
+ else if (typeof child === "object" && child !== null) {
3201
+ if ("tab" in child) {
3202
+ parts.push("<w:tab/>");
3203
+ continue;
3204
+ }
3205
+ if ("pageBreak" in child) {
3206
+ parts.push("<w:br w:type=\"page\"/>");
3207
+ continue;
3208
+ }
3209
+ if ("columnBreak" in child) {
3210
+ parts.push("<w:br w:type=\"column\"/>");
3211
+ continue;
3212
+ }
3213
+ if ("commentReference" in child) {
3214
+ parts.push(`<w:commentReference w:id="${Number(child.commentReference)}"/>`);
3215
+ continue;
3216
+ }
3217
+ const emptyXml = EMPTY_RUN_ELEMENTS[Object.keys(child)[0]];
3218
+ if (emptyXml) {
3219
+ parts.push(emptyXml);
3220
+ continue;
3221
+ }
3222
+ const jsonResult = stringifyChildDispatch(child, ctx);
3223
+ if (jsonResult !== void 0) if (Array.isArray(jsonResult)) parts.push(...jsonResult);
3224
+ else parts.push(jsonResult);
3225
+ else throw new Error(`Unsupported run child type: ${Object.keys(child).join(", ")}`);
3226
+ }
3227
+ } else if (opts.text !== void 0) parts.push(`<w:t xml:space="preserve">${escapeXml(String(opts.text))}</w:t>`);
3228
+ const rsidAttrs = [];
3229
+ if (opts.rsidRPr) rsidAttrs.push(` w:rsidRPr="${opts.rsidRPr}"`);
3230
+ if (opts.rsidDel) rsidAttrs.push(` w:rsidDel="${opts.rsidDel}"`);
3231
+ const attr = rsidAttrs.join("");
3232
+ const body = parts.join("");
3233
+ return body.length === 0 ? attr ? `<w:r${attr}/>` : "<w:r/>" : `<w:r${attr}>${body}</w:r>`;
3110
3234
  }
3111
3235
  /**
3112
- * Parse a block-level w:sdt element.
3113
- * Returns an object suitable for the { sdt: ... } SectionChild variant.
3236
+ * Stringify a paragraph (w:p) from pure JSON options or string.
3237
+ *
3238
+ * Handles paragraph properties, numbering registration, and run children.
3114
3239
  */
3115
- function parseSdtBlock(el, ctx, parseChildren) {
3116
- const sdtPr = findChild(el, "w:sdtPr");
3117
- const properties = sdtPr ? parseSdtProperties(sdtPr) : {};
3118
- const sdtContent = findChild(el, "w:sdtContent");
3119
- let childList;
3120
- if (sdtContent) {
3121
- childList = parseChildren(sdtContent.elements ?? [], ctx);
3122
- if (childList.length === 0) childList = void 0;
3240
+ function stringifyParagraph(opts, ctx, sectionPropertiesXml) {
3241
+ const resolved = typeof opts === "string" ? { text: opts } : opts;
3242
+ const parts = [];
3243
+ const props = stringifyParagraphProperties(resolved);
3244
+ if (!(ctx.viewWrapper instanceof FontWrapper)) for (const ref of props.numberingReferences) ctx.file.numbering.createConcreteNumberingInstance(ref.reference, ref.instance);
3245
+ if (props.xml) if (sectionPropertiesXml) parts.push(props.xml.replace("</w:pPr>", sectionPropertiesXml + "</w:pPr>"));
3246
+ else parts.push(props.xml);
3247
+ else if (sectionPropertiesXml) parts.push(`<w:pPr>${sectionPropertiesXml}</w:pPr>`);
3248
+ if (resolved.text !== void 0) parts.push(stringifyRun({ text: resolved.text }, ctx));
3249
+ if (resolved.children) {
3250
+ for (const child of resolved.children) if (typeof child === "string") parts.push(stringifyRun({ text: child }, ctx));
3251
+ else if (typeof child === "object" && child !== null) {
3252
+ const jsonResult = stringifyChildDispatch(child, ctx);
3253
+ if (jsonResult !== void 0) if (Array.isArray(jsonResult)) parts.push(...jsonResult);
3254
+ else parts.push(jsonResult);
3255
+ else if ("text" in child || "children" in child || "break" in child) parts.push(stringifyRun(child, ctx));
3256
+ else throw new Error(`Unsupported paragraph child type: ${Object.keys(child).join(", ")}`);
3257
+ }
3123
3258
  }
3124
- return {
3125
- properties,
3126
- children: childList
3127
- };
3259
+ const body = parts.join("");
3260
+ return body ? `<w:p>${body}</w:p>` : "<w:p/>";
3128
3261
  }
3129
- //#endregion
3130
- //#region src/parts/perm-start.ts
3131
3262
  /**
3132
- * Permission range markers for WordprocessingML document protection.
3133
- *
3134
- * These elements mark editable ranges within a protected document.
3135
- *
3136
- * Reference: ISO/IEC 29500-4, wml.xsd, CT_PermStart, CT_PermEnd
3263
+ * Stringify a body-level child element.
3137
3264
  *
3138
- * @module
3265
+ * Dispatches to the appropriate stringifier based on the child type.
3266
+ * Pure JSON API — no class instance support.
3139
3267
  */
3268
+ function stringifyBodyChild(child, ctx) {
3269
+ if ("paragraph" in child) return stringifyParagraph(child.paragraph, ctx);
3270
+ if ("table" in child) return tableDesc.stringify(child.table, ctx) ?? "";
3271
+ if ("toc" in child) {
3272
+ const { alias, ...options } = child.toc;
3273
+ return stringifyTableOfContents(alias, options);
3274
+ }
3275
+ if ("textbox" in child) return stringifyTextbox(child.textbox, ctx);
3276
+ if ("sdt" in child) return sdtBlockDesc.stringify(child.sdt, ctx) ?? "";
3277
+ if ("altChunk" in child) return altChunkDesc.stringify(child.altChunk, ctx) ?? "";
3278
+ if ("subDoc" in child) return subDocDesc.stringify(child.subDoc, ctx) ?? "";
3279
+ if ("customXml" in child) return customXmlBlockDesc.stringify(child.customXml, ctx) ?? "";
3280
+ if ("rawXml" in child) return child.rawXml;
3281
+ throw new Error("Unknown section child type");
3282
+ }
3283
+ /** Re-export styleToKeyMap for use in stringifyTextboxStyle. */
3284
+ const vmlStyleMap = styleToKeyMap;
3285
+ function stringifyDocumentBackground(opts, ctx) {
3286
+ const attrs = [];
3287
+ if (opts.color !== void 0) attrs.push(`w:color="${hexColorValue(opts.color)}"`);
3288
+ if (opts.themeColor !== void 0) attrs.push(`w:themeColor="${opts.themeColor}"`);
3289
+ if (opts.themeShade !== void 0) attrs.push(`w:themeShade="${uCharHexNumber(opts.themeShade)}"`);
3290
+ if (opts.themeTint !== void 0) attrs.push(`w:themeTint="${uCharHexNumber(opts.themeTint)}"`);
3291
+ const attrStr = attrs.join(" ");
3292
+ if (opts.image) {
3293
+ const fileName = `${uniqueId()}.${opts.image.type}`;
3294
+ const rawData = toUint8Array(opts.image.data);
3295
+ ctx.file.media.addImage(fileName, {
3296
+ type: opts.image.type,
3297
+ data: rawData,
3298
+ fileName,
3299
+ transformation: {
3300
+ emus: {
3301
+ x: 0,
3302
+ y: 0
3303
+ },
3304
+ pixels: {
3305
+ x: 0,
3306
+ y: 0
3307
+ }
3308
+ }
3309
+ });
3310
+ return `<w:background ${attrStr}>${`<v:background id="_x0000_s1025"><v:fill r:id="{${fileName}}" o:title="${fileName}" recolor="t" type="frame"/></v:background>`}</w:background>`;
3311
+ }
3312
+ return `<w:background ${attrStr}/>`;
3313
+ }
3314
+ function stringifyTextbox(opts, ctx) {
3315
+ const { style, children, ...paraOpts } = opts;
3316
+ const pPrXml = stringifyParagraphProperties(paraOpts).xml ?? "";
3317
+ const styleStr = style ? Object.entries(style).map(([k, v]) => `${vmlStyleMap[k]}:${v}`).join(";") : void 0;
3318
+ const shapeAttrs = [`id="_x0000_s${uniqueId()}"`, `type="#_x0000_t202"`];
3319
+ if (styleStr) shapeAttrs.push(`style="${styleStr}"`);
3320
+ const contentParts = [];
3321
+ if (children) for (const c of children) contentParts.push(stringifyBodyChild(c, ctx));
3322
+ const vmlTextbox = `<v:textbox style="mso-fit-shape-to-text:t;" insetmode="auto"><w:txbxContent>${contentParts.join("")}</w:txbxContent></v:textbox>`;
3323
+ return `<w:p>${pPrXml}<w:pict>${`<v:shape ${shapeAttrs.join(" ")}>${vmlTextbox}</v:shape>`}</w:pict></w:p>`;
3324
+ }
3325
+ /** Document-level namespace string (cached). */
3326
+ const DOC_NS = "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\" xmlns:cx=\"http://schemas.microsoft.com/office/drawing/2014/chartex\" xmlns:cx1=\"http://schemas.microsoft.com/office/drawing/2015/9/8/chartex\" xmlns:cx2=\"http://schemas.microsoft.com/office/drawing/2015/10/21/chartex\" xmlns:cx3=\"http://schemas.microsoft.com/office/drawing/2016/5/9/chartex\" xmlns:cx4=\"http://schemas.microsoft.com/office/drawing/2016/5/10/chartex\" xmlns:cx5=\"http://schemas.microsoft.com/office/drawing/2016/5/11/chartex\" xmlns:cx6=\"http://schemas.microsoft.com/office/drawing/2016/5/12/chartex\" xmlns:cx7=\"http://schemas.microsoft.com/office/drawing/2016/5/13/chartex\" xmlns:cx8=\"http://schemas.microsoft.com/office/drawing/2016/5/14/chartex\" xmlns:aink=\"http://schemas.microsoft.com/office/drawing/2016/ink\" xmlns:am3d=\"http://schemas.microsoft.com/office/drawing/2017/model3d\" xmlns:w16cex=\"http://schemas.microsoft.com/office/word/2018/wordml/cex\" xmlns:w16cid=\"http://schemas.microsoft.com/office/word/2016/wordml/cid\" xmlns:w16=\"http://schemas.microsoft.com/office/word/2018/wordml\" xmlns:w16sdtdh=\"http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash\" xmlns:w16se=\"http://schemas.microsoft.com/office/word/2015/wordml/symex\"";
3140
3327
  /**
3141
- * Editing group values for permission ranges.
3328
+ * Stringify the complete document.xml from context data.
3142
3329
  *
3143
- * Defines who can edit within a permission range.
3330
+ * This is the pure JSON path iterates raw section children via
3331
+ * `stringifyBodyChild()` while reusing existing SectionProperties
3332
+ * instances for sectPr XML (which are already created with correct
3333
+ * header/footer references).
3144
3334
  *
3145
- * Reference: ISO/IEC 29500-4, ST_EdGrp
3335
+ * Produces the complete `<w:document>` element including namespaces,
3336
+ * background, body content with interleaved section properties.
3146
3337
  */
3147
- const EditGroupType = {
3148
- NONE: "none",
3149
- EVERYONE: "everyone",
3150
- ADMINISTRATORS: "administrators",
3151
- CONTRIBUTORS: "contributors",
3152
- EDITORS: "editors",
3153
- OWNERS: "owners",
3154
- CURRENT: "current"
3338
+ function stringifyDocumentXml(ctx, docCtx) {
3339
+ const sections = ctx._options.sections;
3340
+ const bodySections = ctx.sectionProperties;
3341
+ const parts = [];
3342
+ parts.push(`<w:document ${DOC_NS} mc:Ignorable="w14 w15 wp14">`);
3343
+ if (ctx._options.background) parts.push(stringifyDocumentBackground(ctx._options.background, docCtx));
3344
+ const bodyParts = [];
3345
+ for (let si = 0; si < sections.length; si++) {
3346
+ const section = sections[si];
3347
+ if (section.children) for (const child of section.children) bodyParts.push(stringifyBodyChild(child, docCtx));
3348
+ const sectPrOpts = bodySections[si];
3349
+ if (sectPrOpts) {
3350
+ const sectPrXml = sectionPropertiesDesc.stringify(sectPrOpts, docCtx) ?? "";
3351
+ if (si < sections.length - 1) bodyParts.push(`<w:p><w:pPr>${sectPrXml}</w:pPr></w:p>`);
3352
+ else bodyParts.push(sectPrXml);
3353
+ }
3354
+ }
3355
+ parts.push(`<w:body>${bodyParts.join("")}</w:body>`);
3356
+ parts.push("</w:document>");
3357
+ return parts.join("");
3358
+ }
3359
+ const HEADING_MAP = {
3360
+ Heading1: HeadingLevel.HEADING_1,
3361
+ Heading2: HeadingLevel.HEADING_2,
3362
+ Heading3: HeadingLevel.HEADING_3,
3363
+ Heading4: HeadingLevel.HEADING_4,
3364
+ Heading5: HeadingLevel.HEADING_5,
3365
+ Heading6: HeadingLevel.HEADING_6,
3366
+ Title: HeadingLevel.TITLE
3155
3367
  };
3156
- //#endregion
3157
- //#region src/parts/alt-chunk/alt-chunk-collection.ts
3158
3368
  /**
3159
- * Manages alternative format chunk parts in a document.
3160
- *
3161
- * Stores external content (HTML, RTF, plain text) that will be
3162
- * serialized into separate parts in the DOCX package.
3369
+ * Parse w:pPr element into paragraph properties (without children).
3163
3370
  */
3164
- var AltChunkCollection = class {
3165
- map;
3166
- constructor() {
3167
- this.map = /* @__PURE__ */ new Map();
3371
+ function parseParagraphProperties(el, ctx) {
3372
+ const opts = {};
3373
+ const pStyle = findChild(el, "w:pStyle");
3374
+ if (pStyle) {
3375
+ const styleVal = attr(pStyle, "w:val");
3376
+ if (styleVal) if (HEADING_MAP[styleVal]) opts.heading = HEADING_MAP[styleVal];
3377
+ else opts.style = styleVal;
3168
3378
  }
3169
- addAltChunk(key, data) {
3170
- this.map.set(key, data);
3379
+ const jc = findChild(el, "w:jc");
3380
+ if (jc) {
3381
+ const val = attr(jc, "w:val");
3382
+ if (val) opts.alignment = val;
3171
3383
  }
3172
- get array() {
3384
+ const spacing = findChild(el, "w:spacing");
3385
+ if (spacing) {
3386
+ const sp = {};
3387
+ const before = attrNum(spacing, "w:before");
3388
+ if (before !== void 0) sp.before = before;
3389
+ const after = attrNum(spacing, "w:after");
3390
+ if (after !== void 0) sp.after = after;
3391
+ const line = attrNum(spacing, "w:line");
3392
+ if (line !== void 0) sp.line = line;
3393
+ const lineRule = attr(spacing, "w:lineRule");
3394
+ if (lineRule) sp.lineRule = lineRule;
3395
+ const beforeAuto = attrBool(spacing, "w:beforeAutospacing") ?? attrBool(spacing, "w:beforeLines");
3396
+ if (beforeAuto !== void 0) sp.beforeAutoSpacing = beforeAuto;
3397
+ const afterAuto = attrBool(spacing, "w:afterAutospacing") ?? attrBool(spacing, "w:afterLines");
3398
+ if (afterAuto !== void 0) sp.afterAutoSpacing = afterAuto;
3399
+ if (Object.keys(sp).length > 0) opts.spacing = sp;
3400
+ }
3401
+ const ind = findChild(el, "w:ind");
3402
+ if (ind) {
3403
+ const indentObj = {};
3404
+ const left = attrNum(ind, "w:left");
3405
+ if (left !== void 0) indentObj.left = left;
3406
+ const right = attrNum(ind, "w:right");
3407
+ if (right !== void 0) indentObj.right = right;
3408
+ const start = attrNum(ind, "w:start");
3409
+ if (start !== void 0) indentObj.start = start;
3410
+ const end = attrNum(ind, "w:end");
3411
+ if (end !== void 0) indentObj.end = end;
3412
+ const hanging = attrNum(ind, "w:hanging");
3413
+ if (hanging !== void 0) indentObj.hanging = hanging;
3414
+ const firstLine = attrNum(ind, "w:firstLine");
3415
+ if (firstLine !== void 0) indentObj.firstLine = firstLine;
3416
+ if (Object.keys(indentObj).length > 0) opts.indent = indentObj;
3417
+ }
3418
+ const numPr = findChild(el, "w:numPr");
3419
+ if (numPr) {
3420
+ const ilvl = findChild(numPr, "w:ilvl");
3421
+ const level = ilvl ? attrNum(ilvl, "w:val") ?? 0 : 0;
3422
+ const numIdEl = findChild(numPr, "w:numId");
3423
+ const numId = numIdEl ? attr(numIdEl, "w:val") : void 0;
3424
+ if (numId !== void 0 && ctx.numberingCache.size > 0) {
3425
+ const numEl = ctx.docx.numbering;
3426
+ if (numEl) {
3427
+ let abstractNumId;
3428
+ for (const child of numEl.elements ?? []) {
3429
+ if (child.name !== "w:num") continue;
3430
+ if (attr(child, "w:numId") === numId) {
3431
+ const absRef = findChild(child, "w:abstractNumId");
3432
+ abstractNumId = absRef ? attr(absRef, "w:val") : void 0;
3433
+ break;
3434
+ }
3435
+ }
3436
+ if (abstractNumId !== void 0) opts.numbering = {
3437
+ reference: `list_${numId}`,
3438
+ level
3439
+ };
3440
+ else opts.bullet = { level };
3441
+ } else opts.bullet = { level };
3442
+ } else opts.bullet = { level };
3443
+ }
3444
+ const tabs = findChild(el, "w:tabs");
3445
+ if (tabs) {
3446
+ const tabStops = [];
3447
+ for (const tab of tabs.elements ?? []) {
3448
+ if (tab.name !== "w:tab") continue;
3449
+ const tabObj = {};
3450
+ const pos = attrNum(tab, "w:pos");
3451
+ if (pos !== void 0) tabObj.position = pos;
3452
+ const val = attr(tab, "w:val");
3453
+ if (val) tabObj.type = val;
3454
+ const leader = attr(tab, "w:leader");
3455
+ if (leader) tabObj.leader = leader;
3456
+ tabStops.push(tabObj);
3457
+ }
3458
+ if (tabStops.length > 0) opts.tabStops = tabStops;
3459
+ }
3460
+ for (const [name, optKey] of [
3461
+ ["w:keepNext", "keepNext"],
3462
+ ["w:keepLines", "keepLines"],
3463
+ ["w:pageBreakBefore", "pageBreakBefore"],
3464
+ ["w:widowControl", "widowControl"],
3465
+ ["w:suppressLineNumbers", "suppressLineNumbers"],
3466
+ ["w:contextualSpacing", "contextualSpacing"],
3467
+ ["w:bidi", "bidirectional"],
3468
+ ["w:wordWrap", "wordWrap"],
3469
+ ["w:suppressAutoHyphens", "suppressAutoHyphens"],
3470
+ ["w:adjustRightInd", "adjustRightInd"],
3471
+ ["w:snapToGrid", "snapToGrid"],
3472
+ ["w:mirrorIndents", "mirrorIndents"],
3473
+ ["w:kinsoku", "kinsoku"],
3474
+ ["w:topLinePunct", "topLinePunct"],
3475
+ ["w:autoSpaceDE", "autoSpaceDE"],
3476
+ ["w:overflowPunct", "overflowPunctuation"],
3477
+ ["w:suppressOverlap", "suppressOverlap"]
3478
+ ]) {
3479
+ const child = findChild(el, name);
3480
+ if (child) opts[optKey] = attrBool(child, "w:val") ?? true;
3481
+ }
3482
+ const pBdr = findChild(el, "w:pBdr");
3483
+ if (pBdr) {
3484
+ const border = {};
3485
+ for (const side of [
3486
+ "top",
3487
+ "bottom",
3488
+ "left",
3489
+ "right"
3490
+ ]) {
3491
+ const sideEl = findChild(pBdr, `w:${side}`);
3492
+ if (sideEl) {
3493
+ const sideOpts = {};
3494
+ const style = attr(sideEl, "w:val");
3495
+ if (style) sideOpts.style = style;
3496
+ const color = attr(sideEl, "w:color");
3497
+ if (color) sideOpts.color = color;
3498
+ const size = attrNum(sideEl, "w:sz");
3499
+ if (size !== void 0) sideOpts.size = size;
3500
+ const space = attrNum(sideEl, "w:space");
3501
+ if (space !== void 0) sideOpts.space = space;
3502
+ border[side] = sideOpts;
3503
+ }
3504
+ }
3505
+ if (Object.keys(border).length > 0) opts.border = border;
3506
+ }
3507
+ const shd = findChild(el, "w:shd");
3508
+ if (shd) {
3509
+ const shdObj = {};
3510
+ const fill = attr(shd, "w:fill");
3511
+ if (fill) shdObj.fill = fill;
3512
+ const color = attr(shd, "w:color");
3513
+ if (color) shdObj.color = color;
3514
+ const val = attr(shd, "w:val");
3515
+ if (val) shdObj.type = val;
3516
+ if (Object.keys(shdObj).length > 0) opts.shading = shdObj;
3517
+ }
3518
+ const textAlignment = findChild(el, "w:textAlignment");
3519
+ if (textAlignment) {
3520
+ const val = attr(textAlignment, "w:val");
3521
+ if (val) opts.textAlignment = val;
3522
+ }
3523
+ const outlineLvl = findChild(el, "w:outlineLvl");
3524
+ if (outlineLvl) {
3525
+ const val = attrNum(outlineLvl, "w:val");
3526
+ if (val !== void 0) opts.outlineLevel = val;
3527
+ }
3528
+ const rPr = findChild(el, "w:rPr");
3529
+ if (rPr) opts.run = parseRunProperties(rPr);
3530
+ const framePr = findChild(el, "w:framePr");
3531
+ if (framePr) {
3532
+ const frame = {};
3533
+ for (const [attrName, optName] of [
3534
+ ["w:dropCap", "dropCap"],
3535
+ ["w:lines", "lines"],
3536
+ ["w:wrap", "wrap"],
3537
+ ["w:vAnchor", "vAnchor"],
3538
+ ["w:hAnchor", "hAnchor"],
3539
+ ["w:x", "x"],
3540
+ ["w:y", "y"],
3541
+ ["w:hRule", "hRule"],
3542
+ ["w:hSpace", "hSpace"],
3543
+ ["w:vSpace", "vSpace"]
3544
+ ]) {
3545
+ const val = attr(framePr, attrName);
3546
+ if (val !== void 0) frame[optName] = val;
3547
+ }
3548
+ const w = attrNum(framePr, "w:w");
3549
+ if (w !== void 0) frame.width = w;
3550
+ const h = attrNum(framePr, "w:h");
3551
+ if (h !== void 0) frame.height = h;
3552
+ if (Object.keys(frame).length > 0) opts.frame = frame;
3553
+ }
3554
+ return opts;
3555
+ }
3556
+ /**
3557
+ * Parse a w:p element into ParagraphOptions.
3558
+ */
3559
+ function parseParagraph(el, ctx) {
3560
+ const opts = {};
3561
+ const pPr = findChild(el, "w:pPr");
3562
+ if (pPr) Object.assign(opts, parseParagraphProperties(pPr, ctx));
3563
+ const childList = [];
3564
+ for (const child of el.elements ?? []) switch (child.name) {
3565
+ case "w:pPr": break;
3566
+ case "w:r": {
3567
+ const drawingEl = findChild(child, "w:drawing");
3568
+ if (drawingEl) {
3569
+ const drawingChild = parseDrawingRun(drawingEl, ctx);
3570
+ if (drawingChild) {
3571
+ childList.push(drawingChild);
3572
+ break;
3573
+ }
3574
+ }
3575
+ const runOpts = parsedRunToOptions(parseRun(child, ctx));
3576
+ if (runOpts !== null) childList.push(runOpts);
3577
+ break;
3578
+ }
3579
+ case "w:hyperlink": {
3580
+ const hl = {};
3581
+ const rId = attr(child, "r:id");
3582
+ if (rId) {
3583
+ const target = ctx.docx.partRefs.hyperlinks.get(rId);
3584
+ if (target) hl.link = target;
3585
+ }
3586
+ const anchor = attr(child, "w:anchor");
3587
+ if (anchor) hl.anchor = anchor;
3588
+ const tooltip = attr(child, "w:tooltip");
3589
+ if (tooltip) hl.tooltip = tooltip;
3590
+ const linkRuns = [];
3591
+ for (const sub of child.elements ?? []) if (sub.name === "w:r") {
3592
+ const runOpts = parsedRunToOptions(parseRun(sub, ctx));
3593
+ linkRuns.push(runOpts);
3594
+ }
3595
+ if (linkRuns.length > 0) {
3596
+ hl.children = linkRuns;
3597
+ childList.push({ hyperlink: hl });
3598
+ }
3599
+ break;
3600
+ }
3601
+ case "w:bookmarkStart": {
3602
+ const id = attrNum(child, "w:id");
3603
+ const name = attr(child, "w:name");
3604
+ if (id !== void 0 && name) childList.push({ bookmarkStart: {
3605
+ id,
3606
+ name
3607
+ } });
3608
+ break;
3609
+ }
3610
+ case "w:bookmarkEnd": {
3611
+ const id = attrNum(child, "w:id");
3612
+ if (id !== void 0) childList.push({ bookmarkEnd: id });
3613
+ break;
3614
+ }
3615
+ case "w:commentRangeStart": {
3616
+ const id = attrNum(child, "w:id");
3617
+ if (id !== void 0) childList.push({ commentRangeStart: id });
3618
+ break;
3619
+ }
3620
+ case "w:commentRangeEnd": {
3621
+ const id = attrNum(child, "w:id");
3622
+ if (id !== void 0) childList.push({ commentRangeEnd: id });
3623
+ break;
3624
+ }
3625
+ case "w:commentReference": {
3626
+ const id = attrNum(child, "w:id");
3627
+ if (id !== void 0) childList.push({ commentReference: id });
3628
+ break;
3629
+ }
3630
+ case "m:oMath": {
3631
+ const mathChildren = parseMathChildren(child);
3632
+ childList.push({ math: { children: mathChildren } });
3633
+ break;
3634
+ }
3635
+ case "w:ins": {
3636
+ const insRun = findChild(child, "w:r");
3637
+ if (insRun) {
3638
+ const runOpts = parsedRunToOptions(parseRun(insRun, ctx));
3639
+ if (runOpts !== null && typeof runOpts === "object" && !("commentReference" in runOpts)) childList.push({ insertion: {
3640
+ id: attrNum(child, "w:id") ?? 0,
3641
+ author: attr(child, "w:author") ?? "",
3642
+ date: attr(child, "w:date") ?? "",
3643
+ ...runOpts
3644
+ } });
3645
+ }
3646
+ break;
3647
+ }
3648
+ case "w:del": {
3649
+ const delRun = findChild(child, "w:r");
3650
+ if (delRun) {
3651
+ const runOpts = parsedRunToOptions(parseRun(delRun, ctx));
3652
+ if (runOpts !== null && typeof runOpts === "object" && !("commentReference" in runOpts)) childList.push({ deletion: {
3653
+ id: attrNum(child, "w:id") ?? 0,
3654
+ author: attr(child, "w:author") ?? "",
3655
+ date: attr(child, "w:date") ?? "",
3656
+ ...runOpts
3657
+ } });
3658
+ }
3659
+ break;
3660
+ }
3661
+ default: break;
3662
+ }
3663
+ if (childList.length > 0) {
3664
+ if (childList.every((c) => typeof c === "object" && c !== null && "text" in c && Object.keys(c).length === 1)) {
3665
+ const combined = childList.map((c) => c.text).join("");
3666
+ if (combined && Object.keys(opts).length === 0) return combined;
3667
+ if (combined) {
3668
+ opts.text = combined;
3669
+ return opts;
3670
+ }
3671
+ }
3672
+ opts.children = childList;
3673
+ }
3674
+ return opts;
3675
+ }
3676
+ //#endregion
3677
+ //#region src/parts/footnotes/descriptor.ts
3678
+ const NS$2 = "xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\" 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:v=\"urn:schemas-microsoft-com:vml\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:w10=\"urn:schemas-microsoft-com:office:word\" xmlns:w14=\"http://schemas.microsoft.com/office/word/2010/wordml\" xmlns:w15=\"http://schemas.microsoft.com/office/word/2012/wordml\" xmlns:wne=\"http://schemas.openxmlformats.org/office/word/2006/wordml\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" xmlns:wp14=\"http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing\" xmlns:wpc=\"http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas\" xmlns:wpg=\"http://schemas.microsoft.com/office/word/2010/wordprocessingGroup\" xmlns:wpi=\"http://schemas.microsoft.com/office/word/2010/wordprocessingInk\" xmlns:wps=\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\"";
3679
+ /** XML for the footnoteRef run — auto-injected at start of first paragraph. */
3680
+ const FOOTNOTE_REF_RUN = "<w:r><w:rPr><w:rStyle w:val=\"FootnoteReference\"/></w:rPr><w:footnoteRef/></w:r>";
3681
+ /** Separator footnote (id=-1). */
3682
+ const SEPARATOR_FOOTNOTE = "<w:footnote w:type=\"separator\" w:id=\"-1\"><w:p><w:pPr><w:spacing w:after=\"0\" w:line=\"240\" w:lineRule=\"auto\"/></w:pPr><w:r><w:separator/></w:r></w:p></w:footnote>";
3683
+ /** Continuation separator footnote (id=0). */
3684
+ const CONTINUATION_SEPARATOR_FOOTNOTE = "<w:footnote w:type=\"continuationSeparator\" w:id=\"0\"><w:p><w:pPr><w:spacing w:after=\"0\" w:line=\"240\" w:lineRule=\"auto\"/></w:pPr><w:r><w:continuationSeparator/></w:r></w:p></w:footnote>";
3685
+ const footnotesDesc = {
3686
+ kind: "custom",
3687
+ stringify(data, ctx) {
3688
+ const parts = [
3689
+ `<w:footnotes ${NS$2} mc:Ignorable="w14 w15 wp14">`,
3690
+ SEPARATOR_FOOTNOTE,
3691
+ CONTINUATION_SEPARATOR_FOOTNOTE
3692
+ ];
3693
+ for (const [id, paragraphs] of data.notes) {
3694
+ parts.push(`<w:footnote w:id="${id}">`);
3695
+ for (let i = 0; i < paragraphs.length; i++) {
3696
+ const pXml = stringifyParagraphInline(paragraphs[i], ctx);
3697
+ if (i === 0) {
3698
+ const openIdx = pXml.indexOf(">");
3699
+ if (openIdx !== -1) parts.push(pXml.slice(0, openIdx + 1) + FOOTNOTE_REF_RUN + pXml.slice(openIdx + 1));
3700
+ else parts.push(pXml);
3701
+ } else parts.push(pXml);
3702
+ }
3703
+ parts.push("</w:footnote>");
3704
+ }
3705
+ parts.push("</w:footnotes>");
3706
+ return parts.join("");
3707
+ },
3708
+ parse(el, ctx) {
3709
+ const notes = /* @__PURE__ */ new Map();
3710
+ for (const child of el.elements ?? []) {
3711
+ if (child.name !== "w:footnote") continue;
3712
+ const id = attrNum(child, "w:id");
3713
+ if (id === void 0) continue;
3714
+ if (attr(child, "w:type") || id < 1) continue;
3715
+ const paragraphs = [];
3716
+ for (const sub of child.elements ?? []) if (sub.name === "w:p") paragraphs.push(parseParagraph(sub, ctx));
3717
+ notes.set(id, paragraphs);
3718
+ }
3719
+ return { notes };
3720
+ }
3721
+ };
3722
+ //#endregion
3723
+ //#region src/parts/endnotes/descriptor.ts
3724
+ const NS$1 = "xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\" 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:v=\"urn:schemas-microsoft-com:vml\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:w10=\"urn:schemas-microsoft-com:office:word\" xmlns:w14=\"http://schemas.microsoft.com/office/word/2010/wordml\" xmlns:w15=\"http://schemas.microsoft.com/office/word/2012/wordml\" xmlns:wne=\"http://schemas.openxmlformats.org/office/word/2006/wordml\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" xmlns:wp14=\"http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing\" xmlns:wpc=\"http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas\" xmlns:wpg=\"http://schemas.microsoft.com/office/word/2010/wordprocessingGroup\" xmlns:wpi=\"http://schemas.microsoft.com/office/word/2010/wordprocessingInk\" xmlns:wps=\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\"";
3725
+ /** XML for the endnoteRef run — auto-injected at start of first paragraph. */
3726
+ const ENDNOTE_REF_RUN = "<w:r><w:rPr><w:rStyle w:val=\"EndnoteReference\"/></w:rPr><w:endnoteRef/></w:r>";
3727
+ /** Separator endnote (id=-1). */
3728
+ const SEPARATOR_ENDNOTE = "<w:endnote w:type=\"separator\" w:id=\"-1\"><w:p><w:pPr><w:spacing w:after=\"0\" w:line=\"240\" w:lineRule=\"auto\"/></w:pPr><w:r><w:separator/></w:r></w:p></w:endnote>";
3729
+ /** Continuation separator endnote (id=0). */
3730
+ const CONTINUATION_SEPARATOR_ENDNOTE = "<w:endnote w:type=\"continuationSeparator\" w:id=\"0\"><w:p><w:pPr><w:spacing w:after=\"0\" w:line=\"240\" w:lineRule=\"auto\"/></w:pPr><w:r><w:continuationSeparator/></w:r></w:p></w:endnote>";
3731
+ const endnotesDesc = {
3732
+ kind: "custom",
3733
+ stringify(data, ctx) {
3734
+ const parts = [
3735
+ `<w:endnotes ${NS$1} mc:Ignorable="w14 w15 wp14">`,
3736
+ SEPARATOR_ENDNOTE,
3737
+ CONTINUATION_SEPARATOR_ENDNOTE
3738
+ ];
3739
+ for (const [id, paragraphs] of data.notes) {
3740
+ parts.push(`<w:endnote w:id="${id}">`);
3741
+ for (let i = 0; i < paragraphs.length; i++) {
3742
+ const pXml = stringifyParagraphInline(paragraphs[i], ctx);
3743
+ if (i === 0) {
3744
+ const openIdx = pXml.indexOf(">");
3745
+ if (openIdx !== -1) parts.push(pXml.slice(0, openIdx + 1) + ENDNOTE_REF_RUN + pXml.slice(openIdx + 1));
3746
+ else parts.push(pXml);
3747
+ } else parts.push(pXml);
3748
+ }
3749
+ parts.push("</w:endnote>");
3750
+ }
3751
+ parts.push("</w:endnotes>");
3752
+ return parts.join("");
3753
+ },
3754
+ parse(el, ctx) {
3755
+ const notes = /* @__PURE__ */ new Map();
3756
+ for (const child of el.elements ?? []) {
3757
+ if (child.name !== "w:endnote") continue;
3758
+ const id = attrNum(child, "w:id");
3759
+ if (id === void 0) continue;
3760
+ if (attr(child, "w:type") || id < 1) continue;
3761
+ const paragraphs = [];
3762
+ for (const sub of child.elements ?? []) if (sub.name === "w:p") paragraphs.push(parseParagraph(sub, ctx));
3763
+ notes.set(id, paragraphs);
3764
+ }
3765
+ return { notes };
3766
+ }
3767
+ };
3768
+ //#endregion
3769
+ //#region src/parts/sdt/sdt-parse.ts
3770
+ /**
3771
+ * Structured Document Tag parser for DOCX documents.
3772
+ *
3773
+ * Parses w:sdt elements into SdtPropertiesOptions + children.
3774
+ *
3775
+ * @module
3776
+ */
3777
+ /**
3778
+ * Parse w:sdtPr element into SdtPropertiesOptions.
3779
+ */
3780
+ function parseSdtProperties(el) {
3781
+ const opts = {};
3782
+ const alias = findChild(el, "w:alias");
3783
+ if (alias) opts.alias = attr(alias, "w:val");
3784
+ const tag = findChild(el, "w:tag");
3785
+ if (tag) {
3786
+ const val = attr(tag, "w:val");
3787
+ if (val) opts.tag = val;
3788
+ }
3789
+ const id = findChild(el, "w:id");
3790
+ if (id) {
3791
+ const val = attrNum(id, "w:val");
3792
+ if (val !== void 0) opts.id = val;
3793
+ }
3794
+ const lock = findChild(el, "w:lock");
3795
+ if (lock) {
3796
+ const val = attr(lock, "w:val");
3797
+ if (val) opts.lock = val;
3798
+ }
3799
+ const temporary = findChild(el, "w:temporary");
3800
+ if (temporary) opts.temporary = attrBool(temporary, "w:val") ?? true;
3801
+ const showingPlcHdr = findChild(el, "w:showingPlcHdr");
3802
+ if (showingPlcHdr) opts.showingPlaceholder = attrBool(showingPlcHdr, "w:val") ?? true;
3803
+ const label = findChild(el, "w:label");
3804
+ if (label) {
3805
+ const val = attrNum(label, "w:val");
3806
+ if (val !== void 0) opts.label = val;
3807
+ }
3808
+ const tabIndex = findChild(el, "w:tabIndex");
3809
+ if (tabIndex) {
3810
+ const val = attrNum(tabIndex, "w:val");
3811
+ if (val !== void 0) opts.tabIndex = val;
3812
+ }
3813
+ const dataBinding = findChild(el, "w:dataBinding");
3814
+ if (dataBinding) opts.dataBinding = {
3815
+ xpath: attr(dataBinding, "w:xpath") ?? "",
3816
+ storeItemID: attr(dataBinding, "w:storeItemID") ?? "",
3817
+ prefixMappings: attr(dataBinding, "w:prefixMappings")
3818
+ };
3819
+ if (findChild(el, "w:equation")) opts.equation = true;
3820
+ else if (findChild(el, "w:comboBox")) {
3821
+ const comboBox = findChild(el, "w:comboBox");
3822
+ const items = [];
3823
+ for (const li of children(comboBox, "w:listItem")) items.push({
3824
+ displayText: attr(li, "w:displayText"),
3825
+ value: attr(li, "w:value")
3826
+ });
3827
+ opts.comboBox = {
3828
+ items: items.length > 0 ? items : void 0,
3829
+ lastValue: attr(comboBox, "w:lastValue")
3830
+ };
3831
+ } else if (findChild(el, "w:date")) {
3832
+ const date = findChild(el, "w:date");
3833
+ const dateOpts = {};
3834
+ const dateFormat = findChild(date, "w:dateFormat");
3835
+ if (dateFormat) dateOpts.dateFormat = textOf(dateFormat);
3836
+ const lid = findChild(date, "w:lid");
3837
+ if (lid) dateOpts.languageId = textOf(lid);
3838
+ const storeMapped = findChild(date, "w:storeMappedDataAs");
3839
+ if (storeMapped) dateOpts.storeMappedDataAs = attr(storeMapped, "w:val");
3840
+ const calendar = findChild(date, "w:calendar");
3841
+ if (calendar) dateOpts.calendar = attr(calendar, "w:val");
3842
+ const fullDate = attr(date, "w:fullDate");
3843
+ if (fullDate) dateOpts.fullDate = fullDate;
3844
+ opts.date = dateOpts;
3845
+ } else if (findChild(el, "w:dropDownList")) {
3846
+ const ddl = findChild(el, "w:dropDownList");
3847
+ const items = [];
3848
+ for (const li of children(ddl, "w:listItem")) items.push({
3849
+ displayText: attr(li, "w:displayText"),
3850
+ value: attr(li, "w:value")
3851
+ });
3852
+ opts.dropDownList = {
3853
+ items: items.length > 0 ? items : void 0,
3854
+ lastValue: attr(ddl, "w:lastValue")
3855
+ };
3856
+ } else if (findChild(el, "w:picture")) opts.picture = true;
3857
+ else if (findChild(el, "w:richText")) opts.richText = true;
3858
+ else if (findChild(el, "w:text")) opts.text = { multiLine: attrBool(findChild(el, "w:text"), "w:multiLine") };
3859
+ else if (findChild(el, "w:citation")) opts.citation = true;
3860
+ else if (findChild(el, "w:group")) opts.group = true;
3861
+ else if (findChild(el, "w:bibliography")) opts.bibliography = true;
3862
+ else if (findChild(el, "w:docPartObj")) {
3863
+ const dp = findChild(el, "w:docPartObj");
3864
+ opts.docPartObj = {};
3865
+ const gallery = findChild(dp, "w:docPartGallery");
3866
+ if (gallery) opts.docPartObj.gallery = attr(gallery, "w:val");
3867
+ const category = findChild(dp, "w:docPartCategory");
3868
+ if (category) opts.docPartObj.category = attr(category, "w:val");
3869
+ } else if (findChild(el, "w:docPartList")) {
3870
+ const dp = findChild(el, "w:docPartList");
3871
+ opts.docPartList = {};
3872
+ const gallery = findChild(dp, "w:docPartGallery");
3873
+ if (gallery) opts.docPartList.gallery = attr(gallery, "w:val");
3874
+ const category = findChild(dp, "w:docPartCategory");
3875
+ if (category) opts.docPartList.category = attr(category, "w:val");
3876
+ }
3877
+ return opts;
3878
+ }
3879
+ /**
3880
+ * Parse a block-level w:sdt element.
3881
+ * Returns an object suitable for the { sdt: ... } SectionChild variant.
3882
+ */
3883
+ function parseSdtBlock(el, ctx, parseChildren) {
3884
+ const sdtPr = findChild(el, "w:sdtPr");
3885
+ const properties = sdtPr ? parseSdtProperties(sdtPr) : {};
3886
+ const sdtContent = findChild(el, "w:sdtContent");
3887
+ let childList;
3888
+ if (sdtContent) {
3889
+ childList = parseChildren(sdtContent.elements ?? [], ctx);
3890
+ if (childList.length === 0) childList = void 0;
3891
+ }
3892
+ return {
3893
+ properties,
3894
+ children: childList
3895
+ };
3896
+ }
3897
+ //#endregion
3898
+ //#region src/parts/perm-start.ts
3899
+ /**
3900
+ * Permission range markers for WordprocessingML document protection.
3901
+ *
3902
+ * These elements mark editable ranges within a protected document.
3903
+ *
3904
+ * Reference: ISO/IEC 29500-4, wml.xsd, CT_PermStart, CT_PermEnd
3905
+ *
3906
+ * @module
3907
+ */
3908
+ /**
3909
+ * Editing group values for permission ranges.
3910
+ *
3911
+ * Defines who can edit within a permission range.
3912
+ *
3913
+ * Reference: ISO/IEC 29500-4, ST_EdGrp
3914
+ */
3915
+ const EditGroupType = {
3916
+ NONE: "none",
3917
+ EVERYONE: "everyone",
3918
+ ADMINISTRATORS: "administrators",
3919
+ CONTRIBUTORS: "contributors",
3920
+ EDITORS: "editors",
3921
+ OWNERS: "owners",
3922
+ CURRENT: "current"
3923
+ };
3924
+ //#endregion
3925
+ //#region src/parts/alt-chunk/alt-chunk-collection.ts
3926
+ /**
3927
+ * Manages alternative format chunk parts in a document.
3928
+ *
3929
+ * Stores external content (HTML, RTF, plain text) that will be
3930
+ * serialized into separate parts in the DOCX package.
3931
+ */
3932
+ var AltChunkCollection = class {
3933
+ map;
3934
+ constructor() {
3935
+ this.map = /* @__PURE__ */ new Map();
3936
+ }
3937
+ addAltChunk(key, data) {
3938
+ this.map.set(key, data);
3939
+ }
3940
+ get array() {
3173
3941
  return [...this.map.values()];
3174
3942
  }
3175
3943
  };
@@ -3206,1631 +3974,1380 @@ const CharacterSet = {
3206
3974
  DEFAULT: "01",
3207
3975
  EASTEUROPE: "EE",
3208
3976
  GB_2312: "86",
3209
- GREEK: "A1",
3210
- HANGUL: "81",
3211
- HEBREW: "B1",
3212
- JIS: "80",
3213
- JOHAB: "82",
3214
- MAC: "4D",
3215
- OEM: "FF",
3216
- RUSSIAN: "CC",
3217
- SYMBOL: "02",
3218
- THAI: "DE",
3219
- TURKISH: "A2",
3220
- VIETNAMESE: "A3"
3221
- };
3222
- //#endregion
3223
- //#region src/parts/fonts/descriptor.ts
3224
- const NS = "xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" 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:w16=\"http://schemas.microsoft.com/office/word/2018/wordml\" xmlns:w16cex=\"http://schemas.microsoft.com/office/word/2018/wordml/cex\" xmlns:w16cid=\"http://schemas.microsoft.com/office/word/2016/wordml/cid\" xmlns:w16sdtdh=\"http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash\" xmlns:w16se=\"http://schemas.microsoft.com/office/word/2015/wordml/symex\"";
3225
- /** Default font signature for regular embedded fonts. */
3226
- const DEFAULT_SIG = {
3227
- usb0: "E0002AFF",
3228
- usb1: "C000247B",
3229
- usb2: "00000009",
3230
- usb3: "00000000",
3231
- csb0: "000001FF",
3232
- csb1: "00000000"
3233
- };
3234
- function fontXml(font, index) {
3235
- const parts = [`<w:font w:name="${escapeXml(font.name)}">`];
3236
- if (font.characterSet) parts.push(`<w:charset w:val="${escapeXml(font.characterSet)}"/>`);
3237
- parts.push(`<w:family w:val="auto"/>`);
3238
- parts.push(`<w:pitch w:val="variable"/>`);
3239
- parts.push(`<w:sig w:usb0="${DEFAULT_SIG.usb0}" w:usb1="${DEFAULT_SIG.usb1}" w:usb2="${DEFAULT_SIG.usb2}" w:usb3="${DEFAULT_SIG.usb3}" w:csb0="${DEFAULT_SIG.csb0}" w:csb1="${DEFAULT_SIG.csb1}"/>`);
3240
- parts.push(`<w:embedRegular r:id="rId${index + 1}" w:fontKey="{${font.fontKey}}"/>`);
3241
- parts.push("</w:font>");
3242
- return parts.join("");
3243
- }
3244
- const fontTableDesc = {
3245
- kind: "custom",
3246
- stringify(opts, _ctx) {
3247
- const parts = [`<w:fonts ${NS} mc:Ignorable="w14 w15 w16se w16cid w16 w16cex w16sdtdh">`];
3248
- for (let i = 0; i < opts.fonts.length; i++) parts.push(fontXml(opts.fonts[i], i));
3249
- parts.push("</w:fonts>");
3250
- return parts.join("");
3251
- },
3252
- parse(el, _ctx) {
3253
- const fonts = [];
3254
- for (const child of el.elements ?? []) {
3255
- if (child.name !== "w:font") continue;
3256
- const name = child.attributes?.["w:name"];
3257
- if (name) fonts.push({ name: String(name) });
3258
- }
3259
- return { fonts };
3260
- }
3261
- };
3262
- //#endregion
3263
- //#region src/parts/bibliography.ts
3264
- function escapeXml$2(s) {
3265
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
3266
- }
3267
- const SOURCE_FIELDS = [
3268
- ["SourceType", "type"],
3269
- ["Title", "title"],
3270
- ["Author", "author"],
3271
- ["Year", "year"],
3272
- ["Month", "month"],
3273
- ["Day", "day"],
3274
- ["BookTitle", "bookTitle"],
3275
- ["JournalName", "journal"],
3276
- ["Volume", "volume"],
3277
- ["Issue", "issue"],
3278
- ["Pages", "pages"],
3279
- ["Publisher", "publisher"],
3280
- ["City", "city"],
3281
- ["URL", "url"],
3282
- ["Edition", "edition"],
3283
- ["Institution", "institution"]
3284
- ];
3285
- const bibliographyDesc = {
3286
- kind: "custom",
3287
- stringify(opts, _ctx) {
3288
- const attrParts = ["xmlns:b=\"http://schemas.openxmlformats.org/officeDocument/2006/bibliography\""];
3289
- if (opts.styleName !== void 0) attrParts.push(`StyleName="${escapeXml$2(opts.styleName)}"`);
3290
- const parts = [`<b:Sources ${attrParts.join(" ")}>`];
3291
- for (const source of opts.sources) {
3292
- const sourceParts = [];
3293
- for (const [tagName, key] of SOURCE_FIELDS) {
3294
- const value = source[key];
3295
- if (value !== void 0) sourceParts.push(`<b:${tagName}>${escapeXml$2(value)}</b:${tagName}>`);
3296
- }
3297
- parts.push(`<b:Source>${sourceParts.join("")}</b:Source>`);
3298
- }
3299
- parts.push("</b:Sources>");
3300
- return parts.join("");
3301
- },
3302
- parse() {
3303
- return { sources: [] };
3304
- }
3305
- };
3306
- //#endregion
3307
- //#region src/parts/glossary-document.ts
3308
- /** Gallery type for building blocks (ST_DocPartGallery) */
3309
- const DocPartGallery = {
3310
- PLACEHOLDER: "placeholder",
3311
- DEFAULT: "default",
3312
- DOC_PARTS: "docParts",
3313
- COVER_PAGE: "coverPg",
3314
- EQUATIONS: "eq",
3315
- FOOTERS: "ftrs",
3316
- HEADERS: "hdrs",
3317
- PAGE_NUMBERS: "pgNum",
3318
- TABLES: "tbls",
3319
- WATERMARKS: "watermarks",
3320
- AUTO_TEXT: "autoTxt",
3321
- TEXT_BOX: "txtBox",
3322
- PAGE_NUMBERS_TOP: "pgNumT",
3323
- PAGE_NUMBERS_BOTTOM: "pgNumB",
3324
- PAGE_NUMBERS_MARGIN: "pgNumMargins",
3325
- TABLE_OF_CONTENTS: "tblOfContents",
3326
- BIBLIOGRAPHY: "bib",
3327
- CUSTOM_QUICK_PARTS: "custQuickParts",
3328
- CUSTOM_COVER_PAGE: "custCoverPg",
3329
- CUSTOM_EQUATIONS: "custEq",
3330
- CUSTOM_FOOTERS: "custFtrs",
3331
- CUSTOM_HEADERS: "custHdrs",
3332
- CUSTOM_PAGE_NUMBERS: "custPgNum",
3333
- CUSTOM_TABLES: "custTbls",
3334
- CUSTOM_WATERMARKS: "custWatermarks",
3335
- CUSTOM_AUTO_TEXT: "custAutoTxt",
3336
- CUSTOM_TEXT_BOX: "custTxtBox",
3337
- CUSTOM_PAGE_NUMBERS_TOP: "custPgNumT",
3338
- CUSTOM_PAGE_NUMBERS_BOTTOM: "custPgNumB",
3339
- CUSTOM_PAGE_NUMBERS_MARGIN: "custPgNumMargins",
3340
- CUSTOM_TABLE_OF_CONTENTS: "custTblOfContents",
3341
- CUSTOM_BIBLIOGRAPHY: "custBib",
3342
- CUSTOM1: "custom1",
3343
- CUSTOM2: "custom2",
3344
- CUSTOM3: "custom3",
3345
- CUSTOM4: "custom4",
3346
- CUSTOM5: "custom5"
3347
- };
3348
- /** Building block type (ST_DocPartType) */
3349
- const DocPartType = {
3350
- NONE: "none",
3351
- NORMAL: "normal",
3352
- AUTO_EXPAND: "autoExp",
3353
- TOOLBAR: "toolbar",
3354
- SPELLER: "speller",
3355
- FORM_FIELD: "formFld",
3356
- BUILDING_BLOCK_PLACEHOLDER: "bbPlcHdr"
3357
- };
3358
- /** Building block behavior (ST_DocPartBehavior) */
3359
- const DocPartBehavior = {
3360
- CONTENT: "content",
3361
- PARAGRAPH: "p",
3362
- PAGE: "pg"
3363
- };
3364
- const GLOSSARY_NS = "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: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: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\"";
3365
- function glossaryEscapeAttr(text) {
3366
- return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
3367
- }
3368
- function docPartPrXml(part) {
3369
- const prParts = [];
3370
- prParts.push(`<w:name w:val="${glossaryEscapeAttr(part.name)}"${part.decorated ? " w:decorated=\"1\"" : ""}/>`);
3371
- if (part.category || part.gallery) {
3372
- const catParts = [];
3373
- if (part.category) catParts.push(`<w:name w:val="${glossaryEscapeAttr(part.category)}"/>`);
3374
- catParts.push(`<w:gallery w:val="${part.gallery}"/>`);
3375
- prParts.push(`<w:category>${catParts.join("")}</w:category>`);
3376
- }
3377
- if (part.types && part.types.length > 0) {
3378
- const typeXml = part.types.map((t) => `<w:type w:val="${t}"/>`).join("");
3379
- const allAttr = part.allTypes ? " w:all=\"1\"" : "";
3380
- prParts.push(`<w:types${allAttr}>${typeXml}</w:types>`);
3381
- }
3382
- if (part.behaviors && part.behaviors.length > 0) {
3383
- const behaviorXml = part.behaviors.map((b) => `<w:behavior w:val="${b}"/>`).join("");
3384
- prParts.push(`<w:behaviors>${behaviorXml}</w:behaviors>`);
3385
- }
3386
- if (part.description) prParts.push(`<w:description w:val="${glossaryEscapeAttr(part.description)}"/>`);
3387
- if (part.guid) prParts.push(`<w:guid w:val="${glossaryEscapeAttr(part.guid)}"/>`);
3388
- return `<w:docPartPr>${prParts.join("")}</w:docPartPr>`;
3389
- }
3390
- const glossaryDesc = {
3391
- kind: "custom",
3392
- stringify(opts, ctx) {
3393
- return `<w:glossaryDocument ${GLOSSARY_NS}><w:docParts>${opts.parts.map((part) => {
3394
- const bodyContent = (part.children ?? []).map((child) => ctx.stringifyChild(child, ctx)).join("");
3395
- return `<w:docPart>${docPartPrXml(part)}<w:docPartBody>${bodyContent}</w:docPartBody></w:docPart>`;
3396
- }).join("")}</w:docParts></w:glossaryDocument>`;
3397
- },
3398
- parse(_el, _ctx) {
3399
- return { parts: [] };
3400
- }
3401
- };
3402
- //#endregion
3403
- //#region src/parts/comments.ts
3404
- function escapeAttr$1(s) {
3405
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
3406
- }
3407
- const COMMENTS_NS = "xmlns:aink=\"http://schemas.microsoft.com/office/drawing/2016/ink\" xmlns:am3d=\"http://schemas.microsoft.com/office/drawing/2017/model3d\" xmlns:cx=\"http://schemas.microsoft.com/office/drawing/2014/chartex\" xmlns:cx1=\"http://schemas.microsoft.com/office/drawing/2015/9/8/chartex\" xmlns:cx2=\"http://schemas.microsoft.com/office/drawing/2015/10/21/chartex\" xmlns:cx3=\"http://schemas.microsoft.com/office/drawing/2016/5/9/chartex\" xmlns:cx4=\"http://schemas.microsoft.com/office/drawing/2016/5/10/chartex\" xmlns:cx5=\"http://schemas.microsoft.com/office/drawing/2016/5/11/chartex\" xmlns:cx6=\"http://schemas.microsoft.com/office/drawing/2016/5/12/chartex\" xmlns:cx7=\"http://schemas.microsoft.com/office/drawing/2016/5/13/chartex\" xmlns:cx8=\"http://schemas.microsoft.com/office/drawing/2016/5/14/chartex\" xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\" 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:v=\"urn:schemas-microsoft-com:vml\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:w10=\"urn:schemas-microsoft-com:office:word\" xmlns:w14=\"http://schemas.microsoft.com/office/word/2010/wordml\" xmlns:w15=\"http://schemas.microsoft.com/office/word/2012/wordml\" xmlns:w16=\"http://schemas.microsoft.com/office/word/2018/wordml\" xmlns:w16cex=\"http://schemas.microsoft.com/office/word/2018/wordml/cex\" xmlns:w16cid=\"http://schemas.microsoft.com/office/word/2016/wordml/cid\" xmlns:w16sdtdh=\"http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash\" xmlns:w16se=\"http://schemas.microsoft.com/office/word/2015/wordml/symex\" xmlns:wne=\"http://schemas.openxmlformats.org/office/word/2006/wordml\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" xmlns:wp14=\"http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing\" xmlns:wpg=\"http://schemas.microsoft.com/office/word/2010/wordprocessingGroup\" xmlns:wpi=\"http://schemas.microsoft.com/office/word/2010/wordprocessingInk\" xmlns:wps=\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\"";
3408
- function stringifyComment(opts, ctx) {
3409
- const dateStr = typeof opts.date === "string" ? opts.date : (opts.date ?? /* @__PURE__ */ new Date()).toISOString();
3410
- const attrs = [`w:id="${opts.id}"`, `w:date="${escapeAttr$1(dateStr)}"`];
3411
- if (opts.author !== void 0) attrs.push(`w:author="${escapeAttr$1(opts.author)}"`);
3412
- if (opts.initials !== void 0) attrs.push(`w:initials="${escapeAttr$1(opts.initials)}"`);
3413
- const parts = [];
3414
- for (const child of opts.children) parts.push(stringifyParagraphInline(child, ctx));
3415
- return `<w:comment ${attrs.join(" ")}>${parts.join("")}</w:comment>`;
3416
- }
3417
- const commentsDesc = {
3418
- kind: "custom",
3419
- stringify(opts, ctx) {
3420
- const parts = [`<w:comments ${COMMENTS_NS}>`];
3421
- for (const child of opts.children) parts.push(stringifyComment(child, ctx));
3422
- parts.push("</w:comments>");
3423
- return parts.join("");
3424
- },
3425
- parse() {
3426
- return {};
3427
- }
3977
+ GREEK: "A1",
3978
+ HANGUL: "81",
3979
+ HEBREW: "B1",
3980
+ JIS: "80",
3981
+ JOHAB: "82",
3982
+ MAC: "4D",
3983
+ OEM: "FF",
3984
+ RUSSIAN: "CC",
3985
+ SYMBOL: "02",
3986
+ THAI: "DE",
3987
+ TURKISH: "A2",
3988
+ VIETNAMESE: "A3"
3428
3989
  };
3429
3990
  //#endregion
3430
- //#region src/parts/contenttypes.ts
3431
- function defaultXml(ext, ct) {
3432
- return `<Default Extension="${ext}" ContentType="${ct}"/>`;
3433
- }
3434
- function overrideXml(partName, ct) {
3435
- return `<Override PartName="${partName}" ContentType="${ct}"/>`;
3991
+ //#region src/parts/fonts/descriptor.ts
3992
+ const NS = "xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" 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:w16=\"http://schemas.microsoft.com/office/word/2018/wordml\" xmlns:w16cex=\"http://schemas.microsoft.com/office/word/2018/wordml/cex\" xmlns:w16cid=\"http://schemas.microsoft.com/office/word/2016/wordml/cid\" xmlns:w16sdtdh=\"http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash\" xmlns:w16se=\"http://schemas.microsoft.com/office/word/2015/wordml/symex\"";
3993
+ /** Default font signature for regular embedded fonts. */
3994
+ const DEFAULT_SIG = {
3995
+ usb0: "E0002AFF",
3996
+ usb1: "C000247B",
3997
+ usb2: "00000009",
3998
+ usb3: "00000000",
3999
+ csb0: "000001FF",
4000
+ csb1: "00000000"
4001
+ };
4002
+ function fontXml(font, index) {
4003
+ const parts = [`<w:font w:name="${escapeXml(font.name)}">`];
4004
+ if (font.characterSet) parts.push(`<w:charset w:val="${escapeXml(font.characterSet)}"/>`);
4005
+ parts.push(`<w:family w:val="auto"/>`);
4006
+ parts.push(`<w:pitch w:val="variable"/>`);
4007
+ parts.push(`<w:sig w:usb0="${DEFAULT_SIG.usb0}" w:usb1="${DEFAULT_SIG.usb1}" w:usb2="${DEFAULT_SIG.usb2}" w:usb3="${DEFAULT_SIG.usb3}" w:csb0="${DEFAULT_SIG.csb0}" w:csb1="${DEFAULT_SIG.csb1}"/>`);
4008
+ parts.push(`<w:embedRegular r:id="rId${index + 1}" w:fontKey="{${font.fontKey}}"/>`);
4009
+ parts.push("</w:font>");
4010
+ return parts.join("");
3436
4011
  }
3437
- const contentTypesDesc = {
4012
+ const fontTableDesc = {
3438
4013
  kind: "custom",
3439
4014
  stringify(opts, _ctx) {
3440
- const p = ["<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">"];
3441
- for (const d of opts.defaults) p.push(defaultXml(d.extension, d.contentType));
3442
- for (const o of opts.overrides) p.push(overrideXml(o.partName, o.contentType));
3443
- p.push("</Types>");
3444
- return p.join("");
4015
+ const parts = [`<w:fonts ${NS} mc:Ignorable="w14 w15 w16se w16cid w16 w16cex w16sdtdh">`];
4016
+ for (let i = 0; i < opts.fonts.length; i++) parts.push(fontXml(opts.fonts[i], i));
4017
+ parts.push("</w:fonts>");
4018
+ return parts.join("");
3445
4019
  },
3446
4020
  parse(el, _ctx) {
3447
- const defaults = [];
3448
- const overrides = [];
3449
- for (const child of el.elements ?? []) if (child.name === "Default") {
3450
- const ext = child.attributes?.["Extension"];
3451
- const ct = child.attributes?.["ContentType"];
3452
- if (ext && ct) defaults.push({
3453
- extension: String(ext),
3454
- contentType: String(ct)
3455
- });
3456
- } else if (child.name === "Override") {
3457
- const pn = child.attributes?.["PartName"];
3458
- const ct = child.attributes?.["ContentType"];
3459
- if (pn && ct) overrides.push({
3460
- partName: String(pn),
3461
- contentType: String(ct)
3462
- });
4021
+ const fonts = [];
4022
+ for (const child of el.elements ?? []) {
4023
+ if (child.name !== "w:font") continue;
4024
+ const font = {};
4025
+ const name = child.attributes?.["w:name"];
4026
+ if (name) font.name = String(name);
4027
+ const charsetEl = findChild(child, "w:charset");
4028
+ if (charsetEl) {
4029
+ const val = attr(charsetEl, "w:val");
4030
+ if (val) font.characterSet = val;
4031
+ }
4032
+ const familyEl = findChild(child, "w:family");
4033
+ if (familyEl) {
4034
+ const val = attr(familyEl, "w:val");
4035
+ if (val) font.family = val;
4036
+ }
4037
+ const pitchEl = findChild(child, "w:pitch");
4038
+ if (pitchEl) {
4039
+ const val = attr(pitchEl, "w:val");
4040
+ if (val) font.pitch = val;
4041
+ }
4042
+ const sigEl = findChild(child, "w:sig");
4043
+ if (sigEl) {
4044
+ const sig = {};
4045
+ for (const key of [
4046
+ "usb0",
4047
+ "usb1",
4048
+ "usb2",
4049
+ "usb3",
4050
+ "csb0",
4051
+ "csb1"
4052
+ ]) {
4053
+ const val = attr(sigEl, `w:${key}`);
4054
+ if (val) sig[key] = val;
4055
+ }
4056
+ if (Object.keys(sig).length > 0) font.sig = sig;
4057
+ }
4058
+ for (const embedTag of [
4059
+ "w:embedRegular",
4060
+ "w:embedBold",
4061
+ "w:embedItalic",
4062
+ "w:embedBoldItalic"
4063
+ ]) {
4064
+ const embedEl = findChild(child, embedTag);
4065
+ if (embedEl) {
4066
+ const rawKey = attr(embedEl, "w:fontKey");
4067
+ if (rawKey) font.fontKey = rawKey.replace(/^\{\{|\}\}$/g, "").replace(/^\{|\}$/g, "");
4068
+ break;
4069
+ }
4070
+ }
4071
+ fonts.push(font);
3463
4072
  }
3464
- return {
3465
- defaults,
3466
- overrides
3467
- };
4073
+ return { fonts };
3468
4074
  }
3469
4075
  };
3470
- /** Helper to build the standard DOCX content types with dynamic overrides. */
3471
- function buildContentTypes(extras = {}) {
3472
- const defaults = [
3473
- {
3474
- extension: "png",
3475
- contentType: "image/png"
3476
- },
3477
- {
3478
- extension: "jpeg",
3479
- contentType: "image/jpeg"
3480
- },
3481
- {
3482
- extension: "jpg",
3483
- contentType: "image/jpeg"
3484
- },
3485
- {
3486
- extension: "bmp",
3487
- contentType: "image/bmp"
3488
- },
3489
- {
3490
- extension: "gif",
3491
- contentType: "image/gif"
3492
- },
3493
- {
3494
- extension: "tif",
3495
- contentType: "image/tiff"
3496
- },
3497
- {
3498
- extension: "tiff",
3499
- contentType: "image/tiff"
3500
- },
3501
- {
3502
- extension: "emf",
3503
- contentType: "image/x-emf"
3504
- },
3505
- {
3506
- extension: "wmf",
3507
- contentType: "image/x-wmf"
3508
- },
3509
- {
3510
- extension: "ico",
3511
- contentType: "image/x-icon"
3512
- },
3513
- {
3514
- extension: "svg",
3515
- contentType: "image/svg+xml"
3516
- },
3517
- {
3518
- extension: "rels",
3519
- contentType: "application/vnd.openxmlformats-package.relationships+xml"
3520
- },
3521
- {
3522
- extension: "xml",
3523
- contentType: "application/xml"
3524
- },
3525
- {
3526
- extension: "odttf",
3527
- contentType: "application/vnd.openxmlformats-officedocument.obfuscatedFont"
3528
- }
3529
- ];
3530
- const overrides = [
3531
- {
3532
- partName: "/word/document.xml",
3533
- contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"
3534
- },
3535
- {
3536
- partName: "/word/styles.xml",
3537
- contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"
3538
- },
3539
- {
3540
- partName: "/docProps/core.xml",
3541
- contentType: "application/vnd.openxmlformats-package.core-properties+xml"
3542
- },
3543
- {
3544
- partName: "/docProps/custom.xml",
3545
- contentType: "application/vnd.openxmlformats-officedocument.custom-properties+xml"
3546
- },
3547
- {
3548
- partName: "/docProps/app.xml",
3549
- contentType: "application/vnd.openxmlformats-officedocument.extended-properties+xml"
3550
- },
3551
- {
3552
- partName: "/word/numbering.xml",
3553
- contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml"
3554
- },
3555
- {
3556
- partName: "/word/footnotes.xml",
3557
- contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml"
3558
- },
3559
- {
3560
- partName: "/word/endnotes.xml",
3561
- contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml"
3562
- },
3563
- {
3564
- partName: "/word/settings.xml",
3565
- contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"
3566
- },
3567
- {
3568
- partName: "/word/comments.xml",
3569
- contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml"
3570
- },
3571
- {
3572
- partName: "/word/fontTable.xml",
3573
- contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"
3574
- }
3575
- ];
3576
- for (let i = 1; i <= (extras.headerCount ?? 0); i++) overrides.push({
3577
- partName: `/word/header${i}.xml`,
3578
- contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml"
3579
- });
3580
- for (let i = 1; i <= (extras.footerCount ?? 0); i++) overrides.push({
3581
- partName: `/word/footer${i}.xml`,
3582
- contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml"
3583
- });
3584
- for (let i = 1; i <= (extras.chartCount ?? 0); i++) overrides.push({
3585
- partName: `/word/charts/chart${i}.xml`,
3586
- contentType: "application/vnd.openxmlformats-officedocument.drawingml.chart+xml"
3587
- });
3588
- for (let i = 1; i <= (extras.smartArtCount ?? 0); i++) {
3589
- overrides.push({
3590
- partName: `/word/diagrams/data${i}.xml`,
3591
- contentType: "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml"
3592
- });
3593
- overrides.push({
3594
- partName: `/word/diagrams/layout${i}.xml`,
3595
- contentType: "application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml"
3596
- });
3597
- overrides.push({
3598
- partName: `/word/diagrams/quickStyle${i}.xml`,
3599
- contentType: "application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml"
3600
- });
3601
- overrides.push({
3602
- partName: `/word/diagrams/colors${i}.xml`,
3603
- contentType: "application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml"
3604
- });
3605
- overrides.push({
3606
- partName: `/word/diagrams/drawing${i}.xml`,
3607
- contentType: "application/vnd.ms-office.drawingml.diagramDrawing+xml"
3608
- });
3609
- }
3610
- if (extras.hasBibliography) overrides.push({
3611
- partName: "/word/bibliography.xml",
3612
- contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.bibliography+xml"
3613
- });
3614
- if (extras.hasGlossary) overrides.push({
3615
- partName: "/word/glossary/document.xml",
3616
- contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.glossary+xml"
3617
- });
3618
- if (extras.hasWebSettings) overrides.push({
3619
- partName: "/word/webSettings.xml",
3620
- contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml"
3621
- });
3622
- for (const ac of extras.altChunks ?? []) overrides.push({
3623
- partName: ac.path.startsWith("/") ? ac.path : `/${ac.path}`,
3624
- contentType: ac.contentType
3625
- });
3626
- for (const sd of extras.subDocs ?? []) overrides.push({
3627
- partName: sd.path.startsWith("/") ? sd.path : `/${sd.path}`,
3628
- contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"
3629
- });
3630
- return {
3631
- defaults,
3632
- overrides
3633
- };
3634
- }
3635
4076
  //#endregion
3636
- //#region src/parts/relationships.ts
3637
- const relationshipsDesc = {
4077
+ //#region src/parts/bibliography.ts
4078
+ function escapeXml$2(s) {
4079
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
4080
+ }
4081
+ const SOURCE_FIELDS = [
4082
+ ["SourceType", "type"],
4083
+ ["Title", "title"],
4084
+ ["Author", "author"],
4085
+ ["Year", "year"],
4086
+ ["Month", "month"],
4087
+ ["Day", "day"],
4088
+ ["BookTitle", "bookTitle"],
4089
+ ["JournalName", "journal"],
4090
+ ["Volume", "volume"],
4091
+ ["Issue", "issue"],
4092
+ ["Pages", "pages"],
4093
+ ["Publisher", "publisher"],
4094
+ ["City", "city"],
4095
+ ["URL", "url"],
4096
+ ["Edition", "edition"],
4097
+ ["Institution", "institution"]
4098
+ ];
4099
+ const bibliographyDesc = {
3638
4100
  kind: "custom",
3639
4101
  stringify(opts, _ctx) {
3640
- const p = ["<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">"];
3641
- for (const rel of opts.relationships) {
3642
- const targetModeAttr = rel.targetMode ? ` TargetMode="${escapeXml(rel.targetMode)}"` : "";
3643
- p.push(`<Relationship Id="rId${rel.id}" Type="${escapeXml(rel.type)}" Target="${escapeXml(rel.target)}"${targetModeAttr}/>`);
4102
+ const attrParts = ["xmlns:b=\"http://schemas.openxmlformats.org/officeDocument/2006/bibliography\""];
4103
+ if (opts.styleName !== void 0) attrParts.push(`StyleName="${escapeXml$2(opts.styleName)}"`);
4104
+ const parts = [`<b:Sources ${attrParts.join(" ")}>`];
4105
+ for (const source of opts.sources) {
4106
+ const sourceParts = [];
4107
+ for (const [tagName, key] of SOURCE_FIELDS) {
4108
+ const value = source[key];
4109
+ if (value !== void 0) sourceParts.push(`<b:${tagName}>${escapeXml$2(value)}</b:${tagName}>`);
4110
+ }
4111
+ parts.push(`<b:Source>${sourceParts.join("")}</b:Source>`);
3644
4112
  }
3645
- p.push("</Relationships>");
3646
- return p.join("");
4113
+ parts.push("</b:Sources>");
4114
+ return parts.join("");
3647
4115
  },
3648
4116
  parse(el, _ctx) {
3649
- const relationships = [];
4117
+ const opts = {};
4118
+ const styleName = el.attributes?.["StyleName"];
4119
+ if (styleName) opts.styleName = styleName;
4120
+ const sources = [];
3650
4121
  for (const child of el.elements ?? []) {
3651
- if (child.name !== "Relationship") continue;
3652
- const id = child.attributes?.["Id"];
3653
- const type = child.attributes?.["Type"];
3654
- const target = child.attributes?.["Target"];
3655
- const targetMode = child.attributes?.["TargetMode"];
3656
- if (id && type && target) {
3657
- const numId = String(id).replace("rId", "");
3658
- relationships.push({
3659
- id: Number(numId) || id,
3660
- type: String(type),
3661
- target: String(target),
3662
- targetMode: targetMode ? String(targetMode) : void 0
3663
- });
4122
+ if (child.name !== "b:Source") continue;
4123
+ const source = {};
4124
+ for (const [, key] of SOURCE_FIELDS) {
4125
+ const xmlChild = findChild(child, `b:${SOURCE_FIELDS.find((f) => f[1] === key)[0]}`);
4126
+ if (xmlChild) {
4127
+ const val = textOf(xmlChild);
4128
+ if (val) source[key] = val;
4129
+ }
3664
4130
  }
4131
+ sources.push(source);
3665
4132
  }
3666
- return { relationships };
4133
+ opts.sources = sources;
4134
+ return opts;
3667
4135
  }
3668
4136
  };
3669
4137
  //#endregion
3670
- //#region src/parts/bodychildren.ts
3671
- /**
3672
- * Body-level child descriptors for DOCX.
3673
- *
3674
- * Provides descriptor-based stringification for section children.
3675
- * All types use pure string builders — zero class instantiation, zero toXml().
3676
- *
3677
- * @module
3678
- */
3679
- function escapeAttr(s) {
3680
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
3681
- }
3682
- const ALTCHUNK_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk";
3683
- function wrapHtmlDocument(fragment) {
3684
- if (/<(!DOCTYPE|html|HTML)/i.test(fragment)) return fragment;
3685
- return `<!DOCTYPE html>\n<html><head><meta charset="utf-8"></head>\n<body>${fragment}</body></html>`;
3686
- }
3687
- const altChunkDesc = {
3688
- kind: "custom",
3689
- stringify(opts, ctx) {
3690
- const relId = uniqueId();
3691
- const extension = opts.extension;
3692
- const partPath = `afchunks/afchunk${relId}.${extension}`;
3693
- const rawData = typeof opts.data === "string" ? new TextEncoder().encode(opts.data) : opts.data;
3694
- const data = opts.contentType === "text/html" && typeof opts.data === "string" ? new TextEncoder().encode(wrapHtmlDocument(opts.data)) : rawData;
3695
- ctx.fileData.document.relationships.addRelationship(relId, ALTCHUNK_REL_TYPE, partPath);
3696
- ctx.fileData.altChunks.addAltChunk(relId, {
3697
- key: relId,
3698
- data,
3699
- path: partPath,
3700
- extension,
3701
- contentType: opts.contentType
3702
- });
3703
- const rId = `rId${relId}`;
3704
- if (opts.matchSrc) return `<w:altChunk r:id="${rId}"><w:altChunkPr><w:matchSrc/></w:altChunkPr></w:altChunk>`;
3705
- return `<w:altChunk r:id="${rId}"/>`;
3706
- },
3707
- parse() {
3708
- return {};
3709
- }
4138
+ //#region src/parts/glossary-document.ts
4139
+ /** Gallery type for building blocks (ST_DocPartGallery) */
4140
+ const DocPartGallery = {
4141
+ PLACEHOLDER: "placeholder",
4142
+ DEFAULT: "default",
4143
+ DOC_PARTS: "docParts",
4144
+ COVER_PAGE: "coverPg",
4145
+ EQUATIONS: "eq",
4146
+ FOOTERS: "ftrs",
4147
+ HEADERS: "hdrs",
4148
+ PAGE_NUMBERS: "pgNum",
4149
+ TABLES: "tbls",
4150
+ WATERMARKS: "watermarks",
4151
+ AUTO_TEXT: "autoTxt",
4152
+ TEXT_BOX: "txtBox",
4153
+ PAGE_NUMBERS_TOP: "pgNumT",
4154
+ PAGE_NUMBERS_BOTTOM: "pgNumB",
4155
+ PAGE_NUMBERS_MARGIN: "pgNumMargins",
4156
+ TABLE_OF_CONTENTS: "tblOfContents",
4157
+ BIBLIOGRAPHY: "bib",
4158
+ CUSTOM_QUICK_PARTS: "custQuickParts",
4159
+ CUSTOM_COVER_PAGE: "custCoverPg",
4160
+ CUSTOM_EQUATIONS: "custEq",
4161
+ CUSTOM_FOOTERS: "custFtrs",
4162
+ CUSTOM_HEADERS: "custHdrs",
4163
+ CUSTOM_PAGE_NUMBERS: "custPgNum",
4164
+ CUSTOM_TABLES: "custTbls",
4165
+ CUSTOM_WATERMARKS: "custWatermarks",
4166
+ CUSTOM_AUTO_TEXT: "custAutoTxt",
4167
+ CUSTOM_TEXT_BOX: "custTxtBox",
4168
+ CUSTOM_PAGE_NUMBERS_TOP: "custPgNumT",
4169
+ CUSTOM_PAGE_NUMBERS_BOTTOM: "custPgNumB",
4170
+ CUSTOM_PAGE_NUMBERS_MARGIN: "custPgNumMargins",
4171
+ CUSTOM_TABLE_OF_CONTENTS: "custTblOfContents",
4172
+ CUSTOM_BIBLIOGRAPHY: "custBib",
4173
+ CUSTOM1: "custom1",
4174
+ CUSTOM2: "custom2",
4175
+ CUSTOM3: "custom3",
4176
+ CUSTOM4: "custom4",
4177
+ CUSTOM5: "custom5"
3710
4178
  };
3711
- const SUBDOC_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/subDocument";
3712
- const subDocDesc = {
3713
- kind: "custom",
3714
- stringify(opts, ctx) {
3715
- const relId = uniqueId();
3716
- const partPath = `subdocs/subdoc${relId}.docx`;
3717
- const data = typeof opts.data === "string" ? new TextEncoder().encode(opts.data) : opts.data;
3718
- ctx.fileData.document.relationships.addRelationship(relId, SUBDOC_REL_TYPE, partPath);
3719
- ctx.fileData.subDocs.addSubDoc(relId, {
3720
- data,
3721
- path: partPath
3722
- });
3723
- return `<w:subDoc r:id="rId${relId}"/>`;
3724
- },
3725
- parse() {
3726
- return {};
3727
- }
4179
+ /** Building block type (ST_DocPartType) */
4180
+ const DocPartType = {
4181
+ NONE: "none",
4182
+ NORMAL: "normal",
4183
+ AUTO_EXPAND: "autoExp",
4184
+ TOOLBAR: "toolbar",
4185
+ SPELLER: "speller",
4186
+ FORM_FIELD: "formFld",
4187
+ BUILDING_BLOCK_PLACEHOLDER: "bbPlcHdr"
3728
4188
  };
3729
- function escapeXml$1(s) {
3730
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
3731
- }
3732
- function sdtListItemXml(item, forceValue) {
3733
- const attrs = [];
3734
- if (item.displayText !== void 0) attrs.push(`w:displayText="${escapeXml$1(item.displayText)}"`);
3735
- const value = item.value ?? (forceValue ? item.displayText : void 0);
3736
- if (value !== void 0) attrs.push(`w:value="${escapeXml$1(value)}"`);
3737
- return `<w:listItem ${attrs.join(" ")}/>`;
3738
- }
3739
- function sdtListTypeXml(name, options) {
3740
- const parts = [];
3741
- if (options.items) for (const item of options.items) parts.push(sdtListItemXml(item, name === "w:dropDownList"));
3742
- const attrs = [];
3743
- if (options.lastValue !== void 0) attrs.push(`w:lastValue="${escapeXml$1(options.lastValue)}"`);
3744
- const attrStr = attrs.length ? " " + attrs.join(" ") : "";
3745
- return parts.length ? `<${name}${attrStr}>${parts.join("")}</${name}>` : `<${name}${attrStr}/>`;
3746
- }
3747
- function sdtDateXml(options) {
3748
- const parts = [];
3749
- if (options.dateFormat !== void 0) parts.push(`<w:dateFormat w:val="${escapeXml$1(options.dateFormat)}"/>`);
3750
- if (options.languageId !== void 0) parts.push(`<w:lid w:val="${escapeXml$1(options.languageId)}"/>`);
3751
- if (options.storeMappedDataAs !== void 0) parts.push(`<w:storeMappedDataAs w:val="${options.storeMappedDataAs}"/>`);
3752
- if (options.calendar !== void 0) parts.push(`<w:calendar w:val="${options.calendar}"/>`);
3753
- const attrs = [];
3754
- if (options.fullDate !== void 0) attrs.push(`w:fullDate="${options.fullDate}"`);
3755
- const attrStr = attrs.length ? " " + attrs.join(" ") : "";
3756
- return parts.length ? `<w:date${attrStr}>${parts.join("")}</w:date>` : `<w:date${attrStr}/>`;
3757
- }
3758
- function sdtDataBindingXml(options) {
3759
- const attrs = [`w:xpath="${escapeXml$1(options.xpath)}"`, `w:storeItemID="${escapeXml$1(options.storeItemID)}"`];
3760
- if (options.prefixMappings !== void 0) attrs.push(`w:prefixMappings="${escapeXml$1(options.prefixMappings)}"`);
3761
- return `<w:dataBinding ${attrs.join(" ")}/>`;
3762
- }
3763
- function sdtDocPartXml(name, options) {
3764
- const parts = [];
3765
- if (options.gallery !== void 0) parts.push(`<w:docPartGallery w:val="${escapeXml$1(options.gallery)}"/>`);
3766
- if (options.category !== void 0) parts.push(`<w:docPartCategory w:val="${escapeXml$1(options.category)}"/>`);
3767
- if (options.unique !== void 0) parts.push(options.unique ? "<w:docPartUnique/>" : "<w:docPartUnique w:val=\"0\"/>");
3768
- return parts.length ? `<${name}>${parts.join("")}</${name}>` : `<${name}/>`;
3769
- }
3770
- function onOffAttr(name, val) {
3771
- return val ? `<${name}/>` : `<${name} w:val="0"/>`;
4189
+ /** Building block behavior (ST_DocPartBehavior) */
4190
+ const DocPartBehavior = {
4191
+ CONTENT: "content",
4192
+ PARAGRAPH: "p",
4193
+ PAGE: "pg"
4194
+ };
4195
+ const GLOSSARY_NS = "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: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: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\"";
4196
+ function glossaryEscapeAttr(text) {
4197
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
3772
4198
  }
3773
- function stringifySdtPr(opts) {
3774
- const parts = [];
3775
- if (opts.alias !== void 0) parts.push(`<w:alias w:val="${escapeXml$1(opts.alias)}"/>`);
3776
- if (opts.tag !== void 0) parts.push(`<w:tag w:val="${escapeXml$1(opts.tag)}"/>`);
3777
- if (opts.id !== void 0) parts.push(`<w:id w:val="${opts.id}"/>`);
3778
- if (opts.lock !== void 0) parts.push(`<w:lock w:val="${opts.lock}"/>`);
3779
- if (opts.temporary !== void 0) parts.push(onOffAttr("w:temporary", opts.temporary));
3780
- const effectiveShowingPlcHdr = opts.showingPlaceholder ?? false;
3781
- if (opts.showingPlaceholder !== void 0 || effectiveShowingPlcHdr) parts.push(onOffAttr("w:showingPlcHdr", effectiveShowingPlcHdr));
3782
- if (opts.dataBinding) parts.push(sdtDataBindingXml(opts.dataBinding));
3783
- if (opts.label !== void 0) parts.push(`<w:label w:val="${opts.label}"/>`);
3784
- if (opts.tabIndex !== void 0) parts.push(`<w:tabIndex w:val="${opts.tabIndex}"/>`);
3785
- if (opts.equation) parts.push("<w:equation/>");
3786
- else if (opts.comboBox) parts.push(sdtListTypeXml("w:comboBox", opts.comboBox));
3787
- else if (opts.date) parts.push(sdtDateXml(opts.date));
3788
- else if (opts.docPartObj) parts.push(sdtDocPartXml("w:docPartObj", opts.docPartObj));
3789
- else if (opts.docPartList) parts.push(sdtDocPartXml("w:docPartList", opts.docPartList));
3790
- else if (opts.dropDownList) parts.push(sdtListTypeXml("w:dropDownList", opts.dropDownList));
3791
- else if (opts.picture) parts.push("<w:picture/>");
3792
- else if (opts.richText) parts.push("<w:richText/>");
3793
- else if (opts.text !== void 0) {
3794
- const multiLine = opts.text.multiLine ?? false;
3795
- parts.push(`<w:text w:multiLine="${multiLine}"/>`);
3796
- } else if (opts.citation) parts.push("<w:citation/>");
3797
- else if (opts.group) parts.push("<w:group/>");
3798
- else if (opts.bibliography) parts.push("<w:bibliography/>");
3799
- return parts.length ? `<w:sdtPr>${parts.join("")}</w:sdtPr>` : "<w:sdtPr/>";
4199
+ function docPartPrXml(part) {
4200
+ const prParts = [];
4201
+ prParts.push(`<w:name w:val="${glossaryEscapeAttr(part.name)}"${part.decorated ? " w:decorated=\"1\"" : ""}/>`);
4202
+ if (part.category || part.gallery) {
4203
+ const catParts = [];
4204
+ if (part.category) catParts.push(`<w:name w:val="${glossaryEscapeAttr(part.category)}"/>`);
4205
+ catParts.push(`<w:gallery w:val="${part.gallery}"/>`);
4206
+ prParts.push(`<w:category>${catParts.join("")}</w:category>`);
4207
+ }
4208
+ if (part.types && part.types.length > 0) {
4209
+ const typeXml = part.types.map((t) => `<w:type w:val="${t}"/>`).join("");
4210
+ const allAttr = part.allTypes ? " w:all=\"1\"" : "";
4211
+ prParts.push(`<w:types${allAttr}>${typeXml}</w:types>`);
4212
+ }
4213
+ if (part.behaviors && part.behaviors.length > 0) {
4214
+ const behaviorXml = part.behaviors.map((b) => `<w:behavior w:val="${b}"/>`).join("");
4215
+ prParts.push(`<w:behaviors>${behaviorXml}</w:behaviors>`);
4216
+ }
4217
+ if (part.description) prParts.push(`<w:description w:val="${glossaryEscapeAttr(part.description)}"/>`);
4218
+ if (part.guid) prParts.push(`<w:guid w:val="${glossaryEscapeAttr(part.guid)}"/>`);
4219
+ return `<w:docPartPr>${prParts.join("")}</w:docPartPr>`;
3800
4220
  }
3801
- const sdtBlockDesc = {
4221
+ const glossaryDesc = {
3802
4222
  kind: "custom",
3803
4223
  stringify(opts, ctx) {
3804
- const parts = ["<w:sdt>"];
3805
- parts.push(stringifySdtPr(opts.properties));
3806
- parts.push("<w:sdtEndPr/>");
3807
- if (opts.children && opts.children.length > 0) {
3808
- const contentParts = [];
3809
- for (const child of opts.children) contentParts.push(ctx.stringifyChild(child, ctx));
3810
- const contentBody = contentParts.join("");
3811
- parts.push(contentBody ? `<w:sdtContent>${contentBody}</w:sdtContent>` : "<w:sdtContent/>");
3812
- }
3813
- parts.push("</w:sdt>");
3814
- return parts.join("");
4224
+ return `<w:glossaryDocument ${GLOSSARY_NS}><w:docParts>${opts.parts.map((part) => {
4225
+ const bodyContent = (part.children ?? []).map((child) => ctx.stringifyChild(child, ctx)).join("");
4226
+ return `<w:docPart>${docPartPrXml(part)}<w:docPartBody>${bodyContent}</w:docPartBody></w:docPart>`;
4227
+ }).join("")}</w:docParts></w:glossaryDocument>`;
3815
4228
  },
3816
- parse() {
3817
- return {};
4229
+ parse(el, ctx) {
4230
+ const dctx = ctx;
4231
+ const parts = [];
4232
+ const docPartsEl = findChild(el, "w:docParts");
4233
+ if (!docPartsEl) return { parts };
4234
+ for (const docPart of docPartsEl.elements ?? []) {
4235
+ if (docPart.name !== "w:docPart") continue;
4236
+ const part = {};
4237
+ const pr = findChild(docPart, "w:docPartPr");
4238
+ if (pr) {
4239
+ const name = findChild(pr, "w:name");
4240
+ if (name) {
4241
+ part.name = attr(name, "w:val") ?? "";
4242
+ if (attr(name, "w:decorated") === "1") part.decorated = true;
4243
+ }
4244
+ const category = findChild(pr, "w:category");
4245
+ if (category) {
4246
+ const catName = findChild(category, "w:name");
4247
+ if (catName) part.category = attr(catName, "w:val");
4248
+ const gallery = findChild(category, "w:gallery");
4249
+ if (gallery) part.gallery = attr(gallery, "w:val");
4250
+ }
4251
+ const types = findChild(pr, "w:types");
4252
+ if (types) {
4253
+ const typeList = [];
4254
+ for (const t of types.elements ?? []) if (t.name === "w:type") {
4255
+ const val = attr(t, "w:val");
4256
+ if (val) typeList.push(val);
4257
+ }
4258
+ if (typeList.length > 0) part.types = typeList;
4259
+ if (attr(types, "w:all") === "1") part.allTypes = true;
4260
+ }
4261
+ const behaviors = findChild(pr, "w:behaviors");
4262
+ if (behaviors) {
4263
+ const behaviorList = [];
4264
+ for (const b of behaviors.elements ?? []) if (b.name === "w:behavior") {
4265
+ const val = attr(b, "w:val");
4266
+ if (val) behaviorList.push(val);
4267
+ }
4268
+ if (behaviorList.length > 0) part.behaviors = behaviorList;
4269
+ }
4270
+ const desc = findChild(pr, "w:description");
4271
+ if (desc) {
4272
+ const val = attr(desc, "w:val");
4273
+ if (val) part.description = val;
4274
+ }
4275
+ const guid = findChild(pr, "w:guid");
4276
+ if (guid) {
4277
+ const val = attr(guid, "w:val");
4278
+ if (val) part.guid = val;
4279
+ }
4280
+ }
4281
+ const body = findChild(docPart, "w:docPartBody");
4282
+ if (body) {
4283
+ const childList = [];
4284
+ for (const sub of body.elements ?? []) if (sub.name === "w:p") childList.push({ paragraph: parseParagraph(sub, dctx) });
4285
+ if (childList.length > 0) part.children = childList;
4286
+ }
4287
+ parts.push(part);
4288
+ }
4289
+ return { parts };
3818
4290
  }
3819
4291
  };
3820
- function buildCustomXmlPrXml(pr) {
3821
- const parts = ["<w:customXmlPr>"];
3822
- if (pr.placeholder !== void 0) parts.push(`<w:placeholder w:val="${escapeAttr(pr.placeholder)}"/>`);
3823
- if (pr.attributes) for (const attr of pr.attributes) {
3824
- const attrParts = [`w:name="${escapeAttr(attr.name)}"`, `w:val="${escapeAttr(attr.val)}"`];
3825
- if (attr.uri !== void 0) attrParts.push(`w:uri="${escapeAttr(attr.uri)}"`);
3826
- parts.push(`<w:attr ${attrParts.join(" ")}/>`);
3827
- }
3828
- parts.push("</w:customXmlPr>");
3829
- return parts.join("");
4292
+ //#endregion
4293
+ //#region src/parts/comments.ts
4294
+ function escapeAttr$1(s) {
4295
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
3830
4296
  }
3831
- const customXmlBlockDesc = {
4297
+ const COMMENTS_NS = "xmlns:aink=\"http://schemas.microsoft.com/office/drawing/2016/ink\" xmlns:am3d=\"http://schemas.microsoft.com/office/drawing/2017/model3d\" xmlns:cx=\"http://schemas.microsoft.com/office/drawing/2014/chartex\" xmlns:cx1=\"http://schemas.microsoft.com/office/drawing/2015/9/8/chartex\" xmlns:cx2=\"http://schemas.microsoft.com/office/drawing/2015/10/21/chartex\" xmlns:cx3=\"http://schemas.microsoft.com/office/drawing/2016/5/9/chartex\" xmlns:cx4=\"http://schemas.microsoft.com/office/drawing/2016/5/10/chartex\" xmlns:cx5=\"http://schemas.microsoft.com/office/drawing/2016/5/11/chartex\" xmlns:cx6=\"http://schemas.microsoft.com/office/drawing/2016/5/12/chartex\" xmlns:cx7=\"http://schemas.microsoft.com/office/drawing/2016/5/13/chartex\" xmlns:cx8=\"http://schemas.microsoft.com/office/drawing/2016/5/14/chartex\" xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\" 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:v=\"urn:schemas-microsoft-com:vml\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:w10=\"urn:schemas-microsoft-com:office:word\" xmlns:w14=\"http://schemas.microsoft.com/office/word/2010/wordml\" xmlns:w15=\"http://schemas.microsoft.com/office/word/2012/wordml\" xmlns:w16=\"http://schemas.microsoft.com/office/word/2018/wordml\" xmlns:w16cex=\"http://schemas.microsoft.com/office/word/2018/wordml/cex\" xmlns:w16cid=\"http://schemas.microsoft.com/office/word/2016/wordml/cid\" xmlns:w16sdtdh=\"http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash\" xmlns:w16se=\"http://schemas.microsoft.com/office/word/2015/wordml/symex\" xmlns:wne=\"http://schemas.openxmlformats.org/office/word/2006/wordml\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" xmlns:wp14=\"http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing\" xmlns:wpg=\"http://schemas.microsoft.com/office/word/2010/wordprocessingGroup\" xmlns:wpi=\"http://schemas.microsoft.com/office/word/2010/wordprocessingInk\" xmlns:wps=\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\"";
4298
+ function stringifyComment(opts, ctx) {
4299
+ const dateStr = typeof opts.date === "string" ? opts.date : (opts.date ?? /* @__PURE__ */ new Date()).toISOString();
4300
+ const attrs = [`w:id="${opts.id}"`, `w:date="${escapeAttr$1(dateStr)}"`];
4301
+ if (opts.author !== void 0) attrs.push(`w:author="${escapeAttr$1(opts.author)}"`);
4302
+ if (opts.initials !== void 0) attrs.push(`w:initials="${escapeAttr$1(opts.initials)}"`);
4303
+ const parts = [];
4304
+ for (const child of opts.children) parts.push(stringifyParagraphInline(child, ctx));
4305
+ return `<w:comment ${attrs.join(" ")}>${parts.join("")}</w:comment>`;
4306
+ }
4307
+ const commentsDesc = {
3832
4308
  kind: "custom",
3833
4309
  stringify(opts, ctx) {
3834
- const attrs = [`w:element="${escapeAttr(opts.element)}"`];
3835
- if (opts.uri !== void 0) attrs.push(`w:uri="${escapeAttr(opts.uri)}"`);
3836
- const parts = [`<w:customXml ${attrs.join(" ")}>`];
3837
- if (opts.customXmlPr) parts.push(buildCustomXmlPrXml(opts.customXmlPr));
3838
- if (opts.children) for (const child of opts.children) parts.push(ctx.stringifyChild(child, ctx));
3839
- parts.push("</w:customXml>");
4310
+ const parts = [`<w:comments ${COMMENTS_NS}>`];
4311
+ for (const child of opts.children) parts.push(stringifyComment(child, ctx));
4312
+ parts.push("</w:comments>");
3840
4313
  return parts.join("");
3841
4314
  },
3842
- parse() {
3843
- return {};
4315
+ parse(el, ctx) {
4316
+ const comments = [];
4317
+ for (const child of el.elements ?? []) {
4318
+ if (child.name !== "w:comment") continue;
4319
+ const id = attrNum(child, "w:id");
4320
+ if (id === void 0) continue;
4321
+ const comment = { id };
4322
+ const date = attr(child, "w:date");
4323
+ if (date) comment.date = date;
4324
+ const author = attr(child, "w:author");
4325
+ if (author) comment.author = author;
4326
+ const initials = attr(child, "w:initials");
4327
+ if (initials) comment.initials = initials;
4328
+ const children = [];
4329
+ for (const sub of child.elements ?? []) if (sub.name === "w:p") children.push(parseParagraph(sub, ctx));
4330
+ comment.children = children;
4331
+ comments.push(comment);
4332
+ }
4333
+ return { children: comments };
3844
4334
  }
3845
4335
  };
3846
4336
  //#endregion
3847
- //#region src/parts/core-properties.ts
3848
- const corePropertiesDesc = {
4337
+ //#region src/parts/contenttypes.ts
4338
+ function defaultXml(ext, ct) {
4339
+ return `<Default Extension="${ext}" ContentType="${ct}"/>`;
4340
+ }
4341
+ function overrideXml(partName, ct) {
4342
+ return `<Override PartName="${partName}" ContentType="${ct}"/>`;
4343
+ }
4344
+ const contentTypesDesc = {
3849
4345
  kind: "custom",
3850
4346
  stringify(opts, _ctx) {
3851
- const now = (/* @__PURE__ */ new Date()).toISOString();
3852
- const p = ["<cp:coreProperties xmlns:cp=\"http://schemas.openxmlformats.org/package/2006/metadata/core-properties\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:dcterms=\"http://purl.org/dc/terms/\" xmlns:dcmitype=\"http://purl.org/dc/dcmitype/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"];
3853
- if (opts.title) p.push(`<dc:title>${escapeXml(opts.title)}</dc:title>`);
3854
- if (opts.subject) p.push(`<dc:subject>${escapeXml(opts.subject)}</dc:subject>`);
3855
- if (opts.creator) p.push(`<dc:creator>${escapeXml(opts.creator)}</dc:creator>`);
3856
- if (opts.keywords) p.push(`<cp:keywords>${escapeXml(opts.keywords)}</cp:keywords>`);
3857
- if (opts.description) p.push(`<dc:description>${escapeXml(opts.description)}</dc:description>`);
3858
- if (opts.lastModifiedBy) p.push(`<cp:lastModifiedBy>${escapeXml(opts.lastModifiedBy)}</cp:lastModifiedBy>`);
3859
- if (opts.revision !== void 0) p.push(`<cp:revision>${opts.revision}</cp:revision>`);
3860
- p.push(`<dcterms:created xsi:type="dcterms:W3CDTF">${now}</dcterms:created>`);
3861
- p.push(`<dcterms:modified xsi:type="dcterms:W3CDTF">${now}</dcterms:modified>`);
3862
- p.push("</cp:coreProperties>");
4347
+ const p = ["<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">"];
4348
+ for (const d of opts.defaults) p.push(defaultXml(d.extension, d.contentType));
4349
+ for (const o of opts.overrides) p.push(overrideXml(o.partName, o.contentType));
4350
+ p.push("</Types>");
3863
4351
  return p.join("");
3864
4352
  },
3865
4353
  parse(el, _ctx) {
3866
- const result = {};
3867
- for (const child of el.elements ?? []) {
3868
- if (typeof child.name !== "string") continue;
3869
- const text = child.elements?.[0]?.text;
3870
- if (typeof text !== "string") continue;
3871
- switch (child.name) {
3872
- case "dc:title":
3873
- result.title = text;
3874
- break;
3875
- case "dc:subject":
3876
- result.subject = text;
3877
- break;
3878
- case "dc:creator":
3879
- result.creator = text;
3880
- break;
3881
- case "cp:keywords":
3882
- result.keywords = text;
3883
- break;
3884
- case "dc:description":
3885
- result.description = text;
3886
- break;
3887
- case "cp:lastModifiedBy":
3888
- result.lastModifiedBy = text;
3889
- break;
3890
- case "cp:revision":
3891
- result.revision = Number(text);
3892
- break;
3893
- }
4354
+ const defaults = [];
4355
+ const overrides = [];
4356
+ for (const child of el.elements ?? []) if (child.name === "Default") {
4357
+ const ext = child.attributes?.["Extension"];
4358
+ const ct = child.attributes?.["ContentType"];
4359
+ if (ext && ct) defaults.push({
4360
+ extension: String(ext),
4361
+ contentType: String(ct)
4362
+ });
4363
+ } else if (child.name === "Override") {
4364
+ const pn = child.attributes?.["PartName"];
4365
+ const ct = child.attributes?.["ContentType"];
4366
+ if (pn && ct) overrides.push({
4367
+ partName: String(pn),
4368
+ contentType: String(ct)
4369
+ });
3894
4370
  }
3895
- return result;
4371
+ return {
4372
+ defaults,
4373
+ overrides
4374
+ };
4375
+ }
4376
+ };
4377
+ /** Helper to build the standard DOCX content types with dynamic overrides. */
4378
+ function buildContentTypes(extras = {}) {
4379
+ const defaults = [
4380
+ {
4381
+ extension: "png",
4382
+ contentType: "image/png"
4383
+ },
4384
+ {
4385
+ extension: "jpeg",
4386
+ contentType: "image/jpeg"
4387
+ },
4388
+ {
4389
+ extension: "jpg",
4390
+ contentType: "image/jpeg"
4391
+ },
4392
+ {
4393
+ extension: "bmp",
4394
+ contentType: "image/bmp"
4395
+ },
4396
+ {
4397
+ extension: "gif",
4398
+ contentType: "image/gif"
4399
+ },
4400
+ {
4401
+ extension: "tif",
4402
+ contentType: "image/tiff"
4403
+ },
4404
+ {
4405
+ extension: "tiff",
4406
+ contentType: "image/tiff"
4407
+ },
4408
+ {
4409
+ extension: "emf",
4410
+ contentType: "image/x-emf"
4411
+ },
4412
+ {
4413
+ extension: "wmf",
4414
+ contentType: "image/x-wmf"
4415
+ },
4416
+ {
4417
+ extension: "ico",
4418
+ contentType: "image/x-icon"
4419
+ },
4420
+ {
4421
+ extension: "svg",
4422
+ contentType: "image/svg+xml"
4423
+ },
4424
+ {
4425
+ extension: "rels",
4426
+ contentType: "application/vnd.openxmlformats-package.relationships+xml"
4427
+ },
4428
+ {
4429
+ extension: "xml",
4430
+ contentType: "application/xml"
4431
+ },
4432
+ {
4433
+ extension: "odttf",
4434
+ contentType: "application/vnd.openxmlformats-officedocument.obfuscatedFont"
4435
+ }
4436
+ ];
4437
+ const overrides = [
4438
+ {
4439
+ partName: "/word/document.xml",
4440
+ contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"
4441
+ },
4442
+ {
4443
+ partName: "/word/styles.xml",
4444
+ contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"
4445
+ },
4446
+ {
4447
+ partName: "/docProps/core.xml",
4448
+ contentType: "application/vnd.openxmlformats-package.core-properties+xml"
4449
+ },
4450
+ {
4451
+ partName: "/docProps/custom.xml",
4452
+ contentType: "application/vnd.openxmlformats-officedocument.custom-properties+xml"
4453
+ },
4454
+ {
4455
+ partName: "/docProps/app.xml",
4456
+ contentType: "application/vnd.openxmlformats-officedocument.extended-properties+xml"
4457
+ },
4458
+ {
4459
+ partName: "/word/numbering.xml",
4460
+ contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml"
4461
+ },
4462
+ {
4463
+ partName: "/word/footnotes.xml",
4464
+ contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml"
4465
+ },
4466
+ {
4467
+ partName: "/word/endnotes.xml",
4468
+ contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml"
4469
+ },
4470
+ {
4471
+ partName: "/word/settings.xml",
4472
+ contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"
4473
+ },
4474
+ {
4475
+ partName: "/word/comments.xml",
4476
+ contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml"
4477
+ },
4478
+ {
4479
+ partName: "/word/fontTable.xml",
4480
+ contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"
4481
+ }
4482
+ ];
4483
+ for (let i = 1; i <= (extras.headerCount ?? 0); i++) overrides.push({
4484
+ partName: `/word/header${i}.xml`,
4485
+ contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml"
4486
+ });
4487
+ for (let i = 1; i <= (extras.footerCount ?? 0); i++) overrides.push({
4488
+ partName: `/word/footer${i}.xml`,
4489
+ contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml"
4490
+ });
4491
+ for (let i = 1; i <= (extras.chartCount ?? 0); i++) overrides.push({
4492
+ partName: `/word/charts/chart${i}.xml`,
4493
+ contentType: "application/vnd.openxmlformats-officedocument.drawingml.chart+xml"
4494
+ });
4495
+ for (let i = 1; i <= (extras.smartArtCount ?? 0); i++) {
4496
+ overrides.push({
4497
+ partName: `/word/diagrams/data${i}.xml`,
4498
+ contentType: "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml"
4499
+ });
4500
+ overrides.push({
4501
+ partName: `/word/diagrams/layout${i}.xml`,
4502
+ contentType: "application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml"
4503
+ });
4504
+ overrides.push({
4505
+ partName: `/word/diagrams/quickStyle${i}.xml`,
4506
+ contentType: "application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml"
4507
+ });
4508
+ overrides.push({
4509
+ partName: `/word/diagrams/colors${i}.xml`,
4510
+ contentType: "application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml"
4511
+ });
4512
+ overrides.push({
4513
+ partName: `/word/diagrams/drawing${i}.xml`,
4514
+ contentType: "application/vnd.ms-office.drawingml.diagramDrawing+xml"
4515
+ });
3896
4516
  }
3897
- };
4517
+ if (extras.hasBibliography) overrides.push({
4518
+ partName: "/word/bibliography.xml",
4519
+ contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.bibliography+xml"
4520
+ });
4521
+ if (extras.hasGlossary) overrides.push({
4522
+ partName: "/word/glossary/document.xml",
4523
+ contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.glossary+xml"
4524
+ });
4525
+ if (extras.hasWebSettings) overrides.push({
4526
+ partName: "/word/webSettings.xml",
4527
+ contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml"
4528
+ });
4529
+ for (const ac of extras.altChunks ?? []) overrides.push({
4530
+ partName: ac.path.startsWith("/") ? ac.path : `/${ac.path}`,
4531
+ contentType: ac.contentType
4532
+ });
4533
+ for (const sd of extras.subDocs ?? []) overrides.push({
4534
+ partName: sd.path.startsWith("/") ? sd.path : `/${sd.path}`,
4535
+ contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"
4536
+ });
4537
+ return {
4538
+ defaults,
4539
+ overrides
4540
+ };
4541
+ }
3898
4542
  //#endregion
3899
- //#region src/parts/custom-properties.ts
3900
- const customPropertiesDesc = {
4543
+ //#region src/parts/relationships.ts
4544
+ const relationshipsDesc = {
3901
4545
  kind: "custom",
3902
4546
  stringify(opts, _ctx) {
3903
- const p = ["<Properties xmlns=\"http://schemas.openxmlformats.org/officeDocument/2006/custom-properties\" xmlns:vt=\"http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes\">"];
3904
- let pid = 2;
3905
- for (const prop of opts.properties) {
3906
- p.push(`<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="${pid}" name="${escapeXml(prop.name)}"><vt:lpwstr>${escapeXml(prop.value)}</vt:lpwstr></property>`);
3907
- pid++;
4547
+ const p = ["<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">"];
4548
+ for (const rel of opts.relationships) {
4549
+ const targetModeAttr = rel.targetMode ? ` TargetMode="${escapeXml(rel.targetMode)}"` : "";
4550
+ p.push(`<Relationship Id="rId${rel.id}" Type="${escapeXml(rel.type)}" Target="${escapeXml(rel.target)}"${targetModeAttr}/>`);
3908
4551
  }
3909
- p.push("</Properties>");
4552
+ p.push("</Relationships>");
3910
4553
  return p.join("");
3911
4554
  },
3912
4555
  parse(el, _ctx) {
3913
- const properties = [];
4556
+ const relationships = [];
3914
4557
  for (const child of el.elements ?? []) {
3915
- if (child.name !== "property") continue;
3916
- const name = attr(child, "name");
3917
- if (!name) continue;
3918
- const valueEl = child.elements?.find((e) => e.name?.startsWith("vt:"));
3919
- const value = valueEl ? textOf(valueEl) ?? "" : "";
3920
- properties.push({
3921
- name,
3922
- value
3923
- });
4558
+ if (child.name !== "Relationship") continue;
4559
+ const id = child.attributes?.["Id"];
4560
+ const type = child.attributes?.["Type"];
4561
+ const target = child.attributes?.["Target"];
4562
+ const targetMode = child.attributes?.["TargetMode"];
4563
+ if (id && type && target) {
4564
+ const numId = String(id).replace("rId", "");
4565
+ relationships.push({
4566
+ id: Number(numId) || id,
4567
+ type: String(type),
4568
+ target: String(target),
4569
+ targetMode: targetMode ? String(targetMode) : void 0
4570
+ });
4571
+ }
3924
4572
  }
3925
- return { properties };
4573
+ return { relationships };
3926
4574
  }
3927
4575
  };
3928
4576
  //#endregion
3929
- //#region src/parts/web-settings.ts
4577
+ //#region src/parts/bodychildren.ts
3930
4578
  /**
3931
- * Screen size types for web settings target.
4579
+ * Body-level child descriptors for DOCX.
4580
+ *
4581
+ * Provides descriptor-based stringification for section children.
4582
+ * All types use pure string builders — zero class instantiation, zero toXml().
4583
+ *
4584
+ * @module
3932
4585
  */
3933
- const TargetScreenSize = {
3934
- SIZE_544X376: "544x376",
3935
- SIZE_640X480: "640x480",
3936
- SIZE_720X512: "720x512",
3937
- SIZE_800X600: "800x600",
3938
- SIZE_1024X768: "1024x768",
3939
- SIZE_1152X882: "1152x882",
3940
- SIZE_1152X900: "1152x900",
3941
- SIZE_1280X1024: "1280x1024",
3942
- SIZE_1600X1200: "1600x1200",
3943
- SIZE_1800X1440: "1800x1440",
3944
- SIZE_1920X1200: "1920x1200"
3945
- };
3946
- const WS_NS = "xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:w15=\"http://schemas.microsoft.com/office/word/2012/wordml\"";
3947
- function wsOnOff(tag, val) {
3948
- return `<${tag} w:val="${val ? "true" : "false"}"/>`;
3949
- }
3950
- function wsStringVal(tag, val) {
3951
- return `<${tag} w:val="${wsEscapeAttr(val)}"/>`;
3952
- }
3953
- function wsNumVal(tag, val) {
3954
- return `<${tag} w:val="${val}"/>`;
3955
- }
3956
- function wsEscapeAttr(s) {
4586
+ function escapeAttr(s) {
3957
4587
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
3958
4588
  }
3959
- function parseFramesetEl(el) {
3960
- const opts = {};
3961
- const sz = findChild(el, "w:sz");
3962
- if (sz) {
3963
- const val = attr(sz, "w:val");
3964
- if (val) opts.size = val;
3965
- }
3966
- const splitbar = findChild(el, "w:framesetSplitbar");
3967
- if (splitbar) opts.splitbar = parseSplitbarEl(splitbar);
3968
- const layout = findChild(el, "w:frameLayout");
3969
- if (layout) {
3970
- const val = attr(layout, "w:val");
3971
- if (val === "rows" || val === "cols") opts.layout = val;
3972
- }
3973
- const title = findChild(el, "w:title");
3974
- if (title) {
3975
- const val = attr(title, "w:val");
3976
- if (val) opts.title = val;
3977
- }
3978
- const children = [];
3979
- for (const child of el.elements ?? []) if (child.name === "w:frameset") children.push(parseFramesetEl(child));
3980
- else if (child.name === "w:frame") children.push(parseFrameEl(child));
3981
- if (children.length > 0) opts.children = children;
3982
- return opts;
3983
- }
3984
- function parseSplitbarEl(el) {
3985
- const opts = {};
3986
- const w = findChild(el, "w:w");
3987
- if (w) {
3988
- const val = attrNum(w, "w:w");
3989
- if (val !== void 0) opts.width = val;
3990
- }
3991
- const color = findChild(el, "w:color");
3992
- if (color) {
3993
- const val = attr(color, "w:val");
3994
- if (val) opts.color = val;
3995
- }
3996
- if (findChild(el, "w:noBorder")) opts.noBorder = true;
3997
- if (findChild(el, "w:flatBorders")) opts.flatBorders = true;
3998
- return opts;
4589
+ const ALTCHUNK_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk";
4590
+ function wrapHtmlDocument(fragment) {
4591
+ if (/<(!DOCTYPE|html|HTML)/i.test(fragment)) return fragment;
4592
+ return `<!DOCTYPE html>\n<html><head><meta charset="utf-8"></head>\n<body>${fragment}</body></html>`;
3999
4593
  }
4000
- function parseFrameEl(el) {
4001
- const opts = {};
4002
- const sz = findChild(el, "w:sz");
4003
- if (sz) {
4004
- const val = attr(sz, "w:val");
4005
- if (val) opts.size = val;
4006
- }
4007
- const name = findChild(el, "w:name");
4008
- if (name) {
4009
- const val = attr(name, "w:val");
4010
- if (val) opts.name = val;
4011
- }
4012
- const title = findChild(el, "w:title");
4013
- if (title) {
4014
- const val = attr(title, "w:val");
4015
- if (val) opts.title = val;
4016
- }
4017
- const source = findChild(el, "w:sourceFileName");
4018
- if (source) {
4019
- const val = attr(source, "r:id");
4020
- if (val) opts.sourceRId = val;
4021
- }
4022
- const marW = findChild(el, "w:marW");
4023
- if (marW) {
4024
- const val = attrNum(marW, "w:val");
4025
- if (val !== void 0) opts.marginWidth = val;
4026
- }
4027
- const marH = findChild(el, "w:marH");
4028
- if (marH) {
4029
- const val = attrNum(marH, "w:val");
4030
- if (val !== void 0) opts.marginHeight = val;
4031
- }
4032
- const scrollbar = findChild(el, "w:scrollbar");
4033
- if (scrollbar) {
4034
- const val = attr(scrollbar, "w:val");
4035
- if (val === "on" || val === "off" || val === "auto") opts.scrollbar = val;
4594
+ const altChunkDesc = {
4595
+ kind: "custom",
4596
+ stringify(opts, ctx) {
4597
+ const relId = uniqueId();
4598
+ const extension = opts.extension;
4599
+ const partPath = `afchunks/afchunk${relId}.${extension}`;
4600
+ const rawData = typeof opts.data === "string" ? new TextEncoder().encode(opts.data) : opts.data;
4601
+ const data = opts.contentType === "text/html" && typeof opts.data === "string" ? new TextEncoder().encode(wrapHtmlDocument(opts.data)) : rawData;
4602
+ ctx.fileData.document.relationships.addRelationship(relId, ALTCHUNK_REL_TYPE, partPath);
4603
+ ctx.fileData.altChunks.addAltChunk(relId, {
4604
+ key: relId,
4605
+ data,
4606
+ path: partPath,
4607
+ extension,
4608
+ contentType: opts.contentType
4609
+ });
4610
+ const rId = `rId${relId}`;
4611
+ if (opts.matchSrc) return `<w:altChunk r:id="${rId}"><w:altChunkPr><w:matchSrc/></w:altChunkPr></w:altChunk>`;
4612
+ return `<w:altChunk r:id="${rId}"/>`;
4613
+ },
4614
+ parse(el, ctx) {
4615
+ const rId = attr(el, "r:id");
4616
+ const opts = {};
4617
+ const altChunkPr = findChild(el, "w:altChunkPr");
4618
+ if (altChunkPr && findChild(altChunkPr, "w:matchSrc")) opts.matchSrc = true;
4619
+ const dctx = ctx;
4620
+ if (rId) {
4621
+ const path = dctx.resolveRelationship(rId);
4622
+ if (path) {
4623
+ const data = dctx.getRaw(path);
4624
+ if (data) {
4625
+ opts.data = data;
4626
+ switch (path.split(".").pop() ?? "txt") {
4627
+ case "html":
4628
+ opts.contentType = "text/html";
4629
+ opts.extension = "html";
4630
+ break;
4631
+ case "rtf":
4632
+ opts.contentType = "application/rtf";
4633
+ opts.extension = "rtf";
4634
+ break;
4635
+ default:
4636
+ opts.contentType = "text/plain";
4637
+ opts.extension = "txt";
4638
+ break;
4639
+ }
4640
+ }
4641
+ }
4642
+ }
4643
+ return opts;
4036
4644
  }
4037
- if (findChild(el, "w:noResizeAllowed")) opts.noResizeAllowed = true;
4038
- if (findChild(el, "w:linkedToFile")) opts.linkedToFile = true;
4039
- const longDesc = findChild(el, "w:longDesc");
4040
- if (longDesc) {
4041
- const val = attr(longDesc, "r:id");
4042
- if (val) opts.longDescRId = val;
4645
+ };
4646
+ const SUBDOC_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/subDocument";
4647
+ const subDocDesc = {
4648
+ kind: "custom",
4649
+ stringify(opts, ctx) {
4650
+ const relId = uniqueId();
4651
+ const partPath = `subdocs/subdoc${relId}.docx`;
4652
+ const data = typeof opts.data === "string" ? new TextEncoder().encode(opts.data) : opts.data;
4653
+ ctx.fileData.document.relationships.addRelationship(relId, SUBDOC_REL_TYPE, partPath);
4654
+ ctx.fileData.subDocs.addSubDoc(relId, {
4655
+ data,
4656
+ path: partPath
4657
+ });
4658
+ return `<w:subDoc r:id="rId${relId}"/>`;
4659
+ },
4660
+ parse(el, ctx) {
4661
+ const rId = attr(el, "r:id");
4662
+ const dctx = ctx;
4663
+ if (rId) {
4664
+ const path = dctx.resolveRelationship(rId);
4665
+ if (path) {
4666
+ const data = dctx.getRaw(path);
4667
+ if (data) return { data };
4668
+ }
4669
+ }
4670
+ return { data: new Uint8Array(0) };
4043
4671
  }
4044
- return opts;
4672
+ };
4673
+ function escapeXml$1(s) {
4674
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
4045
4675
  }
4046
- function parseDivsEl(el) {
4047
- const result = [];
4048
- for (const child of el.elements ?? []) if (child.name === "w:div") result.push(parseDivEl(child));
4049
- return result;
4676
+ function sdtListItemXml(item, forceValue) {
4677
+ const attrs = [];
4678
+ if (item.displayText !== void 0) attrs.push(`w:displayText="${escapeXml$1(item.displayText)}"`);
4679
+ const value = item.value ?? (forceValue ? item.displayText : void 0);
4680
+ if (value !== void 0) attrs.push(`w:value="${escapeXml$1(value)}"`);
4681
+ return `<w:listItem ${attrs.join(" ")}/>`;
4050
4682
  }
4051
- function parseDivEl(el) {
4052
- const opts = { id: attrNum(el, "w:id") ?? 0 };
4053
- const marLeft = findChild(el, "w:marLeft");
4054
- if (marLeft) {
4055
- const val = attrNum(marLeft, "w:val");
4056
- if (val !== void 0) opts.marginLeft = val;
4683
+ function sdtListTypeXml(name, options) {
4684
+ const parts = [];
4685
+ if (options.items) for (const item of options.items) parts.push(sdtListItemXml(item, name === "w:dropDownList"));
4686
+ const attrs = [];
4687
+ if (options.lastValue !== void 0) attrs.push(`w:lastValue="${escapeXml$1(options.lastValue)}"`);
4688
+ const attrStr = attrs.length ? " " + attrs.join(" ") : "";
4689
+ return parts.length ? `<${name}${attrStr}>${parts.join("")}</${name}>` : `<${name}${attrStr}/>`;
4690
+ }
4691
+ function sdtDateXml(options) {
4692
+ const parts = [];
4693
+ if (options.dateFormat !== void 0) parts.push(`<w:dateFormat w:val="${escapeXml$1(options.dateFormat)}"/>`);
4694
+ if (options.languageId !== void 0) parts.push(`<w:lid w:val="${escapeXml$1(options.languageId)}"/>`);
4695
+ if (options.storeMappedDataAs !== void 0) parts.push(`<w:storeMappedDataAs w:val="${options.storeMappedDataAs}"/>`);
4696
+ if (options.calendar !== void 0) parts.push(`<w:calendar w:val="${options.calendar}"/>`);
4697
+ const attrs = [];
4698
+ if (options.fullDate !== void 0) attrs.push(`w:fullDate="${options.fullDate}"`);
4699
+ const attrStr = attrs.length ? " " + attrs.join(" ") : "";
4700
+ return parts.length ? `<w:date${attrStr}>${parts.join("")}</w:date>` : `<w:date${attrStr}/>`;
4701
+ }
4702
+ function sdtDataBindingXml(options) {
4703
+ const attrs = [`w:xpath="${escapeXml$1(options.xpath)}"`, `w:storeItemID="${escapeXml$1(options.storeItemID)}"`];
4704
+ if (options.prefixMappings !== void 0) attrs.push(`w:prefixMappings="${escapeXml$1(options.prefixMappings)}"`);
4705
+ return `<w:dataBinding ${attrs.join(" ")}/>`;
4706
+ }
4707
+ function sdtDocPartXml(name, options) {
4708
+ const parts = [];
4709
+ if (options.gallery !== void 0) parts.push(`<w:docPartGallery w:val="${escapeXml$1(options.gallery)}"/>`);
4710
+ if (options.category !== void 0) parts.push(`<w:docPartCategory w:val="${escapeXml$1(options.category)}"/>`);
4711
+ if (options.unique !== void 0) parts.push(options.unique ? "<w:docPartUnique/>" : "<w:docPartUnique w:val=\"0\"/>");
4712
+ return parts.length ? `<${name}>${parts.join("")}</${name}>` : `<${name}/>`;
4713
+ }
4714
+ function onOffAttr(name, val) {
4715
+ return val ? `<${name}/>` : `<${name} w:val="0"/>`;
4716
+ }
4717
+ function stringifySdtPr(opts) {
4718
+ const parts = [];
4719
+ if (opts.alias !== void 0) parts.push(`<w:alias w:val="${escapeXml$1(opts.alias)}"/>`);
4720
+ if (opts.tag !== void 0) parts.push(`<w:tag w:val="${escapeXml$1(opts.tag)}"/>`);
4721
+ if (opts.id !== void 0) parts.push(`<w:id w:val="${opts.id}"/>`);
4722
+ if (opts.lock !== void 0) parts.push(`<w:lock w:val="${opts.lock}"/>`);
4723
+ if (opts.temporary !== void 0) parts.push(onOffAttr("w:temporary", opts.temporary));
4724
+ const effectiveShowingPlcHdr = opts.showingPlaceholder ?? false;
4725
+ if (opts.showingPlaceholder !== void 0 || effectiveShowingPlcHdr) parts.push(onOffAttr("w:showingPlcHdr", effectiveShowingPlcHdr));
4726
+ if (opts.dataBinding) parts.push(sdtDataBindingXml(opts.dataBinding));
4727
+ if (opts.label !== void 0) parts.push(`<w:label w:val="${opts.label}"/>`);
4728
+ if (opts.tabIndex !== void 0) parts.push(`<w:tabIndex w:val="${opts.tabIndex}"/>`);
4729
+ if (opts.equation) parts.push("<w:equation/>");
4730
+ else if (opts.comboBox) parts.push(sdtListTypeXml("w:comboBox", opts.comboBox));
4731
+ else if (opts.date) parts.push(sdtDateXml(opts.date));
4732
+ else if (opts.docPartObj) parts.push(sdtDocPartXml("w:docPartObj", opts.docPartObj));
4733
+ else if (opts.docPartList) parts.push(sdtDocPartXml("w:docPartList", opts.docPartList));
4734
+ else if (opts.dropDownList) parts.push(sdtListTypeXml("w:dropDownList", opts.dropDownList));
4735
+ else if (opts.picture) parts.push("<w:picture/>");
4736
+ else if (opts.richText) parts.push("<w:richText/>");
4737
+ else if (opts.text !== void 0) {
4738
+ const multiLine = opts.text.multiLine ?? false;
4739
+ parts.push(`<w:text w:multiLine="${multiLine}"/>`);
4740
+ } else if (opts.citation) parts.push("<w:citation/>");
4741
+ else if (opts.group) parts.push("<w:group/>");
4742
+ else if (opts.bibliography) parts.push("<w:bibliography/>");
4743
+ return parts.length ? `<w:sdtPr>${parts.join("")}</w:sdtPr>` : "<w:sdtPr/>";
4744
+ }
4745
+ /** Parse w:sdtPr element into SdtPropertiesOptions. */
4746
+ function parseSdtPr(el) {
4747
+ const opts = {};
4748
+ const alias = findChild(el, "w:alias");
4749
+ if (alias) opts.alias = attr(alias, "w:val");
4750
+ const tag = findChild(el, "w:tag");
4751
+ if (tag) {
4752
+ const val = attr(tag, "w:val");
4753
+ if (val) opts.tag = val;
4057
4754
  }
4058
- const marRight = findChild(el, "w:marRight");
4059
- if (marRight) {
4060
- const val = attrNum(marRight, "w:val");
4061
- if (val !== void 0) opts.marginRight = val;
4755
+ const id = findChild(el, "w:id");
4756
+ if (id) {
4757
+ const val = attrNum(id, "w:val");
4758
+ if (val !== void 0) opts.id = val;
4062
4759
  }
4063
- const marTop = findChild(el, "w:marTop");
4064
- if (marTop) {
4065
- const val = attrNum(marTop, "w:val");
4066
- if (val !== void 0) opts.marginTop = val;
4760
+ const lock = findChild(el, "w:lock");
4761
+ if (lock) {
4762
+ const val = attr(lock, "w:val");
4763
+ if (val) opts.lock = val;
4067
4764
  }
4068
- const marBottom = findChild(el, "w:marBottom");
4069
- if (marBottom) {
4070
- const val = attrNum(marBottom, "w:val");
4071
- if (val !== void 0) opts.marginBottom = val;
4765
+ const temporary = findChild(el, "w:temporary");
4766
+ if (temporary) opts.temporary = attrBool(temporary, "w:val") ?? true;
4767
+ const showingPlcHdr = findChild(el, "w:showingPlcHdr");
4768
+ if (showingPlcHdr) opts.showingPlaceholder = attrBool(showingPlcHdr, "w:val") ?? true;
4769
+ const label = findChild(el, "w:label");
4770
+ if (label) {
4771
+ const val = attrNum(label, "w:val");
4772
+ if (val !== void 0) opts.label = val;
4072
4773
  }
4073
- const blockQuote = findChild(el, "w:blockQuote");
4074
- if (blockQuote) opts.blockQuote = attr(blockQuote, "w:val") !== "off";
4075
- const bodyDiv = findChild(el, "w:bodyDiv");
4076
- if (bodyDiv) opts.bodyDiv = attr(bodyDiv, "w:val") !== "off";
4077
- const divBdr = findChild(el, "w:divBdr");
4078
- if (divBdr) opts.border = parseDivBorderEl(divBdr);
4079
- const divsChild = findChild(el, "w:divsChild");
4080
- if (divsChild) {
4081
- const children = parseDivsEl(divsChild);
4082
- if (children.length > 0) opts.children = children;
4774
+ const tabIndex = findChild(el, "w:tabIndex");
4775
+ if (tabIndex) {
4776
+ const val = attrNum(tabIndex, "w:val");
4777
+ if (val !== void 0) opts.tabIndex = val;
4083
4778
  }
4779
+ const dataBinding = findChild(el, "w:dataBinding");
4780
+ if (dataBinding) opts.dataBinding = {
4781
+ xpath: attr(dataBinding, "w:xpath") ?? "",
4782
+ storeItemID: attr(dataBinding, "w:storeItemID") ?? "",
4783
+ prefixMappings: attr(dataBinding, "w:prefixMappings")
4784
+ };
4785
+ if (findChild(el, "w:equation")) opts.equation = true;
4786
+ else if (findChild(el, "w:comboBox")) {
4787
+ const comboBox = findChild(el, "w:comboBox");
4788
+ const items = [];
4789
+ for (const li of children(comboBox, "w:listItem")) items.push({
4790
+ displayText: attr(li, "w:displayText"),
4791
+ value: attr(li, "w:value")
4792
+ });
4793
+ opts.comboBox = {
4794
+ items: items.length > 0 ? items : void 0,
4795
+ lastValue: attr(comboBox, "w:lastValue")
4796
+ };
4797
+ } else if (findChild(el, "w:date")) {
4798
+ const date = findChild(el, "w:date");
4799
+ const dateOpts = {};
4800
+ const dateFormat = findChild(date, "w:dateFormat");
4801
+ if (dateFormat) dateOpts.dateFormat = textOf(dateFormat);
4802
+ const lid = findChild(date, "w:lid");
4803
+ if (lid) dateOpts.languageId = textOf(lid);
4804
+ const storeMapped = findChild(date, "w:storeMappedDataAs");
4805
+ if (storeMapped) dateOpts.storeMappedDataAs = attr(storeMapped, "w:val");
4806
+ const calendar = findChild(date, "w:calendar");
4807
+ if (calendar) dateOpts.calendar = attr(calendar, "w:val");
4808
+ const fullDate = attr(date, "w:fullDate");
4809
+ if (fullDate) dateOpts.fullDate = fullDate;
4810
+ opts.date = dateOpts;
4811
+ } else if (findChild(el, "w:docPartObj")) {
4812
+ const dp = findChild(el, "w:docPartObj");
4813
+ const dpObj = {};
4814
+ const gallery = findChild(dp, "w:docPartGallery");
4815
+ if (gallery) dpObj.gallery = attr(gallery, "w:val");
4816
+ const category = findChild(dp, "w:docPartCategory");
4817
+ if (category) dpObj.category = attr(category, "w:val");
4818
+ if (findChild(dp, "w:docPartUnique")) dpObj.unique = true;
4819
+ opts.docPartObj = dpObj;
4820
+ } else if (findChild(el, "w:docPartList")) {
4821
+ const dp = findChild(el, "w:docPartList");
4822
+ const dpObj = {};
4823
+ const gallery = findChild(dp, "w:docPartGallery");
4824
+ if (gallery) dpObj.gallery = attr(gallery, "w:val");
4825
+ const category = findChild(dp, "w:docPartCategory");
4826
+ if (category) dpObj.category = attr(category, "w:val");
4827
+ if (findChild(dp, "w:docPartUnique")) dpObj.unique = true;
4828
+ opts.docPartList = dpObj;
4829
+ } else if (findChild(el, "w:dropDownList")) {
4830
+ const ddl = findChild(el, "w:dropDownList");
4831
+ const items = [];
4832
+ for (const li of children(ddl, "w:listItem")) items.push({
4833
+ displayText: attr(li, "w:displayText"),
4834
+ value: attr(li, "w:value")
4835
+ });
4836
+ opts.dropDownList = {
4837
+ items: items.length > 0 ? items : void 0,
4838
+ lastValue: attr(ddl, "w:lastValue")
4839
+ };
4840
+ } else if (findChild(el, "w:picture")) opts.picture = true;
4841
+ else if (findChild(el, "w:richText")) opts.richText = true;
4842
+ else if (findChild(el, "w:text")) opts.text = { multiLine: attrBool(findChild(el, "w:text"), "w:multiLine") };
4843
+ else if (findChild(el, "w:citation")) opts.citation = true;
4844
+ else if (findChild(el, "w:group")) opts.group = true;
4845
+ else if (findChild(el, "w:bibliography")) opts.bibliography = true;
4084
4846
  return opts;
4085
4847
  }
4086
- function parseDivBorderEl(el) {
4848
+ /** Parse w:customXmlPr element into CustomXmlPrOptions. */
4849
+ function parseCustomXmlPr(el) {
4087
4850
  const opts = {};
4088
- for (const side of [
4089
- "top",
4090
- "left",
4091
- "bottom",
4092
- "right"
4093
- ]) {
4094
- const sideEl = findChild(el, `w:${side}`);
4095
- if (sideEl) {
4096
- const b = {};
4097
- const val = attr(sideEl, "w:val");
4098
- if (val) b.style = val;
4099
- const color = attr(sideEl, "w:color");
4100
- if (color) b.color = color;
4101
- const sz = attrNum(sideEl, "w:sz");
4102
- if (sz !== void 0) b.size = sz;
4103
- opts[side] = b;
4851
+ const placeholder = findChild(el, "w:placeholder");
4852
+ if (placeholder) {
4853
+ const val = attr(placeholder, "w:val");
4854
+ if (val) opts.placeholder = val;
4855
+ }
4856
+ const attributes = [];
4857
+ for (const child of el.elements ?? []) {
4858
+ if (child.name !== "w:attr") continue;
4859
+ const name = attr(child, "w:name");
4860
+ const val = attr(child, "w:val");
4861
+ if (name && val) {
4862
+ const attrOpts = {
4863
+ name,
4864
+ val
4865
+ };
4866
+ const uriVal = attr(child, "w:uri");
4867
+ if (uriVal) attrOpts.uri = uriVal;
4868
+ attributes.push(attrOpts);
4104
4869
  }
4105
4870
  }
4871
+ if (attributes.length > 0) opts.attributes = attributes;
4106
4872
  return opts;
4107
4873
  }
4108
- function wsDivBorderXml(b) {
4109
- const parts = ["<w:divBdr>"];
4110
- const sides = [
4111
- ["w:top", b.top],
4112
- ["w:left", b.left],
4113
- ["w:bottom", b.bottom],
4114
- ["w:right", b.right]
4115
- ];
4116
- for (const [tag, side] of sides) {
4117
- if (!side) continue;
4118
- const attrParts = [`w:val="${wsEscapeAttr(side.style)}"`];
4119
- if (side.color) attrParts.push(`w:color="${wsEscapeAttr(side.color)}"`);
4120
- if (side.size !== void 0) attrParts.push(`w:sz="${side.size}"`);
4121
- parts.push(`<${tag} ${attrParts.join(" ")}/>`);
4122
- }
4123
- parts.push("</w:divBdr>");
4124
- return parts.join("");
4874
+ /** Body child element parsing callback for SDT/customXml content. */
4875
+ let _parseBodyChild;
4876
+ /** Register the body child parser (called from parse/body.ts to break circular dependency). */
4877
+ function setBodyParseChild(parser) {
4878
+ _parseBodyChild = parser;
4125
4879
  }
4126
- function wsDivXml(d) {
4127
- const parts = [`<w:div w:id="${d.id}">`];
4128
- if (d.blockQuote !== void 0) parts.push(wsStringVal("w:blockQuote", d.blockQuote ? "on" : "off"));
4129
- if (d.bodyDiv !== void 0) parts.push(wsStringVal("w:bodyDiv", d.bodyDiv ? "on" : "off"));
4130
- parts.push(wsNumVal("w:marLeft", d.marginLeft));
4131
- parts.push(wsNumVal("w:marRight", d.marginRight));
4132
- parts.push(wsNumVal("w:marTop", d.marginTop));
4133
- parts.push(wsNumVal("w:marBottom", d.marginBottom));
4134
- if (d.border) parts.push(wsDivBorderXml(d.border));
4135
- if (d.children?.length) {
4136
- parts.push("<w:divsChild>");
4137
- for (const child of d.children) parts.push(wsDivXml(child));
4138
- parts.push("</w:divsChild>");
4880
+ function parseBodyChildren(elements, ctx) {
4881
+ if (!_parseBodyChild) return [];
4882
+ const result = [];
4883
+ for (const el of elements) result.push(_parseBodyChild(el, ctx));
4884
+ return result;
4885
+ }
4886
+ const sdtBlockDesc = {
4887
+ kind: "custom",
4888
+ stringify(opts, ctx) {
4889
+ const parts = ["<w:sdt>"];
4890
+ parts.push(stringifySdtPr(opts.properties));
4891
+ parts.push("<w:sdtEndPr/>");
4892
+ if (opts.children && opts.children.length > 0) {
4893
+ const contentParts = [];
4894
+ for (const child of opts.children) contentParts.push(ctx.stringifyChild(child, ctx));
4895
+ const contentBody = contentParts.join("");
4896
+ parts.push(contentBody ? `<w:sdtContent>${contentBody}</w:sdtContent>` : "<w:sdtContent/>");
4897
+ }
4898
+ parts.push("</w:sdt>");
4899
+ return parts.join("");
4900
+ },
4901
+ parse(el, ctx) {
4902
+ const dctx = ctx;
4903
+ const sdtPr = findChild(el, "w:sdtPr");
4904
+ const properties = sdtPr ? parseSdtPr(sdtPr) : {};
4905
+ const sdtContent = findChild(el, "w:sdtContent");
4906
+ let childList;
4907
+ if (sdtContent && sdtContent.elements?.length) {
4908
+ childList = parseBodyChildren(sdtContent.elements, dctx);
4909
+ if (childList.length === 0) childList = void 0;
4910
+ }
4911
+ return {
4912
+ properties,
4913
+ children: childList
4914
+ };
4139
4915
  }
4140
- parts.push("</w:div>");
4141
- return parts.join("");
4142
- }
4143
- function framesetXml(fs) {
4144
- const parts = ["<w:frameset>"];
4145
- if (fs.size !== void 0) parts.push(wsStringVal("w:sz", fs.size));
4146
- if (fs.splitbar) {
4147
- parts.push("<w:framesetSplitbar>");
4148
- if (fs.splitbar.width !== void 0) parts.push(`<w:w w:w="${fs.splitbar.width}" w:type="dxa"/>`);
4149
- if (fs.splitbar.color !== void 0) parts.push(wsStringVal("w:color", fs.splitbar.color));
4150
- if (fs.splitbar.noBorder) parts.push("<w:noBorder/>");
4151
- if (fs.splitbar.flatBorders) parts.push("<w:flatBorders/>");
4152
- parts.push("</w:framesetSplitbar>");
4916
+ };
4917
+ function buildCustomXmlPrXml(pr) {
4918
+ const parts = ["<w:customXmlPr>"];
4919
+ if (pr.placeholder !== void 0) parts.push(`<w:placeholder w:val="${escapeAttr(pr.placeholder)}"/>`);
4920
+ if (pr.attributes) for (const attr of pr.attributes) {
4921
+ const attrParts = [`w:name="${escapeAttr(attr.name)}"`, `w:val="${escapeAttr(attr.val)}"`];
4922
+ if (attr.uri !== void 0) attrParts.push(`w:uri="${escapeAttr(attr.uri)}"`);
4923
+ parts.push(`<w:attr ${attrParts.join(" ")}/>`);
4153
4924
  }
4154
- if (fs.layout !== void 0) parts.push(`<w:frameLayout w:val="${fs.layout}"/>`);
4155
- if (fs.title !== void 0) parts.push(wsStringVal("w:title", fs.title));
4156
- if (fs.children) for (const child of fs.children) if ("children" in child || "layout" in child || "splitbar" in child) parts.push(framesetXml(child));
4157
- else parts.push(frameXml(child));
4158
- parts.push("</w:frameset>");
4159
- return parts.join("");
4160
- }
4161
- function frameXml(f) {
4162
- const parts = ["<w:frame>"];
4163
- if (f.size !== void 0) parts.push(wsStringVal("w:sz", f.size));
4164
- if (f.name !== void 0) parts.push(wsStringVal("w:name", f.name));
4165
- if (f.title !== void 0) parts.push(wsStringVal("w:title", f.title));
4166
- if (f.sourceRId !== void 0) parts.push(`<w:sourceFileName r:id="${wsEscapeAttr(f.sourceRId)}"/>`);
4167
- if (f.marginWidth !== void 0) parts.push(wsNumVal("w:marW", f.marginWidth));
4168
- if (f.marginHeight !== void 0) parts.push(wsNumVal("w:marH", f.marginHeight));
4169
- if (f.scrollbar !== void 0) parts.push(`<w:scrollbar w:val="${f.scrollbar}"/>`);
4170
- if (f.noResizeAllowed) parts.push("<w:noResizeAllowed/>");
4171
- if (f.linkedToFile) parts.push("<w:linkedToFile/>");
4172
- if (f.longDescRId !== void 0) parts.push(`<w:longDesc r:id="${wsEscapeAttr(f.longDescRId)}"/>`);
4173
- parts.push("</w:frame>");
4925
+ parts.push("</w:customXmlPr>");
4174
4926
  return parts.join("");
4175
4927
  }
4176
- const webSettingsDesc = {
4928
+ const customXmlBlockDesc = {
4177
4929
  kind: "custom",
4178
- stringify(opts, _ctx) {
4179
- const p = [`<w:webSettings ${WS_NS}>`];
4180
- if (opts.frameset !== void 0) p.push(framesetXml(opts.frameset));
4181
- if (opts.divs?.length) {
4182
- p.push("<w:divs>");
4183
- for (const d of opts.divs) p.push(wsDivXml(d));
4184
- p.push("</w:divs>");
4185
- }
4186
- if (opts.encoding !== void 0) p.push(wsStringVal("w:encoding", opts.encoding));
4187
- if (opts.optimizeForBrowser !== void 0) p.push(wsOnOff("w:optimizeForBrowser", opts.optimizeForBrowser));
4188
- if (opts.relyOnVML !== void 0) p.push(wsOnOff("w:relyOnVML", opts.relyOnVML));
4189
- if (opts.allowPNG !== void 0) p.push(wsOnOff("w:allowPNG", opts.allowPNG));
4190
- if (opts.doNotRelyOnCSS !== void 0) p.push(wsOnOff("w:doNotRelyOnCSS", opts.doNotRelyOnCSS));
4191
- if (opts.doNotSaveAsSingleFile !== void 0) p.push(wsOnOff("w:doNotSaveAsSingleFile", opts.doNotSaveAsSingleFile));
4192
- if (opts.doNotOrganizeInFolder !== void 0) p.push(wsOnOff("w:doNotOrganizeInFolder", opts.doNotOrganizeInFolder));
4193
- if (opts.doNotUseLongFileNames !== void 0) p.push(wsOnOff("w:doNotUseLongFileNames", opts.doNotUseLongFileNames));
4194
- if (opts.pixelsPerInch !== void 0) p.push(wsNumVal("w:pixelsPerInch", opts.pixelsPerInch));
4195
- if (opts.targetScreenSz !== void 0) p.push(wsStringVal("w:targetScreenSz", opts.targetScreenSz));
4196
- if (opts.saveSmartTagsAsXml !== void 0) p.push(wsOnOff("w:saveSmartTagsAsXml", opts.saveSmartTagsAsXml));
4197
- p.push("</w:webSettings>");
4198
- return p.join("");
4930
+ stringify(opts, ctx) {
4931
+ const attrs = [`w:element="${escapeAttr(opts.element)}"`];
4932
+ if (opts.uri !== void 0) attrs.push(`w:uri="${escapeAttr(opts.uri)}"`);
4933
+ const parts = [`<w:customXml ${attrs.join(" ")}>`];
4934
+ if (opts.customXmlPr) parts.push(buildCustomXmlPrXml(opts.customXmlPr));
4935
+ if (opts.children) for (const child of opts.children) parts.push(ctx.stringifyChild(child, ctx));
4936
+ parts.push("</w:customXml>");
4937
+ return parts.join("");
4199
4938
  },
4200
- parse(el, _ctx) {
4939
+ parse(el, ctx) {
4940
+ const dctx = ctx;
4201
4941
  const opts = {};
4202
- const frameset = findChild(el, "w:frameset");
4203
- if (frameset) opts.frameset = parseFramesetEl(frameset);
4204
- const divs = findChild(el, "w:divs");
4205
- if (divs) {
4206
- const parsed = parseDivsEl(divs);
4207
- if (parsed.length > 0) opts.divs = parsed;
4208
- }
4209
- const encoding = findChild(el, "w:encoding");
4210
- if (encoding) {
4211
- const val = attr(encoding, "w:val");
4212
- if (val) opts.encoding = val;
4213
- }
4214
- for (const [name, optKey] of [
4215
- ["w:optimizeForBrowser", "optimizeForBrowser"],
4216
- ["w:relyOnVML", "relyOnVML"],
4217
- ["w:allowPNG", "allowPNG"],
4218
- ["w:doNotRelyOnCSS", "doNotRelyOnCSS"],
4219
- ["w:doNotSaveAsSingleFile", "doNotSaveAsSingleFile"],
4220
- ["w:doNotOrganizeInFolder", "doNotOrganizeInFolder"],
4221
- ["w:doNotUseLongFileNames", "doNotUseLongFileNames"],
4222
- ["w:saveSmartTagsAsXml", "saveSmartTagsAsXml"]
4223
- ]) {
4224
- const child = findChild(el, name);
4225
- if (child) opts[optKey] = attrBool(child, "w:val") ?? true;
4226
- }
4227
- const ppi = findChild(el, "w:pixelsPerInch");
4228
- if (ppi) {
4229
- const val = attrNum(ppi, "w:val");
4230
- if (val !== void 0) opts.pixelsPerInch = val;
4231
- }
4232
- const targetSz = findChild(el, "w:targetScreenSz");
4233
- if (targetSz) {
4234
- const val = attr(targetSz, "w:val");
4235
- if (val) opts.targetScreenSz = val;
4942
+ const element = attr(el, "w:element");
4943
+ if (element) opts.element = element;
4944
+ const uri = attr(el, "w:uri");
4945
+ if (uri) opts.uri = uri;
4946
+ const xmlPr = findChild(el, "w:customXmlPr");
4947
+ if (xmlPr) opts.customXmlPr = parseCustomXmlPr(xmlPr);
4948
+ const childList = [];
4949
+ for (const child of el.elements ?? []) {
4950
+ if (child.name === "w:customXmlPr") continue;
4951
+ if (_parseBodyChild) childList.push(_parseBodyChild(child, dctx));
4236
4952
  }
4953
+ if (childList.length > 0) opts.children = childList;
4237
4954
  return opts;
4238
4955
  }
4239
4956
  };
4240
4957
  //#endregion
4241
- //#region src/parts/fonts/font-wrapper.ts
4242
- /**
4243
- * Wrapper class for managing embedded font relationships.
4244
- *
4245
- * Each font is assigned a unique key for obfuscation.
4246
- * The actual font table XML is generated by `fontTableDesc.stringify()`.
4247
- *
4248
- * @example
4249
- * ```typescript
4250
- * const fontWrapper = new FontWrapper([
4251
- * { name: "CustomFont", data: fontBuffer }
4252
- * ]);
4253
- * ```
4254
- */
4255
- var FontWrapper = class {
4256
- options;
4257
- relationships;
4258
- fontOptionsWithKey = [];
4259
- constructor(options) {
4260
- this.options = options;
4261
- this.fontOptionsWithKey = options.map((o) => ({
4262
- ...o,
4263
- fontKey: uniqueUuid()
4264
- }));
4265
- this.relationships = new Relationships();
4266
- for (let i = 0; i < options.length; i++) this.relationships.addRelationship(i + 1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/font", `fonts/${options[i].name}.odttf`);
4267
- }
4268
- };
4269
- //#endregion
4270
- //#region src/parts/textbox/shape/shape.ts
4271
- /**
4272
- * Maps VmlShapeStyle property names to their corresponding CSS-style property names.
4273
- * Used internally for converting TypeScript-friendly property names to VML style attributes.
4274
- */
4275
- const styleToKeyMap = {
4276
- flip: "flip",
4277
- height: "height",
4278
- left: "left",
4279
- marginBottom: "margin-bottom",
4280
- marginLeft: "margin-left",
4281
- marginRight: "margin-right",
4282
- marginTop: "margin-top",
4283
- position: "position",
4284
- positionHorizontal: "mso-position-horizontal",
4285
- positionHorizontalRelative: "mso-position-horizontal-relative",
4286
- positionVertical: "mso-position-vertical",
4287
- positionVerticalRelative: "mso-position-vertical-relative",
4288
- rotation: "rotation",
4289
- top: "top",
4290
- visibility: "visibility",
4291
- width: "width",
4292
- wrapDistanceBottom: "mso-wrap-distance-bottom",
4293
- wrapDistanceLeft: "mso-wrap-distance-left",
4294
- wrapDistanceRight: "mso-wrap-distance-right",
4295
- wrapDistanceTop: "mso-wrap-distance-top",
4296
- wrapEdited: "mso-wrap-edited",
4297
- wrapStyle: "mso-wrap-style",
4298
- zIndex: "z-index"
4299
- };
4300
- //#endregion
4301
- //#region src/body.ts
4302
- /**
4303
- * Body-level stringification for DOCX documents.
4304
- *
4305
- * Converts pure JSON options to XML strings for document body content.
4306
- * Pure string concatenation — zero IXmlableObject, zero BaseXmlComponent.
4307
- *
4308
- * @module
4309
- */
4310
- /**
4311
- * Mapping from empty child property name to self-closing XML element.
4312
- *
4313
- * These are single-key objects like `{ noBreakHyphen: true }` that map to
4314
- * self-closing XML elements with no attributes.
4315
- *
4316
- * XSD reference: EG_RunInnerContent group in wml.xsd.
4317
- */
4318
- const EMPTY_RUN_ELEMENTS = {
4319
- noBreakHyphen: "<w:noBreakHyphen/>",
4320
- softHyphen: "<w:softHyphen/>",
4321
- dayShort: "<w:dayShort/>",
4322
- monthShort: "<w:monthShort/>",
4323
- yearShort: "<w:yearShort/>",
4324
- dayLong: "<w:dayLong/>",
4325
- monthLong: "<w:monthLong/>",
4326
- yearLong: "<w:yearLong/>",
4327
- annotationRef: "<w:annotationRef/>",
4328
- footnoteRef: "<w:footnoteRef/>",
4329
- endnoteRef: "<w:endnoteRef/>",
4330
- separator: "<w:separator/>",
4331
- continuationSeparator: "<w:continuationSeparator/>",
4332
- pgNum: "<w:pgNum/>",
4333
- carriageReturn: "<w:cr/>",
4334
- lastRenderedPageBreak: "<w:lastRenderedPageBreak/>"
4335
- };
4336
- /**
4337
- * Stringify a run (w:r) from pure JSON options.
4338
- *
4339
- * Handles text, children, breaks, and run properties.
4340
- */
4341
- function stringifyRun(opts, ctx) {
4342
- const parts = [];
4343
- let commentRefStyle = false;
4344
- if (opts.children) {
4345
- for (const child of opts.children) if (typeof child === "object" && child !== null && "commentReference" in child) {
4346
- commentRefStyle = true;
4347
- break;
4958
+ //#region src/parts/core-properties.ts
4959
+ const corePropertiesDesc = {
4960
+ kind: "custom",
4961
+ stringify(opts, _ctx) {
4962
+ const now = (/* @__PURE__ */ new Date()).toISOString();
4963
+ const p = ["<cp:coreProperties xmlns:cp=\"http://schemas.openxmlformats.org/package/2006/metadata/core-properties\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:dcterms=\"http://purl.org/dc/terms/\" xmlns:dcmitype=\"http://purl.org/dc/dcmitype/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"];
4964
+ if (opts.title) p.push(`<dc:title>${escapeXml(opts.title)}</dc:title>`);
4965
+ if (opts.subject) p.push(`<dc:subject>${escapeXml(opts.subject)}</dc:subject>`);
4966
+ if (opts.creator) p.push(`<dc:creator>${escapeXml(opts.creator)}</dc:creator>`);
4967
+ if (opts.keywords) p.push(`<cp:keywords>${escapeXml(opts.keywords)}</cp:keywords>`);
4968
+ if (opts.description) p.push(`<dc:description>${escapeXml(opts.description)}</dc:description>`);
4969
+ if (opts.lastModifiedBy) p.push(`<cp:lastModifiedBy>${escapeXml(opts.lastModifiedBy)}</cp:lastModifiedBy>`);
4970
+ if (opts.revision !== void 0) p.push(`<cp:revision>${opts.revision}</cp:revision>`);
4971
+ p.push(`<dcterms:created xsi:type="dcterms:W3CDTF">${now}</dcterms:created>`);
4972
+ p.push(`<dcterms:modified xsi:type="dcterms:W3CDTF">${now}</dcterms:modified>`);
4973
+ p.push("</cp:coreProperties>");
4974
+ return p.join("");
4975
+ },
4976
+ parse(el, _ctx) {
4977
+ const result = {};
4978
+ for (const child of el.elements ?? []) {
4979
+ if (typeof child.name !== "string") continue;
4980
+ const text = child.elements?.[0]?.text;
4981
+ if (typeof text !== "string") continue;
4982
+ switch (child.name) {
4983
+ case "dc:title":
4984
+ result.title = text;
4985
+ break;
4986
+ case "dc:subject":
4987
+ result.subject = text;
4988
+ break;
4989
+ case "dc:creator":
4990
+ result.creator = text;
4991
+ break;
4992
+ case "cp:keywords":
4993
+ result.keywords = text;
4994
+ break;
4995
+ case "dc:description":
4996
+ result.description = text;
4997
+ break;
4998
+ case "cp:lastModifiedBy":
4999
+ result.lastModifiedBy = text;
5000
+ break;
5001
+ case "cp:revision":
5002
+ result.revision = Number(text);
5003
+ break;
5004
+ }
4348
5005
  }
5006
+ return result;
4349
5007
  }
4350
- const rPr = stringifyRunProperties(commentRefStyle ? {
4351
- ...opts,
4352
- style: "CommentReference"
4353
- } : opts);
4354
- if (rPr) parts.push(rPr);
4355
- if (opts.break) for (let i = 0; i < opts.break; i++) parts.push("<w:br/>");
4356
- if (opts.children) {
4357
- for (const child of opts.children) if (typeof child === "string") parts.push(`<w:t xml:space="preserve">${escapeXml(child)}</w:t>`);
4358
- else if (typeof child === "object" && child !== null) {
4359
- if ("tab" in child) {
4360
- parts.push("<w:tab/>");
4361
- continue;
4362
- }
4363
- if ("pageBreak" in child) {
4364
- parts.push("<w:br w:type=\"page\"/>");
4365
- continue;
4366
- }
4367
- if ("columnBreak" in child) {
4368
- parts.push("<w:br w:type=\"column\"/>");
4369
- continue;
4370
- }
4371
- if ("commentReference" in child) {
4372
- parts.push(`<w:commentReference w:id="${Number(child.commentReference)}"/>`);
4373
- continue;
4374
- }
4375
- const emptyXml = EMPTY_RUN_ELEMENTS[Object.keys(child)[0]];
4376
- if (emptyXml) {
4377
- parts.push(emptyXml);
4378
- continue;
4379
- }
4380
- const jsonResult = stringifyJsonChild(child, ctx);
4381
- if (jsonResult !== void 0) if (Array.isArray(jsonResult)) parts.push(...jsonResult);
4382
- else parts.push(jsonResult);
4383
- else throw new Error(`Unsupported run child type: ${Object.keys(child).join(", ")}`);
5008
+ };
5009
+ //#endregion
5010
+ //#region src/parts/custom-properties.ts
5011
+ const customPropertiesDesc = {
5012
+ kind: "custom",
5013
+ stringify(opts, _ctx) {
5014
+ const p = ["<Properties xmlns=\"http://schemas.openxmlformats.org/officeDocument/2006/custom-properties\" xmlns:vt=\"http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes\">"];
5015
+ let pid = 2;
5016
+ for (const prop of opts.properties) {
5017
+ p.push(`<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="${pid}" name="${escapeXml(prop.name)}"><vt:lpwstr>${escapeXml(prop.value)}</vt:lpwstr></property>`);
5018
+ pid++;
4384
5019
  }
4385
- } else if (opts.text !== void 0) parts.push(`<w:t xml:space="preserve">${escapeXml(String(opts.text))}</w:t>`);
4386
- const rsidAttrs = [];
4387
- if (opts.rsidRPr) rsidAttrs.push(` w:rsidRPr="${opts.rsidRPr}"`);
4388
- if (opts.rsidDel) rsidAttrs.push(` w:rsidDel="${opts.rsidDel}"`);
4389
- const attr = rsidAttrs.join("");
4390
- const body = parts.join("");
4391
- return body.length === 0 ? attr ? `<w:r${attr}/>` : "<w:r/>" : `<w:r${attr}>${body}</w:r>`;
4392
- }
4393
- /**
4394
- * Stringify a paragraph (w:p) from pure JSON options or string.
4395
- *
4396
- * Handles paragraph properties, numbering registration, and run children.
4397
- */
4398
- function stringifyParagraph(opts, ctx, sectionPropertiesXml) {
4399
- const resolved = typeof opts === "string" ? { text: opts } : opts;
4400
- const parts = [];
4401
- const props = stringifyParagraphProperties(resolved);
4402
- if (!(ctx.viewWrapper instanceof FontWrapper)) for (const ref of props.numberingReferences) ctx.file.numbering.createConcreteNumberingInstance(ref.reference, ref.instance);
4403
- if (props.xml) if (sectionPropertiesXml) parts.push(props.xml.replace("</w:pPr>", sectionPropertiesXml + "</w:pPr>"));
4404
- else parts.push(props.xml);
4405
- else if (sectionPropertiesXml) parts.push(`<w:pPr>${sectionPropertiesXml}</w:pPr>`);
4406
- if (resolved.text !== void 0) parts.push(stringifyRun({ text: resolved.text }, ctx));
4407
- if (resolved.children) {
4408
- for (const child of resolved.children) if (typeof child === "string") parts.push(stringifyRun({ text: child }, ctx));
4409
- else if (typeof child === "object" && child !== null) {
4410
- const jsonResult = stringifyJsonChild(child, ctx);
4411
- if (jsonResult !== void 0) if (Array.isArray(jsonResult)) parts.push(...jsonResult);
4412
- else parts.push(jsonResult);
4413
- else if ("text" in child || "children" in child || "break" in child) parts.push(stringifyRun(child, ctx));
4414
- else throw new Error(`Unsupported paragraph child type: ${Object.keys(child).join(", ")}`);
5020
+ p.push("</Properties>");
5021
+ return p.join("");
5022
+ },
5023
+ parse(el, _ctx) {
5024
+ const properties = [];
5025
+ for (const child of el.elements ?? []) {
5026
+ if (child.name !== "property") continue;
5027
+ const name = attr(child, "name");
5028
+ if (!name) continue;
5029
+ const valueEl = child.elements?.find((e) => e.name?.startsWith("vt:"));
5030
+ const value = valueEl ? textOf(valueEl) ?? "" : "";
5031
+ properties.push({
5032
+ name,
5033
+ value
5034
+ });
4415
5035
  }
5036
+ return { properties };
4416
5037
  }
4417
- const body = parts.join("");
4418
- return body ? `<w:p>${body}</w:p>` : "<w:p/>";
4419
- }
5038
+ };
5039
+ //#endregion
5040
+ //#region src/parts/web-settings.ts
4420
5041
  /**
4421
- * Stringify a body-level child element.
4422
- *
4423
- * Dispatches to the appropriate stringifier based on the child type.
4424
- * Pure JSON API — no class instance support.
5042
+ * Screen size types for web settings target.
4425
5043
  */
4426
- function stringifyBodyChild(child, ctx) {
4427
- if ("paragraph" in child) return stringifyParagraph(child.paragraph, ctx);
4428
- if ("table" in child) return tableDesc.stringify(child.table, ctx) ?? "";
4429
- if ("toc" in child) {
4430
- const { alias, ...options } = child.toc;
4431
- return stringifyTableOfContents(alias, options);
4432
- }
4433
- if ("textbox" in child) return stringifyTextbox(child.textbox, ctx);
4434
- if ("sdt" in child) return sdtBlockDesc.stringify(child.sdt, ctx) ?? "";
4435
- if ("altChunk" in child) return altChunkDesc.stringify(child.altChunk, ctx) ?? "";
4436
- if ("subDoc" in child) return subDocDesc.stringify(child.subDoc, ctx) ?? "";
4437
- if ("customXml" in child) return customXmlBlockDesc.stringify(child.customXml, ctx) ?? "";
4438
- if ("rawXml" in child) return child.rawXml;
4439
- throw new Error("Unknown section child type");
5044
+ const TargetScreenSize = {
5045
+ SIZE_544X376: "544x376",
5046
+ SIZE_640X480: "640x480",
5047
+ SIZE_720X512: "720x512",
5048
+ SIZE_800X600: "800x600",
5049
+ SIZE_1024X768: "1024x768",
5050
+ SIZE_1152X882: "1152x882",
5051
+ SIZE_1152X900: "1152x900",
5052
+ SIZE_1280X1024: "1280x1024",
5053
+ SIZE_1600X1200: "1600x1200",
5054
+ SIZE_1800X1440: "1800x1440",
5055
+ SIZE_1920X1200: "1920x1200"
5056
+ };
5057
+ const WS_NS = "xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:w15=\"http://schemas.microsoft.com/office/word/2012/wordml\"";
5058
+ function wsOnOff(tag, val) {
5059
+ return `<${tag} w:val="${val ? "true" : "false"}"/>`;
4440
5060
  }
4441
- /** Re-export styleToKeyMap for use in stringifyTextboxStyle. */
4442
- const vmlStyleMap = styleToKeyMap;
4443
- function stringifyDocumentBackground(opts, ctx) {
4444
- const attrs = [];
4445
- if (opts.color !== void 0) attrs.push(`w:color="${hexColorValue(opts.color)}"`);
4446
- if (opts.themeColor !== void 0) attrs.push(`w:themeColor="${opts.themeColor}"`);
4447
- if (opts.themeShade !== void 0) attrs.push(`w:themeShade="${uCharHexNumber(opts.themeShade)}"`);
4448
- if (opts.themeTint !== void 0) attrs.push(`w:themeTint="${uCharHexNumber(opts.themeTint)}"`);
4449
- const attrStr = attrs.join(" ");
4450
- if (opts.image) {
4451
- const fileName = `${uniqueId()}.${opts.image.type}`;
4452
- const rawData = toUint8Array(opts.image.data);
4453
- ctx.file.media.addImage(fileName, {
4454
- type: opts.image.type,
4455
- data: rawData,
4456
- fileName,
4457
- transformation: {
4458
- emus: {
4459
- x: 0,
4460
- y: 0
4461
- },
4462
- pixels: {
4463
- x: 0,
4464
- y: 0
4465
- }
4466
- }
4467
- });
4468
- return `<w:background ${attrStr}>${`<v:background id="_x0000_s1025"><v:fill r:id="{${fileName}}" o:title="${fileName}" recolor="t" type="frame"/></v:background>`}</w:background>`;
4469
- }
4470
- return `<w:background ${attrStr}/>`;
5061
+ function wsStringVal(tag, val) {
5062
+ return `<${tag} w:val="${wsEscapeAttr(val)}"/>`;
4471
5063
  }
4472
- function stringifyTextbox(opts, ctx) {
4473
- const { style, children, ...paraOpts } = opts;
4474
- const pPrXml = stringifyParagraphProperties(paraOpts).xml ?? "";
4475
- const styleStr = style ? Object.entries(style).map(([k, v]) => `${vmlStyleMap[k]}:${v}`).join(";") : void 0;
4476
- const shapeAttrs = [`id="_x0000_s${uniqueId()}"`, `type="#_x0000_t202"`];
4477
- if (styleStr) shapeAttrs.push(`style="${styleStr}"`);
4478
- const contentParts = [];
4479
- if (children) for (const c of children) contentParts.push(stringifyBodyChild(c, ctx));
4480
- const vmlTextbox = `<v:textbox style="mso-fit-shape-to-text:t;" insetmode="auto"><w:txbxContent>${contentParts.join("")}</w:txbxContent></v:textbox>`;
4481
- return `<w:p>${pPrXml}<w:pict>${`<v:shape ${shapeAttrs.join(" ")}>${vmlTextbox}</v:shape>`}</w:pict></w:p>`;
5064
+ function wsNumVal(tag, val) {
5065
+ return `<${tag} w:val="${val}"/>`;
4482
5066
  }
4483
- /** Document-level namespace string (cached). */
4484
- const DOC_NS = "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\" xmlns:cx=\"http://schemas.microsoft.com/office/drawing/2014/chartex\" xmlns:cx1=\"http://schemas.microsoft.com/office/drawing/2015/9/8/chartex\" xmlns:cx2=\"http://schemas.microsoft.com/office/drawing/2015/10/21/chartex\" xmlns:cx3=\"http://schemas.microsoft.com/office/drawing/2016/5/9/chartex\" xmlns:cx4=\"http://schemas.microsoft.com/office/drawing/2016/5/10/chartex\" xmlns:cx5=\"http://schemas.microsoft.com/office/drawing/2016/5/11/chartex\" xmlns:cx6=\"http://schemas.microsoft.com/office/drawing/2016/5/12/chartex\" xmlns:cx7=\"http://schemas.microsoft.com/office/drawing/2016/5/13/chartex\" xmlns:cx8=\"http://schemas.microsoft.com/office/drawing/2016/5/14/chartex\" xmlns:aink=\"http://schemas.microsoft.com/office/drawing/2016/ink\" xmlns:am3d=\"http://schemas.microsoft.com/office/drawing/2017/model3d\" xmlns:w16cex=\"http://schemas.microsoft.com/office/word/2018/wordml/cex\" xmlns:w16cid=\"http://schemas.microsoft.com/office/word/2016/wordml/cid\" xmlns:w16=\"http://schemas.microsoft.com/office/word/2018/wordml\" xmlns:w16sdtdh=\"http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash\" xmlns:w16se=\"http://schemas.microsoft.com/office/word/2015/wordml/symex\"";
4485
- /**
4486
- * Stringify the complete document.xml from context data.
4487
- *
4488
- * This is the pure JSON path — iterates raw section children via
4489
- * `stringifyBodyChild()` while reusing existing SectionProperties
4490
- * instances for sectPr XML (which are already created with correct
4491
- * header/footer references).
4492
- *
4493
- * Produces the complete `<w:document>` element including namespaces,
4494
- * background, body content with interleaved section properties.
4495
- */
4496
- function stringifyDocumentXml(ctx, docCtx) {
4497
- const sections = ctx._options.sections;
4498
- const bodySections = ctx.sectionProperties;
4499
- const parts = [];
4500
- parts.push(`<w:document ${DOC_NS} mc:Ignorable="w14 w15 wp14">`);
4501
- if (ctx._options.background) parts.push(stringifyDocumentBackground(ctx._options.background, docCtx));
4502
- const bodyParts = [];
4503
- for (let si = 0; si < sections.length; si++) {
4504
- const section = sections[si];
4505
- if (section.children) for (const child of section.children) bodyParts.push(stringifyBodyChild(child, docCtx));
4506
- const sectPrOpts = bodySections[si];
4507
- if (sectPrOpts) {
4508
- const sectPrXml = sectionPropertiesDesc.stringify(sectPrOpts, docCtx) ?? "";
4509
- if (si < sections.length - 1) bodyParts.push(`<w:p><w:pPr>${sectPrXml}</w:pPr></w:p>`);
4510
- else bodyParts.push(sectPrXml);
4511
- }
5067
+ function wsEscapeAttr(s) {
5068
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
5069
+ }
5070
+ function parseFramesetEl(el) {
5071
+ const opts = {};
5072
+ const sz = findChild(el, "w:sz");
5073
+ if (sz) {
5074
+ const val = attr(sz, "w:val");
5075
+ if (val) opts.size = val;
4512
5076
  }
4513
- parts.push(`<w:body>${bodyParts.join("")}</w:body>`);
4514
- parts.push("</w:document>");
4515
- return parts.join("");
5077
+ const splitbar = findChild(el, "w:framesetSplitbar");
5078
+ if (splitbar) opts.splitbar = parseSplitbarEl(splitbar);
5079
+ const layout = findChild(el, "w:frameLayout");
5080
+ if (layout) {
5081
+ const val = attr(layout, "w:val");
5082
+ if (val === "rows" || val === "cols") opts.layout = val;
5083
+ }
5084
+ const title = findChild(el, "w:title");
5085
+ if (title) {
5086
+ const val = attr(title, "w:val");
5087
+ if (val) opts.title = val;
5088
+ }
5089
+ const children = [];
5090
+ for (const child of el.elements ?? []) if (child.name === "w:frameset") children.push(parseFramesetEl(child));
5091
+ else if (child.name === "w:frame") children.push(parseFrameEl(child));
5092
+ if (children.length > 0) opts.children = children;
5093
+ return opts;
5094
+ }
5095
+ function parseSplitbarEl(el) {
5096
+ const opts = {};
5097
+ const w = findChild(el, "w:w");
5098
+ if (w) {
5099
+ const val = attrNum(w, "w:w");
5100
+ if (val !== void 0) opts.width = val;
5101
+ }
5102
+ const color = findChild(el, "w:color");
5103
+ if (color) {
5104
+ const val = attr(color, "w:val");
5105
+ if (val) opts.color = val;
5106
+ }
5107
+ if (findChild(el, "w:noBorder")) opts.noBorder = true;
5108
+ if (findChild(el, "w:flatBorders")) opts.flatBorders = true;
5109
+ return opts;
4516
5110
  }
4517
- const HEADING_MAP = {
4518
- Heading1: HeadingLevel.HEADING_1,
4519
- Heading2: HeadingLevel.HEADING_2,
4520
- Heading3: HeadingLevel.HEADING_3,
4521
- Heading4: HeadingLevel.HEADING_4,
4522
- Heading5: HeadingLevel.HEADING_5,
4523
- Heading6: HeadingLevel.HEADING_6,
4524
- Title: HeadingLevel.TITLE
4525
- };
4526
- /**
4527
- * Parse w:pPr element into paragraph properties (without children).
4528
- */
4529
- function parseParagraphProperties(el, ctx) {
5111
+ function parseFrameEl(el) {
4530
5112
  const opts = {};
4531
- const pStyle = findChild(el, "w:pStyle");
4532
- if (pStyle) {
4533
- const styleVal = attr(pStyle, "w:val");
4534
- if (styleVal) if (HEADING_MAP[styleVal]) opts.heading = HEADING_MAP[styleVal];
4535
- else opts.style = styleVal;
5113
+ const sz = findChild(el, "w:sz");
5114
+ if (sz) {
5115
+ const val = attr(sz, "w:val");
5116
+ if (val) opts.size = val;
4536
5117
  }
4537
- const jc = findChild(el, "w:jc");
4538
- if (jc) {
4539
- const val = attr(jc, "w:val");
4540
- if (val) opts.alignment = val;
5118
+ const name = findChild(el, "w:name");
5119
+ if (name) {
5120
+ const val = attr(name, "w:val");
5121
+ if (val) opts.name = val;
4541
5122
  }
4542
- const spacing = findChild(el, "w:spacing");
4543
- if (spacing) {
4544
- const sp = {};
4545
- const before = attrNum(spacing, "w:before");
4546
- if (before !== void 0) sp.before = before;
4547
- const after = attrNum(spacing, "w:after");
4548
- if (after !== void 0) sp.after = after;
4549
- const line = attrNum(spacing, "w:line");
4550
- if (line !== void 0) sp.line = line;
4551
- const lineRule = attr(spacing, "w:lineRule");
4552
- if (lineRule) sp.lineRule = lineRule;
4553
- const beforeAuto = attrBool(spacing, "w:beforeAutospacing") ?? attrBool(spacing, "w:beforeLines");
4554
- if (beforeAuto !== void 0) sp.beforeAutoSpacing = beforeAuto;
4555
- const afterAuto = attrBool(spacing, "w:afterAutospacing") ?? attrBool(spacing, "w:afterLines");
4556
- if (afterAuto !== void 0) sp.afterAutoSpacing = afterAuto;
4557
- if (Object.keys(sp).length > 0) opts.spacing = sp;
5123
+ const title = findChild(el, "w:title");
5124
+ if (title) {
5125
+ const val = attr(title, "w:val");
5126
+ if (val) opts.title = val;
4558
5127
  }
4559
- const ind = findChild(el, "w:ind");
4560
- if (ind) {
4561
- const indentObj = {};
4562
- const left = attrNum(ind, "w:left");
4563
- if (left !== void 0) indentObj.left = left;
4564
- const right = attrNum(ind, "w:right");
4565
- if (right !== void 0) indentObj.right = right;
4566
- const start = attrNum(ind, "w:start");
4567
- if (start !== void 0) indentObj.start = start;
4568
- const end = attrNum(ind, "w:end");
4569
- if (end !== void 0) indentObj.end = end;
4570
- const hanging = attrNum(ind, "w:hanging");
4571
- if (hanging !== void 0) indentObj.hanging = hanging;
4572
- const firstLine = attrNum(ind, "w:firstLine");
4573
- if (firstLine !== void 0) indentObj.firstLine = firstLine;
4574
- if (Object.keys(indentObj).length > 0) opts.indent = indentObj;
5128
+ const source = findChild(el, "w:sourceFileName");
5129
+ if (source) {
5130
+ const val = attr(source, "r:id");
5131
+ if (val) opts.sourceRId = val;
4575
5132
  }
4576
- const numPr = findChild(el, "w:numPr");
4577
- if (numPr) {
4578
- const ilvl = findChild(numPr, "w:ilvl");
4579
- const level = ilvl ? attrNum(ilvl, "w:val") ?? 0 : 0;
4580
- const numIdEl = findChild(numPr, "w:numId");
4581
- const numId = numIdEl ? attr(numIdEl, "w:val") : void 0;
4582
- if (numId !== void 0 && ctx.numberingCache.size > 0) {
4583
- const numEl = ctx.docx.numbering;
4584
- if (numEl) {
4585
- let abstractNumId;
4586
- for (const child of numEl.elements ?? []) {
4587
- if (child.name !== "w:num") continue;
4588
- if (attr(child, "w:numId") === numId) {
4589
- const absRef = findChild(child, "w:abstractNumId");
4590
- abstractNumId = absRef ? attr(absRef, "w:val") : void 0;
4591
- break;
4592
- }
4593
- }
4594
- if (abstractNumId !== void 0) opts.numbering = {
4595
- reference: `list_${numId}`,
4596
- level
4597
- };
4598
- else opts.bullet = { level };
4599
- } else opts.bullet = { level };
4600
- } else opts.bullet = { level };
5133
+ const marW = findChild(el, "w:marW");
5134
+ if (marW) {
5135
+ const val = attrNum(marW, "w:val");
5136
+ if (val !== void 0) opts.marginWidth = val;
4601
5137
  }
4602
- const tabs = findChild(el, "w:tabs");
4603
- if (tabs) {
4604
- const tabStops = [];
4605
- for (const tab of tabs.elements ?? []) {
4606
- if (tab.name !== "w:tab") continue;
4607
- const tabObj = {};
4608
- const pos = attrNum(tab, "w:pos");
4609
- if (pos !== void 0) tabObj.position = pos;
4610
- const val = attr(tab, "w:val");
4611
- if (val) tabObj.type = val;
4612
- const leader = attr(tab, "w:leader");
4613
- if (leader) tabObj.leader = leader;
4614
- tabStops.push(tabObj);
4615
- }
4616
- if (tabStops.length > 0) opts.tabStops = tabStops;
5138
+ const marH = findChild(el, "w:marH");
5139
+ if (marH) {
5140
+ const val = attrNum(marH, "w:val");
5141
+ if (val !== void 0) opts.marginHeight = val;
4617
5142
  }
4618
- for (const [name, optKey] of [
4619
- ["w:keepNext", "keepNext"],
4620
- ["w:keepLines", "keepLines"],
4621
- ["w:pageBreakBefore", "pageBreakBefore"],
4622
- ["w:widowControl", "widowControl"],
4623
- ["w:suppressLineNumbers", "suppressLineNumbers"],
4624
- ["w:contextualSpacing", "contextualSpacing"],
4625
- ["w:bidi", "bidirectional"],
4626
- ["w:wordWrap", "wordWrap"],
4627
- ["w:suppressAutoHyphens", "suppressAutoHyphens"],
4628
- ["w:adjustRightInd", "adjustRightInd"],
4629
- ["w:snapToGrid", "snapToGrid"],
4630
- ["w:mirrorIndents", "mirrorIndents"],
4631
- ["w:kinsoku", "kinsoku"],
4632
- ["w:topLinePunct", "topLinePunct"],
4633
- ["w:autoSpaceDE", "autoSpaceDE"],
4634
- ["w:overflowPunct", "overflowPunctuation"],
4635
- ["w:suppressOverlap", "suppressOverlap"]
4636
- ]) {
4637
- const child = findChild(el, name);
4638
- if (child) opts[optKey] = attrBool(child, "w:val") ?? true;
5143
+ const scrollbar = findChild(el, "w:scrollbar");
5144
+ if (scrollbar) {
5145
+ const val = attr(scrollbar, "w:val");
5146
+ if (val === "on" || val === "off" || val === "auto") opts.scrollbar = val;
4639
5147
  }
4640
- const pBdr = findChild(el, "w:pBdr");
4641
- if (pBdr) {
4642
- const border = {};
4643
- for (const side of [
4644
- "top",
4645
- "bottom",
4646
- "left",
4647
- "right"
4648
- ]) {
4649
- const sideEl = findChild(pBdr, `w:${side}`);
4650
- if (sideEl) {
4651
- const sideOpts = {};
4652
- const style = attr(sideEl, "w:val");
4653
- if (style) sideOpts.style = style;
4654
- const color = attr(sideEl, "w:color");
4655
- if (color) sideOpts.color = color;
4656
- const size = attrNum(sideEl, "w:sz");
4657
- if (size !== void 0) sideOpts.size = size;
4658
- const space = attrNum(sideEl, "w:space");
4659
- if (space !== void 0) sideOpts.space = space;
4660
- border[side] = sideOpts;
4661
- }
4662
- }
4663
- if (Object.keys(border).length > 0) opts.border = border;
5148
+ if (findChild(el, "w:noResizeAllowed")) opts.noResizeAllowed = true;
5149
+ if (findChild(el, "w:linkedToFile")) opts.linkedToFile = true;
5150
+ const longDesc = findChild(el, "w:longDesc");
5151
+ if (longDesc) {
5152
+ const val = attr(longDesc, "r:id");
5153
+ if (val) opts.longDescRId = val;
4664
5154
  }
4665
- const shd = findChild(el, "w:shd");
4666
- if (shd) {
4667
- const shdObj = {};
4668
- const fill = attr(shd, "w:fill");
4669
- if (fill) shdObj.fill = fill;
4670
- const color = attr(shd, "w:color");
4671
- if (color) shdObj.color = color;
4672
- const val = attr(shd, "w:val");
4673
- if (val) shdObj.type = val;
4674
- if (Object.keys(shdObj).length > 0) opts.shading = shdObj;
5155
+ return opts;
5156
+ }
5157
+ function parseDivsEl(el) {
5158
+ const result = [];
5159
+ for (const child of el.elements ?? []) if (child.name === "w:div") result.push(parseDivEl(child));
5160
+ return result;
5161
+ }
5162
+ function parseDivEl(el) {
5163
+ const opts = { id: attrNum(el, "w:id") ?? 0 };
5164
+ const marLeft = findChild(el, "w:marLeft");
5165
+ if (marLeft) {
5166
+ const val = attrNum(marLeft, "w:val");
5167
+ if (val !== void 0) opts.marginLeft = val;
4675
5168
  }
4676
- const textAlignment = findChild(el, "w:textAlignment");
4677
- if (textAlignment) {
4678
- const val = attr(textAlignment, "w:val");
4679
- if (val) opts.textAlignment = val;
5169
+ const marRight = findChild(el, "w:marRight");
5170
+ if (marRight) {
5171
+ const val = attrNum(marRight, "w:val");
5172
+ if (val !== void 0) opts.marginRight = val;
4680
5173
  }
4681
- const outlineLvl = findChild(el, "w:outlineLvl");
4682
- if (outlineLvl) {
4683
- const val = attrNum(outlineLvl, "w:val");
4684
- if (val !== void 0) opts.outlineLevel = val;
5174
+ const marTop = findChild(el, "w:marTop");
5175
+ if (marTop) {
5176
+ const val = attrNum(marTop, "w:val");
5177
+ if (val !== void 0) opts.marginTop = val;
4685
5178
  }
4686
- const rPr = findChild(el, "w:rPr");
4687
- if (rPr) opts.run = parseRunProperties(rPr);
4688
- const framePr = findChild(el, "w:framePr");
4689
- if (framePr) {
4690
- const frame = {};
4691
- for (const [attrName, optName] of [
4692
- ["w:dropCap", "dropCap"],
4693
- ["w:lines", "lines"],
4694
- ["w:wrap", "wrap"],
4695
- ["w:vAnchor", "vAnchor"],
4696
- ["w:hAnchor", "hAnchor"],
4697
- ["w:x", "x"],
4698
- ["w:y", "y"],
4699
- ["w:hRule", "hRule"],
4700
- ["w:hSpace", "hSpace"],
4701
- ["w:vSpace", "vSpace"]
4702
- ]) {
4703
- const val = attr(framePr, attrName);
4704
- if (val !== void 0) frame[optName] = val;
4705
- }
4706
- const w = attrNum(framePr, "w:w");
4707
- if (w !== void 0) frame.width = w;
4708
- const h = attrNum(framePr, "w:h");
4709
- if (h !== void 0) frame.height = h;
4710
- if (Object.keys(frame).length > 0) opts.frame = frame;
5179
+ const marBottom = findChild(el, "w:marBottom");
5180
+ if (marBottom) {
5181
+ const val = attrNum(marBottom, "w:val");
5182
+ if (val !== void 0) opts.marginBottom = val;
5183
+ }
5184
+ const blockQuote = findChild(el, "w:blockQuote");
5185
+ if (blockQuote) opts.blockQuote = attr(blockQuote, "w:val") !== "off";
5186
+ const bodyDiv = findChild(el, "w:bodyDiv");
5187
+ if (bodyDiv) opts.bodyDiv = attr(bodyDiv, "w:val") !== "off";
5188
+ const divBdr = findChild(el, "w:divBdr");
5189
+ if (divBdr) opts.border = parseDivBorderEl(divBdr);
5190
+ const divsChild = findChild(el, "w:divsChild");
5191
+ if (divsChild) {
5192
+ const children = parseDivsEl(divsChild);
5193
+ if (children.length > 0) opts.children = children;
4711
5194
  }
4712
5195
  return opts;
4713
5196
  }
4714
- /**
4715
- * Parse a w:p element into ParagraphOptions.
4716
- */
4717
- function parseParagraph(el, ctx) {
5197
+ function parseDivBorderEl(el) {
4718
5198
  const opts = {};
4719
- const pPr = findChild(el, "w:pPr");
4720
- if (pPr) Object.assign(opts, parseParagraphProperties(pPr, ctx));
4721
- const childList = [];
4722
- for (const child of el.elements ?? []) switch (child.name) {
4723
- case "w:pPr": break;
4724
- case "w:r": {
4725
- const drawingEl = findChild(child, "w:drawing");
4726
- if (drawingEl) {
4727
- const drawingChild = parseDrawingRun(drawingEl, ctx);
4728
- if (drawingChild) {
4729
- childList.push(drawingChild);
4730
- break;
4731
- }
4732
- }
4733
- const runOpts = parsedRunToOptions(parseRun(child, ctx));
4734
- if (runOpts !== null) childList.push(runOpts);
4735
- break;
4736
- }
4737
- case "w:hyperlink": {
4738
- const hl = {};
4739
- const rId = attr(child, "r:id");
4740
- if (rId) {
4741
- const target = ctx.docx.partRefs.hyperlinks.get(rId);
4742
- if (target) hl.link = target;
4743
- }
4744
- const anchor = attr(child, "w:anchor");
4745
- if (anchor) hl.anchor = anchor;
4746
- const tooltip = attr(child, "w:tooltip");
4747
- if (tooltip) hl.tooltip = tooltip;
4748
- const linkRuns = [];
4749
- for (const sub of child.elements ?? []) if (sub.name === "w:r") {
4750
- const runOpts = parsedRunToOptions(parseRun(sub, ctx));
4751
- linkRuns.push(runOpts);
4752
- }
4753
- if (linkRuns.length > 0) {
4754
- hl.children = linkRuns;
4755
- childList.push({ hyperlink: hl });
4756
- }
4757
- break;
4758
- }
4759
- case "w:bookmarkStart": {
4760
- const id = attrNum(child, "w:id");
4761
- const name = attr(child, "w:name");
4762
- if (id !== void 0 && name) childList.push({ bookmarkStart: {
4763
- id,
4764
- name
4765
- } });
4766
- break;
4767
- }
4768
- case "w:bookmarkEnd": {
4769
- const id = attrNum(child, "w:id");
4770
- if (id !== void 0) childList.push({ bookmarkEnd: id });
4771
- break;
4772
- }
4773
- case "w:commentRangeStart": {
4774
- const id = attrNum(child, "w:id");
4775
- if (id !== void 0) childList.push({ commentRangeStart: id });
4776
- break;
5199
+ for (const side of [
5200
+ "top",
5201
+ "left",
5202
+ "bottom",
5203
+ "right"
5204
+ ]) {
5205
+ const sideEl = findChild(el, `w:${side}`);
5206
+ if (sideEl) {
5207
+ const b = {};
5208
+ const val = attr(sideEl, "w:val");
5209
+ if (val) b.style = val;
5210
+ const color = attr(sideEl, "w:color");
5211
+ if (color) b.color = color;
5212
+ const sz = attrNum(sideEl, "w:sz");
5213
+ if (sz !== void 0) b.size = sz;
5214
+ opts[side] = b;
4777
5215
  }
4778
- case "w:commentRangeEnd": {
4779
- const id = attrNum(child, "w:id");
4780
- if (id !== void 0) childList.push({ commentRangeEnd: id });
4781
- break;
5216
+ }
5217
+ return opts;
5218
+ }
5219
+ function wsDivBorderXml(b) {
5220
+ const parts = ["<w:divBdr>"];
5221
+ const sides = [
5222
+ ["w:top", b.top],
5223
+ ["w:left", b.left],
5224
+ ["w:bottom", b.bottom],
5225
+ ["w:right", b.right]
5226
+ ];
5227
+ for (const [tag, side] of sides) {
5228
+ if (!side) continue;
5229
+ const attrParts = [`w:val="${wsEscapeAttr(side.style)}"`];
5230
+ if (side.color) attrParts.push(`w:color="${wsEscapeAttr(side.color)}"`);
5231
+ if (side.size !== void 0) attrParts.push(`w:sz="${side.size}"`);
5232
+ parts.push(`<${tag} ${attrParts.join(" ")}/>`);
5233
+ }
5234
+ parts.push("</w:divBdr>");
5235
+ return parts.join("");
5236
+ }
5237
+ function wsDivXml(d) {
5238
+ const parts = [`<w:div w:id="${d.id}">`];
5239
+ if (d.blockQuote !== void 0) parts.push(wsStringVal("w:blockQuote", d.blockQuote ? "on" : "off"));
5240
+ if (d.bodyDiv !== void 0) parts.push(wsStringVal("w:bodyDiv", d.bodyDiv ? "on" : "off"));
5241
+ parts.push(wsNumVal("w:marLeft", d.marginLeft));
5242
+ parts.push(wsNumVal("w:marRight", d.marginRight));
5243
+ parts.push(wsNumVal("w:marTop", d.marginTop));
5244
+ parts.push(wsNumVal("w:marBottom", d.marginBottom));
5245
+ if (d.border) parts.push(wsDivBorderXml(d.border));
5246
+ if (d.children?.length) {
5247
+ parts.push("<w:divsChild>");
5248
+ for (const child of d.children) parts.push(wsDivXml(child));
5249
+ parts.push("</w:divsChild>");
5250
+ }
5251
+ parts.push("</w:div>");
5252
+ return parts.join("");
5253
+ }
5254
+ function framesetXml(fs) {
5255
+ const parts = ["<w:frameset>"];
5256
+ if (fs.size !== void 0) parts.push(wsStringVal("w:sz", fs.size));
5257
+ if (fs.splitbar) {
5258
+ parts.push("<w:framesetSplitbar>");
5259
+ if (fs.splitbar.width !== void 0) parts.push(`<w:w w:w="${fs.splitbar.width}" w:type="dxa"/>`);
5260
+ if (fs.splitbar.color !== void 0) parts.push(wsStringVal("w:color", fs.splitbar.color));
5261
+ if (fs.splitbar.noBorder) parts.push("<w:noBorder/>");
5262
+ if (fs.splitbar.flatBorders) parts.push("<w:flatBorders/>");
5263
+ parts.push("</w:framesetSplitbar>");
5264
+ }
5265
+ if (fs.layout !== void 0) parts.push(`<w:frameLayout w:val="${fs.layout}"/>`);
5266
+ if (fs.title !== void 0) parts.push(wsStringVal("w:title", fs.title));
5267
+ if (fs.children) for (const child of fs.children) if ("children" in child || "layout" in child || "splitbar" in child) parts.push(framesetXml(child));
5268
+ else parts.push(frameXml(child));
5269
+ parts.push("</w:frameset>");
5270
+ return parts.join("");
5271
+ }
5272
+ function frameXml(f) {
5273
+ const parts = ["<w:frame>"];
5274
+ if (f.size !== void 0) parts.push(wsStringVal("w:sz", f.size));
5275
+ if (f.name !== void 0) parts.push(wsStringVal("w:name", f.name));
5276
+ if (f.title !== void 0) parts.push(wsStringVal("w:title", f.title));
5277
+ if (f.sourceRId !== void 0) parts.push(`<w:sourceFileName r:id="${wsEscapeAttr(f.sourceRId)}"/>`);
5278
+ if (f.marginWidth !== void 0) parts.push(wsNumVal("w:marW", f.marginWidth));
5279
+ if (f.marginHeight !== void 0) parts.push(wsNumVal("w:marH", f.marginHeight));
5280
+ if (f.scrollbar !== void 0) parts.push(`<w:scrollbar w:val="${f.scrollbar}"/>`);
5281
+ if (f.noResizeAllowed) parts.push("<w:noResizeAllowed/>");
5282
+ if (f.linkedToFile) parts.push("<w:linkedToFile/>");
5283
+ if (f.longDescRId !== void 0) parts.push(`<w:longDesc r:id="${wsEscapeAttr(f.longDescRId)}"/>`);
5284
+ parts.push("</w:frame>");
5285
+ return parts.join("");
5286
+ }
5287
+ const webSettingsDesc = {
5288
+ kind: "custom",
5289
+ stringify(opts, _ctx) {
5290
+ const p = [`<w:webSettings ${WS_NS}>`];
5291
+ if (opts.frameset !== void 0) p.push(framesetXml(opts.frameset));
5292
+ if (opts.divs?.length) {
5293
+ p.push("<w:divs>");
5294
+ for (const d of opts.divs) p.push(wsDivXml(d));
5295
+ p.push("</w:divs>");
4782
5296
  }
4783
- case "w:commentReference": {
4784
- const id = attrNum(child, "w:id");
4785
- if (id !== void 0) childList.push({ commentReference: id });
4786
- break;
5297
+ if (opts.encoding !== void 0) p.push(wsStringVal("w:encoding", opts.encoding));
5298
+ if (opts.optimizeForBrowser !== void 0) p.push(wsOnOff("w:optimizeForBrowser", opts.optimizeForBrowser));
5299
+ if (opts.relyOnVML !== void 0) p.push(wsOnOff("w:relyOnVML", opts.relyOnVML));
5300
+ if (opts.allowPNG !== void 0) p.push(wsOnOff("w:allowPNG", opts.allowPNG));
5301
+ if (opts.doNotRelyOnCSS !== void 0) p.push(wsOnOff("w:doNotRelyOnCSS", opts.doNotRelyOnCSS));
5302
+ if (opts.doNotSaveAsSingleFile !== void 0) p.push(wsOnOff("w:doNotSaveAsSingleFile", opts.doNotSaveAsSingleFile));
5303
+ if (opts.doNotOrganizeInFolder !== void 0) p.push(wsOnOff("w:doNotOrganizeInFolder", opts.doNotOrganizeInFolder));
5304
+ if (opts.doNotUseLongFileNames !== void 0) p.push(wsOnOff("w:doNotUseLongFileNames", opts.doNotUseLongFileNames));
5305
+ if (opts.pixelsPerInch !== void 0) p.push(wsNumVal("w:pixelsPerInch", opts.pixelsPerInch));
5306
+ if (opts.targetScreenSz !== void 0) p.push(wsStringVal("w:targetScreenSz", opts.targetScreenSz));
5307
+ if (opts.saveSmartTagsAsXml !== void 0) p.push(wsOnOff("w:saveSmartTagsAsXml", opts.saveSmartTagsAsXml));
5308
+ p.push("</w:webSettings>");
5309
+ return p.join("");
5310
+ },
5311
+ parse(el, _ctx) {
5312
+ const opts = {};
5313
+ const frameset = findChild(el, "w:frameset");
5314
+ if (frameset) opts.frameset = parseFramesetEl(frameset);
5315
+ const divs = findChild(el, "w:divs");
5316
+ if (divs) {
5317
+ const parsed = parseDivsEl(divs);
5318
+ if (parsed.length > 0) opts.divs = parsed;
4787
5319
  }
4788
- case "m:oMath": {
4789
- const mathChildren = parseMathChildren(child);
4790
- childList.push({ math: { children: mathChildren } });
4791
- break;
5320
+ const encoding = findChild(el, "w:encoding");
5321
+ if (encoding) {
5322
+ const val = attr(encoding, "w:val");
5323
+ if (val) opts.encoding = val;
4792
5324
  }
4793
- case "w:ins": {
4794
- const insRun = findChild(child, "w:r");
4795
- if (insRun) {
4796
- const runOpts = parsedRunToOptions(parseRun(insRun, ctx));
4797
- if (runOpts !== null && typeof runOpts === "object" && !("commentReference" in runOpts)) childList.push({ insertion: {
4798
- id: attrNum(child, "w:id") ?? 0,
4799
- author: attr(child, "w:author") ?? "",
4800
- date: attr(child, "w:date") ?? "",
4801
- ...runOpts
4802
- } });
4803
- }
4804
- break;
5325
+ for (const [name, optKey] of [
5326
+ ["w:optimizeForBrowser", "optimizeForBrowser"],
5327
+ ["w:relyOnVML", "relyOnVML"],
5328
+ ["w:allowPNG", "allowPNG"],
5329
+ ["w:doNotRelyOnCSS", "doNotRelyOnCSS"],
5330
+ ["w:doNotSaveAsSingleFile", "doNotSaveAsSingleFile"],
5331
+ ["w:doNotOrganizeInFolder", "doNotOrganizeInFolder"],
5332
+ ["w:doNotUseLongFileNames", "doNotUseLongFileNames"],
5333
+ ["w:saveSmartTagsAsXml", "saveSmartTagsAsXml"]
5334
+ ]) {
5335
+ const child = findChild(el, name);
5336
+ if (child) opts[optKey] = attrBool(child, "w:val") ?? true;
4805
5337
  }
4806
- case "w:del": {
4807
- const delRun = findChild(child, "w:r");
4808
- if (delRun) {
4809
- const runOpts = parsedRunToOptions(parseRun(delRun, ctx));
4810
- if (runOpts !== null && typeof runOpts === "object" && !("commentReference" in runOpts)) childList.push({ deletion: {
4811
- id: attrNum(child, "w:id") ?? 0,
4812
- author: attr(child, "w:author") ?? "",
4813
- date: attr(child, "w:date") ?? "",
4814
- ...runOpts
4815
- } });
4816
- }
4817
- break;
5338
+ const ppi = findChild(el, "w:pixelsPerInch");
5339
+ if (ppi) {
5340
+ const val = attrNum(ppi, "w:val");
5341
+ if (val !== void 0) opts.pixelsPerInch = val;
4818
5342
  }
4819
- default: break;
4820
- }
4821
- if (childList.length > 0) {
4822
- if (childList.every((c) => typeof c === "object" && c !== null && "text" in c && Object.keys(c).length === 1)) {
4823
- const combined = childList.map((c) => c.text).join("");
4824
- if (combined && Object.keys(opts).length === 0) return combined;
4825
- if (combined) {
4826
- opts.text = combined;
4827
- return opts;
4828
- }
5343
+ const targetSz = findChild(el, "w:targetScreenSz");
5344
+ if (targetSz) {
5345
+ const val = attr(targetSz, "w:val");
5346
+ if (val) opts.targetScreenSz = val;
4829
5347
  }
4830
- opts.children = childList;
5348
+ return opts;
4831
5349
  }
4832
- return opts;
4833
- }
5350
+ };
4834
5351
  //#endregion
4835
5352
  //#region src/parts/styles/external-styles-factory.ts
4836
5353
  /**
@@ -5062,6 +5579,6 @@ var DocxReadContext = class {
5062
5579
  }
5063
5580
  };
5064
5581
  //#endregion
5065
- export { TableAnchorType as $, EditGroupType as A, Styles as B, DocPartType as C, CharacterSet as D, fontTableDesc as E, parseToc as F, parseNumberingDefinitions as G, buildStyleCache as H, SdtDateMappingType as I, TABLE_BORDERS_NONE as J, LevelFormat as K, SdtLock as L, endnotesDesc as M, footnotesDesc as N, SubDocCollection as O, stringifyTableOfContents as P, RelativeVerticalPosition as Q, StyleLevel as R, DocPartGallery as S, bibliographyDesc as T, parseStyleDefinitions as U, buildNumberingCache as V, Numbering as W, OverlapType as X, TableLayoutType as Y, RelativeHorizontalPosition as Z, relationshipsDesc as _, stringifyBodyChild as a, PositionalTabLeader as at, commentsDesc as b, frameXml as c, UnderlineType as ct, customPropertiesDesc as d, TextEffect as dt, ProofErrorType as et, corePropertiesDesc as f, PageNumber as ft, subDocDesc as g, AlignmentType as gt, sdtBlockDesc as h, HeadingLevel as ht, parseParagraphProperties as i, PositionalTabAlignment as it, parseSdtBlock as j, AltChunkCollection as k, framesetXml as l, createImageData as lt, customXmlBlockDesc as m, TextboxTightWrapType as mt, DocxWriteContext as n, createFormFieldData as nt, stringifyDocumentXml as o, PositionalTabRelativeTo as ot, altChunkDesc as p, TextAlignmentType as pt, LevelSuffix as q, parseParagraph as r, RubyAlign as rt, TargetScreenSize as s, EmphasisMarkType as st, DocxReadContext as t, FormFieldTextType as tt, webSettingsDesc as u, HighlightColor as ut, buildContentTypes as v, glossaryDesc as w, DocPartBehavior as x, contentTypesDesc as y, settingsDesc as z };
5582
+ export { RelativeVerticalPosition as $, footnotesDesc as A, settingsDesc as B, fontTableDesc as C, EditGroupType as D, AltChunkCollection as E, stringifyTableOfContents as F, Numbering as G, buildNumberingCache as H, parseToc as I, LevelSuffix as J, parseNumberingDefinitions as K, SdtDateMappingType as L, parseParagraphProperties as M, stringifyBodyChild as N, parseSdtBlock as O, stringifyDocumentXml as P, RelativeHorizontalPosition as Q, SdtLock as R, bibliographyDesc as S, SubDocCollection as T, buildStyleCache as U, Styles as V, parseStyleDefinitions as W, TableLayoutType as X, TABLE_BORDERS_NONE as Y, OverlapType as Z, commentsDesc as _, AlignmentType as _t, framesetXml as a, PositionalTabAlignment as at, DocPartType as b, corePropertiesDesc as c, EmphasisMarkType as ct, sdtBlockDesc as d, HighlightColor as dt, TableAnchorType as et, setBodyParseChild as f, TextEffect as ft, contentTypesDesc as g, HeadingLevel as gt, buildContentTypes as h, TextboxTightWrapType as ht, frameXml as i, RubyAlign as it, parseParagraph as j, endnotesDesc as k, altChunkDesc as l, UnderlineType as lt, relationshipsDesc as m, TextAlignmentType as mt, DocxWriteContext as n, FormFieldTextType as nt, webSettingsDesc as o, PositionalTabLeader as ot, subDocDesc as p, PageNumber as pt, LevelFormat as q, TargetScreenSize as r, createFormFieldData as rt, customPropertiesDesc as s, PositionalTabRelativeTo as st, DocxReadContext as t, ProofErrorType as tt, customXmlBlockDesc as u, createImageData as ut, DocPartBehavior as v, CharacterSet as w, glossaryDesc as x, DocPartGallery as y, StyleLevel as z };
5066
5583
 
5067
- //# sourceMappingURL=context-Ca7nmKV2.mjs.map
5584
+ //# sourceMappingURL=context-CERMOUn0.mjs.map