@arbidocs/coedit 0.4.111 → 0.4.113
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.
- package/dist/commands.cjs +687 -0
- package/dist/commands.cjs.map +1 -1
- package/dist/commands.d.cts +263 -157
- package/dist/commands.d.ts +263 -157
- package/dist/commands.js +646 -2
- package/dist/commands.js.map +1 -1
- package/dist/port-ip7WByvH.d.cts +188 -0
- package/dist/port-ip7WByvH.d.ts +188 -0
- package/dist/server.cjs +675 -65
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +15 -4
- package/dist/server.d.ts +15 -4
- package/dist/server.js +676 -67
- package/dist/server.js.map +1 -1
- package/dist/template.d.cts +3 -17
- package/dist/template.d.ts +3 -17
- package/dist/track-eYC94jTp.d.cts +17 -0
- package/dist/track-eYC94jTp.d.ts +17 -0
- package/package.json +1 -1
package/dist/commands.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { ACCEPTED_PARAGRAPH_PROPERTIES, openHeadlessDocument } from '@docx-editor.dev/core/store';
|
|
1
|
+
import { ACCEPTED_PARAGRAPH_PROPERTIES, openHeadlessDocument, readXml } from '@docx-editor.dev/core/store';
|
|
2
2
|
import { resolveNumberingLevel, resolveStoryListItems, buildStyleCascadeTable, withNumberingStyleLinks, buildNumberingIndex } from '@docx-editor.dev/core/layout';
|
|
3
|
+
import { zipSync, strToU8, strFromU8, unzipSync } from 'fflate';
|
|
3
4
|
|
|
4
5
|
// src/commands/index.ts
|
|
5
6
|
|
|
@@ -263,6 +264,35 @@ function documentNumbering(source) {
|
|
|
263
264
|
}
|
|
264
265
|
};
|
|
265
266
|
}
|
|
267
|
+
var W_NAMESPACES = 'xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"';
|
|
268
|
+
var INVALID_XML = /[\u0000-\u0008\u000B\u000C\u000E-\u001F]/g;
|
|
269
|
+
var esc = (text) => text.replace(INVALID_XML, "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
270
|
+
var documentXml = (body) => `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
271
|
+
<w:document ${W_NAMESPACES}><w:body>${body}</w:body></w:document>`;
|
|
272
|
+
var stylesXml = (defaults, styles) => `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
273
|
+
<w:styles xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">${defaults}${styles}</w:styles>`;
|
|
274
|
+
var CONTENT_TYPES = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
275
|
+
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/><Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/><Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/></Types>`;
|
|
276
|
+
var ROOT_RELS = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
277
|
+
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/><Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/></Relationships>`;
|
|
278
|
+
var documentRels = (more = "") => `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
279
|
+
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>${more}</Relationships>`;
|
|
280
|
+
var hyperlinkRelationship = (id, url) => `<Relationship Id="${esc(id)}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" Target="${esc(url)}" TargetMode="External"/>`;
|
|
281
|
+
var coreXml = (title, at) => `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
282
|
+
<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><dc:title>${esc(
|
|
283
|
+
title
|
|
284
|
+
)}</dc:title><dcterms:created xsi:type="dcterms:W3CDTF">${at}</dcterms:created><dcterms:modified xsi:type="dcterms:W3CDTF">${at}</dcterms:modified></cp:coreProperties>`;
|
|
285
|
+
function docxPackage(parts) {
|
|
286
|
+
const at = new Date(parts.at ?? Date.now()).toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
287
|
+
return zipSync({
|
|
288
|
+
"[Content_Types].xml": strToU8(CONTENT_TYPES),
|
|
289
|
+
"_rels/.rels": strToU8(ROOT_RELS),
|
|
290
|
+
"docProps/core.xml": strToU8(coreXml(parts.title, at)),
|
|
291
|
+
"word/document.xml": strToU8(parts.document),
|
|
292
|
+
"word/styles.xml": strToU8(parts.styles),
|
|
293
|
+
"word/_rels/document.xml.rels": strToU8(documentRels(parts.relationships))
|
|
294
|
+
});
|
|
295
|
+
}
|
|
266
296
|
|
|
267
297
|
// src/commands/references.ts
|
|
268
298
|
var REF_BOOKMARK_PREFIX = "_Ref";
|
|
@@ -312,6 +342,126 @@ function brokenCrossReferences(port) {
|
|
|
312
342
|
(p) => (p.marks ?? []).filter((m) => m.styleId === BROKEN_CROSS_REFERENCE_STYLE).map((m) => ({ paragraphId: p.id, offset: m.offset, text: m.text }))
|
|
313
343
|
);
|
|
314
344
|
}
|
|
345
|
+
function newRefBookmark(taken, random = Math.random) {
|
|
346
|
+
for (; ; ) {
|
|
347
|
+
const name = `${REF_BOOKMARK_PREFIX}${String(Math.floor(random() * 9e8) + 1e8)}`;
|
|
348
|
+
if (!taken.has(name)) return name;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
var styled = (style) => style ? `<w:rPr><w:rStyle w:val="${style}"/></w:rPr>` : "";
|
|
352
|
+
var run = (text, style) => `<w:r>${styled(style)}<w:t xml:space="preserve">${esc(text)}</w:t></w:r>`;
|
|
353
|
+
function refFieldXml(instruction, cached) {
|
|
354
|
+
const r = (inner) => `<w:r>${styled(CROSS_REFERENCE_STYLE)}${inner}</w:r>`;
|
|
355
|
+
return `${r('<w:fldChar w:fldCharType="begin"/>')}${r(
|
|
356
|
+
`<w:instrText xml:space="preserve"> ${esc(instruction)} </w:instrText>`
|
|
357
|
+
)}${r('<w:fldChar w:fldCharType="separate"/>')}${run(cached, CROSS_REFERENCE_STYLE)}${r(
|
|
358
|
+
'<w:fldChar w:fldCharType="end"/>'
|
|
359
|
+
)}`;
|
|
360
|
+
}
|
|
361
|
+
var refTooltip = (value, mode) => mode === "number" ? `Cross-reference to clause ${value}` : `Cross-reference to \u201C${value}\u201D`;
|
|
362
|
+
function crossReferenceXml(bookmark, mode, value) {
|
|
363
|
+
return `<w:hyperlink w:anchor="${esc(bookmark)}" w:tooltip="${esc(
|
|
364
|
+
refTooltip(value, mode)
|
|
365
|
+
)}" w:history="1">${refFieldXml(refInstruction(bookmark, mode), value)}</w:hyperlink>`;
|
|
366
|
+
}
|
|
367
|
+
var refInstruction = (bookmark, mode) => mode === "number" ? `REF ${bookmark} \\r \\h` : `REF ${bookmark} \\h`;
|
|
368
|
+
var refResult = (target, mode) => mode === "number" && target.number ? target.number : target.text;
|
|
369
|
+
var allBookmarks = (port) => new Set(port.paragraphs().flatMap((p) => p.bookmarks));
|
|
370
|
+
function ensureTargetBookmark(port, target, mode) {
|
|
371
|
+
const paragraph = port.paragraphs().find((p) => p.id === target.paragraphId);
|
|
372
|
+
if (!paragraph) throw new Error("That clause is no longer in the document.");
|
|
373
|
+
const existing = paragraph.bookmarks.find((b) => b.startsWith(REF_BOOKMARK_PREFIX));
|
|
374
|
+
if (existing && mode === "number") return existing;
|
|
375
|
+
const name = newRefBookmark(allBookmarks(port));
|
|
376
|
+
const start = `<w:bookmarkStart w:id="0" w:name="${name}"/>`;
|
|
377
|
+
const end = '<w:bookmarkEnd w:id="0"/>';
|
|
378
|
+
if (mode === "number") {
|
|
379
|
+
port.setCaret({ paragraphId: paragraph.id, offset: 0 });
|
|
380
|
+
if (!port.paste(`<w:p>${start}${end}</w:p>`, "", false))
|
|
381
|
+
throw new Error("The cross-reference target could not be marked.");
|
|
382
|
+
return name;
|
|
383
|
+
}
|
|
384
|
+
const runs = port.runsXml(paragraph.id);
|
|
385
|
+
if (!runs) throw new Error("This heading cannot be referred to by its text; use its number.");
|
|
386
|
+
port.deleteRange(
|
|
387
|
+
{ paragraphId: paragraph.id, offset: 0 },
|
|
388
|
+
{ paragraphId: paragraph.id, offset: paragraph.text.length }
|
|
389
|
+
);
|
|
390
|
+
if (!port.paste(`<w:p>${start}${runs}${end}</w:p>`, paragraph.text, false))
|
|
391
|
+
throw new Error("The cross-reference target could not be marked.");
|
|
392
|
+
return name;
|
|
393
|
+
}
|
|
394
|
+
function pastePoint(port, caret) {
|
|
395
|
+
const paragraph = port.paragraphs().find((p) => p.id === caret.paragraphId);
|
|
396
|
+
if (paragraph?.text[caret.offset - 1] !== FIELD_ATOM) return caret;
|
|
397
|
+
port.setCaret(caret);
|
|
398
|
+
port.typeText(" ");
|
|
399
|
+
return { paragraphId: caret.paragraphId, offset: caret.offset + 1 };
|
|
400
|
+
}
|
|
401
|
+
function markCrossReferenceTarget(port, target, mode) {
|
|
402
|
+
if (mode === "number" && !target.number) mode = "text";
|
|
403
|
+
const bookmark = ensureTargetBookmark(port, target, mode);
|
|
404
|
+
return { bookmark, mode, value: refResult(target, mode) };
|
|
405
|
+
}
|
|
406
|
+
function insertCrossReferenceField(port, { bookmark, mode, value }, caret) {
|
|
407
|
+
caret = pastePoint(port, caret);
|
|
408
|
+
port.setCaret(caret);
|
|
409
|
+
if (!port.paste(`<w:p>${crossReferenceXml(bookmark, mode, value)}</w:p>`, value, false))
|
|
410
|
+
throw new Error("The cross-reference could not be inserted.");
|
|
411
|
+
port.setCaret({ paragraphId: caret.paragraphId, offset: caret.offset + 1 });
|
|
412
|
+
return { bookmark };
|
|
413
|
+
}
|
|
414
|
+
function insertCrossReference(port, target, mode, caret) {
|
|
415
|
+
return insertCrossReferenceField(port, markCrossReferenceTarget(port, target, mode), caret);
|
|
416
|
+
}
|
|
417
|
+
var documentReferenceTooltip = (text, appName = "ARBI") => `Cross-reference: ${text} \u2014 opens in ${appName}`;
|
|
418
|
+
function insertDocumentReference(port, reference, caret) {
|
|
419
|
+
const text = reference.text.trim();
|
|
420
|
+
if (!text) throw new Error("Enter the reference text.");
|
|
421
|
+
const tooltip = documentReferenceTooltip(text, reference.appName).slice(0, 255);
|
|
422
|
+
caret = pastePoint(port, caret);
|
|
423
|
+
port.setCaret(caret);
|
|
424
|
+
const link = `<w:p><w:hyperlink r:id="rIdRef1"${tooltip ? ` w:tooltip="${esc(tooltip)}"` : ""} w:history="1">${run(text, CROSS_REFERENCE_STYLE)}</w:hyperlink></w:p>`;
|
|
425
|
+
if (!port.paste(link, text, false, hyperlinkRelationship("rIdRef1", reference.url)))
|
|
426
|
+
throw new Error("The reference could not be inserted.");
|
|
427
|
+
port.setCaret({ paragraphId: caret.paragraphId, offset: caret.offset + text.length });
|
|
428
|
+
}
|
|
429
|
+
function refreshCrossReferences(port) {
|
|
430
|
+
const stale = staleCrossReferences(port).sort(
|
|
431
|
+
(a, b) => a.paragraphId === b.paragraphId ? b.offset - a.offset : 0
|
|
432
|
+
);
|
|
433
|
+
let refreshed = 0;
|
|
434
|
+
for (const ref of stale) {
|
|
435
|
+
const paragraph = port.paragraphs().find((p) => p.id === ref.paragraphId);
|
|
436
|
+
if (!paragraph || paragraph.text[ref.offset - 1] === FIELD_ATOM) continue;
|
|
437
|
+
const at = { paragraphId: ref.paragraphId, offset: ref.offset };
|
|
438
|
+
port.deleteRange(at, { paragraphId: ref.paragraphId, offset: ref.offset + 1 });
|
|
439
|
+
port.setCaret(at);
|
|
440
|
+
const text = ref.value ?? (ref.cached.trim() || ref.bookmark);
|
|
441
|
+
const body = ref.value === null ? run(text, BROKEN_CROSS_REFERENCE_STYLE) : crossReferenceXml(ref.bookmark, ref.mode, ref.value);
|
|
442
|
+
if (port.paste(`<w:p>${body}</w:p>`, text, false) && ref.value !== null) refreshed++;
|
|
443
|
+
}
|
|
444
|
+
return { refreshed, broken: brokenCrossReferences(port) };
|
|
445
|
+
}
|
|
446
|
+
var RUN_PARTS = /* @__PURE__ */ new Set(["rPr", "t", "tab", "br", "lastRenderedPageBreak"]);
|
|
447
|
+
var SKIPPED = /* @__PURE__ */ new Set(["pPr", "bookmarkStart", "bookmarkEnd", "proofErr", "permStart", "permEnd"]);
|
|
448
|
+
function serialize(node) {
|
|
449
|
+
if (node.kind === "textValue") return esc(node.value ?? "");
|
|
450
|
+
const name = `${node.prefix ?? "w"}:${node.localName}`;
|
|
451
|
+
const attrs = (node.attributes ?? []).map((a) => ` ${a.prefix ? `${a.prefix}:` : ""}${a.localName}="${esc(a.value)}"`).join("");
|
|
452
|
+
const children = (node.children ?? []).map((c) => serialize(c)).join("");
|
|
453
|
+
return children ? `<${name}${attrs}>${children}</${name}>` : `<${name}${attrs}/>`;
|
|
454
|
+
}
|
|
455
|
+
function paragraphRunsXml(paragraph) {
|
|
456
|
+
const runs = [];
|
|
457
|
+
for (const child2 of paragraph.children ?? []) {
|
|
458
|
+
if (child2.localName && SKIPPED.has(child2.localName)) continue;
|
|
459
|
+
if (child2.localName !== "r") return null;
|
|
460
|
+
if ((child2.children ?? []).some((c) => !c.localName || !RUN_PARTS.has(c.localName))) return null;
|
|
461
|
+
runs.push(serialize(child2));
|
|
462
|
+
}
|
|
463
|
+
return runs.length ? runs.join("") : null;
|
|
464
|
+
}
|
|
315
465
|
var AGENT_UNDO_MAP = "agentUndo";
|
|
316
466
|
var attr2 = (node, name) => node.attributes?.find((a) => a.localName === name)?.value;
|
|
317
467
|
var child = (node, name) => node?.children?.find((c) => c.localName === name);
|
|
@@ -475,17 +625,511 @@ function undoOps(root, record) {
|
|
|
475
625
|
return ops;
|
|
476
626
|
}
|
|
477
627
|
|
|
628
|
+
// src/commands/terms.ts
|
|
629
|
+
var QUOTES = `"\u201C\u201D\u201E\u201F'\u2018\u2019\u201A\u201B\xAB\xBB`;
|
|
630
|
+
var OPEN_CLOSE = {
|
|
631
|
+
'"': '"',
|
|
632
|
+
"\u201C": "\u201D",
|
|
633
|
+
"\u201E": "\u201C",
|
|
634
|
+
"\u201F": "\u201D",
|
|
635
|
+
"'": "'",
|
|
636
|
+
"\u2018": "\u2019",
|
|
637
|
+
"\u201A": "\u2018",
|
|
638
|
+
"\u201B": "\u2019",
|
|
639
|
+
"\xAB": "\xBB"
|
|
640
|
+
};
|
|
641
|
+
var EMPHASIS = /^(\*\*|__|\*|_)/;
|
|
642
|
+
var CONNECTORS = /^(?:shall\s+(?:have\s+the\s+meaning|mean|include)s?|ha(?:s|ve)\s+the\s+meanings?|means?\s+and\s+includes?|means|mean|includes|include|[:—–]|\s-\s|-\s)/i;
|
|
643
|
+
var MAX_TERM_LENGTH = 80;
|
|
644
|
+
var MAX_TERM_WORDS = 10;
|
|
645
|
+
function plain(text) {
|
|
646
|
+
return text.replace(/\\([\\`*_{}[\]()#+\-.!"'])/g, "$1").replace(/(\*\*|__)(.+?)\1/g, "$2").replace(/\s+/g, " ").trim();
|
|
647
|
+
}
|
|
648
|
+
function termKey(term) {
|
|
649
|
+
return plain(term).replace(new RegExp(`[${QUOTES}*_]`, "g"), "").replace(/\s+/g, " ").trim().toLowerCase();
|
|
650
|
+
}
|
|
651
|
+
var validTerm = (term) => term.length > 0 && term.length <= MAX_TERM_LENGTH && term.split(/\s+/).length <= MAX_TERM_WORDS && /\p{L}/u.test(term);
|
|
652
|
+
function connectorAt(rest) {
|
|
653
|
+
const lead = rest.length - rest.trimStart().length;
|
|
654
|
+
const spaced = /^\s-\s/.exec(rest);
|
|
655
|
+
if (spaced) return spaced[0].length;
|
|
656
|
+
const match = CONNECTORS.exec(rest.slice(lead));
|
|
657
|
+
return match ? lead + match[0].length : 0;
|
|
658
|
+
}
|
|
659
|
+
function parseDefinition(text) {
|
|
660
|
+
let s = plain(text);
|
|
661
|
+
for (let i = 0; i < 3; i++) s = s.replace(EMPHASIS, "").trimStart();
|
|
662
|
+
let term;
|
|
663
|
+
let rest;
|
|
664
|
+
const open = s[0];
|
|
665
|
+
const close = open ? OPEN_CLOSE[open] : void 0;
|
|
666
|
+
if (close) {
|
|
667
|
+
const end = s.indexOf(close, 1);
|
|
668
|
+
if (end < 0) return null;
|
|
669
|
+
term = s.slice(1, end);
|
|
670
|
+
rest = s.slice(end + 1);
|
|
671
|
+
rest = rest.replace(new RegExp(`^(?:\\*\\*|__|\\*|_|[${QUOTES}])+`), "");
|
|
672
|
+
} else {
|
|
673
|
+
const match = /^(.+?)(\s+(?:shall\s+(?:have\s+the\s+meaning|mean|include)s?|ha(?:s|ve)\s+the\s+meanings?|means?\s+and\s+includes?|means|includes)\b|\s*[:—–]|\s+-\s)/i.exec(
|
|
674
|
+
s
|
|
675
|
+
);
|
|
676
|
+
if (!match) return null;
|
|
677
|
+
term = match[1];
|
|
678
|
+
rest = s.slice(match[1].length);
|
|
679
|
+
}
|
|
680
|
+
term = term.replace(/(\*\*|__|\*|_)/g, "").trim();
|
|
681
|
+
const joint = connectorAt(rest);
|
|
682
|
+
if (!joint || !validTerm(term)) return null;
|
|
683
|
+
const meaning = rest.slice(joint).trim();
|
|
684
|
+
if (!meaning) return null;
|
|
685
|
+
return { term, rest: rest.replace(/^\s+/, " ").replace(/^ (?=[:—–])/, ""), meaning };
|
|
686
|
+
}
|
|
687
|
+
var compareTerms = (a, b) => a.localeCompare(b, void 0, { sensitivity: "base", numeric: true });
|
|
688
|
+
var DEFINITION_BOOKMARK_PREFIX = "_dt_";
|
|
689
|
+
var MAX_BOOKMARK_LENGTH = 40;
|
|
690
|
+
function definitionBookmark(factId) {
|
|
691
|
+
return (DEFINITION_BOOKMARK_PREFIX + factId.replace(/[^A-Za-z0-9_]/g, "_")).slice(
|
|
692
|
+
0,
|
|
693
|
+
MAX_BOOKMARK_LENGTH
|
|
694
|
+
);
|
|
695
|
+
}
|
|
696
|
+
function definitionIdOfBookmark(name) {
|
|
697
|
+
const match = /^_dt_([a-z]{3})_([A-Za-z0-9]+)$/.exec(name);
|
|
698
|
+
return match ? `${match[1]}-${match[2]}` : null;
|
|
699
|
+
}
|
|
700
|
+
var W_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
701
|
+
var TemplateError = class extends Error {
|
|
702
|
+
constructor(message) {
|
|
703
|
+
super(message);
|
|
704
|
+
this.name = "TemplateError";
|
|
705
|
+
}
|
|
706
|
+
};
|
|
707
|
+
function parse(xml, part = "part") {
|
|
708
|
+
const read = readXml(xml, { maxBytes: 64 * 1024 * 1024, maxElements: 2e6 });
|
|
709
|
+
if (!read.ok) throw new TemplateError(`${part} is not readable XML (${read.reason})`);
|
|
710
|
+
const convert = (node) => node.type === "text" ? node.value : { name: node.name, attrs: { ...node.attributes }, children: node.children.map(convert) };
|
|
711
|
+
const root = read.nodes.map(convert).find((n) => typeof n !== "string");
|
|
712
|
+
if (!root) throw new TemplateError(`${part} has no root element`);
|
|
713
|
+
const w = root.attrs["xmlns:w"];
|
|
714
|
+
if (w !== void 0 && w !== W_NS) throw new TemplateError(`${part} binds w: to ${w}`);
|
|
715
|
+
return root;
|
|
716
|
+
}
|
|
717
|
+
var escText = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
718
|
+
var escAttr = (s) => escText(s).replace(/"/g, """);
|
|
719
|
+
function serialize2(root) {
|
|
720
|
+
const out = ['<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n'];
|
|
721
|
+
const walk = (node) => {
|
|
722
|
+
if (typeof node === "string") return void out.push(escText(node));
|
|
723
|
+
out.push("<", node.name);
|
|
724
|
+
for (const [k, v] of Object.entries(node.attrs)) out.push(" ", k, '="', escAttr(v), '"');
|
|
725
|
+
if (node.children.length === 0) return void out.push("/>");
|
|
726
|
+
out.push(">");
|
|
727
|
+
node.children.forEach(walk);
|
|
728
|
+
out.push("</", node.name, ">");
|
|
729
|
+
};
|
|
730
|
+
walk(root);
|
|
731
|
+
return out.join("");
|
|
732
|
+
}
|
|
733
|
+
var el = (name, attrs = {}, children = []) => ({
|
|
734
|
+
name,
|
|
735
|
+
attrs,
|
|
736
|
+
children
|
|
737
|
+
});
|
|
738
|
+
var isEl = (n) => typeof n === "object" && n !== null;
|
|
739
|
+
var kids = (e, name) => e.children.filter((c) => isEl(c) && (name === void 0 || c.name === name));
|
|
740
|
+
var kid = (e, name) => e ? kids(e, name)[0] : void 0;
|
|
741
|
+
|
|
742
|
+
// src/template/pkg.ts
|
|
743
|
+
var REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
|
|
744
|
+
var RT = {
|
|
745
|
+
officeDocument: `${REL}/officeDocument`};
|
|
746
|
+
var Pkg = class _Pkg {
|
|
747
|
+
files;
|
|
748
|
+
types;
|
|
749
|
+
constructor(files) {
|
|
750
|
+
this.files = files;
|
|
751
|
+
const ct = this.find("[Content_Types].xml");
|
|
752
|
+
if (!ct) throw new TemplateError("not a Word package: no [Content_Types].xml");
|
|
753
|
+
this.types = parse(strFromU8(files.get(ct)), "[Content_Types].xml");
|
|
754
|
+
}
|
|
755
|
+
static read(bytes) {
|
|
756
|
+
let files;
|
|
757
|
+
try {
|
|
758
|
+
files = unzipSync(bytes);
|
|
759
|
+
} catch {
|
|
760
|
+
throw new TemplateError("not a Word package: not a zip");
|
|
761
|
+
}
|
|
762
|
+
return new _Pkg(new Map(Object.entries(files).filter(([n]) => !n.endsWith("/"))));
|
|
763
|
+
}
|
|
764
|
+
write() {
|
|
765
|
+
this.files.set(
|
|
766
|
+
this.find("[Content_Types].xml") ?? "[Content_Types].xml",
|
|
767
|
+
strToU8(serialize2(this.types))
|
|
768
|
+
);
|
|
769
|
+
return zipSync(Object.fromEntries(this.files), { level: 6 });
|
|
770
|
+
}
|
|
771
|
+
/** The stored name of a part, matched case-insensitively as OPC does. */
|
|
772
|
+
find(name) {
|
|
773
|
+
const key = name.replace(/^\//, "").toLowerCase();
|
|
774
|
+
for (const n of this.files.keys()) if (n.toLowerCase() === key) return n;
|
|
775
|
+
return void 0;
|
|
776
|
+
}
|
|
777
|
+
has(name) {
|
|
778
|
+
return this.find(name) !== void 0;
|
|
779
|
+
}
|
|
780
|
+
text(name) {
|
|
781
|
+
const n = this.find(name);
|
|
782
|
+
return n === void 0 ? void 0 : strFromU8(this.files.get(n));
|
|
783
|
+
}
|
|
784
|
+
xml(name) {
|
|
785
|
+
const t = this.text(name);
|
|
786
|
+
return t === void 0 ? void 0 : parse(t, name);
|
|
787
|
+
}
|
|
788
|
+
setXml(name, root, contentType) {
|
|
789
|
+
this.files.set(this.find(name) ?? name, strToU8(serialize2(root)));
|
|
790
|
+
if (contentType) this.setContentType(name, contentType);
|
|
791
|
+
}
|
|
792
|
+
setBytes(name, bytes, contentType) {
|
|
793
|
+
this.files.set(this.find(name) ?? name, bytes);
|
|
794
|
+
if (contentType) this.setContentType(name, contentType);
|
|
795
|
+
}
|
|
796
|
+
remove(name) {
|
|
797
|
+
const n = this.find(name);
|
|
798
|
+
if (n === void 0) return;
|
|
799
|
+
this.files.delete(n);
|
|
800
|
+
this.types.children = this.types.children.filter(
|
|
801
|
+
(c) => !(typeof c !== "string" && c.name === "Override" && c.attrs.PartName.toLowerCase() === `/${n.toLowerCase()}`)
|
|
802
|
+
);
|
|
803
|
+
this.files.delete(relsName(n));
|
|
804
|
+
}
|
|
805
|
+
contentType(name) {
|
|
806
|
+
const part = `/${name.replace(/^\//, "")}`.toLowerCase();
|
|
807
|
+
const override = kids(this.types, "Override").find(
|
|
808
|
+
(o) => o.attrs.PartName.toLowerCase() === part
|
|
809
|
+
);
|
|
810
|
+
if (override) return override.attrs.ContentType;
|
|
811
|
+
const ext = part.slice(part.lastIndexOf(".") + 1);
|
|
812
|
+
return kids(this.types, "Default").find((d) => d.attrs.Extension.toLowerCase() === ext)?.attrs.ContentType;
|
|
813
|
+
}
|
|
814
|
+
setContentType(name, type) {
|
|
815
|
+
const part = `/${name.replace(/^\//, "")}`;
|
|
816
|
+
const override = kids(this.types, "Override").find(
|
|
817
|
+
(o) => o.attrs.PartName.toLowerCase() === part.toLowerCase()
|
|
818
|
+
);
|
|
819
|
+
if (override) override.attrs.ContentType = type;
|
|
820
|
+
else this.types.children.push(el("Override", { PartName: part, ContentType: type }));
|
|
821
|
+
}
|
|
822
|
+
/** A `Default` for an extension (media), unless one exists. */
|
|
823
|
+
ensureDefault(ext, type) {
|
|
824
|
+
if (!kids(this.types, "Default").some(
|
|
825
|
+
(d) => d.attrs.Extension.toLowerCase() === ext.toLowerCase()
|
|
826
|
+
))
|
|
827
|
+
this.types.children.unshift(el("Default", { Extension: ext, ContentType: type }));
|
|
828
|
+
}
|
|
829
|
+
rels(owner) {
|
|
830
|
+
const root = this.xml(relsName(owner));
|
|
831
|
+
if (!root) return [];
|
|
832
|
+
return kids(root, "Relationship").map((r) => ({
|
|
833
|
+
id: r.attrs.Id,
|
|
834
|
+
type: r.attrs.Type,
|
|
835
|
+
target: r.attrs.Target,
|
|
836
|
+
external: r.attrs.TargetMode === "External"
|
|
837
|
+
}));
|
|
838
|
+
}
|
|
839
|
+
setRels(owner, rels) {
|
|
840
|
+
const root = el(
|
|
841
|
+
"Relationships",
|
|
842
|
+
{ xmlns: "http://schemas.openxmlformats.org/package/2006/relationships" },
|
|
843
|
+
rels.map(
|
|
844
|
+
(r) => el("Relationship", {
|
|
845
|
+
Id: r.id,
|
|
846
|
+
Type: r.type,
|
|
847
|
+
Target: r.target,
|
|
848
|
+
...r.external ? { TargetMode: "External" } : {}
|
|
849
|
+
})
|
|
850
|
+
)
|
|
851
|
+
);
|
|
852
|
+
this.setXml(relsName(owner), root);
|
|
853
|
+
}
|
|
854
|
+
/** Add a relationship from `owner`; returns its new id. */
|
|
855
|
+
addRel(owner, type, target, external = false) {
|
|
856
|
+
const rels = this.rels(owner);
|
|
857
|
+
const id = freshId(new Set(rels.map((r) => r.id)), "rIdT");
|
|
858
|
+
rels.push({ id, type, target, external });
|
|
859
|
+
this.setRels(owner, rels);
|
|
860
|
+
return id;
|
|
861
|
+
}
|
|
862
|
+
/** The part a relationship of `owner` points at (internal targets only). */
|
|
863
|
+
target(owner, rel) {
|
|
864
|
+
return resolveTarget(owner, rel.target);
|
|
865
|
+
}
|
|
866
|
+
/** The first internal part of a relationship type from `owner`. */
|
|
867
|
+
partOf(owner, type) {
|
|
868
|
+
const rel = this.rels(owner).find((r) => r.type === type && !r.external);
|
|
869
|
+
return rel && this.find(this.target(owner, rel));
|
|
870
|
+
}
|
|
871
|
+
/** The main document part (`word/document.xml` by convention). */
|
|
872
|
+
get main() {
|
|
873
|
+
const main = this.partOf("", RT.officeDocument);
|
|
874
|
+
if (!main) throw new TemplateError("not a Word package: no main document part");
|
|
875
|
+
return main;
|
|
876
|
+
}
|
|
877
|
+
};
|
|
878
|
+
function relsName(owner) {
|
|
879
|
+
const slash = owner.lastIndexOf("/");
|
|
880
|
+
return `${owner.slice(0, slash + 1)}_rels/${owner.slice(slash + 1)}.rels`;
|
|
881
|
+
}
|
|
882
|
+
function resolveTarget(owner, target) {
|
|
883
|
+
if (target.startsWith("/")) return target.slice(1);
|
|
884
|
+
const base = owner.slice(0, owner.lastIndexOf("/") + 1).split("/").filter(Boolean);
|
|
885
|
+
for (const seg of target.split("/")) {
|
|
886
|
+
if (seg === "..") base.pop();
|
|
887
|
+
else if (seg !== "." && seg !== "") base.push(seg);
|
|
888
|
+
}
|
|
889
|
+
return base.join("/");
|
|
890
|
+
}
|
|
891
|
+
function freshId(taken, prefix) {
|
|
892
|
+
for (let i = 1; ; i++) if (!taken.has(`${prefix}${i}`)) return `${prefix}${i}`;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
// src/template/track.ts
|
|
896
|
+
var TRACKED = /* @__PURE__ */ new Set(["w:ins", "w:del", "w:moveFrom", "w:moveTo"]);
|
|
897
|
+
function trackInsertion(fragment, revision, covered) {
|
|
898
|
+
const pkg = Pkg.read(fragment);
|
|
899
|
+
const main = pkg.main;
|
|
900
|
+
const root = pkg.xml(main);
|
|
901
|
+
const body = kid(root, "w:body");
|
|
902
|
+
if (!root || !body) return fragment;
|
|
903
|
+
const attrs = { "w:id": "1", "w:author": revision.author, "w:date": revision.date };
|
|
904
|
+
const lastParagraph = body.children.filter(isEl).findLast((c) => c.name === "w:p");
|
|
905
|
+
const visit = (node) => {
|
|
906
|
+
node.children = node.children.map((child2) => {
|
|
907
|
+
if (!isEl(child2)) return child2;
|
|
908
|
+
if (child2.name === "w:r") return TRACKED.has(node.name) ? child2 : el("w:ins", attrs, [child2]);
|
|
909
|
+
if (TRACKED.has(child2.name)) return child2;
|
|
910
|
+
if (child2.name === "w:tr") {
|
|
911
|
+
markRow(child2, attrs);
|
|
912
|
+
return child2;
|
|
913
|
+
}
|
|
914
|
+
visit(child2);
|
|
915
|
+
if (child2.name === "w:p" && (covered || child2 !== lastParagraph)) markParagraph(child2, attrs);
|
|
916
|
+
return child2;
|
|
917
|
+
});
|
|
918
|
+
};
|
|
919
|
+
visit(body);
|
|
920
|
+
pkg.setXml(main, root);
|
|
921
|
+
return pkg.write();
|
|
922
|
+
}
|
|
923
|
+
function markParagraph(p, attrs) {
|
|
924
|
+
let pPr = kid(p, "w:pPr");
|
|
925
|
+
if (!pPr) p.children.unshift(pPr = el("w:pPr"));
|
|
926
|
+
let rPr = kid(pPr, "w:rPr");
|
|
927
|
+
if (!rPr) {
|
|
928
|
+
rPr = el("w:rPr");
|
|
929
|
+
const at = pPr.children.findIndex(
|
|
930
|
+
(c) => isEl(c) && (c.name === "w:sectPr" || c.name === "w:pPrChange")
|
|
931
|
+
);
|
|
932
|
+
pPr.children.splice(at < 0 ? pPr.children.length : at, 0, rPr);
|
|
933
|
+
}
|
|
934
|
+
if (!kid(rPr, "w:ins")) rPr.children.unshift(el("w:ins", attrs));
|
|
935
|
+
}
|
|
936
|
+
function markRow(tr, attrs) {
|
|
937
|
+
let trPr = kid(tr, "w:trPr");
|
|
938
|
+
if (!trPr) {
|
|
939
|
+
trPr = el("w:trPr");
|
|
940
|
+
const after = tr.children.findIndex((c) => isEl(c) && c.name === "w:tblPrEx");
|
|
941
|
+
tr.children.splice(after + 1, 0, trPr);
|
|
942
|
+
}
|
|
943
|
+
if (kid(trPr, "w:ins")) return;
|
|
944
|
+
const at = trPr.children.findIndex((c) => isEl(c) && c.name === "w:trPrChange");
|
|
945
|
+
trPr.children.splice(at < 0 ? trPr.children.length : at, 0, el("w:ins", attrs));
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
// src/commands/fragment.ts
|
|
949
|
+
var CHARACTER_STYLES = {
|
|
950
|
+
[DEFINED_TERM_STYLE]: `<w:style w:type="character" w:customStyle="1" w:styleId="${DEFINED_TERM_STYLE}"><w:name w:val="Defined Term"/><w:rPr><w:u w:val="dotted" w:color="7F7F7F"/></w:rPr></w:style>`,
|
|
951
|
+
[CROSS_REFERENCE_STYLE]: `<w:style w:type="character" w:customStyle="1" w:styleId="${CROSS_REFERENCE_STYLE}"><w:name w:val="Cross Reference"/><w:rPr><w:color w:val="1F4E79"/><w:u w:val="dotted" w:color="8EA9C1"/></w:rPr></w:style>`,
|
|
952
|
+
[BROKEN_CROSS_REFERENCE_STYLE]: `<w:style w:type="character" w:customStyle="1" w:styleId="${BROKEN_CROSS_REFERENCE_STYLE}"><w:name w:val="Cross Reference Broken"/><w:basedOn w:val="${CROSS_REFERENCE_STYLE}"/><w:rPr><w:color w:val="C00000"/><w:u w:val="wave" w:color="C00000"/></w:rPr></w:style>`
|
|
953
|
+
};
|
|
954
|
+
function stylesUsed(body) {
|
|
955
|
+
return [...new Set([...body.matchAll(/<w:rStyle w:val="([^"]+)"/g)].map((m) => m[1]))];
|
|
956
|
+
}
|
|
957
|
+
var fragmentStyles = (ids) => stylesXml(
|
|
958
|
+
"",
|
|
959
|
+
`<w:style w:type="paragraph" w:default="1" w:styleId="Normal"><w:name w:val="Normal"/><w:qFormat/></w:style>${ids.map((id) => CHARACTER_STYLES[id] ?? "").join("")}`
|
|
960
|
+
);
|
|
961
|
+
var textRun = (text, props = "") => `<w:r>${props ? `<w:rPr>${props}</w:rPr>` : ""}<w:t xml:space="preserve">${esc(text)}</w:t></w:r>`;
|
|
962
|
+
function definitionTooltip(definition) {
|
|
963
|
+
const line = `\u201C${definition.term}\u201D${definition.rest}`.replace(/\s+/g, " ").trim();
|
|
964
|
+
return line.length > 255 ? `${line.slice(0, 254)}\u2026` : line;
|
|
965
|
+
}
|
|
966
|
+
var definitionParagraphText = (definition) => `\u201C${definition.term}\u201D${definition.rest}`;
|
|
967
|
+
function definitionParagraphXml(definition, bookmark, id = 0) {
|
|
968
|
+
return `<w:p><w:bookmarkStart w:id="${id}" w:name="${esc(bookmark)}"/>${textRun("\u201C")}${textRun(
|
|
969
|
+
definition.term,
|
|
970
|
+
"<w:b/>"
|
|
971
|
+
)}${textRun("\u201D")}<w:bookmarkEnd w:id="${id}"/>${textRun(definition.rest)}</w:p>`;
|
|
972
|
+
}
|
|
973
|
+
function headingParagraphXml(text, styleId) {
|
|
974
|
+
return styleId ? `<w:p><w:pPr><w:pStyle w:val="${esc(styleId)}"/></w:pPr>${textRun(text)}</w:p>` : `<w:p><w:pPr><w:keepNext/></w:pPr>${textRun(text, "<w:b/>")}</w:p>`;
|
|
975
|
+
}
|
|
976
|
+
function termLinkXml(term, bookmark, tooltip) {
|
|
977
|
+
return `<w:p><w:hyperlink w:anchor="${esc(bookmark)}" w:tooltip="${esc(tooltip)}" w:history="1">${textRun(
|
|
978
|
+
term,
|
|
979
|
+
`<w:rStyle w:val="${DEFINED_TERM_STYLE}"/>`
|
|
980
|
+
)}</w:hyperlink></w:p>`;
|
|
981
|
+
}
|
|
982
|
+
function fragmentPackage(body, covered, {
|
|
983
|
+
revision,
|
|
984
|
+
relationships,
|
|
985
|
+
styles = stylesUsed(body)
|
|
986
|
+
} = {}) {
|
|
987
|
+
const untracked = docxPackage({
|
|
988
|
+
document: documentXml(body),
|
|
989
|
+
styles: fragmentStyles(styles),
|
|
990
|
+
title: "Defined terms",
|
|
991
|
+
relationships
|
|
992
|
+
});
|
|
993
|
+
return revision ? trackInsertion(untracked, revision, covered) : untracked;
|
|
994
|
+
}
|
|
995
|
+
var attr3 = (node, name) => node.attributes?.find((a) => a.localName === name)?.value;
|
|
996
|
+
function documentStyleIds(root) {
|
|
997
|
+
const ids = /* @__PURE__ */ new Set();
|
|
998
|
+
for (const style of root?.children ?? [])
|
|
999
|
+
if (style.localName === "style") {
|
|
1000
|
+
const id = attr3(style, "styleId");
|
|
1001
|
+
if (id) ids.add(id);
|
|
1002
|
+
}
|
|
1003
|
+
return ids;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
// src/commands/definitions.ts
|
|
1007
|
+
var DEFINITIONS_HEADING = "Definitions";
|
|
1008
|
+
var SECTION_TITLE = /^(definitions?(\s*(and|&)\s*interpretations?)?|interpretations?(\s*(and|&)\s*definitions?)?|defined\s+terms|glossary)$/i;
|
|
1009
|
+
var NUMBERING = /^(?:(?:clause|section|article|schedule|part)\s+)?(?:[0-9]+(?:\.[0-9]+)*|[A-Z]|[ivxlc]+)[.):]?\s+(?:[-–—]\s*)?/i;
|
|
1010
|
+
function isDefinitionsTitle(paragraph) {
|
|
1011
|
+
if (!paragraph.topLevel) return false;
|
|
1012
|
+
const title = paragraph.text.trim().replace(NUMBERING, "").replace(/[.:]+$/, "").trim();
|
|
1013
|
+
return SECTION_TITLE.test(title) && (paragraph.heading || title.length <= 40);
|
|
1014
|
+
}
|
|
1015
|
+
function findDefinitionsSection(paragraphs) {
|
|
1016
|
+
const title = paragraphs.findIndex(isDefinitionsTitle);
|
|
1017
|
+
if (title < 0) return null;
|
|
1018
|
+
let end = title + 1;
|
|
1019
|
+
while (end < paragraphs.length && paragraphs[end].topLevel && !paragraphs[end].heading) end++;
|
|
1020
|
+
return { title, start: title + 1, end };
|
|
1021
|
+
}
|
|
1022
|
+
var termOf = (paragraph) => parseDefinition(paragraph.text)?.term ?? null;
|
|
1023
|
+
function insertionIndex(paragraphs, section, term, skip = /* @__PURE__ */ new Set()) {
|
|
1024
|
+
let afterLast = section.start;
|
|
1025
|
+
for (let i = section.start; i < section.end; i++) {
|
|
1026
|
+
if (skip.has(paragraphs[i].id)) continue;
|
|
1027
|
+
const other = termOf(paragraphs[i]);
|
|
1028
|
+
if (other === null) continue;
|
|
1029
|
+
if (compareTerms(other, term) > 0) return i;
|
|
1030
|
+
afterLast = i + 1;
|
|
1031
|
+
}
|
|
1032
|
+
return afterLast;
|
|
1033
|
+
}
|
|
1034
|
+
var headingStyle = (paragraphs) => paragraphs.find((p) => p.topLevel && p.heading && p.styleId)?.styleId;
|
|
1035
|
+
function insertParagraphs(port, index, body, count, keep) {
|
|
1036
|
+
const before = port.paragraphs();
|
|
1037
|
+
const kept = keep ? before.findIndex((p) => p.id === keep.paragraphId) : -1;
|
|
1038
|
+
if (index < before.length) {
|
|
1039
|
+
port.setCaret({ paragraphId: before[index].id, offset: 0 });
|
|
1040
|
+
} else {
|
|
1041
|
+
const last = before[before.length - 1];
|
|
1042
|
+
port.setCaret({ paragraphId: last.id, offset: last.text.length });
|
|
1043
|
+
port.splitParagraph();
|
|
1044
|
+
const opened = port.paragraphs();
|
|
1045
|
+
port.setCaret({ paragraphId: opened[opened.length - 1].id, offset: 0 });
|
|
1046
|
+
}
|
|
1047
|
+
if (!port.paste(body, "", true)) throw new Error("The definition could not be added.");
|
|
1048
|
+
if (!keep || kept < 0) return keep;
|
|
1049
|
+
const after = port.paragraphs();
|
|
1050
|
+
const moved = index <= kept ? kept + count : kept;
|
|
1051
|
+
return { paragraphId: after[moved]?.id ?? keep.paragraphId, offset: keep.offset };
|
|
1052
|
+
}
|
|
1053
|
+
function addDefinition(port, definition, keep) {
|
|
1054
|
+
const paragraphs = port.paragraphs();
|
|
1055
|
+
const section = findDefinitionsSection(paragraphs);
|
|
1056
|
+
const paragraph = definitionParagraphXml(definition, definitionBookmark(definition.id));
|
|
1057
|
+
if (section)
|
|
1058
|
+
return insertParagraphs(
|
|
1059
|
+
port,
|
|
1060
|
+
insertionIndex(paragraphs, section, definition.term),
|
|
1061
|
+
paragraph,
|
|
1062
|
+
1,
|
|
1063
|
+
keep
|
|
1064
|
+
);
|
|
1065
|
+
return insertParagraphs(
|
|
1066
|
+
port,
|
|
1067
|
+
paragraphs.length,
|
|
1068
|
+
headingParagraphXml(DEFINITIONS_HEADING, headingStyle(paragraphs)) + paragraph,
|
|
1069
|
+
2,
|
|
1070
|
+
keep
|
|
1071
|
+
);
|
|
1072
|
+
}
|
|
1073
|
+
var hasBookmark = (paragraphs, name) => paragraphs.some((p) => p.bookmarks.includes(name));
|
|
1074
|
+
function insertDefinedTerm(port, definition, options = {}) {
|
|
1075
|
+
const start = port.caret();
|
|
1076
|
+
if (!start) throw new Error("Place the cursor where the term should go.");
|
|
1077
|
+
let caret = start;
|
|
1078
|
+
if (options.replace) {
|
|
1079
|
+
caret = { paragraphId: start.paragraphId, offset: Math.max(0, start.offset - options.replace) };
|
|
1080
|
+
port.deleteRange(caret, start);
|
|
1081
|
+
}
|
|
1082
|
+
const bookmark = definitionBookmark(definition.id);
|
|
1083
|
+
const addedDefinition = !hasBookmark(port.paragraphs(), bookmark);
|
|
1084
|
+
if (addedDefinition) caret = addDefinition(port, definition, caret) ?? caret;
|
|
1085
|
+
port.setCaret(caret);
|
|
1086
|
+
if (!port.paste(
|
|
1087
|
+
termLinkXml(definition.term, bookmark, definitionTooltip(definition)),
|
|
1088
|
+
definition.term,
|
|
1089
|
+
false
|
|
1090
|
+
))
|
|
1091
|
+
throw new Error("The term could not be inserted.");
|
|
1092
|
+
port.setCaret({ paragraphId: caret.paragraphId, offset: caret.offset + definition.term.length });
|
|
1093
|
+
return { addedDefinition };
|
|
1094
|
+
}
|
|
1095
|
+
function definitionsById(definitions) {
|
|
1096
|
+
return new Map(definitions.map((d) => [d.id, d]));
|
|
1097
|
+
}
|
|
1098
|
+
function definitionOfAnchor(anchor, definitions) {
|
|
1099
|
+
const id = definitionIdOfBookmark(anchor.replace(/^#/, ""));
|
|
1100
|
+
return id ? definitions.get(id) : void 0;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
478
1103
|
// src/commands/index.ts
|
|
479
1104
|
function documentReader(view) {
|
|
480
1105
|
const root = () => view.part().root;
|
|
481
1106
|
let paragraphs;
|
|
482
1107
|
let items;
|
|
483
1108
|
let names;
|
|
1109
|
+
let notes;
|
|
1110
|
+
const readNotes = () => {
|
|
1111
|
+
const out = /* @__PURE__ */ new Map();
|
|
1112
|
+
for (const part of view.currentPackage?.().parts.values() ?? []) {
|
|
1113
|
+
const root2 = part.root;
|
|
1114
|
+
const kind = root2?.localName === "footnotes" ? "footnote" : root2?.localName === "endnotes" ? "endnote" : null;
|
|
1115
|
+
if (!kind) continue;
|
|
1116
|
+
for (const note of root2?.children ?? []) {
|
|
1117
|
+
const id = note.attributes?.find((a) => a.localName === "id")?.value;
|
|
1118
|
+
if (id)
|
|
1119
|
+
out.set(
|
|
1120
|
+
`${kind}:${id}`,
|
|
1121
|
+
readParagraphs(note).map((p) => p.text).join(" ")
|
|
1122
|
+
);
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
return out;
|
|
1126
|
+
};
|
|
484
1127
|
const numbering = documentNumbering({ ...view, root });
|
|
485
1128
|
return {
|
|
486
1129
|
paragraphs: () => paragraphs ??= readParagraphs(root()),
|
|
487
1130
|
listItems: () => items ??= numbering.listItems(),
|
|
488
1131
|
levelOf: numbering.levelOf,
|
|
1132
|
+
noteText: (kind, id) => (notes ??= readNotes()).get(`${kind}:${id}`),
|
|
489
1133
|
styleName: (id) => (names ??= styleNames(view.stylesRoot())).get(id) ?? id
|
|
490
1134
|
};
|
|
491
1135
|
}
|
|
@@ -495,6 +1139,6 @@ function readDocument(bytes) {
|
|
|
495
1139
|
return documentReader(opened.view);
|
|
496
1140
|
}
|
|
497
1141
|
|
|
498
|
-
export { AGENT_UNDO_MAP, BROKEN_CROSS_REFERENCE_STYLE, CROSS_REFERENCE_STYLE, DEFINED_TERM_STYLE, FIELD_ATOM, REF_BOOKMARK_PREFIX, WATCHED_STYLES, brokenCrossReferences, crossReferences, documentNumbering, documentReader, fieldNodeIds, filterTargets, listTargets, paragraphIndex, paragraphNumber, paragraphState, readDocument, readParagraphs, sectionStates, staleCrossReferences, styleNames, tableOf, tableState, undoOps };
|
|
1142
|
+
export { AGENT_UNDO_MAP, BROKEN_CROSS_REFERENCE_STYLE, CHARACTER_STYLES, CROSS_REFERENCE_STYLE, DEFINED_TERM_STYLE, DEFINITIONS_HEADING, DEFINITION_BOOKMARK_PREFIX, FIELD_ATOM, REF_BOOKMARK_PREFIX, WATCHED_STYLES, W_NAMESPACES, addDefinition, brokenCrossReferences, compareTerms, crossReferenceXml, crossReferences, definitionBookmark, definitionIdOfBookmark, definitionOfAnchor, definitionParagraphText, definitionParagraphXml, definitionTooltip, definitionsById, documentNumbering, documentReader, documentReferenceTooltip, documentStyleIds, documentXml, docxPackage, ensureTargetBookmark, esc, fieldNodeIds, filterTargets, findDefinitionsSection, fragmentPackage, headingParagraphXml, hyperlinkRelationship, insertCrossReference, insertCrossReferenceField, insertDefinedTerm, insertDocumentReference, insertionIndex, isDefinitionsTitle, listTargets, markCrossReferenceTarget, newRefBookmark, paragraphIndex, paragraphNumber, paragraphRunsXml, paragraphState, parseDefinition, readDocument, readParagraphs, refFieldXml, refInstruction, refResult, refTooltip, refreshCrossReferences, sectionStates, staleCrossReferences, styleNames, stylesUsed, stylesXml, tableOf, tableState, termKey, termLinkXml, undoOps };
|
|
499
1143
|
//# sourceMappingURL=commands.js.map
|
|
500
1144
|
//# sourceMappingURL=commands.js.map
|