@portone/docx-editor 0.4.0 → 0.5.1

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.
Files changed (180) hide show
  1. package/CHANGELOG.md +201 -0
  2. package/CONTRIBUTING.md +2 -0
  3. package/assets/editor.png +0 -0
  4. package/dist/DocxEditor.d.ts +1 -1
  5. package/dist/DocxEditor.js +44 -25
  6. package/dist/docx/cloning.js +4 -9
  7. package/dist/docx/commentOnlyChange.d.ts +5 -3
  8. package/dist/docx/comments/grammar.d.ts +27 -10
  9. package/dist/docx/comments/grammar.js +18 -67
  10. package/dist/docx/comments/model.d.ts +5 -6
  11. package/dist/docx/comments/model.js +0 -9
  12. package/dist/docx/comments/parts.d.ts +16 -10
  13. package/dist/docx/comments/parts.js +65 -13
  14. package/dist/docx/comments/people.d.ts +11 -3
  15. package/dist/docx/comments/people.js +20 -6
  16. package/dist/docx/comments/policy.js +7 -1
  17. package/dist/docx/comments/reading.d.ts +4 -2
  18. package/dist/docx/comments/reading.js +1 -14
  19. package/dist/docx/comments/writing.js +65 -28
  20. package/dist/docx/exportDocx.js +10 -14
  21. package/dist/docx/exportRefs.d.ts +8 -3
  22. package/dist/docx/exportRefs.js +2 -1
  23. package/dist/docx/fidelity.js +24 -10
  24. package/dist/docx/fields.d.ts +42 -0
  25. package/dist/docx/fields.js +76 -0
  26. package/dist/docx/formatting/styles.d.ts +0 -2
  27. package/dist/docx/formatting/styles.js +2 -15
  28. package/dist/docx/headersFooters.d.ts +89 -20
  29. package/dist/docx/headersFooters.js +163 -172
  30. package/dist/docx/identities.js +17 -26
  31. package/dist/docx/importDocx.d.ts +1 -1
  32. package/dist/docx/importDocx.js +100 -48
  33. package/dist/docx/importParagraph.d.ts +18 -5
  34. package/dist/docx/importParagraph.js +75 -128
  35. package/dist/docx/importPolicy.d.ts +70 -0
  36. package/dist/docx/importPolicy.js +195 -0
  37. package/dist/docx/importPreserved.d.ts +30 -0
  38. package/dist/docx/importPreserved.js +54 -0
  39. package/dist/docx/importTable.js +56 -12
  40. package/dist/docx/invariants.js +16 -18
  41. package/dist/docx/notes.d.ts +6 -1
  42. package/dist/docx/notes.js +6 -16
  43. package/dist/docx/pageGeometry.d.ts +5 -14
  44. package/dist/docx/pageGeometry.js +0 -12
  45. package/dist/docx/protectionPolicy.d.ts +13 -5
  46. package/dist/docx/protectionPolicy.js +32 -22
  47. package/dist/docx/scan.d.ts +18 -8
  48. package/dist/docx/scan.js +17 -11
  49. package/dist/docx/sections.d.ts +126 -0
  50. package/dist/docx/sections.js +207 -0
  51. package/dist/docx/serializeBlock.d.ts +13 -4
  52. package/dist/docx/serializeBlock.js +16 -18
  53. package/dist/docx/serializeParagraph.d.ts +9 -4
  54. package/dist/docx/serializeParagraph.js +23 -58
  55. package/dist/docx/serializePreserved.d.ts +14 -0
  56. package/dist/docx/serializePreserved.js +24 -0
  57. package/dist/docx/serializeStory.d.ts +17 -0
  58. package/dist/docx/serializeStory.js +17 -0
  59. package/dist/docx/serializeTable.js +10 -13
  60. package/dist/docx/session.d.ts +23 -6
  61. package/dist/docx/session.js +26 -5
  62. package/dist/docx/story.d.ts +140 -0
  63. package/dist/docx/story.js +237 -0
  64. package/dist/docx/storyProjection.js +6 -1
  65. package/dist/docx/tableTemplate.d.ts +25 -0
  66. package/dist/docx/tableTemplate.js +30 -16
  67. package/dist/docx/wrappers.d.ts +67 -0
  68. package/dist/docx/wrappers.js +117 -0
  69. package/dist/editor/clipboard/blockReaders.d.ts +74 -0
  70. package/dist/editor/clipboard/blockReaders.js +193 -0
  71. package/dist/editor/clipboard/htmlReader.d.ts +26 -0
  72. package/dist/editor/clipboard/htmlReader.js +376 -0
  73. package/dist/editor/clipboard/inlineFormatting.d.ts +0 -7
  74. package/dist/editor/clipboard/inlineFormatting.js +1 -7
  75. package/dist/editor/clipboard/internalChannel.d.ts +57 -0
  76. package/dist/editor/clipboard/internalChannel.js +58 -0
  77. package/dist/editor/clipboard/normalizers.d.ts +99 -0
  78. package/dist/editor/clipboard/normalizers.js +199 -0
  79. package/dist/editor/clipboard/parser.d.ts +34 -0
  80. package/dist/editor/clipboard/parser.js +58 -0
  81. package/dist/editor/clipboard/plugin.d.ts +21 -0
  82. package/dist/editor/clipboard/plugin.js +188 -0
  83. package/dist/editor/clipboard/readContext.d.ts +34 -0
  84. package/dist/editor/clipboard/readContext.js +25 -0
  85. package/dist/editor/clipboard/readers.d.ts +33 -0
  86. package/dist/editor/clipboard/readers.js +37 -0
  87. package/dist/editor/clipboard/source.d.ts +12 -0
  88. package/dist/editor/clipboard/source.js +21 -0
  89. package/dist/editor/commands/comments/editing.d.ts +26 -6
  90. package/dist/editor/commands/comments/editing.js +177 -106
  91. package/dist/editor/commands/comments/model.d.ts +34 -17
  92. package/dist/editor/commands/comments/model.js +11 -0
  93. package/dist/editor/commands/comments/reading.d.ts +5 -3
  94. package/dist/editor/commands/comments/reading.js +8 -58
  95. package/dist/editor/commands/index.d.ts +2 -2
  96. package/dist/editor/commands/index.js +2 -0
  97. package/dist/editor/commands/linkCommands.js +20 -5
  98. package/dist/editor/commands/listCommands.d.ts +6 -0
  99. package/dist/editor/commands/listCommands.js +3 -2
  100. package/dist/editor/commands/lockCommands.js +59 -16
  101. package/dist/editor/commands/noteQueries.d.ts +22 -5
  102. package/dist/editor/commands/noteQueries.js +34 -6
  103. package/dist/editor/commands/paragraphCommands.js +2 -2
  104. package/dist/editor/createEditor.js +13 -3
  105. package/dist/editor/documentStyles.d.ts +26 -4
  106. package/dist/editor/documentStyles.js +9 -4
  107. package/dist/editor/imageFiles.d.ts +2 -2
  108. package/dist/editor/imageFiles.js +2 -0
  109. package/dist/editor/insertTable.d.ts +1 -1
  110. package/dist/editor/insertTable.js +2 -2
  111. package/dist/editor/plainText.d.ts +12 -0
  112. package/dist/editor/plainText.js +2 -1
  113. package/dist/editor/plugins/columnResize.js +6 -3
  114. package/dist/editor/plugins/commentComposer.d.ts +28 -0
  115. package/dist/editor/plugins/commentComposer.js +46 -0
  116. package/dist/editor/plugins/commentDecorations.d.ts +29 -2
  117. package/dist/editor/plugins/commentDecorations.js +89 -15
  118. package/dist/editor/plugins/documentProjection.d.ts +31 -0
  119. package/dist/editor/plugins/documentProjection.js +22 -0
  120. package/dist/editor/plugins/imagePaste.js +15 -8
  121. package/dist/editor/plugins/linkPanel.d.ts +7 -3
  122. package/dist/editor/plugins/linkPanel.js +13 -27
  123. package/dist/editor/plugins/panelState.d.ts +67 -0
  124. package/dist/editor/plugins/panelState.js +54 -0
  125. package/dist/editor/plugins/tableContextMenu.d.ts +1 -1
  126. package/dist/editor/plugins/tableContextMenu.js +30 -47
  127. package/dist/editor/plugins/textContextMenu.d.ts +1 -1
  128. package/dist/editor/plugins/textContextMenu.js +30 -47
  129. package/dist/ooxml/fragment.d.ts +11 -0
  130. package/dist/ooxml/fragment.js +14 -4
  131. package/dist/ooxml/image.d.ts +3 -4
  132. package/dist/ooxml/image.js +50 -5
  133. package/dist/ooxml/names.d.ts +6 -0
  134. package/dist/ooxml/names.js +2 -0
  135. package/dist/ooxml/props.d.ts +10 -0
  136. package/dist/ooxml/props.js +28 -4
  137. package/dist/ooxml/rangeMarkers.d.ts +5 -0
  138. package/dist/ooxml/rangeMarkers.js +24 -0
  139. package/dist/page/PageGuides.d.ts +7 -3
  140. package/dist/page/PageGuides.js +13 -24
  141. package/dist/page/pageLayout.d.ts +64 -5
  142. package/dist/page/pageLayout.js +90 -29
  143. package/dist/page/usePageLayout.d.ts +14 -4
  144. package/dist/page/usePageLayout.js +19 -20
  145. package/dist/schema/attrRoles.js +46 -23
  146. package/dist/schema/clipboard.d.ts +72 -0
  147. package/dist/schema/clipboard.js +288 -0
  148. package/dist/schema/docxSchema.d.ts +9 -1
  149. package/dist/schema/docxSchema.js +217 -165
  150. package/dist/schema/editGuard.d.ts +1 -1
  151. package/dist/schema/guards.js +2 -2
  152. package/dist/schema/index.d.ts +1 -0
  153. package/dist/schema/locks.d.ts +3 -0
  154. package/dist/schema/locks.js +29 -12
  155. package/dist/schema/preservedFragments.d.ts +12 -0
  156. package/dist/schema/preservedFragments.js +38 -0
  157. package/dist/schema/preservedGuards.d.ts +9 -7
  158. package/dist/schema/preservedGuards.js +112 -11
  159. package/dist/schema/protection.d.ts +34 -5
  160. package/dist/schema/protection.js +42 -14
  161. package/dist/schema/rendering.d.ts +14 -0
  162. package/dist/schema/rendering.js +27 -12
  163. package/dist/schema/stories.d.ts +49 -0
  164. package/dist/schema/stories.js +78 -0
  165. package/dist/schema/wrappers.d.ts +58 -0
  166. package/dist/schema/wrappers.js +77 -0
  167. package/dist/styles/classNames.d.ts +3 -5
  168. package/dist/styles/classNames.js +3 -5
  169. package/dist/styles.css +74 -12
  170. package/dist/table/resize.d.ts +5 -3
  171. package/dist/ui/CommentsPanel.d.ts +1 -3
  172. package/dist/ui/CommentsPanel.js +24 -15
  173. package/dist/ui/NotesPanel.js +2 -2
  174. package/dist/ui/TextMenu.d.ts +1 -3
  175. package/dist/ui/TextMenu.js +10 -6
  176. package/dist/ui/comments/CommentComposer.d.ts +6 -1
  177. package/dist/ui/comments/CommentComposer.js +26 -3
  178. package/package.json +5 -4
  179. package/dist/editor/externalClipboard.d.ts +0 -22
  180. package/dist/editor/externalClipboard.js +0 -486
