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