@arbidocs/blocks 0.4.120 → 0.4.122

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/agents/index.cjs +208 -208
  2. package/dist/agents/index.js +3 -3
  3. package/dist/{chunk-FXUQZFAN.cjs → chunk-Z2NSU7D5.cjs} +4 -4
  4. package/dist/{chunk-FXUQZFAN.cjs.map → chunk-Z2NSU7D5.cjs.map} +1 -1
  5. package/dist/{chunk-6Z7DLJU2.js → chunk-ZP4IFW2E.js} +4 -4
  6. package/dist/{chunk-6Z7DLJU2.js.map → chunk-ZP4IFW2E.js.map} +1 -1
  7. package/dist/collaboration/index.cjs +1 -1
  8. package/dist/collaboration/index.js +1 -1
  9. package/dist/connect/index.cjs +15 -5
  10. package/dist/connect/index.cjs.map +1 -1
  11. package/dist/connect/index.js +15 -5
  12. package/dist/connect/index.js.map +1 -1
  13. package/dist/facts/index.cjs +1 -1
  14. package/dist/facts/index.js +1 -1
  15. package/dist/files/index.cjs +1 -1
  16. package/dist/files/index.js +1 -1
  17. package/dist/index.cjs +217 -217
  18. package/dist/index.js +3 -3
  19. package/dist/shell/index.cjs +9 -9
  20. package/dist/shell/index.js +1 -1
  21. package/dist/workflow-canvas/index.cjs +10 -10
  22. package/dist/workflow-canvas/index.js +3 -3
  23. package/node_modules/@arbidocs/coedit/dist/commands.cjs +222 -12
  24. package/node_modules/@arbidocs/coedit/dist/commands.cjs.map +1 -1
  25. package/node_modules/@arbidocs/coedit/dist/commands.d.cts +82 -5
  26. package/node_modules/@arbidocs/coedit/dist/commands.d.ts +82 -5
  27. package/node_modules/@arbidocs/coedit/dist/commands.js +217 -13
  28. package/node_modules/@arbidocs/coedit/dist/commands.js.map +1 -1
  29. package/node_modules/@arbidocs/coedit/dist/encoding.d.cts +2 -0
  30. package/node_modules/@arbidocs/coedit/dist/encoding.d.ts +2 -0
  31. package/node_modules/@arbidocs/coedit/dist/hocuspocus.cjs +27 -0
  32. package/node_modules/@arbidocs/coedit/dist/hocuspocus.cjs.map +1 -1
  33. package/node_modules/@arbidocs/coedit/dist/hocuspocus.js +27 -0
  34. package/node_modules/@arbidocs/coedit/dist/hocuspocus.js.map +1 -1
  35. package/node_modules/@arbidocs/coedit/dist/index.cjs +27 -0
  36. package/node_modules/@arbidocs/coedit/dist/index.cjs.map +1 -1
  37. package/node_modules/@arbidocs/coedit/dist/index.js +27 -0
  38. package/node_modules/@arbidocs/coedit/dist/index.js.map +1 -1
  39. package/node_modules/@arbidocs/coedit/dist/{port-ip7WByvH.d.cts → port-BbN5OZHx.d.cts} +24 -1
  40. package/node_modules/@arbidocs/coedit/dist/{port-ip7WByvH.d.ts → port-BbN5OZHx.d.ts} +24 -1
  41. package/node_modules/@arbidocs/coedit/dist/server.cjs +65 -2
  42. package/node_modules/@arbidocs/coedit/dist/server.cjs.map +1 -1
  43. package/node_modules/@arbidocs/coedit/dist/server.d.cts +1 -1
  44. package/node_modules/@arbidocs/coedit/dist/server.d.ts +1 -1
  45. package/node_modules/@arbidocs/coedit/dist/server.js +65 -2
  46. package/node_modules/@arbidocs/coedit/dist/server.js.map +1 -1
  47. package/node_modules/@arbidocs/coedit/package.json +1 -1
  48. package/package.json +4 -4
@@ -1,5 +1,5 @@
1
- import { g as DocParagraph, k as ListItemInfo, j as LevelOf, R as ReferencesPort, a as CrossReferenceTarget, h as DocPoint, O as OoxmlNodeLike, b as DefinitionsPort, i as DocumentNumbering } from './port-ip7WByvH.cjs';
2
- export { B as BROKEN_CROSS_REFERENCE_STYLE, C as CROSS_REFERENCE_STYLE, D as DEFINED_TERM_STYLE, c as DocField, d as DocLink, e as DocMark, f as DocNote, F as FIELD_ATOM, L as LevelInfo, N as NumberingSource, W as WATCHED_STYLES, l as documentNumbering, m as filterTargets, n as listTargets, p as paragraphNumber, r as readParagraphs, s as styleNames } from './port-ip7WByvH.cjs';
1
+ import { g as DocParagraph, l as ListItemInfo, k as LevelOf, R as ReferencesPort, a as CrossReferenceTarget, h as DocPoint, O as OoxmlNodeLike, b as DefinitionsPort, j as DocumentNumbering } from './port-BbN5OZHx.cjs';
2
+ export { B as BROKEN_CROSS_REFERENCE_STYLE, C as CROSS_REFERENCE_STYLE, D as DEFINED_TERM_STYLE, c as DocField, d as DocLink, e as DocMark, f as DocNote, i as DocRevision, F as FIELD_ATOM, L as LevelInfo, N as NumberingSource, W as WATCHED_STYLES, m as documentNumbering, n as engineLength, o as engineOffset, p as filterTargets, q as listTargets, r as paragraphNumber, s as readParagraphs, t as styleNames } from './port-BbN5OZHx.cjs';
3
3
  import { OoxmlProperty, TabStopWrite, TreeDocOp } from '@docx-editor.dev/core/store';
