@arbidocs/coedit 0.4.108 → 0.4.109

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.
@@ -0,0 +1,356 @@
1
+ 'use strict';
2
+
3
+ var store = require('@docx-editor.dev/core/store');
4
+ var layout = require('@docx-editor.dev/core/layout');
5
+
6
+ // src/commands/index.ts
7
+
8
+ // src/commands/read.ts
9
+ var DEFINED_TERM_STYLE = "DefinedTerm";
10
+ var CROSS_REFERENCE_STYLE = "CrossReference";
11
+ var BROKEN_CROSS_REFERENCE_STYLE = "CrossReferenceBroken";
12
+ var WATCHED_STYLES = /* @__PURE__ */ new Set([BROKEN_CROSS_REFERENCE_STYLE]);
13
+ var attr = (node, name) => node.attributes?.find((a) => a.localName === name)?.value;
14
+ var FIELD_ATOM = "\uFFFC";
15
+ var HEADING_STYLE = /^(heading|berschrift|titre|t[ií]tulo|titolo|kop)\s*\d/i;
16
+ function readParagraphs(root) {
17
+ const out = [];
18
+ const body = root.children?.find((n) => n.kind === "body") ?? root;
19
+ const visit = (node, topLevel, pending) => {
20
+ for (const child of node.children ?? []) {
21
+ if (child.kind === "paragraph") {
22
+ out.push(readParagraph(child, topLevel, pending.splice(0)));
23
+ } else if (child.localName === "bookmarkStart") {
24
+ const name = attr(child, "name");
25
+ if (name) pending.push(name);
26
+ } else if (child.localName === "tbl" || child.localName === "tr" || child.localName === "tc") {
27
+ visit(child, false, pending);
28
+ } else if (child.localName === "sdt" || child.localName === "sdtContent") {
29
+ visit(child, topLevel, pending);
30
+ }
31
+ }
32
+ };
33
+ visit(body, true, []);
34
+ return out;
35
+ }
36
+ function readParagraph(node, topLevel, bookmarks) {
37
+ let text = "";
38
+ const links = [];
39
+ let styleId;
40
+ let outline = false;
41
+ let fieldDepth = 0;
42
+ const marks = [];
43
+ let runStyle;
44
+ const fields = [];
45
+ const notes = [];
46
+ let current = null;
47
+ const field = (c) => {
48
+ const type = attr(c, "fldCharType");
49
+ if (type === "begin") {
50
+ if (fieldDepth === 0) {
51
+ current = { offset: text.length, instruction: "", result: "", inResult: false };
52
+ text += FIELD_ATOM;
53
+ }
54
+ fieldDepth++;
55
+ } else if (type === "separate" && fieldDepth === 1 && current) current.inResult = true;
56
+ else if (type === "end") {
57
+ fieldDepth = Math.max(0, fieldDepth - 1);
58
+ if (fieldDepth === 0 && current) {
59
+ const { offset, instruction, result } = current;
60
+ fields.push({ offset, instruction: instruction.trim(), result });
61
+ current = null;
62
+ }
63
+ }
64
+ };
65
+ const walk = (n, link) => {
66
+ for (const c of n.children ?? []) {
67
+ if (c.localName === "fldChar") {
68
+ field(c);
69
+ continue;
70
+ }
71
+ if (c.localName === "fldSimple") {
72
+ if (fieldDepth === 0) text += FIELD_ATOM;
73
+ continue;
74
+ }
75
+ if (c.localName === "instrText") {
76
+ if (fieldDepth === 1 && current)
77
+ current.instruction += (c.children ?? []).map((t) => t.value ?? "").join("");
78
+ continue;
79
+ }
80
+ if (c.kind === "paragraphProperties" || c.localName === "pPr") {
81
+ for (const p of c.children ?? []) {
82
+ if (p.localName === "pStyle") styleId = attr(p, "val");
83
+ if (p.localName === "outlineLvl" && Number(attr(p, "val")) < 9) outline = true;
84
+ }
85
+ continue;
86
+ }
87
+ if (c.localName === "delText" || c.localName === "del" || c.localName === "rPr") continue;
88
+ if (c.localName === "r") {
89
+ const rStyle = c.children?.find((x) => x.localName === "rPr")?.children?.find((x) => x.localName === "rStyle");
90
+ const watched = rStyle && attr(rStyle, "val");
91
+ runStyle = watched && WATCHED_STYLES.has(watched) ? watched : void 0;
92
+ walk(c, link);
93
+ runStyle = void 0;
94
+ continue;
95
+ }
96
+ if ((c.localName === "footnoteReference" || c.localName === "endnoteReference") && fieldDepth === 0) {
97
+ notes.push({
98
+ offset: text.length,
99
+ kind: c.localName === "footnoteReference" ? "footnote" : "endnote",
100
+ id: attr(c, "id") ?? ""
101
+ });
102
+ text += FIELD_ATOM;
103
+ continue;
104
+ }
105
+ if (c.localName === "bookmarkStart") {
106
+ const name = attr(c, "name");
107
+ if (name) bookmarks.push(name);
108
+ continue;
109
+ }
110
+ if (c.localName === "hyperlink") {
111
+ const anchor = attr(c, "anchor");
112
+ const next = anchor ? { anchor, text: "", offset: text.length } : void 0;
113
+ walk(c, next ?? link);
114
+ if (next) links.push(next);
115
+ continue;
116
+ }
117
+ if (c.kind === "textValue") {
118
+ if (fieldDepth > 0) {
119
+ const open = current;
120
+ if (fieldDepth === 1 && open?.inResult) open.result += c.value ?? "";
121
+ continue;
122
+ }
123
+ if (runStyle && c.value) {
124
+ const last = marks[marks.length - 1];
125
+ if (last && last.styleId === runStyle && last.offset + last.text.length === text.length)
126
+ last.text += c.value;
127
+ else marks.push({ styleId: runStyle, offset: text.length, text: c.value });
128
+ }
129
+ text += c.value ?? "";
130
+ if (link) link.text += c.value ?? "";
131
+ continue;
132
+ }
133
+ if (c.localName === "tab" && fieldDepth === 0) text += " ";
134
+ walk(c, link);
135
+ }
136
+ };
137
+ walk(node);
138
+ const paraId = attr(node, "paraId");
139
+ return {
140
+ id: node.id,
141
+ ...paraId ? { paraId } : {},
142
+ text,
143
+ heading: outline || !!styleId && HEADING_STYLE.test(styleId),
144
+ styleId,
145
+ topLevel,
146
+ bookmarks,
147
+ links,
148
+ ...fields.length ? { fields } : {},
149
+ ...marks.length ? { marks } : {},
150
+ ...notes.length ? { notes } : {}
151
+ };
152
+ }
153
+ function styleNames(root) {
154
+ const names = /* @__PURE__ */ new Map();
155
+ for (const style of root?.children ?? []) {
156
+ if (style.localName !== "style") continue;
157
+ const id = attr(style, "styleId");
158
+ const name = style.children?.find((c) => c.localName === "name");
159
+ if (id) names.set(id, name && attr(name, "val") || id);
160
+ }
161
+ return names;
162
+ }
163
+ var numbers = (level) => !!level && level.numFmt !== "bullet" && level.numFmt !== "none" && (level.lvlText ?? level.markerText ?? "").length > 0;
164
+ function paragraphNumber(order, items, levelOf, paragraphId) {
165
+ const item = items.get(paragraphId);
166
+ if (!item || !numbers(item)) return null;
167
+ const at = order.indexOf(paragraphId);
168
+ const markerAt = (ilvl) => {
169
+ if (ilvl === item.ilvl) return item.markerText;
170
+ for (let i = at - 1; i >= 0; i--) {
171
+ const other = items.get(order[i]);
172
+ if (other && other.numId === item.numId && other.ilvl === ilvl) return other.markerText;
173
+ }
174
+ return null;
175
+ };
176
+ const chain = [];
177
+ const texts = [];
178
+ for (let u = item.ilvl; u >= 0; u--) {
179
+ const level = levelOf(item.numId, u);
180
+ if (!level || !numbers(level)) continue;
181
+ if (u !== item.ilvl && texts.some((t) => t.includes(`%${u + 1}`))) continue;
182
+ chain.push(u);
183
+ texts.push(level.lvlText);
184
+ }
185
+ const value = chain.reverse().map((u) => markerAt(u) ?? "").join("");
186
+ if (!value) return null;
187
+ return value.length > 1 && value.endsWith(".") ? value.slice(0, -1) : value;
188
+ }
189
+ function listTargets(paragraphs, items, levelOf) {
190
+ const order = paragraphs.map((p) => p.id);
191
+ const out = [];
192
+ for (const p of paragraphs) {
193
+ const text = p.text.replace(//g, "").trim();
194
+ if (!text) continue;
195
+ const number = paragraphNumber(order, items, levelOf, p.id);
196
+ const item = items.get(p.id);
197
+ if (number !== null)
198
+ out.push({
199
+ paragraphId: p.id,
200
+ kind: "numbered",
201
+ number,
202
+ marker: item?.markerText ?? "",
203
+ text,
204
+ heading: p.heading,
205
+ level: item?.ilvl ?? 0
206
+ });
207
+ else if (p.heading)
208
+ out.push({
209
+ paragraphId: p.id,
210
+ kind: "heading",
211
+ number: null,
212
+ marker: "",
213
+ text,
214
+ heading: true,
215
+ level: 0
216
+ });
217
+ }
218
+ return out;
219
+ }
220
+ function filterTargets(targets, query) {
221
+ const q = query.trim().toLowerCase();
222
+ if (!q) return [...targets];
223
+ return targets.filter(
224
+ (t) => (t.number ?? "").toLowerCase().startsWith(q) || t.text.toLowerCase().includes(q)
225
+ );
226
+ }
227
+ function documentNumbering(source) {
228
+ let numbering;
229
+ let cascade;
230
+ const index = () => {
231
+ if (!numbering) {
232
+ cascade = layout.buildStyleCascadeTable(
233
+ source.stylesRoot(),
234
+ void 0,
235
+ source.settingsRoot()
236
+ );
237
+ numbering = layout.withNumberingStyleLinks(
238
+ layout.buildNumberingIndex(source.numberingRoot()),
239
+ cascade
240
+ );
241
+ }
242
+ return numbering;
243
+ };
244
+ return {
245
+ listItems: () => {
246
+ const body = source.root().children?.find((n) => n.kind === "body");
247
+ const items = layout.resolveStoryListItems(
248
+ body?.children ?? [],
249
+ index(),
250
+ cascade
251
+ );
252
+ const out = /* @__PURE__ */ new Map();
253
+ for (const [id, item] of items)
254
+ out.set(id, {
255
+ numId: item.numId,
256
+ ilvl: item.ilvl,
257
+ markerText: item.markerText,
258
+ numFmt: item.numFmt
259
+ });
260
+ return out;
261
+ },
262
+ levelOf: (numId, ilvl) => {
263
+ const level = layout.resolveNumberingLevel(index(), numId, ilvl)?.level;
264
+ return level ? { lvlText: level.lvlText, numFmt: level.numFmt } : null;
265
+ }
266
+ };
267
+ }
268
+
269
+ // src/commands/references.ts
270
+ var REF_BOOKMARK_PREFIX = "_Ref";
271
+ var REF_FIELD = /^REF\s+(\S+)((?:\s+\\[A-Za-z*]+(?:\s+MERGEFORMAT)?)*)\s*$/i;
272
+ function crossReferences(port) {
273
+ const paragraphs = port.paragraphs();
274
+ if (!paragraphs.some((p) => p.fields?.length)) return [];
275
+ const items = port.listItems();
276
+ const order = paragraphs.map((p) => p.id);
277
+ const owner = /* @__PURE__ */ new Map();
278
+ for (const p of paragraphs) for (const b of p.bookmarks) if (!owner.has(b)) owner.set(b, p.id);
279
+ const out = [];
280
+ for (const p of paragraphs)
281
+ for (const field of p.fields ?? []) {
282
+ const match = REF_FIELD.exec(field.instruction);
283
+ if (!match || !match[1].startsWith(REF_BOOKMARK_PREFIX)) continue;
284
+ const switches = match[2].toLowerCase();
285
+ const mode = /\\[rwn]\b/.test(switches) ? "number" : "text";
286
+ const target = owner.get(match[1]) ?? null;
287
+ const value = !target ? null : mode === "number" ? switches.includes("\\r") ? paragraphNumber(order, items, port.levelOf, target) : null : (paragraphs.find((x) => x.id === target)?.text ?? "").replace(//g, "").trim();
288
+ out.push({
289
+ paragraphId: p.id,
290
+ offset: field.offset,
291
+ instruction: field.instruction,
292
+ bookmark: match[1],
293
+ mode,
294
+ cached: field.result,
295
+ target,
296
+ value
297
+ });
298
+ }
299
+ return out;
300
+ }
301
+ function staleCrossReferences(port) {
302
+ return crossReferences(port).filter((ref) => !ref.target || ref.value && ref.value !== ref.cached.trim()).map(({ paragraphId, offset, instruction, value, cached, bookmark, mode }) => ({
303
+ paragraphId,
304
+ offset,
305
+ instruction,
306
+ value,
307
+ cached,
308
+ bookmark,
309
+ mode
310
+ }));
311
+ }
312
+ function brokenCrossReferences(port) {
313
+ return port.paragraphs().flatMap(
314
+ (p) => (p.marks ?? []).filter((m) => m.styleId === BROKEN_CROSS_REFERENCE_STYLE).map((m) => ({ paragraphId: p.id, offset: m.offset, text: m.text }))
315
+ );
316
+ }
317
+
318
+ // src/commands/index.ts
319
+ function documentReader(view) {
320
+ const root = () => view.part().root;
321
+ let paragraphs;
322
+ let items;
323
+ let names;
324
+ const numbering = documentNumbering({ ...view, root });
325
+ return {
326
+ paragraphs: () => paragraphs ??= readParagraphs(root()),
327
+ listItems: () => items ??= numbering.listItems(),
328
+ levelOf: numbering.levelOf,
329
+ styleName: (id) => (names ??= styleNames(view.stylesRoot())).get(id) ?? id
330
+ };
331
+ }
332
+ function readDocument(bytes) {
333
+ const opened = store.openHeadlessDocument(bytes);
334
+ if (!opened.ok) throw new Error(`The document cannot be read (${opened.reason}).`);
335
+ return documentReader(opened.view);
336
+ }
337
+
338
+ exports.BROKEN_CROSS_REFERENCE_STYLE = BROKEN_CROSS_REFERENCE_STYLE;
339
+ exports.CROSS_REFERENCE_STYLE = CROSS_REFERENCE_STYLE;
340
+ exports.DEFINED_TERM_STYLE = DEFINED_TERM_STYLE;
341
+ exports.FIELD_ATOM = FIELD_ATOM;
342
+ exports.REF_BOOKMARK_PREFIX = REF_BOOKMARK_PREFIX;
343
+ exports.WATCHED_STYLES = WATCHED_STYLES;
344
+ exports.brokenCrossReferences = brokenCrossReferences;
345
+ exports.crossReferences = crossReferences;
346
+ exports.documentNumbering = documentNumbering;
347
+ exports.documentReader = documentReader;
348
+ exports.filterTargets = filterTargets;
349
+ exports.listTargets = listTargets;
350
+ exports.paragraphNumber = paragraphNumber;
351
+ exports.readDocument = readDocument;
352
+ exports.readParagraphs = readParagraphs;
353
+ exports.staleCrossReferences = staleCrossReferences;
354
+ exports.styleNames = styleNames;
355
+ //# sourceMappingURL=commands.cjs.map
356
+ //# sourceMappingURL=commands.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/read.ts","../src/commands/numbering.ts","../src/commands/references.ts","../src/commands/index.ts"],"names":["buildStyleCascadeTable","withNumberingStyleLinks","buildNumberingIndex","resolveStoryListItems","resolveNumberingLevel","openHeadlessDocument"],"mappings":"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","file":"commands.cjs","sourcesContent":["/**\n * The read side of the Word-editor commands: a document's paragraphs as the commands see them\n * (text in the engine's offset vocabulary, bookmarks, internal links, fields, note references),\n * read from the engine's OOXML tree. The same tree comes from a live editor\n * (`surface.session.part().root`) or from document bytes (`openHeadlessDocument`), so the toolbar\n * and ARBI's headless tools read a document the same way.\n */\n\n/** Character style of an inserted term: a dotted underline, so a defined term reads as one. */\nexport const DEFINED_TERM_STYLE = 'DefinedTerm'\n\n/** Character style of a cross-reference: a muted blue with a dotted underline (Word's name). */\nexport const CROSS_REFERENCE_STYLE = 'CrossReference'\n/** Character style of a cross-reference whose target is gone: its last text, flagged. */\nexport const BROKEN_CROSS_REFERENCE_STYLE = 'CrossReferenceBroken'\n\n/** A position: a paragraph (the engine's node id) and a UTF-16 offset into its text. */\nexport interface DocPoint {\n paragraphId: string\n offset: number\n}\n\n/** An internal link in a paragraph. */\nexport interface DocLink {\n anchor: string\n text: string\n /** Where its text starts in the paragraph's text. */\n offset?: number\n}\n\n/** A footnote or endnote reference: one character of the paragraph, as the engine counts it. */\nexport interface DocNote {\n offset: number\n kind: 'footnote' | 'endnote'\n /** `w:id` of the note. */\n id: string\n}\n\n/** One paragraph, in document order. */\nexport interface DocParagraph {\n id: string\n /** `w14:paraId`, the id that is the same in every replica of a collaboration room. */\n paraId?: string\n text: string\n /** Styled as a heading (a `Heading n` style or an outline level). */\n heading: boolean\n styleId?: string\n /** A paragraph of the body itself, not inside a table. */\n topLevel: boolean\n /** Names of the bookmarks that start in it. */\n bookmarks: string[]\n /** Its internal links (`w:hyperlink w:anchor`). */\n links: DocLink[]\n /** Its complex fields: where each sits (its one-character offset), its instruction and result. */\n fields?: DocField[]\n /** Its runs in a watched character style (a broken cross-reference's mark), with their text. */\n marks?: DocMark[]\n /** Its footnote and endnote references. */\n notes?: DocNote[]\n}\n\n/** A stretch of a paragraph's text in a watched character style. */\nexport interface DocMark {\n styleId: string\n offset: number\n text: string\n}\n\n/** Character styles whose runs a paragraph read reports as marks. */\nexport const WATCHED_STYLES = new Set([BROKEN_CROSS_REFERENCE_STYLE])\n\n/** A complex field of a paragraph. */\nexport interface DocField {\n offset: number\n instruction: string\n result: string\n}\n\nexport type OoxmlNodeLike = {\n id: string\n kind: string\n localName?: string\n value?: string\n attributes?: readonly { localName: string; value: string }[]\n children?: readonly OoxmlNodeLike[]\n}\n\nconst attr = (node: OoxmlNodeLike, name: string) =>\n node.attributes?.find((a) => a.localName === name)?.value\n\n/** How a field (or a note reference) counts in a paragraph's text (the engine's model vocabulary). */\nexport const FIELD_ATOM = '\\uFFFC'\n\n/** A heading style id in any of the spellings Word localises it to (`Heading1`, `berschrift1`…). */\nconst HEADING_STYLE = /^(heading|berschrift|titre|t[ií]tulo|titolo|kop)\\s*\\d/i\n\n/** The paragraphs of a part's body, read from the engine's OOXML tree. */\nexport function readParagraphs(root: OoxmlNodeLike): DocParagraph[] {\n const out: DocParagraph[] = []\n const body = root.children?.find((n) => n.kind === 'body') ?? root\n const visit = (node: OoxmlNodeLike, topLevel: boolean, pending: string[]) => {\n for (const child of node.children ?? []) {\n if (child.kind === 'paragraph') {\n out.push(readParagraph(child, topLevel, pending.splice(0)))\n } else if (child.localName === 'bookmarkStart') {\n // A bookmark between paragraphs belongs to the next one.\n const name = attr(child, 'name')\n if (name) pending.push(name)\n } else if (\n child.localName === 'tbl' ||\n child.localName === 'tr' ||\n child.localName === 'tc'\n ) {\n visit(child, false, pending)\n } else if (child.localName === 'sdt' || child.localName === 'sdtContent') {\n visit(child, topLevel, pending)\n }\n }\n }\n visit(body, true, [])\n return out\n}\n\nfunction readParagraph(node: OoxmlNodeLike, topLevel: boolean, bookmarks: string[]): DocParagraph {\n let text = ''\n const links: DocLink[] = []\n let styleId: string | undefined\n let outline = false\n // A field reads as ONE character (U+FFFC), as the engine counts offsets: its instruction and\n // its cached result are not text of the paragraph.\n let fieldDepth = 0\n const marks: DocMark[] = []\n /** The watched style of the run being walked, if any. */\n let runStyle: string | undefined\n const fields: DocField[] = []\n const notes: DocNote[] = []\n let current: (DocField & { inResult: boolean }) | null = null\n const field = (c: OoxmlNodeLike) => {\n const type = attr(c, 'fldCharType')\n if (type === 'begin') {\n if (fieldDepth === 0) {\n current = { offset: text.length, instruction: '', result: '', inResult: false }\n text += FIELD_ATOM\n }\n fieldDepth++\n } else if (type === 'separate' && fieldDepth === 1 && current) current.inResult = true\n else if (type === 'end') {\n fieldDepth = Math.max(0, fieldDepth - 1)\n if (fieldDepth === 0 && current) {\n const { offset, instruction, result } = current\n fields.push({ offset, instruction: instruction.trim(), result })\n current = null\n }\n }\n }\n const walk = (n: OoxmlNodeLike, link?: DocLink) => {\n for (const c of n.children ?? []) {\n if (c.localName === 'fldChar') {\n field(c)\n continue\n }\n if (c.localName === 'fldSimple') {\n if (fieldDepth === 0) text += FIELD_ATOM\n continue\n }\n if (c.localName === 'instrText') {\n if (fieldDepth === 1 && current)\n (current as DocField).instruction += (c.children ?? []).map((t) => t.value ?? '').join('')\n continue\n }\n if (c.kind === 'paragraphProperties' || c.localName === 'pPr') {\n for (const p of c.children ?? []) {\n if (p.localName === 'pStyle') styleId = attr(p, 'val')\n if (p.localName === 'outlineLvl' && Number(attr(p, 'val')) < 9) outline = true\n }\n continue\n }\n if (c.localName === 'delText' || c.localName === 'del' || c.localName === 'rPr') continue\n if (c.localName === 'r') {\n const rStyle = c.children\n ?.find((x) => x.localName === 'rPr')\n ?.children?.find((x) => x.localName === 'rStyle')\n const watched = rStyle && attr(rStyle, 'val')\n runStyle = watched && WATCHED_STYLES.has(watched) ? watched : undefined\n walk(c, link)\n runStyle = undefined\n continue\n }\n if (\n (c.localName === 'footnoteReference' || c.localName === 'endnoteReference') &&\n fieldDepth === 0\n ) {\n notes.push({\n offset: text.length,\n kind: c.localName === 'footnoteReference' ? 'footnote' : 'endnote',\n id: attr(c, 'id') ?? '',\n })\n text += FIELD_ATOM\n continue\n }\n if (c.localName === 'bookmarkStart') {\n const name = attr(c, 'name')\n if (name) bookmarks.push(name)\n continue\n }\n if (c.localName === 'hyperlink') {\n const anchor = attr(c, 'anchor')\n const next = anchor ? { anchor, text: '', offset: text.length } : undefined\n walk(c, next ?? link)\n if (next) links.push(next)\n continue\n }\n if (c.kind === 'textValue') {\n if (fieldDepth > 0) {\n const open = current as (DocField & { inResult: boolean }) | null\n if (fieldDepth === 1 && open?.inResult) open.result += c.value ?? ''\n continue\n }\n if (runStyle && c.value) {\n const last = marks[marks.length - 1]\n if (last && last.styleId === runStyle && last.offset + last.text.length === text.length)\n last.text += c.value\n else marks.push({ styleId: runStyle, offset: text.length, text: c.value })\n }\n text += c.value ?? ''\n if (link) link.text += c.value ?? ''\n continue\n }\n if (c.localName === 'tab' && fieldDepth === 0) text += '\\t'\n walk(c, link)\n }\n }\n walk(node)\n const paraId = attr(node, 'paraId')\n return {\n id: node.id,\n ...(paraId ? { paraId } : {}),\n text,\n heading: outline || (!!styleId && HEADING_STYLE.test(styleId)),\n styleId,\n topLevel,\n bookmarks,\n links,\n ...(fields.length ? { fields } : {}),\n ...(marks.length ? { marks } : {}),\n ...(notes.length ? { notes } : {}),\n }\n}\n\n/** Style id to style name (`Heading1` → `heading 1`), from a styles part's tree. */\nexport function styleNames(root: OoxmlNodeLike | null | undefined): Map<string, string> {\n const names = new Map<string, string>()\n for (const style of root?.children ?? []) {\n if (style.localName !== 'style') continue\n const id = attr(style, 'styleId')\n const name = style.children?.find((c) => c.localName === 'name')\n if (id) names.set(id, (name && attr(name, 'val')) || id)\n }\n return names\n}\n","/**\n * Cross-reference targets: the document's numbered paragraphs (clauses, sub-clauses, numbered\n * captions) and its headings, with the number Word's `REF \\r` shows for each.\n *\n * The number is what the editor computes for a `REF … \\r` field — and it has to be exactly that,\n * because the engine shows a field's live value only while the field's cached result matches what\n * it computes (otherwise it keeps the cached text for good). So this mirrors the engine: the\n * paragraph's own list level, preceded by each higher level whose number its level text does not\n * already show (`%1.%2` already shows level 1; `(%3)` does not show `2.1`), and one trailing\n * period dropped (`2.` reads `2`).\n */\n\nimport type { DocParagraph, OoxmlNodeLike } from './read'\nimport {\n buildNumberingIndex,\n buildStyleCascadeTable,\n resolveNumberingLevel,\n resolveStoryListItems,\n withNumberingStyleLinks,\n} from '@docx-editor.dev/core/layout'\n\n/** A paragraph's resolved list numbering (the engine's list item). */\nexport interface ListItemInfo {\n numId: string\n ilvl: number\n markerText: string\n numFmt: string\n}\n\n/** A list level's definition: its level text (`%1.%2`) and number format. */\nexport interface LevelInfo {\n lvlText: string\n numFmt: string\n}\n\nexport type LevelOf = (numId: string, ilvl: number) => LevelInfo | null\n\nconst numbers = (level: { numFmt: string; lvlText?: string; markerText?: string } | null) =>\n !!level &&\n level.numFmt !== 'bullet' &&\n level.numFmt !== 'none' &&\n (level.lvlText ?? level.markerText ?? '').length > 0\n\n/**\n * The number `REF \\r` shows for a paragraph, or null when it is not numbered. `order` is every\n * paragraph id in document order (for the markers of the levels above it).\n */\nexport function paragraphNumber(\n order: readonly string[],\n items: ReadonlyMap<string, ListItemInfo>,\n levelOf: LevelOf,\n paragraphId: string\n): string | null {\n const item = items.get(paragraphId)\n if (!item || !numbers(item)) return null\n const at = order.indexOf(paragraphId)\n /** The marker the nearest paragraph at `ilvl` of this list had, up to the target. */\n const markerAt = (ilvl: number): string | null => {\n if (ilvl === item.ilvl) return item.markerText\n for (let i = at - 1; i >= 0; i--) {\n const other = items.get(order[i])\n if (other && other.numId === item.numId && other.ilvl === ilvl) return other.markerText\n }\n return null\n }\n const chain: number[] = []\n const texts: string[] = []\n for (let u = item.ilvl; u >= 0; u--) {\n const level = levelOf(item.numId, u)\n if (!level || !numbers(level)) continue\n if (u !== item.ilvl && texts.some((t) => t.includes(`%${u + 1}`))) continue\n chain.push(u)\n texts.push(level.lvlText)\n }\n const value = chain\n .reverse()\n .map((u) => markerAt(u) ?? '')\n .join('')\n if (!value) return null\n return value.length > 1 && value.endsWith('.') ? value.slice(0, -1) : value\n}\n\n/** One place a cross-reference can point at. */\nexport interface CrossReferenceTarget {\n paragraphId: string\n /** A numbered paragraph (clause, sub-clause, caption) or an unnumbered heading. */\n kind: 'numbered' | 'heading'\n /** What `REF \\r` shows (`8.2`), or null for an unnumbered heading. */\n number: string | null\n /** The paragraph's list marker as painted (`8.2`, `(a)`), or empty. */\n marker: string\n /** The paragraph's text (without its marker). */\n text: string\n heading: boolean\n /** Its list level (0 for a top-level clause), or 0 for a heading. */\n level: number\n}\n\n/** Every numbered paragraph and every heading, in document order. */\nexport function listTargets(\n paragraphs: readonly DocParagraph[],\n items: ReadonlyMap<string, ListItemInfo>,\n levelOf: LevelOf\n): CrossReferenceTarget[] {\n const order = paragraphs.map((p) => p.id)\n const out: CrossReferenceTarget[] = []\n for (const p of paragraphs) {\n const text = p.text.replace(//g, '').trim()\n if (!text) continue\n const number = paragraphNumber(order, items, levelOf, p.id)\n const item = items.get(p.id)\n if (number !== null)\n out.push({\n paragraphId: p.id,\n kind: 'numbered',\n number,\n marker: item?.markerText ?? '',\n text,\n heading: p.heading,\n level: item?.ilvl ?? 0,\n })\n else if (p.heading)\n out.push({\n paragraphId: p.id,\n kind: 'heading',\n number: null,\n marker: '',\n text,\n heading: true,\n level: 0,\n })\n }\n return out\n}\n\n/** Targets whose number or text contains the query (case-insensitive). */\nexport function filterTargets(\n targets: readonly CrossReferenceTarget[],\n query: string\n): CrossReferenceTarget[] {\n const q = query.trim().toLowerCase()\n if (!q) return [...targets]\n return targets.filter(\n (t) => (t.number ?? '').toLowerCase().startsWith(q) || t.text.toLowerCase().includes(q)\n )\n}\n\n/** What the engine's numbering needs of a document: its parts' trees. */\nexport interface NumberingSource {\n /** The main document part's root. */\n root(): OoxmlNodeLike\n stylesRoot(): unknown\n numberingRoot(): unknown\n settingsRoot(): unknown\n}\n\n/** A document's list numbering as the engine resolves it. */\nexport interface DocumentNumbering {\n /** Each numbered paragraph's list item, by paragraph (node) id. */\n listItems(): ReadonlyMap<string, ListItemInfo>\n levelOf: LevelOf\n}\n\n/**\n * The numbering of a document, as the editor paints it: from a live editor's session or from a\n * headless document view alike.\n */\nexport function documentNumbering(source: NumberingSource): DocumentNumbering {\n type Index = ReturnType<typeof buildNumberingIndex>\n type Cascade = ReturnType<typeof buildStyleCascadeTable>\n let numbering: Index | undefined\n let cascade: Cascade | undefined\n const index = () => {\n if (!numbering) {\n cascade = buildStyleCascadeTable(\n source.stylesRoot() as Parameters<typeof buildStyleCascadeTable>[0],\n undefined,\n source.settingsRoot() as Parameters<typeof buildStyleCascadeTable>[2]\n )\n numbering = withNumberingStyleLinks(\n buildNumberingIndex(source.numberingRoot() as Parameters<typeof buildNumberingIndex>[0]),\n cascade\n )\n }\n return numbering\n }\n return {\n listItems: () => {\n const body = source.root().children?.find((n) => n.kind === 'body')\n const items = resolveStoryListItems(\n (body?.children ?? []) as unknown as Parameters<typeof resolveStoryListItems>[0],\n index(),\n cascade\n )\n const out = new Map<string, ListItemInfo>()\n for (const [id, item] of items)\n out.set(id, {\n numId: item.numId,\n ilvl: item.ilvl,\n markerText: item.markerText,\n numFmt: item.numFmt,\n })\n return out\n },\n levelOf: (numId, ilvl) => {\n const level = resolveNumberingLevel(index(), numId, ilvl)?.level\n return level ? { lvlText: level.lvlText, numFmt: level.numFmt } : null\n },\n }\n}\n","/**\n * The cross-references of a document (`REF` fields to `_Ref` bookmarks), each with what it shows\n * and what its target now is: current, stale (a clause renumbered, a heading reworded) or broken\n * (the target is gone).\n */\n\nimport { BROKEN_CROSS_REFERENCE_STYLE, type DocParagraph } from './read'\nimport { paragraphNumber, type LevelOf, type ListItemInfo } from './numbering'\n\n/** Prefix of Word's hidden cross-reference bookmarks. */\nexport const REF_BOOKMARK_PREFIX = '_Ref'\n\nexport type CrossReferenceMode = 'number' | 'text'\n\nconst REF_FIELD = /^REF\\s+(\\S+)((?:\\s+\\\\[A-Za-z*]+(?:\\s+MERGEFORMAT)?)*)\\s*$/i\n\n/** What reading cross-references needs of a document. */\nexport interface ReferencesReader {\n paragraphs(): DocParagraph[]\n /** Each numbered paragraph's list item, by paragraph id. */\n listItems(): ReadonlyMap<string, ListItemInfo>\n levelOf: LevelOf\n}\n\n/** One `REF` field to a `_Ref` bookmark. */\nexport interface CrossReference {\n paragraphId: string\n offset: number\n instruction: string\n bookmark: string\n mode: CrossReferenceMode\n /** The field's cached result (what it shows). */\n cached: string\n /** The paragraph the bookmark is in, or null when it is gone (the reference is broken). */\n target: string | null\n /** What the reference should show now, or null when that cannot be computed. */\n value: string | null\n}\n\n/** A `REF` field whose cached result no longer says what its target now is. */\nexport interface StaleReference {\n paragraphId: string\n offset: number\n instruction: string\n /** The current value, or null when the target is gone (the reference is broken). */\n value: string | null\n /** The field's cached result (what it last showed). */\n cached: string\n bookmark: string\n mode: CrossReferenceMode\n}\n\n/** A cross-reference whose target was deleted: its last text, marked in the Broken style. */\nexport interface BrokenReference {\n paragraphId: string\n offset: number\n text: string\n}\n\n/** Every cross-reference of the document, in document order. */\nexport function crossReferences(port: ReferencesReader): CrossReference[] {\n const paragraphs = port.paragraphs()\n if (!paragraphs.some((p) => p.fields?.length)) return []\n const items = port.listItems()\n const order = paragraphs.map((p) => p.id)\n const owner = new Map<string, string>()\n for (const p of paragraphs) for (const b of p.bookmarks) if (!owner.has(b)) owner.set(b, p.id)\n const out: CrossReference[] = []\n for (const p of paragraphs)\n for (const field of p.fields ?? []) {\n const match = REF_FIELD.exec(field.instruction)\n if (!match || !match[1].startsWith(REF_BOOKMARK_PREFIX)) continue\n const switches = match[2].toLowerCase()\n const mode: CrossReferenceMode = /\\\\[rwn]\\b/.test(switches) ? 'number' : 'text'\n const target = owner.get(match[1]) ?? null\n const value = !target\n ? null\n : mode === 'number'\n ? switches.includes('\\\\r')\n ? paragraphNumber(order, items, port.levelOf, target)\n : null\n : (paragraphs.find((x) => x.id === target)?.text ?? '').replace(//g, '').trim()\n out.push({\n paragraphId: p.id,\n offset: field.offset,\n instruction: field.instruction,\n bookmark: match[1],\n mode,\n cached: field.result,\n target,\n value,\n })\n }\n return out\n}\n\n/**\n * The cross-references whose cached result is out of date: a clause renumbered, a heading\n * reworded, or the target gone. The editor paints a field's live value only while its cached\n * result matches what it computes, so a stale cache shows the OLD number after the document is\n * reopened (and Word shows the cached result until its fields are updated).\n */\nexport function staleCrossReferences(port: ReferencesReader): StaleReference[] {\n return crossReferences(port)\n .filter((ref) => !ref.target || (ref.value && ref.value !== ref.cached.trim()))\n .map(({ paragraphId, offset, instruction, value, cached, bookmark, mode }) => ({\n paragraphId,\n offset,\n instruction,\n value,\n cached,\n bookmark,\n mode,\n }))\n}\n\n/** The broken cross-references marked in the document, in document order. */\nexport function brokenCrossReferences(\n port: Pick<ReferencesReader, 'paragraphs'>\n): BrokenReference[] {\n return port\n .paragraphs()\n .flatMap((p) =>\n (p.marks ?? [])\n .filter((m) => m.styleId === BROKEN_CROSS_REFERENCE_STYLE)\n .map((m) => ({ paragraphId: p.id, offset: m.offset, text: m.text }))\n )\n}\n","/**\n * Word-editor commands shared by the editor's toolbar and ARBI's headless tools in the\n * collaboration service. Pure functions over the engine's OOXML tree, so they run on a live\n * editor's session and on a headless document view alike.\n */\nimport { openHeadlessDocument } from '@docx-editor.dev/core/store'\nimport { readParagraphs, styleNames, type DocParagraph, type OoxmlNodeLike } from './read'\nimport { documentNumbering, type DocumentNumbering } from './numbering'\nimport type { ReferencesReader } from './references'\n\nexport * from './read'\nexport * from './numbering'\nexport * from './references'\n\n/** A document's parts as trees: a live editor's session or a headless view (`openHeadlessDocument`). */\nexport interface DocumentTrees {\n part(): { root: unknown }\n stylesRoot(): unknown\n numberingRoot(): unknown\n settingsRoot(): unknown\n}\n\n/** A read-only snapshot of a document: its paragraphs, numbering and style names. */\nexport interface DocumentReader extends ReferencesReader, DocumentNumbering {\n /** A style's name (`heading 1`) by its id, or the id when the document does not name it. */\n styleName(styleId: string): string\n}\n\n/** Read a document whose trees do not change while the reader is used (a headless view). */\nexport function documentReader(view: DocumentTrees): DocumentReader {\n const root = () => view.part().root as OoxmlNodeLike\n let paragraphs: DocParagraph[] | undefined\n let items: ReturnType<DocumentNumbering['listItems']> | undefined\n let names: Map<string, string> | undefined\n const numbering = documentNumbering({ ...view, root })\n return {\n paragraphs: () => (paragraphs ??= readParagraphs(root())),\n listItems: () => (items ??= numbering.listItems()),\n levelOf: numbering.levelOf,\n styleName: (id) =>\n (names ??= styleNames(view.stylesRoot() as OoxmlNodeLike | null)).get(id) ?? id,\n }\n}\n\n/** Read a document from its bytes (a collaboration room's `readRoom`). Throws on a bad package. */\nexport function readDocument(bytes: Uint8Array): DocumentReader {\n const opened = openHeadlessDocument(bytes)\n if (!opened.ok) throw new Error(`The document cannot be read (${opened.reason}).`)\n return documentReader(opened.view)\n}\n"]}