docxodus 7.1.0 → 9.0.0

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 (91) hide show
  1. package/README.md +65 -24
  2. package/dist/docxodus.worker.js +2 -2
  3. package/dist/docxodus.worker.js.map +1 -1
  4. package/dist/editor-headerfooter.d.ts +166 -0
  5. package/dist/editor-headerfooter.d.ts.map +1 -0
  6. package/dist/editor-headerfooter.js +530 -0
  7. package/dist/editor-headerfooter.js.map +1 -0
  8. package/dist/editor-reconcile.d.ts +75 -0
  9. package/dist/editor-reconcile.d.ts.map +1 -0
  10. package/dist/editor-reconcile.js +125 -0
  11. package/dist/editor-reconcile.js.map +1 -0
  12. package/dist/editor.bundle.js +1861 -110
  13. package/dist/editor.d.ts +200 -6
  14. package/dist/editor.d.ts.map +1 -1
  15. package/dist/editor.js +868 -86
  16. package/dist/editor.js.map +1 -1
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +3 -4
  20. package/dist/index.js.map +1 -1
  21. package/dist/page-number-format.d.ts +22 -0
  22. package/dist/page-number-format.d.ts.map +1 -0
  23. package/dist/page-number-format.js +60 -0
  24. package/dist/page-number-format.js.map +1 -0
  25. package/dist/pagination.bundle.js +635 -37
  26. package/dist/pagination.d.ts +119 -0
  27. package/dist/pagination.d.ts.map +1 -1
  28. package/dist/pagination.js +706 -52
  29. package/dist/pagination.js.map +1 -1
  30. package/dist/react.d.ts +3 -1
  31. package/dist/react.d.ts.map +1 -1
  32. package/dist/react.js +6 -4
  33. package/dist/react.js.map +1 -1
  34. package/dist/session.bundle.js +241 -4
  35. package/dist/session.d.ts +160 -6
  36. package/dist/session.d.ts.map +1 -1
  37. package/dist/session.js +202 -4
  38. package/dist/session.js.map +1 -1
  39. package/dist/types.d.ts +238 -14
  40. package/dist/types.d.ts.map +1 -1
  41. package/dist/types.js +9 -11
  42. package/dist/types.js.map +1 -1
  43. package/dist/wasm/_framework/Docxodus.wasm +0 -0
  44. package/dist/wasm/_framework/DocxodusWasm.wasm +0 -0
  45. package/dist/wasm/_framework/System.Collections.Concurrent.wasm +0 -0
  46. package/dist/wasm/_framework/System.Collections.Immutable.wasm +0 -0
  47. package/dist/wasm/_framework/System.Collections.NonGeneric.wasm +0 -0
  48. package/dist/wasm/_framework/System.Collections.Specialized.wasm +0 -0
  49. package/dist/wasm/_framework/System.Collections.wasm +0 -0
  50. package/dist/wasm/_framework/System.ComponentModel.Primitives.wasm +0 -0
  51. package/dist/wasm/_framework/System.ComponentModel.TypeConverter.wasm +0 -0
  52. package/dist/wasm/_framework/System.ComponentModel.wasm +0 -0
  53. package/dist/wasm/_framework/System.Console.wasm +0 -0
  54. package/dist/wasm/_framework/System.Diagnostics.Process.wasm +0 -0
  55. package/dist/wasm/_framework/System.IO.Compression.wasm +0 -0
  56. package/dist/wasm/_framework/System.IO.Pipelines.wasm +0 -0
  57. package/dist/wasm/_framework/System.Linq.Expressions.wasm +0 -0
  58. package/dist/wasm/_framework/System.Linq.wasm +0 -0
  59. package/dist/wasm/_framework/System.Memory.wasm +0 -0
  60. package/dist/wasm/_framework/System.Net.Http.wasm +0 -0
  61. package/dist/wasm/_framework/System.Net.Primitives.wasm +0 -0
  62. package/dist/wasm/_framework/System.ObjectModel.wasm +0 -0
  63. package/dist/wasm/_framework/System.Private.CoreLib.wasm +0 -0
  64. package/dist/wasm/_framework/System.Private.Uri.wasm +0 -0
  65. package/dist/wasm/_framework/System.Private.Xml.Linq.wasm +0 -0
  66. package/dist/wasm/_framework/System.Private.Xml.wasm +0 -0
  67. package/dist/wasm/_framework/System.Runtime.InteropServices.JavaScript.wasm +0 -0
  68. package/dist/wasm/_framework/System.Runtime.wasm +0 -0
  69. package/dist/wasm/_framework/System.Security.Cryptography.wasm +0 -0
  70. package/dist/wasm/_framework/System.Text.Encoding.Extensions.wasm +0 -0
  71. package/dist/wasm/_framework/System.Text.Encodings.Web.wasm +0 -0
  72. package/dist/wasm/_framework/System.Text.Json.wasm +0 -0
  73. package/dist/wasm/_framework/System.Text.RegularExpressions.wasm +0 -0
  74. package/dist/wasm/_framework/System.Threading.Thread.wasm +0 -0
  75. package/dist/wasm/_framework/System.Threading.wasm +0 -0
  76. package/dist/wasm/_framework/System.Xml.Linq.wasm +0 -0
  77. package/dist/wasm/_framework/System.Xml.ReaderWriter.wasm +0 -0
  78. package/dist/wasm/_framework/System.Xml.XDocument.wasm +0 -0
  79. package/dist/wasm/_framework/System.Xml.XPath.XDocument.wasm +0 -0
  80. package/dist/wasm/_framework/System.Xml.XPath.wasm +0 -0
  81. package/dist/wasm/_framework/System.wasm +0 -0
  82. package/dist/wasm/_framework/dotnet.boot.js +41 -41
  83. package/dist/wasm/_framework/dotnet.js +1 -1
  84. package/dist/wasm/_framework/dotnet.js.map +1 -1
  85. package/dist/wasm/_framework/dotnet.native.js +3 -3
  86. package/dist/wasm/_framework/dotnet.native.js.symbols +2102 -2101
  87. package/dist/wasm/_framework/dotnet.native.wasm +0 -0
  88. package/dist/wasm/_framework/dotnet.runtime.js +1 -1
  89. package/dist/wasm/_framework/dotnet.runtime.js.map +1 -1
  90. package/dist/wasm/index.html +2 -1
  91. package/package.json +17 -4