4
4
  import { R as Revision } from './track-eYC94jTp.cjs';
5
5
 
@@ -377,11 +377,26 @@ interface InsertTermResult {
377
377
  /** The definition was not in the document yet and was added to its Definitions section. */
378
378
  addedDefinition: boolean;
379
379
  }
380
+ /** A paragraph's words between two engine offsets, as a replacement addresses them. */
381
+ interface ReplacedSpan {
382
+ paragraphId: string;
383
+ from: number;
384
+ to: number;
385
+ }
386
+ /**
387
+ * Replace `span` with what `insert` puts at the caret (`length` characters), as one change that
388
+ * never removes words without their replacement: the replacement goes in first, right after the
389
+ * words, and only once it is in are the words deleted. A refused insert changes nothing; a refused
390
+ * deletion takes the insert back out (deleting an insertion of one's own removes it). Answers
391
+ * whether the replacement landed, the caret after it.
392
+ */
393
+ declare function replaceSpan(port: DefinitionsPort, span: ReplacedSpan, insert: () => boolean, length: number): boolean;
380
394
  /**
381
395
  * Insert a defined term at the caret: the term as an internal link to its definition's bookmark
382
396
  * (its definition as the link's tooltip), the definition added to the Definitions section first
383
- * when the document does not have it. `replace` characters before the caret (a typed `@@query`)
384
- * are removed first. The caret ends after the term.
397
+ * when the document does not have it. `replace` characters before the caret (a typed `@@query`,
398
+ * or the term's own plain words) are replaced by it, as one change (see {@link replaceSpan}): a
399
+ * term that cannot be inserted leaves them in place. The caret ends after the term.
385
400
  */