@@ -1,131 +1,32 @@
1
1
  // src/docx/headersFooters.ts
2
- import { ALIGN_BY_JC, isOnElement } from "../ooxml/units.js";
2
+ import { toParagraphFormat } from "../model/format.js";
3
+ import { NAMESPACES } from "../ooxml/names.js";
3
4
  import {
4
- attributeByLocalName,
5
- decodeUtf8,
6
- elementChildren,
7
- parseXml,
8
- R_NS,
9
- W_NS
10
- } from "../ooxml/xml.js";
5
+ ensureRootDeclarations
6
+ } from "../ooxml/partSplice.js";
7
+ import { isOnElement } from "../ooxml/units.js";
8
+ import { decodeUtf8, encodeUtf8, parseXml, R_NS, W_NS } from "../ooxml/xml.js";
9
+ import { docxSchema } from "../schema/index.js";
10
+ import { sameSource } from "../schema/sourceEquality.js";
11
+ import { storyKey, storyNodeOf } from "../schema/stories.js";
12
+ import { NO_EXPORT_REFS } from "./exportRefs.js";
13
+ import { fieldSpans, isFieldCharacter } from "./fields.js";
11
14
  import { relatedPartPath } from "./packageParts.js";
12
15
  import { readRelationships, relsPathOf, resolveTarget } from "./relationships.js";