@@ -0,0 +1,530 @@
1
+ /**
2
+ * HeaderFooterRegion — the DocxEditor's docked header/footer editing bands.
3
+ *
4
+ * Header and footer stories live in their own OOXML parts (HeaderPart/FooterPart) *outside*
5
+ * the body, so they cannot be another block in the body flow. This module renders them as two
6
+ * docked bands — one above the body, one below — each composed PER STORY PARAGRAPH via the
7
+ * session-attached `RenderBlockHtml`, which resolves `hdr`/`ftr` anchors natively.
8
+ *
9
+ * Using the same renderer for first paint and for the post-edit incremental swap means there is
10
+ * no fidelity drift between them. It is also the only option that works in continuous mode at
11
+ * all: the editor's full-document render only asks for headers/footers in paginated mode, and it
12
+ * never stamps `data-anchor` inside header/footer parts (Unids are assigned to the main document
13
+ * part only). In paginated mode the page boxes additionally clone one header node onto every
14
+ * page, so page-margin nodes could never be uniquely addressable — bands keep exactly one DOM
15
+ * node per story paragraph.
16
+ *
17
+ * Once rendered, a story paragraph is an ORDINARY editable block: DocxSession's anchor
18
+ * resolution indexes every scope and routes by part, so ReplaceText/ApplyFormat/SetParagraphFormat
19
+ * all accept a `p:hdr1:<unid>` anchor. The editor wires band blocks with the same `wireBlock` it
20
+ * uses for the body, which is why the whole ribbon works inside a band with no new command code.
21
+ */
22
+ /** The page-number formats Word's *Format Page Numbers…* dialog offers, in its order. The blank
23
+ * entry means "leave the section's format alone" — not "decimal", which would write an attribute
24
+ * the document may never have had. */
25
+ const PAGE_FORMAT_LABELS = [
26
+ { value: "", label: "Format…" },
27
+ { value: "decimal", label: "1, 2, 3" },
28
+ { value: "lowerLetter", label: "a, b, c" },
29
+ { value: "upperLetter", label: "A, B, C" },
30
+ { value: "lowerRoman", label: "i, ii, iii" },
31
+ { value: "upperRoman", label: "I, II, III" },
32
+ ];
33
+ const KIND_LABELS = [
34
+ { value: "default", label: "Default" },
35
+ { value: "first", label: "First page" },
36
+ { value: "even", label: "Even pages" },
37
+ ];
38
+ /**
39
+ * Verbatim from docs/architecture/docx_mutation_api.md. `w:evenAndOddHeaders` is set on the
40
+ * SETTINGS part, so it is document-global and governs footers as well as headers: once set,
41
+ * even pages stop inheriting the Default stories entirely. A demo user who creates only an
42
+ * even header hits this immediately and sees their footer vanish on page 2.
43
+ */
44
+ const EVEN_WARNING = "w:evenAndOddHeaders is document-global and governs footers too — even pages stop " +
45
+ "inheriting the Default stories, so a section with only a Default footer shows no footer " +
46
+ "at all on even pages.";
47
+ /**
48
+ * `w:titlePg` is per-section but has the same shape of surprise: once set, page 1 uses its OWN
49
+ * header AND footer, so an empty first-page footer means page 1 shows no footer even though the
50
+ * Default one is populated.
51
+ */
52
+ const FIRST_WARNING = "w:titlePg makes page 1 use its own first-page header AND footer instead of the Default " +
53
+ "ones, so an empty first-page footer leaves page 1 with no footer.";
54
+ /** Kinds/scopes the markdown projection addresses as editable text blocks. */
55
+ const STORY_BLOCK_KINDS = new Set(["p", "h", "li"]);
56
+ export class HeaderFooterRegion {
57
+ constructor(bridge, handle, options, callbacks) {
58
+ /** The body anchor whose section the bands currently describe (needed to seed a story). */
59
+ this.bodyAnchorId = null;
60
+ this.sectionInfo = null;
61
+ /** Memoized body anchor → governing sectionUnid, so repeat focus costs no bridge call. */
62
+ this.sectionOfAnchor = new Map();
63
+ this.kinds = {
64
+ header: "default",
65
+ footer: "default",
66
+ };
67
+ this.bridge = bridge;
68
+ this.handle = handle;
69
+ this.options = options;
70
+ this.callbacks = callbacks;
71
+ this.headerBand = this.buildBand("header");
72
+ this.footerBand = this.buildBand("footer");
73
+ }
74
+ // ─── public surface ──────────────────────────────────────────────────
75
+ /**
76
+ * Point the bands at the section governing `bodyAnchorId` and repaint if it changed.
77
+ * Cheap to call on every focus change: the anchor → section lookup is memoized, and an
78
+ * unchanged `sectionUnid` returns without touching the DOM (so it never clobbers the
79
+ * user's kind selection).
80
+ */
81
+ syncToBody(bodyAnchorId) {
82
+ if (!bodyAnchorId)
83
+ return;
84
+ const cached = this.sectionOfAnchor.get(bodyAnchorId);
85
+ if (cached !== undefined && cached === this.sectionInfo?.sectionUnid) {
86
+ this.bodyAnchorId = bodyAnchorId; // same section — keep it as the seed target
87
+ return;
88
+ }
89
+ const info = this.readSectionInfo(bodyAnchorId);
90
+ if (!info)
91
+ return; // not a body anchor (or no sectPr) — leave the bands as they are
92
+ this.sectionOfAnchor.set(bodyAnchorId, info.sectionUnid);
93
+ const changed = info.sectionUnid !== this.sectionInfo?.sectionUnid;
94
+ this.bodyAnchorId = bodyAnchorId;
95
+ this.sectionInfo = info;
96
+ if (changed)
97
+ this.refreshAll();
98
+ }
99
+ /** Repaint one band from the live session. */
100
+ refresh(which) {
101
+ this.sectionInfo = this.bodyAnchorId ? this.readSectionInfo(this.bodyAnchorId) : null;
102
+ this.renderBand(which);
103
+ }
104
+ /** Repaint both bands from the live session (after a remount, undo/redo, or section change). */
105
+ refreshAll() {
106
+ this.renderBand("header");
107
+ this.renderBand("footer");
108
+ }
109
+ /** Select (and, if absent, create) the story kind a band edits, and make it render. */
110
+ setKind(which, kind) {
111
+ this.kinds[which] = kind;
112
+ const select = this.bandFor(which).querySelector("[data-hf-kind]");
113
+ if (select && select.value !== kind)
114
+ select.value = kind;
115
+ if (!this.partUriFor(which, kind))
116
+ this.seedStory(which, kind);
117
+ // Selecting first/even IS the user saying "use a different first/even page", so the section's
118
+ // visibility flag must be set even when the part already exists — seedStory (which sets it as
119
+ // a side effect of writing content) doesn't run then. Word leaves first/even parts behind when
120
+ // those options are switched off, so a real document commonly has the reference WITHOUT the
121
+ // flag; without this the typed story is saved but never rendered.
122
+ if (this.bodyAnchorId && kind !== "default") {
123
+ this.bridge.EnsureHeaderFooterVisible(this.handle, this.bodyAnchorId, kind);
124
+ }
125
+ this.refresh(which);
126
+ }
127
+ /** The kind a band is currently editing. */
128
+ kindOf(which) {
129
+ return this.kinds[which];
130
+ }
131
+ /** Append a PAGE / NUMPAGES field to the story paragraph addressed by `anchorId`.
132
+ * Deliberately a PLAIN field (no `\*` switch), exactly as Word inserts one, so it follows the
133
+ * section's page-number format — see {@link setPageNumbering}. Stamping the section's current
134
+ * format as a switch here would silently WIN over any later format change. */
135
+ insertPageNumber(which, anchorId, field) {
136
+ const res = parseResult(this.bridge.InsertPageNumberField(this.handle, anchorId, field, ""));
137
+ if (!res.success)
138
+ return false;
139
+ this.refresh(which);
140
+ return true;
141
+ }
142
+ /**
143
+ * Set this section's page numbering (`w:pgNumType`) — Word's *Format Page Numbers…*. Omitted
144
+ * fields are left alone, so the format and the start are independently settable. Both bands then
145
+ * repaint, because the values belong to the section rather than to either story.
146
+ *
147
+ * The rendered page numbers in the editor do not change: a page-number field's cached result is
148
+ * what the browser shows, and Word recomputes it on open. Paginated mode substitutes the real
149
+ * per-page number, so it does reflect the format immediately.
150
+ */
151
+ setPageNumbering(op) {
152
+ if (!this.bodyAnchorId)
153
+ return false;
154
+ const res = parseResult(this.bridge.SetPageNumbering(this.handle, this.bodyAnchorId, JSON.stringify(op)));
155
+ if (!res.success)
156
+ return false;
157
+ this.reloadSection();
158
+ return true;
159
+ }
160
+ /** This section's page numbering as the live document states it. Fields are absent, not
161
+ * defaulted — "continues the previous section" is not the same claim as "starts at 1". */
162
+ pageNumbering() {
163
+ return {
164
+ start: this.sectionInfo?.pageNumberStart,
165
+ format: this.sectionInfo?.pageNumberFormat,
166
+ };
167
+ }
168
+ /** Remove this section's page-numbering start/format — it reverts to continuing the previous
169
+ * section's numbering in Word's default `1, 2, 3`. */
170
+ clearPageNumbering() {
171
+ if (!this.bodyAnchorId)
172
+ return false;
173
+ const res = parseResult(this.bridge.ClearPageNumbering(this.handle, this.bodyAnchorId));
174
+ if (!res.success)
175
+ return false;
176
+ this.reloadSection();
177
+ return true;
178
+ }
179
+ /**
180
+ * Re-read the section from the live document and repaint BOTH bands.
181
+ *
182
+ * `refreshAll` only repaints — it deliberately does not re-read, because its callers (remount,
183
+ * undo/redo) already refreshed the section. A section-property write has no such caller, and
184
+ * repainting from the stale snapshot would leave the chrome reporting the value the document had
185
+ * before the edit.
186
+ */
187
+ reloadSection() {
188
+ this.sectionInfo = this.bodyAnchorId ? this.readSectionInfo(this.bodyAnchorId) : null;
189
+ this.refreshAll();
190
+ }
191
+ /** Insert a page number into a band's own target paragraph (focused, else last). Seeds the
192
+ * story first if the band's selected kind has none, so the command is never a silent no-op. */
193
+ insertPageNumberInBand(which, field) {
194
+ if (!this.partUriFor(which, this.kinds[which])) {
195
+ this.seedStory(which, this.kinds[which]);
196
+ this.renderBand(which);
197
+ }
198
+ const target = this.pageNumberTarget(which);
199
+ return target ? this.insertPageNumber(which, target, field) : false;
200
+ }
201
+ /** The band element containing `node`, or null. */
202
+ bandOf(node) {
203
+ const el = node && node.nodeType === 1 ? node : node?.parentElement ?? null;
204
+ const band = el?.closest("[data-hf-band]") ?? null;
205
+ return band === this.headerBand || band === this.footerBand ? band : null;
206
+ }
207
+ /** The block-list root (a band's story container) owning `node`, or null. */
208
+ blockRootOf(node) {
209
+ const band = this.bandOf(node);
210
+ return band ? band.querySelector("[data-hf-body]") : null;
211
+ }
212
+ /** True when `node` is inside either band (including its chrome). */
213
+ contains(node) {
214
+ return this.bandOf(node) !== null;
215
+ }
216
+ /** `"header"` / `"footer"` for a band element produced by this region. */
217
+ whichOf(band) {
218
+ return band === this.footerBand ? "footer" : "header";
219
+ }
220
+ // ─── section + anchor resolution ─────────────────────────────────────
221
+ readSectionInfo(bodyAnchorId) {
222
+ try {
223
+ const raw = this.bridge.GetSectionInfo(this.handle, bodyAnchorId);
224
+ const parsed = JSON.parse(raw);
225
+ return parsed && typeof parsed.sectionUnid === "string" ? parsed : null;
226
+ }
227
+ catch {
228
+ return null;
229
+ }
230
+ }
231
+ refsFor(which) {
232
+ const info = this.sectionInfo;
233
+ if (!info)
234
+ return [];
235
+ return (which === "header" ? info.headerRefs : info.footerRefs) ?? [];
236
+ }
237
+ /** The reference supplying `kind` for this band — possibly inherited from an earlier section. */
238
+ refFor(which, kind) {
239
+ return this.refsFor(which).find((r) => r.kind === kind) ?? null;
240
+ }
241
+ /** URI of the part supplying `kind` for this band, or null when the story doesn't exist. */
242
+ partUriFor(which, kind) {
243
+ return this.refFor(which, kind)?.partUri ?? null;
244
+ }
245
+ /** Full anchor ids of the story paragraphs held in `partUri`, in document order. */
246
+ storyAnchors(partUri) {
247
+ let index;
248
+ try {
249
+ index = JSON.parse(this.bridge.Project(this.handle)).anchorIndex;
250
+ }
251
+ catch {
252
+ return [];
253
+ }
254
+ return Object.entries(index)
255
+ .filter(([, t]) => t.partUri === partUri && STORY_BLOCK_KINDS.has(t.kind))
256
+ .map(([id]) => id);
257
+ }
258
+ /**
259
+ * Create an empty story for `kind`. Seeding happens the moment a kind is selected rather than
260
+ * lazily on first keystroke: an absent story renders no contenteditable element, so there
261
+ * would be nothing to click into.
262
+ */
263
+ seedStory(which, kind) {
264
+ if (!this.bodyAnchorId)
265
+ return;
266
+ const set = which === "header" ? this.bridge.SetHeaderText : this.bridge.SetFooterText;
267
+ const res = parseResult(set(this.handle, this.bodyAnchorId, kind, ""));
268
+ if (!res.success)
269
+ return;
270
+ // A new part changes the projection (fresh hdr{N}/ftr{N} scope) and the section's refs.
271
+ this.callbacks.refreshAnchorMap();
272
+ this.sectionInfo = this.readSectionInfo(this.bodyAnchorId);
273
+ }
274
+ // ─── rendering ───────────────────────────────────────────────────────
275
+ bandFor(which) {
276
+ return which === "header" ? this.headerBand : this.footerBand;
277
+ }
278
+ buildBand(which) {
279
+ const band = document.createElement("div");
280
+ band.className = "docx-hf-band";
281
+ band.setAttribute("data-hf-band", which);
282
+ const chrome = document.createElement("div");
283
+ chrome.className = "docx-hf-chrome";
284
+ const label = document.createElement("span");
285
+ label.className = "docx-hf-label";
286
+ label.textContent = which === "header" ? "Header" : "Footer";
287
+ chrome.appendChild(label);
288
+ const kindSelect = document.createElement("select");
289
+ kindSelect.setAttribute("data-hf-kind", "");
290
+ kindSelect.title = "Which header/footer story to edit";
291
+ for (const k of KIND_LABELS) {
292
+ const opt = document.createElement("option");
293
+ opt.value = k.value;
294
+ opt.textContent = k.label;
295
+ kindSelect.appendChild(opt);
296
+ }
297
+ kindSelect.addEventListener("change", () => this.setKind(which, kindSelect.value));
298
+ chrome.appendChild(kindSelect);
299
+ const pageNum = document.createElement("select");
300
+ pageNum.setAttribute("data-hf-pagenum", "");
301
+ pageNum.title = "Insert a page-number field into the focused story paragraph";
302
+ for (const o of [
303
+ { value: "", label: "Page №…" },
304
+ { value: "currentPage", label: "Page number" },
305
+ { value: "totalPages", label: "Total pages" },
306
+ ]) {
307
+ const opt = document.createElement("option");
308
+ opt.value = o.value;
309
+ opt.textContent = o.label;
310
+ pageNum.appendChild(opt);
311
+ }
312
+ // The <select> steals focus from the story paragraph, collapsing the caret, so the target
313
+ // is resolved from the band's own blocks rather than from the editor's live selection.
314
+ pageNum.addEventListener("change", () => {
315
+ const field = pageNum.value;
316
+ pageNum.value = "";
317
+ if (field !== "currentPage" && field !== "totalPages")
318
+ return;
319
+ const target = this.pageNumberTarget(which);
320
+ if (target)
321
+ this.insertPageNumber(which, target, field);
322
+ });
323
+ chrome.appendChild(pageNum);
324
+ // Word's "Format Page Numbers…": these are SECTION properties (w:pgNumType), not properties of
325
+ // this band's story, so both bands show the same values and either can set them. An inserted
326
+ // page-number field is plain, so it renders through whatever is chosen here.
327
+ const pageFmt = document.createElement("select");
328
+ pageFmt.setAttribute("data-hf-pagefmt", "");
329
+ pageFmt.title = "Page-number format for this section";
330
+ for (const o of PAGE_FORMAT_LABELS) {
331
+ const opt = document.createElement("option");
332
+ opt.value = o.value;
333
+ opt.textContent = o.label;
334
+ pageFmt.appendChild(opt);
335
+ }
336
+ pageFmt.addEventListener("change", () => {
337
+ if (pageFmt.value === "")
338
+ return;
339
+ this.setPageNumbering({ format: pageFmt.value });
340
+ });
341
+ chrome.appendChild(pageFmt);
342
+ const pageStart = document.createElement("input");
343
+ pageStart.setAttribute("data-hf-pagestart", "");
344
+ pageStart.type = "number";
345
+ pageStart.min = "0";
346
+ pageStart.placeholder = "Start at";
347
+ pageStart.title = "Restart this section's page numbering at this number";
348
+ // Commit on blur/Enter, not on every keystroke: typing "12" would otherwise apply a start of 1
349
+ // first, and each apply is an undo step.
350
+ const commitStart = () => {
351
+ const raw = pageStart.value.trim();
352
+ if (raw === "")
353
+ return;
354
+ const start = Number(raw);
355
+ if (!Number.isInteger(start) || start < 0)
356
+ return;
357
+ this.setPageNumbering({ start });
358
+ };
359
+ pageStart.addEventListener("blur", commitStart);
360
+ pageStart.addEventListener("keydown", (e) => {
361
+ if (e.key === "Enter") {
362
+ e.preventDefault();
363
+ commitStart();
364
+ }
365
+ });
366
+ chrome.appendChild(pageStart);
367
+ const inheritedNote = document.createElement("span");
368
+ inheritedNote.className = "docx-hf-inherited";
369
+ inheritedNote.setAttribute("data-hf-inherited-note", "");
370
+ inheritedNote.hidden = true;
371
+ chrome.appendChild(inheritedNote);
372
+ band.appendChild(chrome);
373
+ const warning = document.createElement("div");
374
+ warning.className = "docx-hf-warning";
375
+ warning.setAttribute("data-hf-warning", "");
376
+ warning.hidden = true;
377
+ band.appendChild(warning);
378
+ const body = document.createElement("div");
379
+ body.className = "docx-hf-body";
380
+ body.setAttribute("data-hf-body", "");
381
+ band.appendChild(body);
382
+ return band;
383
+ }
384
+ /**
385
+ * Which story paragraph a page-number insert targets: the last one the user focused in this
386
+ * band if it is still attached, else the band's last paragraph (Word's convention — the page
387
+ * number goes at the end of the footer line).
388
+ */
389
+ pageNumberTarget(which) {
390
+ const body = this.bandFor(which).querySelector("[data-hf-body]");
391
+ if (!body)
392
+ return null;
393
+ const focused = body.querySelector('[data-hf-focused="true"][data-hf-anchor]');
394
+ const blocks = Array.from(body.querySelectorAll("[data-hf-anchor]"));
395
+ const target = focused ?? blocks[blocks.length - 1];
396
+ return target?.getAttribute("data-hf-anchor") ?? null;
397
+ }
398
+ renderBand(which) {
399
+ const band = this.bandFor(which);
400
+ const body = band.querySelector("[data-hf-body]");
401
+ if (!body)
402
+ return;
403
+ const kind = this.kinds[which];
404
+ const select = band.querySelector("[data-hf-kind]");
405
+ if (select && select.value !== kind)
406
+ select.value = kind;
407
+ // Section-level page numbering — the same values on both bands, seeded from the live sectPr so
408
+ // the chrome reports what the document says rather than what was last clicked.
409
+ const pageFmt = band.querySelector("[data-hf-pagefmt]");
410
+ if (pageFmt)
411
+ pageFmt.value = this.sectionInfo?.pageNumberFormat ?? "";
412
+ const pageStart = band.querySelector("[data-hf-pagestart]");
413
+ if (pageStart && document.activeElement !== pageStart) {
414
+ const start = this.sectionInfo?.pageNumberStart;
415
+ pageStart.value = start === undefined ? "" : String(start);
416
+ }
417
+ // A section that declares no reference of this kind shows the story it inherits from an
418
+ // earlier section. Say so: editing it changes BOTH sections, because they share one part.
419
+ const inherited = this.refFor(which, kind)?.inherited === true;
420
+ band.toggleAttribute("data-hf-inherited", inherited);
421
+ const note = band.querySelector("[data-hf-inherited-note]");
422
+ if (note) {
423
+ note.hidden = !inherited;
424
+ note.textContent = inherited ? "inherited from an earlier section" : "";
425
+ }
426
+ this.renderKindWarning(which);
427
+ body.innerHTML = "";
428
+ const partUri = this.partUriFor(which, kind);
429
+ if (!partUri) {
430
+ body.appendChild(this.placeholder(which, kind));
431
+ band.setAttribute("data-hf-empty", "true");
432
+ return;
433
+ }
434
+ band.removeAttribute("data-hf-empty");
435
+ const anchors = this.storyAnchors(partUri);
436
+ if (anchors.length === 0) {
437
+ body.appendChild(this.placeholder(which, kind));
438
+ return;
439
+ }
440
+ for (const anchorId of anchors) {
441
+ const el = this.renderStoryBlock(anchorId);
442
+ if (!el)
443
+ continue;
444
+ body.appendChild(el);
445
+ // Adopt BEFORE wiring: the editor resolves a block's anchor from `data-hf-anchor` first,
446
+ // because a story paragraph's content-addressed unid can collide with another part's.
447
+ this.adoptBlock(el, anchorId);
448
+ this.callbacks.wireBlock(el);
449
+ }
450
+ }
451
+ /**
452
+ * Mark a story paragraph as belonging to this region. The full anchor id is stamped alongside
453
+ * `data-anchor` (which carries only the bare unid, matching the body's convention) so band
454
+ * chrome can address the block without going through the editor's unid map. Called on first
455
+ * render AND after an incremental swap, which replaces the DOM node.
456
+ */
457
+ adoptBlock(el, anchorId) {
458
+ const body = this.blockRootOf(el);
459
+ if (!body)
460
+ return;
461
+ el.setAttribute("data-hf-anchor", anchorId);
462
+ if (el.dataset.hfAdopted === "true")
463
+ return;
464
+ el.dataset.hfAdopted = "true";
465
+ el.addEventListener("focus", () => {
466
+ body
467
+ .querySelectorAll("[data-hf-focused]")
468
+ .forEach((sib) => sib.removeAttribute("data-hf-focused"));
469
+ el.setAttribute("data-hf-focused", "true");
470
+ });
471
+ }
472
+ renderStoryBlock(anchorId) {
473
+ const html = this.bridge.RenderBlockHtml(this.handle, anchorId, this.options.cssPrefix, this.options.fabricateClasses);
474
+ if (html.charCodeAt(0) === 0x7b /* error object */)
475
+ return null;
476
+ return new DOMParser().parseFromString(html, "text/html").body
477
+ .firstElementChild;
478
+ }
479
+ placeholder(which, kind) {
480
+ const el = document.createElement("div");
481
+ el.className = "docx-hf-placeholder";
482
+ el.setAttribute("data-hf-placeholder", "");
483
+ const label = KIND_LABELS.find((k) => k.value === kind)?.label ?? kind;
484
+ el.textContent = `No ${label.toLowerCase()} ${which} — pick a kind to create one.`;
485
+ return el;
486
+ }
487
+ /**
488
+ * Surface the caveat that comes with the selected kind. Turning on first/even means those pages
489
+ * stop using the Default stories entirely, which bites hardest on the OTHER band: enabling an
490
+ * even header with no even footer leaves even pages footer-less, and enabling a first-page
491
+ * header with an empty first-page footer leaves page 1 footer-less. The note is shown whenever
492
+ * first/even is selected (the behavior change is real either way); the fix button appears only
493
+ * when the counterpart story is missing entirely, which is what a user almost always wants next.
494
+ */
495
+ renderKindWarning(which) {
496
+ const band = this.bandFor(which);
497
+ const warning = band.querySelector("[data-hf-warning]");
498
+ if (!warning)
499
+ return;
500
+ const kind = this.kinds[which];
501
+ if (kind === "default") {
502
+ warning.hidden = true;
503
+ warning.textContent = "";
504
+ return;
505
+ }
506
+ const other = which === "header" ? "footer" : "header";
507
+ warning.hidden = false;
508
+ warning.textContent = `${kind === "even" ? EVEN_WARNING : FIRST_WARNING} `;
509
+ if (this.partUriFor(other, kind))
510
+ return; // counterpart exists — nothing to offer
511
+ const fix = document.createElement("button");
512
+ fix.type = "button";
513
+ fix.setAttribute("data-hf-fix-counterpart", "");
514
+ fix.textContent = `Also create a ${kind === "even" ? "matching even" : "first-page"} ${other}`;
515
+ fix.addEventListener("click", () => {
516
+ this.setKind(other, kind);
517
+ this.renderKindWarning(which);
518
+ });
519
+ warning.appendChild(fix);
520
+ }
521
+ }
522
+ function parseResult(json) {
523
+ try {
524
+ return JSON.parse(json);
525
+ }
526
+ catch {
527
+ return { success: false };
528
+ }
529
+ }
530
+ //# sourceMappingURL=editor-headerfooter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor-headerfooter.js","sourceRoot":"","sources":["../src/editor-headerfooter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Unit-sequence diff for the editor's incremental structural repaint.
3
+ *
4
+ * After a structural op (insert table/row, footnote, delete block, undo/redo)
5
+ * the editor fetches the session's {@link RenderPlan} (`ListBlocks`) and diffs
6
+ * each container's unit sequence against the DOM's, so unchanged blocks keep
7
+ * their DOM nodes and only changed/created units re-render — replacing the
8
+ * whole-document remount that cost seconds on large documents.
9
+ *
10
+ * Pure functions only: DOM walking, rendering, and fallback policy live in
11
+ * `editor.ts` (`DocxEditor.reconcile`).
12
+ */
13
+ /** One top-level render unit: a body block (`p`/`h`/`li`), one whole table
14
+ * (`tbl`), or one footnote/endnote definition (`fn`/`en`). Mirrors the wire
15
+ * shape of `DocxSessionBridge.ListBlocks`. `sig` (container units only) is a
16
+ * content signature: a table or note keeps its unid when content INSIDE it
17
+ * changes, so the diff tokens must include it or a changed container would be
18
+ * kept stale. */
19
+ export interface RenderUnit {
20
+ id: string;
21
+ kind: string;
22
+ sig?: string;
23
+ }
24
+ /** The diff token for a unit: unid plus the container content signature. The DOM
25
+ * side composes the same token from a node's `data-anchor` + `data-render-sig`
26
+ * stamp, so a container whose inside changed diffs as an in-place substitution. */
27
+ export declare function tokenOf(unit: RenderUnit): string;
28
+ /** Per-container render plan — the wire shape of `DocxSessionBridge.ListBlocks`. */
29
+ export interface RenderPlan {
30
+ body: RenderUnit[];
31
+ footnotes: RenderUnit[];
32
+ endnotes: RenderUnit[];
33
+ }
34
+ export interface UnitDiff {
35
+ /** newIndex → oldIndex for units that keep their existing DOM node. */
36
+ keep: Map<number, number>;
37
+ /** Indices into the OLD DOM sequence whose nodes must be removed. */
38
+ removed: number[];
39
+ /** Indices into the NEW plan that need a fresh render. */
40
+ added: number[];
41
+ /**
42
+ * added/removed pairs that are an IN-PLACE change (same number of kept units
43
+ * on each side) — e.g. a text edit re-hashing a block's content-addressed
44
+ * unid. A substituted list item keeps its list position, so it renumbers no
45
+ * siblings and may reconcile where a pure li insert/remove may not.
46
+ */
47
+ substituted: Array<{
48
+ oldIndex: number;
49
+ newIndex: number;
50
+ }>;
51
+ }
52
+ /** unid ("a1b2…") from a full anchor id ("p:body:a1b2…"). */
53
+ export declare function unidOf(id: string): string;
54
+ /**
55
+ * LCS diff of the DOM's unit-token sequence against the new plan's. Old entries
56
+ * are tokens (see {@link tokenOf} — bare unids for leaf blocks, `unid|sig` for
57
+ * containers). Equal tokens are interchangeable (content-addressed: equal token
58
+ * ⇒ equal content ⇒ equal rendering, up to position-dependent chrome the caller
59
+ * handles). O(n·m) — sequences are document block counts, a few hundred.
60
+ */
61
+ export declare function diffUnits(oldUnids: string[], newUnits: RenderUnit[]): UnitDiff;
62
+ /**
63
+ * Whether this diff must fall back to a full remount:
64
+ * - a PURE li insert or removal (not an in-place substitution) — sibling list
65
+ * items renumber without their own XML changing, which a unit diff cannot see;
66
+ * - total churn above `threshold` (a remount is cheaper and simpler than
67
+ * rendering half the document block-by-block).
68
+ *
69
+ * `oldKinds[i]` is the kind of the old sequence's i-th unit (the DOM knows it).
70
+ * An li substitution deliberately does NOT force a remount — its list position
71
+ * is unchanged; the CALLER must still verify its list facts (numId/ilvl)
72
+ * survived, and remount when they changed.
73
+ */
74
+ export declare function needsRemount(diff: UnitDiff, newUnits: RenderUnit[], oldKinds: string[], threshold?: number): boolean;
75
+ //# sourceMappingURL=editor-reconcile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor-reconcile.d.ts","sourceRoot":"","sources":["../src/editor-reconcile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;kBAKkB;AAClB,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;oFAEoF;AACpF,wBAAgB,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAEhD;AAED,oFAAoF;AACpF,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,UAAU,EAAE,CAAC;IACnB,SAAS,EAAE,UAAU,EAAE,CAAC;IACxB,QAAQ,EAAE,UAAU,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,QAAQ;IACvB,uEAAuE;IACvE,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1B,qEAAqE;IACrE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,0DAA0D;IAC1D,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;;;;OAKG;IACH,WAAW,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC5D;AAED,6DAA6D;AAC7D,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAEzC;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,QAAQ,CA8D9E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,QAAQ,EACd,QAAQ,EAAE,UAAU,EAAE,EACtB,QAAQ,EAAE,MAAM,EAAE,EAClB,SAAS,SAAK,GACb,OAAO,CAWT"}