386
401
  declare function insertDefinedTerm(port: DefinitionsPort, definition: Definition, options?: {
387
402
  replace?: number;
@@ -391,6 +406,68 @@ declare function definitionsById<D extends Definition>(definitions: readonly D[]
391
406
  /** The definition an internal link points at, from its bookmark name. */
392
407
  declare function definitionOfAnchor<D extends Definition>(anchor: string, definitions: ReadonlyMap<string, D>): D | undefined;
393
408
 
409
+ interface TermSpec {
410
+ /** The defined term, as the document writes it ("Supplier"). */
411
+ term: string;
412
+ /** Other words used for it, each replaced by the term. */
413
+ variants?: readonly string[];
414
+ /** Link every use of the term (the replaced variants included) to its definition. */
415
+ link?: boolean;
416
+ }
417
+ /** One use of the term or a variant: `offset` into its paragraph's `text`. */
418
+ interface TermUse {
419
+ paragraphId: string;
420
+ paraId?: string;
421
+ offset: number;
422
+ text: string;
423
+ kind: 'term' | 'variant';
424
+ }
425
+ type TermSkipReason = 'definition' | 'linked' | 'link' | 'field' | 'pending-change' | 'unsupported-content' | 'refused';
426
+ /** A use left as it is, and why. */
427
+ interface TermSkip extends TermUse {
428
+ reason: TermSkipReason;
429
+ }
430
+ /** A use changed: replaced by the term (`text` → `to`), linked to its definition or both. */
431
+ interface TermChange extends TermUse {
432
+ to: string;
433
+ linked: boolean;
434
+ }
435
+ interface TermEverywhereResult {
436
+ changed: TermChange[];
437
+ skipped: TermSkip[];
438
+ /** The definition was not in the document and was added to its Definitions section. */
439
+ addedDefinition: boolean;
440
+ }
441
+ /**
442
+ * Every use of the term (when linking) and of its variants in `paragraphs`: the ones to change,
443
+ * and the ones left as they are with the reason. `bookmark` is the definition's, which tells an
444
+ * already linked term apart from a word inside some other link.
445
+ */
446
+ declare function findTermUses(paragraphs: readonly DocParagraph[], spec: TermSpec, bookmark?: string): {
447
+ uses: TermUse[];
448
+ skipped: TermSkip[];
449
+ };
450
+ /** Raised when a paragraph does not read as intended afterwards: the caller discards the change. */
451
+ declare class TermEverywhereError extends Error {
452
+ constructor(message: string);
453
+ }
454
+ /**
455
+ * Apply a defined term across the document (see the module's description): variants replaced by
456
+ * the term, and with `link` every use linked to `definition` (added to the Definitions section
457
+ * first when the document does not have it). Every replacement is one change that never leaves
458
+ * words removed without the term in their place ({@link replaceSpan}); a use the editor refuses is
459
+ * reported as skipped. After each paragraph its text is checked against what the replacements
460
+ * should make it, and a paragraph that reads otherwise throws {@link TermEverywhereError}: run
461
+ * this on a staged copy of the document and keep the copy only when it returns.
462
+ *
463
+ * `accept` may turn a whole paragraph down (its uses are skipped as `unsupported-content`).
464
+ */
465
+ declare function applyTermEverywhere(port: DefinitionsPort, spec: TermSpec & {
466
+ definition?: DefinitionText;
467
+ }, { accept }?: {
468
+ accept?: (paragraph: DocParagraph) => boolean;
469
+ }): TermEverywhereResult;
470
+
394
471
  /** A document's parts as trees: a live editor's session or a headless view (`openHeadlessDocument`). */
395
472
  interface DocumentTrees {
396
473
  part(): {
@@ -418,4 +495,4 @@ declare function documentReader(view: DocumentTrees): DocumentReader;
418
495
  /** Read a document from its bytes (a collaboration room's `readRoom`). Throws on a bad package. */
419
496
  declare function readDocument(bytes: Uint8Array): DocumentReader;
420
497
 
421
- export { AGENT_UNDO_MAP, type BrokenReference, CHARACTER_STYLES, type CrossReference, type CrossReferenceMode, CrossReferenceTarget, DEFINITIONS_HEADING, DEFINITION_BOOKMARK_PREFIX, type DefinitionText, DefinitionsPort, type DefinitionsSection, DocParagraph, DocPoint, DocumentNumbering, type DocumentReader, type DocumentTrees, type InsertTermResult, LevelOf, ListItemInfo, OoxmlNodeLike, type ParagraphState, type ParsedDefinition, REF_BOOKMARK_PREFIX, ReferencesPort, type ReferencesReader, type RefreshResult, type SectionState, type StaleReference, type UndoRecord, W_NAMESPACES, addDefinition, brokenCrossReferences, compareTerms, crossReferenceXml, crossReferences, definitionBookmark, definitionIdOfBookmark, definitionOfAnchor, definitionParagraphText, definitionParagraphXml, definitionTooltip, definitionsById, documentReader, documentReferenceTooltip, documentStyleIds, documentXml, docxPackage, ensureTargetBookmark, esc, fieldNodeIds, findDefinitionsSection, fragmentPackage, headingParagraphXml, hyperlinkRelationship, insertCrossReference, insertCrossReferenceField, insertDefinedTerm, insertDocumentReference, insertionIndex, isDefinitionsTitle, markCrossReferenceTarget, newRefBookmark, paragraphIndex, paragraphRunsXml, paragraphState, parseDefinition, readDocument, refFieldXml, refInstruction, refResult, refTooltip, refreshCrossReferences, sectionStates, staleCrossReferences, stylesUsed, stylesXml, tableOf, tableState, termKey, termLinkXml, undoOps };
498
+ export { AGENT_UNDO_MAP, type BrokenReference, CHARACTER_STYLES, type CrossReference, type CrossReferenceMode, CrossReferenceTarget, DEFINITIONS_HEADING, DEFINITION_BOOKMARK_PREFIX, type DefinitionText, DefinitionsPort, type DefinitionsSection, DocParagraph, DocPoint, DocumentNumbering, type DocumentReader, type DocumentTrees, type InsertTermResult, LevelOf, ListItemInfo, OoxmlNodeLike, type ParagraphState, type ParsedDefinition, REF_BOOKMARK_PREFIX, ReferencesPort, type ReferencesReader, type RefreshResult, type ReplacedSpan, type SectionState, type StaleReference, type TermChange, TermEverywhereError, type TermEverywhereResult, type TermSkip, type TermSkipReason, type TermSpec, type TermUse, type UndoRecord, W_NAMESPACES, addDefinition, applyTermEverywhere, brokenCrossReferences, compareTerms, crossReferenceXml, crossReferences, definitionBookmark, definitionIdOfBookmark, definitionOfAnchor, definitionParagraphText, definitionParagraphXml, definitionTooltip, definitionsById, documentReader, documentReferenceTooltip, documentStyleIds, documentXml, docxPackage, ensureTargetBookmark, esc, fieldNodeIds, findDefinitionsSection, findTermUses, fragmentPackage, headingParagraphXml, hyperlinkRelationship, insertCrossReference, insertCrossReferenceField, insertDefinedTerm, insertDocumentReference, insertionIndex, isDefinitionsTitle, markCrossReferenceTarget, newRefBookmark, paragraphIndex, paragraphRunsXml, paragraphState, parseDefinition, readDocument, refFieldXml, refInstruction, refResult, refTooltip, refreshCrossReferences, replaceSpan, sectionStates, staleCrossReferences, stylesUsed, stylesXml, tableOf, tableState, termKey, termLinkXml, undoOps };
@@ -1,5 +1,5 @@
1
- import { g as DocParagraph, k as ListItemInfo, j as LevelOf, R as ReferencesPort, a as CrossReferenceTarget, h as DocPoint, O as OoxmlNodeLike, b as DefinitionsPort, i as DocumentNumbering } from './port-ip7WByvH.js';
2
- export { B as BROKEN_CROSS_REFERENCE_STYLE, C as CROSS_REFERENCE_STYLE, D as DEFINED_TERM_STYLE, c as DocField, d as DocLink, e as DocMark, f as DocNote, F as FIELD_ATOM, L as LevelInfo, N as NumberingSource, W as WATCHED_STYLES, l as documentNumbering, m as filterTargets, n as listTargets, p as paragraphNumber, r as readParagraphs, s as styleNames } from './port-ip7WByvH.js';
1
+ import { g as DocParagraph, l as ListItemInfo, k as LevelOf, R as ReferencesPort, a as CrossReferenceTarget, h as DocPoint, O as OoxmlNodeLike, b as DefinitionsPort, j as DocumentNumbering } from './port-BbN5OZHx.js';
2
+ export { B as BROKEN_CROSS_REFERENCE_STYLE, C as CROSS_REFERENCE_STYLE, D as DEFINED_TERM_STYLE, c as DocField, d as DocLink, e as DocMark, f as DocNote, i as DocRevision, F as FIELD_ATOM, L as LevelInfo, N as NumberingSource, W as WATCHED_STYLES, m as documentNumbering, n as engineLength, o as engineOffset, p as filterTargets, q as listTargets, r as paragraphNumber, s as readParagraphs, t as styleNames } from './port-BbN5OZHx.js';
3
3
  import { OoxmlProperty, TabStopWrite, TreeDocOp } from '@docx-editor.dev/core/store';
4
4
  import { R as Revision } from './track-eYC94jTp.js';
5
5
 
@@ -377,11 +377,26 @@ interface InsertTermResult {
377
377
  /** The definition was not in the document yet and was added to its Definitions section. */
378
378
  addedDefinition: boolean;
379
379
  }
380
+ /** A paragraph's words between two engine offsets, as a replacement addresses them. */
381
+ interface ReplacedSpan {
382
+ paragraphId: string;
383
+ from: number;
384
+ to: number;
385
+ }
386
+ /**
387
+ * Replace `span` with what `insert` puts at the caret (`length` characters), as one change that
388
+ * never removes words without their replacement: the replacement goes in first, right after the
389
+ * words, and only once it is in are the words deleted. A refused insert changes nothing; a refused
390
+ * deletion takes the insert back out (deleting an insertion of one's own removes it). Answers
391
+ * whether the replacement landed, the caret after it.
392
+ */
393
+ declare function replaceSpan(port: DefinitionsPort, span: ReplacedSpan, insert: () => boolean, length: number): boolean;
380
394
  /**
381
395
  * Insert a defined term at the caret: the term as an internal link to its definition's bookmark
382
396
  * (its definition as the link's tooltip), the definition added to the Definitions section first
383
- * when the document does not have it. `replace` characters before the caret (a typed `@@query`)
384
- * are removed first. The caret ends after the term.
397
+ * when the document does not have it. `replace` characters before the caret (a typed `@@query`,
398
+ * or the term's own plain words) are replaced by it, as one change (see {@link replaceSpan}): a
399
+ * term that cannot be inserted leaves them in place. The caret ends after the term.
385
400
  */
386
401
  declare function insertDefinedTerm(port: DefinitionsPort, definition: Definition, options?: {
387
402
  replace?: number;
@@ -391,6 +406,68 @@ declare function definitionsById<D extends Definition>(definitions: readonly D[]
391
406
  /** The definition an internal link points at, from its bookmark name. */
392
407
  declare function definitionOfAnchor<D extends Definition>(anchor: string, definitions: ReadonlyMap<string, D>): D | undefined;
393
408
 
409
+ interface TermSpec {
410
+ /** The defined term, as the document writes it ("Supplier"). */
411
+ term: string;
412
+ /** Other words used for it, each replaced by the term. */
413
+ variants?: readonly string[];
414
+ /** Link every use of the term (the replaced variants included) to its definition. */
415
+ link?: boolean;
416
+ }
417
+ /** One use of the term or a variant: `offset` into its paragraph's `text`. */
418
+ interface TermUse {
419
+ paragraphId: string;
420
+ paraId?: string;
421
+ offset: number;
422
+ text: string;
423
+ kind: 'term' | 'variant';
424
+ }
425
+ type TermSkipReason = 'definition' | 'linked' | 'link' | 'field' | 'pending-change' | 'unsupported-content' | 'refused';
426
+ /** A use left as it is, and why. */
427
+ interface TermSkip extends TermUse {
428
+ reason: TermSkipReason;
429
+ }
430
+ /** A use changed: replaced by the term (`text` → `to`), linked to its definition or both. */
431
+ interface TermChange extends TermUse {
432
+ to: string;
433
+ linked: boolean;
434
+ }
435
+ interface TermEverywhereResult {
436
+ changed: TermChange[];
437
+ skipped: TermSkip[];
438
+ /** The definition was not in the document and was added to its Definitions section. */
439
+ addedDefinition: boolean;
440
+ }
441
+ /**
442
+ * Every use of the term (when linking) and of its variants in `paragraphs`: the ones to change,
443
+ * and the ones left as they are with the reason. `bookmark` is the definition's, which tells an
444
+ * already linked term apart from a word inside some other link.
445
+ */
446
+ declare function findTermUses(paragraphs: readonly DocParagraph[], spec: TermSpec, bookmark?: string): {
447
+ uses: TermUse[];
448
+ skipped: TermSkip[];
449
+ };
450
+ /** Raised when a paragraph does not read as intended afterwards: the caller discards the change. */
451
+ declare class TermEverywhereError extends Error {
452
+ constructor(message: string);
453
+ }
454
+ /**
455
+ * Apply a defined term across the document (see the module's description): variants replaced by
456
+ * the term, and with `link` every use linked to `definition` (added to the Definitions section
457
+ * first when the document does not have it). Every replacement is one change that never leaves
458
+ * words removed without the term in their place ({@link replaceSpan}); a use the editor refuses is
459
+ * reported as skipped. After each paragraph its text is checked against what the replacements
460
+ * should make it, and a paragraph that reads otherwise throws {@link TermEverywhereError}: run
461
+ * this on a staged copy of the document and keep the copy only when it returns.
462
+ *
463
+ * `accept` may turn a whole paragraph down (its uses are skipped as `unsupported-content`).
464
+ */
465
+ declare function applyTermEverywhere(port: DefinitionsPort, spec: TermSpec & {
466
+ definition?: DefinitionText;
467
+ }, { accept }?: {
468
+ accept?: (paragraph: DocParagraph) => boolean;
469
+ }): TermEverywhereResult;
470
+
394
471
  /** A document's parts as trees: a live editor's session or a headless view (`openHeadlessDocument`). */
395
472
  interface DocumentTrees {
396
473
  part(): {
@@ -418,4 +495,4 @@ declare function documentReader(view: DocumentTrees): DocumentReader;
418
495
  /** Read a document from its bytes (a collaboration room's `readRoom`). Throws on a bad package. */
419
496
  declare function readDocument(bytes: Uint8Array): DocumentReader;
420
497
 
421
- export { AGENT_UNDO_MAP, type BrokenReference, CHARACTER_STYLES, type CrossReference, type CrossReferenceMode, CrossReferenceTarget, DEFINITIONS_HEADING, DEFINITION_BOOKMARK_PREFIX, type DefinitionText, DefinitionsPort, type DefinitionsSection, DocParagraph, DocPoint, DocumentNumbering, type DocumentReader, type DocumentTrees, type InsertTermResult, LevelOf, ListItemInfo, OoxmlNodeLike, type ParagraphState, type ParsedDefinition, REF_BOOKMARK_PREFIX, ReferencesPort, type ReferencesReader, type RefreshResult, type SectionState, type StaleReference, type UndoRecord, W_NAMESPACES, addDefinition, brokenCrossReferences, compareTerms, crossReferenceXml, crossReferences, definitionBookmark, definitionIdOfBookmark, definitionOfAnchor, definitionParagraphText, definitionParagraphXml, definitionTooltip, definitionsById, documentReader, documentReferenceTooltip, documentStyleIds, documentXml, docxPackage, ensureTargetBookmark, esc, fieldNodeIds, findDefinitionsSection, fragmentPackage, headingParagraphXml, hyperlinkRelationship, insertCrossReference, insertCrossReferenceField, insertDefinedTerm, insertDocumentReference, insertionIndex, isDefinitionsTitle, markCrossReferenceTarget, newRefBookmark, paragraphIndex, paragraphRunsXml, paragraphState, parseDefinition, readDocument, refFieldXml, refInstruction, refResult, refTooltip, refreshCrossReferences, sectionStates, staleCrossReferences, stylesUsed, stylesXml, tableOf, tableState, termKey, termLinkXml, undoOps };
498
+ export { AGENT_UNDO_MAP, type BrokenReference, CHARACTER_STYLES, type CrossReference, type CrossReferenceMode, CrossReferenceTarget, DEFINITIONS_HEADING, DEFINITION_BOOKMARK_PREFIX, type DefinitionText, DefinitionsPort, type DefinitionsSection, DocParagraph, DocPoint, DocumentNumbering, type DocumentReader, type DocumentTrees, type InsertTermResult, LevelOf, ListItemInfo, OoxmlNodeLike, type ParagraphState, type ParsedDefinition, REF_BOOKMARK_PREFIX, ReferencesPort, type ReferencesReader, type RefreshResult, type ReplacedSpan, type SectionState, type StaleReference, type TermChange, TermEverywhereError, type TermEverywhereResult, type TermSkip, type TermSkipReason, type TermSpec, type TermUse, type UndoRecord, W_NAMESPACES, addDefinition, applyTermEverywhere, brokenCrossReferences, compareTerms, crossReferenceXml, crossReferences, definitionBookmark, definitionIdOfBookmark, definitionOfAnchor, definitionParagraphText, definitionParagraphXml, definitionTooltip, definitionsById, documentReader, documentReferenceTooltip, documentStyleIds, documentXml, docxPackage, ensureTargetBookmark, esc, fieldNodeIds, findDefinitionsSection, findTermUses, fragmentPackage, headingParagraphXml, hyperlinkRelationship, insertCrossReference, insertCrossReferenceField, insertDefinedTerm, insertDocumentReference, insertionIndex, isDefinitionsTitle, markCrossReferenceTarget, newRefBookmark, paragraphIndex, paragraphRunsXml, paragraphState, parseDefinition, readDocument, refFieldXml, refInstruction, refResult, refTooltip, refreshCrossReferences, replaceSpan, sectionStates, staleCrossReferences, stylesUsed, stylesXml, tableOf, tableState, termKey, termLinkXml, undoOps };
@@ -8,6 +8,14 @@ import { zipSync, strToU8, strFromU8, unzipSync } from 'fflate';
8
8
  var DEFINED_TERM_STYLE = "DefinedTerm";
9
9
  var CROSS_REFERENCE_STYLE = "CrossReference";
10
10
  var BROKEN_CROSS_REFERENCE_STYLE = "CrossReferenceBroken";
11
+ function engineOffset(paragraph, offset, pastDeletions = false) {
12
+ let out = offset;
13
+ for (const r of paragraph.revisions ?? [])
14
+ if (r.kind === "delete" && (r.offset < offset || pastDeletions && r.offset === offset))
15
+ out += r.length;
16
+ return out;
17
+ }
18
+ var engineLength = (paragraph) => engineOffset(paragraph, paragraph.text.length, true);
11
19
  var WATCHED_STYLES = /* @__PURE__ */ new Set([BROKEN_CROSS_REFERENCE_STYLE]);
12
20
  var attr = (node, name) => node.attributes?.find((a) => a.localName === name)?.value;
13
21
  var FIELD_ATOM = "\uFFFC";
@@ -42,6 +50,7 @@ function readParagraph(node, topLevel, bookmarks) {
42
50
  let runStyle;
43
51
  const fields = [];
44
52
  const notes = [];
53
+ const revisions = [];
45
54
  let current = null;
46
55
  const field = (c) => {
47
56
  const type = attr(c, "fldCharType");
@@ -83,7 +92,31 @@ function readParagraph(node, topLevel, bookmarks) {
83
92
  }
84
93
  continue;
85
94
  }
86
- if (c.localName === "delText" || c.localName === "del" || c.localName === "rPr") continue;
95
+ if (c.localName === "del") {
96
+ const deleted = deletedText(c);
97
+ if (deleted && fieldDepth === 0)
98
+ revisions.push({
99
+ kind: "delete",
100
+ offset: text.length,
101
+ length: deleted.length,
102
+ author: attr(c, "author"),
103
+ text: deleted
104
+ });
105
+ continue;
106
+ }
107
+ if (c.localName === "ins") {
108
+ const start = text.length;
109
+ walk(c, link);
110
+ if (text.length > start && fieldDepth === 0)
111
+ revisions.push({
112
+ kind: "insert",
113
+ offset: start,
114
+ length: text.length - start,
115
+ author: attr(c, "author")
116
+ });
117
+ continue;
118
+ }
119
+ if (c.localName === "delText" || c.localName === "rPr") continue;
87
120
  if (c.localName === "r") {
88
121
  const rStyle = c.children?.find((x) => x.localName === "rPr")?.children?.find((x) => x.localName === "rStyle");
89
122
  const watched = rStyle && attr(rStyle, "val");
@@ -146,9 +179,20 @@ function readParagraph(node, topLevel, bookmarks) {
146
179
  links,
147
180
  ...fields.length ? { fields } : {},
148
181
  ...marks.length ? { marks } : {},
149
- ...notes.length ? { notes } : {}
182
+ ...notes.length ? { notes } : {},
183
+ ...revisions.length ? { revisions } : {}
150
184
  };
151
185
  }
186
+ function deletedText(node) {
187
+ let out = "";
188
+ for (const c of node.children ?? []) {
189
+ if (c.localName === "instrText") continue;
190
+ if (c.localName === "delText") out += (c.children ?? []).map((t) => t.value ?? "").join("");
191
+ else if (c.localName === "tab") out += " ";
192
+ else if (c.localName !== "rPr") out += deletedText(c);
193
+ }
194
+ return out;
195
+ }
152
196
  function styleNames(root) {
153
197
  const names = /* @__PURE__ */ new Map();
154
198
  for (const style of root?.children ?? []) {
@@ -1039,7 +1083,7 @@ function insertParagraphs(port, index, body, count, keep) {
1039
1083
  port.setCaret({ paragraphId: before[index].id, offset: 0 });
1040
1084
  } else {
1041
1085
  const last = before[before.length - 1];
1042
- port.setCaret({ paragraphId: last.id, offset: last.text.length });
1086
+ port.setCaret({ paragraphId: last.id, offset: engineLength(last) });
1043
1087
  port.splitParagraph();
1044
1088
  const opened = port.paragraphs();
1045
1089
  port.setCaret({ paragraphId: opened[opened.length - 1].id, offset: 0 });
@@ -1071,25 +1115,47 @@ function addDefinition(port, definition, keep) {
1071
1115
  );
1072
1116
  }
1073
1117
  var hasBookmark = (paragraphs, name) => paragraphs.some((p) => p.bookmarks.includes(name));
1118
+ var paragraphOf = (port, id) => port.paragraphs().find((p) => p.id === id);
1119
+ function replaceSpan(port, span, insert, length) {
1120
+ const { paragraphId, from, to } = span;
1121
+ if (from > to) throw new Error("A replacement runs forwards.");
1122
+ const before = paragraphOf(port, paragraphId);
1123
+ if (!before) throw new Error("That paragraph is no longer in the document.");
1124
+ const length0 = engineLength(before);
1125
+ port.setCaret({ paragraphId, offset: to });
1126
+ if (!insert()) return false;
1127
+ if (from < to) {
1128
+ try {
1129
+ port.deleteRange({ paragraphId, offset: from }, { paragraphId, offset: to });
1130
+ } catch (error) {
1131
+ port.deleteRange({ paragraphId, offset: to }, { paragraphId, offset: to + length });
1132
+ throw error;
1133
+ }
1134
+ }
1135
+ const after = paragraphOf(port, paragraphId);
1136
+ const kept = after && engineLength(after) - length0 === length;
1137
+ port.setCaret({ paragraphId, offset: (kept ? to : from) + length });
1138
+ return true;
1139
+ }
1074
1140
  function insertDefinedTerm(port, definition, options = {}) {
1075
1141
  const start = port.caret();
1076
1142
  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
1143
  const bookmark = definitionBookmark(definition.id);
1083
1144
  const addedDefinition = !hasBookmark(port.paragraphs(), bookmark);
1084
- if (addedDefinition) caret = addDefinition(port, definition, caret) ?? caret;
1085
- port.setCaret(caret);
1086
- if (!port.paste(
1145
+ const caret = addedDefinition && addDefinition(port, definition, start) || start;
1146
+ const insert = () => port.paste(
1087
1147
  termLinkXml(definition.term, bookmark, definitionTooltip(definition)),
1088
1148
  definition.term,
1089
1149
  false
1150
+ );
1151
+ const from = Math.max(0, caret.offset - (options.replace ?? 0));
1152
+ if (!replaceSpan(
1153
+ port,
1154
+ { paragraphId: caret.paragraphId, from, to: caret.offset },
1155
+ insert,
1156
+ definition.term.length
1090
1157
  ))
1091
1158
  throw new Error("The term could not be inserted.");
1092
- port.setCaret({ paragraphId: caret.paragraphId, offset: caret.offset + definition.term.length });
1093
1159
  return { addedDefinition };
1094
1160
  }
1095
1161
  function definitionsById(definitions) {
@@ -1100,6 +1166,144 @@ function definitionOfAnchor(anchor, definitions) {
1100
1166
  return id ? definitions.get(id) : void 0;
1101
1167
  }
1102
1168
 
1169
+ // src/commands/everywhere.ts
1170
+ var WORD = "[\\p{L}\\p{N}_\\-\u2010\u2011]";
1171
+ var escape = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1172
+ function needlesOf(spec) {
1173
+ const term = spec.term.replace(/\s+/g, " ").trim();
1174
+ const variants = [
1175
+ ...new Set((spec.variants ?? []).map((v) => v.replace(/\s+/g, " ").trim()))
1176
+ ].filter((v) => v && v !== term);
1177
+ const needles = [
1178
+ ...variants.map((text) => ({ text, kind: "variant" })),
1179
+ ...spec.link ? [{ text: term, kind: "term" }] : []
1180
+ ];
1181
+ return needles.map((n) => ({
1182
+ ...n,
1183
+ pattern: new RegExp(
1184
+ `(?<!${WORD})${n.text.split(" ").map(escape).join("\\s+")}(?!${WORD})`,
1185
+ "gu"
1186
+ )
1187
+ }));
1188
+ }
1189
+ function matchesIn(text, needles) {
1190
+ const found = [];
1191
+ for (const needle of needles)
1192
+ for (const m of text.matchAll(needle.pattern))
1193
+ found.push({ offset: m.index ?? 0, text: m[0], kind: needle.kind });
1194
+ found.sort((a, b) => a.offset - b.offset || b.text.length - a.text.length);
1195
+ const out = [];
1196
+ for (const m of found)
1197
+ if (!out.length || m.offset >= out[out.length - 1].offset + out[out.length - 1].text.length)
1198
+ out.push(m);
1199
+ return out;
1200
+ }
1201
+ var overlaps = (start, end, from, to) => start < to && from < end;
1202
+ function findTermUses(paragraphs, spec, bookmark) {
1203
+ const needles = needlesOf(spec);
1204
+ const defining = new Set([spec.term, ...spec.variants ?? []].map(termKey));
1205
+ const uses = [];
1206
+ const skipped = [];
1207
+ for (const p of paragraphs) {
1208
+ const at = { paragraphId: p.id, ...p.paraId ? { paraId: p.paraId } : {} };
1209
+ const defined = parseDefinition(p.text.split(FIELD_ATOM).join(""));
1210
+ const isDefinition = defined !== null && defining.has(termKey(defined.term));
1211
+ for (const m of matchesIn(p.text, needles)) {
1212
+ const use = { ...at, ...m };
1213
+ const end = m.offset + m.text.length;
1214
+ const link = p.links.find(
1215
+ (l) => l.offset !== void 0 && overlaps(m.offset, end, l.offset, l.offset + l.text.length)
1216
+ );
1217
+ const pending = (p.revisions ?? []).some(
1218
+ (r) => r.kind === "insert" ? overlaps(m.offset, end, r.offset, r.offset + r.length) : r.offset > m.offset && r.offset < end
1219
+ );
1220
+ const reason = isDefinition ? "definition" : link ? link.anchor === bookmark ? "linked" : "link" : pending ? "pending-change" : null;
1221
+ if (reason) skipped.push({ ...use, reason });
1222
+ else uses.push(use);
1223
+ }
1224
+ for (const field of p.fields ?? [])
1225
+ for (const m of matchesIn(field.result, needles))
1226
+ skipped.push({ ...at, offset: field.offset, text: m.text, kind: m.kind, reason: "field" });
1227
+ }
1228
+ return { uses, skipped };
1229
+ }
1230
+ function replacedText(text, uses, term) {
1231
+ let out = text;
1232
+ for (const use of [...uses].sort((a, b) => b.offset - a.offset))
1233
+ out = out.slice(0, use.offset) + term + out.slice(use.offset + use.text.length);
1234
+ return out;
1235
+ }
1236
+ var TermEverywhereError = class extends Error {
1237
+ constructor(message) {
1238
+ super(message);
1239
+ this.name = "TermEverywhereError";
1240
+ }
1241
+ };
1242
+ function applyTermEverywhere(port, spec, { accept } = {}) {
1243
+ const term = spec.term.replace(/\s+/g, " ").trim();
1244
+ if (!term) throw new Error("Name the defined term.");
1245
+ let addedDefinition = false;
1246
+ let link;
1247
+ if (spec.link) {
1248
+ if (!spec.definition) throw new Error(`Linking "${term}" needs its definition.`);
1249
+ link = {
1250
+ bookmark: definitionBookmark(spec.definition.id),
1251
+ tooltip: definitionTooltip(spec.definition)
1252
+ };
1253
+ if (!port.paragraphs().some((p) => p.bookmarks.includes(link.bookmark))) {
1254
+ addDefinition(port, spec.definition);
1255
+ addedDefinition = true;
1256
+ }
1257
+ }
1258
+ const paragraphs = port.paragraphs();
1259
+ const { uses, skipped } = findTermUses(paragraphs, { ...spec, term }, link?.bookmark);
1260
+ const changed = [];
1261
+ const insert = link ? () => port.paste(termLinkXml(term, link.bookmark, link.tooltip), term, false) : () => {
1262
+ port.typeText(term);
1263
+ return true;
1264
+ };
1265
+ for (const p of paragraphs) {
1266
+ const mine = uses.filter((u) => u.paragraphId === p.id);
1267
+ if (!mine.length) continue;
1268
+ if (accept && !accept(p)) {
1269
+ skipped.push(...mine.map((u) => ({ ...u, reason: "unsupported-content" })));
1270
+ continue;
1271
+ }
1272
+ const current = () => port.paragraphs().find((x) => p.paraId ? x.paraId === p.paraId : x.id === p.id);
1273
+ const done = [];
1274
+ for (const use of [...mine].sort((a, b) => b.offset - a.offset)) {
1275
+ const now = current();
1276
+ let ok = false;
1277
+ if (now) {
1278
+ const span = {
1279
+ paragraphId: now.id,
1280
+ from: engineOffset(p, use.offset, true),
1281
+ to: engineOffset(p, use.offset + use.text.length)
1282
+ };
1283
+ try {
1284
+ ok = replaceSpan(port, span, insert, term.length);
1285
+ } catch {
1286
+ ok = false;
1287
+ }
1288
+ }
1289
+ if (ok) {
1290
+ done.push(use);
1291
+ changed.push({ ...use, to: term, linked: Boolean(link) });
1292
+ } else skipped.push({ ...use, reason: "refused" });
1293
+ }
1294
+ const want = replacedText(p.text, done, term);
1295
+ const got = current()?.text;
1296
+ if (got !== want)
1297
+ throw new TermEverywhereError(
1298
+ `A paragraph did not read as intended after the changes: expected "${want}", got "${got ?? "(missing)"}".`
1299
+ );
1300
+ }
1301
+ changed.sort(
1302
+ (a, b) => paragraphs.findIndex((p) => p.id === a.paragraphId) - paragraphs.findIndex((p) => p.id === b.paragraphId) || a.offset - b.offset
1303
+ );
1304
+ return { changed, skipped, addedDefinition };
1305
+ }
1306
+
1103
1307
  // src/commands/index.ts
1104
1308
  function documentReader(view) {
1105
1309
  const root = () => view.part().root;
@@ -1139,6 +1343,6 @@ function readDocument(bytes) {
1139
1343
  return documentReader(opened.view);
1140
1344
  }
1141
1345
 
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 };
1346
+ 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, TermEverywhereError, WATCHED_STYLES, W_NAMESPACES, addDefinition, applyTermEverywhere, brokenCrossReferences, compareTerms, crossReferenceXml, crossReferences, definitionBookmark, definitionIdOfBookmark, definitionOfAnchor, definitionParagraphText, definitionParagraphXml, definitionTooltip, definitionsById, documentNumbering, documentReader, documentReferenceTooltip, documentStyleIds, documentXml, docxPackage, engineLength, engineOffset, ensureTargetBookmark, esc, fieldNodeIds, filterTargets, findDefinitionsSection, findTermUses, fragmentPackage, headingParagraphXml, hyperlinkRelationship, insertCrossReference, insertCrossReferenceField, insertDefinedTerm, insertDocumentReference, insertionIndex, isDefinitionsTitle, listTargets, markCrossReferenceTarget, newRefBookmark, paragraphIndex, paragraphNumber, paragraphRunsXml, paragraphState, parseDefinition, readDocument, readParagraphs, refFieldXml, refInstruction, refResult, refTooltip, refreshCrossReferences, replaceSpan, sectionStates, staleCrossReferences, styleNames, stylesUsed, stylesXml, tableOf, tableState, termKey, termLinkXml, undoOps };
1143
1347
  //# sourceMappingURL=commands.js.map
1144
1348
  //# sourceMappingURL=commands.js.map