16
+ import {
17
+ HEADER_FOOTER_VARIANTS
18
+ } from "./sections.js";
19
+ import { serializeStory } from "./serializeStory.js";
20
+ import {
21
+ readStory,
22
+ storyLeafText
23
+ } from "./story.js";
13
24
  var EMPTY_VARIANTS = {
14
25
  default: null,
15
26
  first: null,
16
27
  even: null
17
28
  };
18
- var NO_HEADERS_FOOTERS = {
19
- headers: EMPTY_VARIANTS,
20
- footers: EMPTY_VARIANTS,
21
- firstPageDifferent: false,
22
- evenAndOdd: false,
23
- pageNumberStart: 1
24
- };
25
- function firstSectPrIn(root) {
26
- const namespaced = root.getElementsByTagNameNS(W_NS, "sectPr").item(0);
27
- if (namespaced) return namespaced;
28
- for (const el of root.getElementsByTagName("*")) {
29
- if (el.localName === "sectPr") return el;
30
- }
31
- return null;
32
- }
33
- function pageField(instruction) {
34
- const name = instruction.trim().split(/\s+/, 1)[0]?.toUpperCase();
35
- return name === "PAGE" || name === "NUMPAGES" ? name : null;
36
- }
37
- function paragraphSegments(paragraph) {
38
- const segments = [];
39
- const fields = [];
40
- const suppressed = () => fields.some((field) => !field.separated || field.field !== null);
41
- const text = (value) => {
42
- if (!value || suppressed()) return;
43
- const previous = segments.at(-1);
44
- if (previous?.kind === "text") previous.value += value;
45
- else segments.push({ kind: "text", value });
46
- };
47
- const dynamic = (field) => {
48
- if (!suppressed()) segments.push({ kind: "field", field });
49
- };
50
- const visit = (el) => {
51
- if (el.namespaceURI === W_NS && (el.localName === "drawing" || el.localName === "pict" || el.localName === "object" || el.localName === "tbl" || el.localName === "txbxContent")) {
52
- return;
53
- }
54
- if (el.namespaceURI === W_NS && el.localName === "fldSimple") {
55
- const field = pageField(attributeByLocalName(el, "instr") ?? "");
56
- if (field) dynamic(field);
57
- else for (const child of elementChildren(el)) visit(child);
58
- return;
59
- }
60
- if (el.namespaceURI === W_NS && el.localName === "fldChar") {
61
- const kind = attributeByLocalName(el, "fldCharType");
62
- if (kind === "begin") {
63
- fields.push({ instruction: "", separated: false, field: null });
64
- } else if (kind === "separate") {
65
- const active = fields.at(-1);
66
- if (active) {
67
- active.field = pageField(active.instruction);
68
- active.separated = true;
69
- if (active.field) {
70
- const outerSuppresses = fields.slice(0, -1).some((field) => !field.separated || field.field !== null);
71
- if (!outerSuppresses) {
72
- segments.push({ kind: "field", field: active.field });
73
- }
74
- }
75
- }
76
- } else if (kind === "end") {
77
- const active = fields.pop();
78
- if (active && !active.separated) {
79
- const field = pageField(active.instruction);
80
- if (field) dynamic(field);
81
- }
82
- }
83
- return;
84
- }
85
- if (el.namespaceURI === W_NS && el.localName === "instrText") {
86
- const active = fields.at(-1);
87
- if (active && !active.separated)
88
- active.instruction += el.textContent ?? "";
89
- return;
90
- }
91
- if (el.namespaceURI === W_NS && el.localName === "t") {
92
- text(el.textContent ?? "");
93
- return;
94
- }
95
- if (el.namespaceURI === W_NS && el.localName === "tab") {
96
- text(" ");
97
- return;
98
- }
99
- if (el.namespaceURI === W_NS && (el.localName === "br" || el.localName === "cr")) {
100
- text("\n");
101
- return;
102
- }
103
- for (const child of elementChildren(el)) visit(child);
104
- };
105
- for (const child of elementChildren(paragraph)) visit(child);
106
- return segments;
107
- }
108
- function readContent(bytes) {
109
- const root = parseXml(decodeUtf8(bytes).text).documentElement;
110
- const paragraphs = elementChildren(root).filter(
111
- (child) => child.namespaceURI === W_NS && child.localName === "p"
112
- );
113
- const segments = [];
114
- paragraphs.forEach((paragraph, index) => {
115
- if (index > 0) segments.push({ kind: "text", value: "\n" });
116
- segments.push(...paragraphSegments(paragraph));
117
- });
118
- const pPr = paragraphs[0] ? elementChildren(paragraphs[0]).find(
119
- (child) => child.namespaceURI === W_NS && child.localName === "pPr"
120
- ) : void 0;
121
- const jc = pPr ? elementChildren(pPr).find(
122
- (child) => child.namespaceURI === W_NS && child.localName === "jc"
123
- ) : void 0;
124
- return {
125
- segments,
126
- align: jc ? ALIGN_BY_JC[attributeByLocalName(jc, "val") ?? ""] ?? null : null
127
- };
128
- }
29
+ var PART_ROOT = { header: "hdr", footer: "ftr" };
129
30
  function settingsEvenAndOdd(parts, mainPartPath) {
130
31
  const path = relatedPartPath(parts, mainPartPath, `${R_NS}/settings`);
131
32
  const bytes = path === null ? void 0 : parts.get(path);
@@ -134,76 +35,166 @@ function settingsEvenAndOdd(parts, mainPartPath) {
134
35
  const setting = root.getElementsByTagNameNS(W_NS, "evenAndOddHeaders").item(0);
135
36
  return isOnElement(setting);
136
37
  }
137
- function readVariants(parts, mainPartPath, sectPr, kind) {
138
- const relationships = new Map(
139
- readRelationships(parts, relsPathOf(mainPartPath)).map((entry) => [
140
- entry.id,
141
- entry
142
- ])
143
- );
144
- const variants = { ...EMPTY_VARIANTS };
145
- for (const reference of elementChildren(sectPr)) {
146
- if (reference.localName !== `${kind}Reference`) continue;
147
- const type = attributeByLocalName(reference, "type") ?? "default";
148
- if (type !== "default" && type !== "first" && type !== "even") continue;
149
- const id = reference.getAttributeNS(R_NS, "id") ?? attributeByLocalName(reference, "id");
150
- if (!id) continue;
151
- const relationship = relationships.get(id);
152
- if (!relationship || relationship.external || relationship.type !== `${R_NS}/${kind}`) {
38
+ function kindOf(relationshipType) {
39
+ if (relationshipType === `${R_NS}/header`) return "header";
40
+ if (relationshipType === `${R_NS}/footer`) return "footer";
41
+ return null;
42
+ }
43
+ function readHeaderFooterStories(parts, mainPartPath, referenced, depsFor) {
44
+ const keyByRelId = /* @__PURE__ */ new Map();
45
+ const read = /* @__PURE__ */ new Map();
46
+ for (const relationship of readRelationships(
47
+ parts,
48
+ relsPathOf(mainPartPath)
49
+ )) {
50
+ if (!referenced.has(relationship.id)) continue;
51
+ const kind = relationship.external ? null : kindOf(relationship.type);
52
+ if (kind === null) continue;
53
+ const partPath = resolveTarget(mainPartPath, relationship.target);
54
+ const key = storyKey(kind, partPath);
55
+ if (read.has(key)) {
56
+ keyByRelId.set(relationship.id, key);
57
+ continue;
58
+ }
59
+ const bytes = parts.get(partPath);
60
+ if (!bytes) continue;
61
+ const xml = decodeUtf8(bytes).text;
62
+ const root = parseXml(xml).documentElement;
63
+ if (root.namespaceURI !== W_NS || root.localName !== PART_ROOT[kind]) {
153
64
  continue;
154
65
  }
155
- const bytes = parts.get(resolveTarget(mainPartPath, relationship.target));
156
- if (bytes) variants[type] = readContent(bytes);
66
+ read.set(
67
+ key,
68
+ readStory(
69
+ { kind, id: partPath, partPath },
70
+ { el: root, xml },
71
+ depsFor(partPath)
72
+ )
73
+ );
74
+ keyByRelId.set(relationship.id, key);
157
75
  }
158
- return variants;
76
+ return {
77
+ stories: Array.from(read.values()),
78
+ refs: { keyByRelId, evenAndOdd: settingsEvenAndOdd(parts, mainPartPath) }
79
+ };
159
80
  }
160
- function pageNumberStart(sectPr) {
161
- const pgNumType = elementChildren(sectPr).find(
162
- (child) => child.localName === "pgNumType"
163
- );
164
- const declared = pgNumType ? attributeByLocalName(pgNumType, "start") : null;
165
- if (declared === null) return 1;
166
- const start = Number(declared);
167
- return Number.isSafeInteger(start) && start >= 0 ? start : 1;
81
+ function firstAlign(story) {
82
+ for (let at = 0; at < story.childCount; at += 1) {
83
+ const block = story.child(at);
84
+ if (block.type !== docxSchema.nodes.paragraph) continue;
85
+ return toParagraphFormat(block.attrs.format)?.align ?? null;
86
+ }
87
+ return null;
168
88
  }
169
- function readHeadersFooters(parts, mainPartPath, body) {
170
- const sectPr = firstSectPrIn(body);
171
- if (!sectPr) return NO_HEADERS_FOOTERS;
89
+ function variantContent(ids, kind, refs, storyOf) {
90
+ const variants = { ...EMPTY_VARIANTS };
91
+ for (const variant of HEADER_FOOTER_VARIANTS) {
92
+ const id = ids[variant];
93
+ const key = id === null ? void 0 : refs.keyByRelId.get(id);
94
+ if (key === void 0 || !key.startsWith(`${kind}:`)) continue;
95
+ const story = storyOf(key);
96
+ if (story !== null) variants[variant] = { story, align: firstAlign(story) };
97
+ }
98
+ return variants;
99
+ }
100
+ function variantsFor(section, refs, storyOf) {
172
101
  return {
173
- headers: readVariants(parts, mainPartPath, sectPr, "header"),
174
- footers: readVariants(parts, mainPartPath, sectPr, "footer"),
175
- firstPageDifferent: isOnElement(
176
- elementChildren(sectPr).find((child) => child.localName === "titlePg") ?? null
177
- ),
178
- evenAndOdd: settingsEvenAndOdd(parts, mainPartPath),
179
- pageNumberStart: pageNumberStart(sectPr)
102
+ headers: variantContent(section.props.headerRefs, "header", refs, storyOf),
103
+ footers: variantContent(section.props.footerRefs, "footer", refs, storyOf),
104
+ firstPageDifferent: section.props.titlePg,
105
+ evenAndOdd: refs.evenAndOdd,
106
+ pageNumberStart: section.props.pageNumberStart ?? 1
180
107
  };
181
108
  }
182
109
  function displayPageNumber(headersFooters, page) {
183
110
  return headersFooters.pageNumberStart + page - 1;
184
111
  }
185
- function contentForPage(variants, headersFooters, page) {
186
- if (page === 1 && headersFooters.firstPageDifferent) return variants.first;
187
- if (headersFooters.evenAndOdd && displayPageNumber(headersFooters, page) % 2 === 0) {
188
- return variants.even;
112
+ function headerFooterOn(variants, headersFooters, pageInSection) {
113
+ if (pageInSection === 1 && headersFooters.firstPageDifferent) {
114
+ return variants.first;
189
115
  }
116
+ const number = headersFooters.pageNumberStart + pageInSection - 1;
117
+ if (headersFooters.evenAndOdd && number % 2 === 0) return variants.even;
190
118
  return variants.default;
191
119
  }
192
- function headerFooterText(variants, headersFooters, page, totalPages) {
193
- const content = contentForPage(variants, headersFooters, page);
194
- if (!content) return null;
195
- return content.segments.map((segment) => {
196
- if (segment.kind === "text") return segment.value;
197
- return segment.field === "PAGE" ? `${displayPageNumber(headersFooters, page)}` : `${totalPages}`;
198
- }).join("");
120
+ function pageField(instruction) {
121
+ const name = instruction.split(/\s+/, 1)[0]?.toUpperCase();
122
+ return name === "PAGE" || name === "NUMPAGES" ? name : null;
123
+ }
124
+ function hiddenBy(field) {
125
+ if (pageField(field.instr) !== null) {
126
+ return { field, from: field.begin, to: field.end };
127
+ }
128
+ if (field.begin === field.end) return null;
129
+ return { field, from: field.begin, to: field.separate ?? field.end };
130
+ }
131
+ function nested(hidden, field) {
132
+ return hidden.some(
133
+ (other) => other.field !== field && field.begin >= other.from && field.begin <= other.to
134
+ );
135
+ }
136
+ function paragraphText(paragraph, page, totalPages) {
137
+ const fields = fieldSpans(paragraph, 0);
138
+ const hidden = fields.flatMap((field) => {
139
+ const range = hiddenBy(field);
140
+ return range === null ? [] : [range];
141
+ });
142
+ const numbers = new Map(
143
+ fields.flatMap((field) => {
144
+ const name = pageField(field.instr);
145
+ if (name === null || nested(hidden, field)) return [];
146
+ return [[field.begin, name === "PAGE" ? `${page}` : `${totalPages}`]];
147
+ })
148
+ );
149
+ const pieces = [];
150
+ paragraph.forEach((child, at) => {
151
+ const number = numbers.get(at);
152
+ if (number !== void 0) pieces.push(number);
153
+ if (isFieldCharacter(child)) return;
154
+ if (hidden.some(({ from, to }) => at >= from && at <= to)) return;
155
+ pieces.push(storyLeafText(child));
156
+ });
157
+ return pieces.join("");
158
+ }
159
+ function headerFooterText(story, page, totalPages) {
160
+ const lines = [];
161
+ story.forEach((block) => {
162
+ if (block.type === docxSchema.nodes.paragraph) {
163
+ lines.push(paragraphText(block, page, totalPages));
164
+ }
165
+ });
166
+ return lines.join("\n");
199
167
  }
200
- function headerFooterAlign(variants, headersFooters, page) {
201
- return contentForPage(variants, headersFooters, page)?.align ?? null;
168
+ var HEADER_MARKUP = { namespaces: { w: NAMESPACES.w } };
169
+ function rewrittenParts(doc, session) {
170
+ const parts = /* @__PURE__ */ new Map();
171
+ for (const [key, imported] of session.stories) {
172
+ if (imported.kind !== "header" && imported.kind !== "footer") continue;
173
+ const current = storyNodeOf(doc, key);
174
+ if (current === null || sameSource(current, imported.doc)) continue;
175
+ const written = serializeStory(current, imported, imported, {
176
+ ...NO_EXPORT_REFS,
177
+ session
178
+ });
179
+ const hadBom = decodeUtf8(
180
+ session.parts.get(imported.partPath) ?? new Uint8Array()
181
+ ).hadBom;
182
+ parts.set(
183
+ imported.partPath,
184
+ encodeUtf8(ensureRootDeclarations(written, HEADER_MARKUP), hadBom)
185
+ );
186
+ }
187
+ return parts.size === 0 ? null : parts;
202
188
  }
189
+ var headerFooterPlanner = {
190
+ name: "headers and footers",
191
+ plan: (doc, session) => rewrittenParts(doc, session)
192
+ };
203
193
  export {
204
- NO_HEADERS_FOOTERS,
205
194
  displayPageNumber,
206
- headerFooterAlign,
195
+ headerFooterOn,
196
+ headerFooterPlanner,
207
197
  headerFooterText,
208
- readHeadersFooters
198
+ readHeaderFooterStories,
199
+ variantsFor
209
200
  };
@@ -4,8 +4,9 @@ import { DocxExportError } from "../ooxml/errors.js";
4
4
  import { qualify } from "../ooxml/names.js";
5
5
  import { parseAttrs } from "../ooxml/tagScan.js";
6
6
  import { docxSchema } from "../schema/index.js";
7
+ import { wrappersOf } from "../schema/wrappers.js";
7
8
  import { withoutParagraphIds } from "./cloning.js";
8
- import { copiedControlPrefix, newControlId } from "./sdt.js";
9
+ import { wrapperKindOf } from "./wrappers.js";
9
10
  var sourceBlockRule = {
10
11
  name: "sourceBlock",
11
12
  visit(block, written) {
@@ -51,21 +52,16 @@ var paragraphIdRule = {
51
52
  );
52
53
  }
53
54
  };
54
- function sdtMarkOf(node) {
55
- return node.marks.find((mark) => mark.type === docxSchema.marks.sdt) ?? null;
55
+ function sdtMarksOf(node) {
56
+ return wrappersOf(node, docxSchema.marks.sdt);
56
57
  }
57
58
  function controlName(mark) {
58
- const key = mark.attrs.sdtKey;
59
+ const key = mark.attrs.key;
59
60
  const prefix = mark.attrs.sdtPrefix;
60
61
  return `${typeof key === "number" ? key : 0} ${typeof prefix === "string" ? prefix : ""}`;
61
62
  }
62
63
  function copiedMark(mark) {
63
- const prefix = mark.attrs.sdtPrefix;
64
- if (typeof prefix !== "string") return mark;
65
- return mark.type.create({
66
- ...mark.attrs,
67
- sdtPrefix: copiedControlPrefix(prefix, newControlId())
68
- });
64
+ return wrapperKindOf(mark).copy?.(mark) ?? mark;
69
65
  }
70
66
  function claim(mark, written) {
71
67
  const name = controlName(mark);
@@ -75,25 +71,20 @@ function claim(mark, written) {
75
71
  }
76
72
  function rewriteParagraph(paragraph, written) {
77
73
  const inline = [];
78
- let running = null;
74
+ let running = [];
79
75
  let renamed = false;
80
76
  paragraph.forEach((child) => {
81
- const mark = sdtMarkOf(child);
82
- if (!mark) {
83
- running = null;
84
- inline.push(child);
85
- return;
86
- }
87
- const control = running?.mark.eq(mark) ? running : claim(mark, written);
88
- running = control;
89
- if (!control.copy) {
90
- inline.push(child);
91
- return;
92
- }
93
- renamed = true;
94
- inline.push(
95
- child.mark(control.copy.addToSet(mark.removeFromSet(child.marks)))
77
+ const controls = sdtMarksOf(child).map(
78
+ (mark) => running.find((control) => control.mark.eq(mark)) ?? claim(mark, written)
96
79
  );
80
+ running = controls;
81
+ let marks = child.marks;
82
+ for (const control of controls) {
83
+ if (!control.copy) continue;
84
+ renamed = true;
85
+ marks = control.copy.addToSet(control.mark.removeFromSet(marks));
86
+ }
87
+ inline.push(marks === child.marks ? child : child.mark(marks));
97
88
  });
98
89
  return renamed ? paragraph.copy(Fragment.fromArray(inline)) : paragraph;
99
90
  }
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * This module knows nothing about the screen. All it knows is the file and the document model.
5
5
  */
6
- import { type Node as PMNode } from "prosemirror-model";
6
+ import type { Node as PMNode } from "prosemirror-model";
7
7
  import { type XmlParser } from "../ooxml/xml";
8
8
  import { type FidelityNote } from "./fidelity";
9
9
  import { SessionStore } from "./session";