@pixerate/editor 0.25.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/README.md +30 -0
  2. package/THIRD_PARTY_NOTICES.md +11 -0
  3. package/dist/agent/index.cjs +174 -11
  4. package/dist/agent/index.cjs.map +1 -1
  5. package/dist/agent/index.d.cts +18 -4
  6. package/dist/agent/index.d.ts +18 -4
  7. package/dist/agent/index.js +167 -4
  8. package/dist/agent/index.js.map +1 -1
  9. package/dist/{arrangeShortcuts-B8O3f8-P.d.cts → arrange-BICutYPk.d.cts} +243 -29
  10. package/dist/{arrangeShortcuts-sLlD2rSX.d.ts → arrange-BICutYPk.d.ts} +243 -29
  11. package/dist/builtins-CdPcLwwF.d.cts +176 -0
  12. package/dist/builtins-Chj6zv_O.d.ts +176 -0
  13. package/dist/canvas/index.cjs +3917 -19
  14. package/dist/canvas/index.cjs.map +1 -1
  15. package/dist/canvas/index.d.cts +1232 -7
  16. package/dist/canvas/index.d.ts +1232 -7
  17. package/dist/canvas/index.js +3916 -18
  18. package/dist/canvas/index.js.map +1 -1
  19. package/dist/chunk-3CC7OPUQ.cjs +831 -0
  20. package/dist/chunk-3CC7OPUQ.cjs.map +1 -0
  21. package/dist/{chunk-AL6JMGWW.cjs → chunk-CS6NZWWA.cjs} +24 -24
  22. package/dist/{chunk-AL6JMGWW.cjs.map → chunk-CS6NZWWA.cjs.map} +1 -1
  23. package/dist/{chunk-C7P22VIP.cjs → chunk-EWCOFSCQ.cjs} +17 -6
  24. package/dist/chunk-EWCOFSCQ.cjs.map +1 -0
  25. package/dist/chunk-HDYMLS3X.cjs +409 -0
  26. package/dist/chunk-HDYMLS3X.cjs.map +1 -0
  27. package/dist/{chunk-X4N4WUKB.cjs → chunk-IFHKKVXH.cjs} +150 -38
  28. package/dist/chunk-IFHKKVXH.cjs.map +1 -0
  29. package/dist/{chunk-ECCCYKGL.js → chunk-JOIREKL7.js} +63 -39
  30. package/dist/chunk-JOIREKL7.js.map +1 -0
  31. package/dist/chunk-KRGXUQ2Y.js +1696 -0
  32. package/dist/chunk-KRGXUQ2Y.js.map +1 -0
  33. package/dist/{chunk-QGYDWPRM.js → chunk-MHEPLBFB.js} +2 -2
  34. package/dist/chunk-MR2764X2.js +831 -0
  35. package/dist/chunk-MR2764X2.js.map +1 -0
  36. package/dist/{chunk-7WISYZFO.cjs → chunk-NFVBT3UZ.cjs} +67 -43
  37. package/dist/chunk-NFVBT3UZ.cjs.map +1 -0
  38. package/dist/{chunk-WSQKHXW7.cjs → chunk-NQF32I6Z.cjs} +1209 -457
  39. package/dist/chunk-NQF32I6Z.cjs.map +1 -0
  40. package/dist/{chunk-IXHSYOVY.js → chunk-Q2OHWD2A.js} +638 -866
  41. package/dist/chunk-Q2OHWD2A.js.map +1 -0
  42. package/dist/{chunk-NAXVVS5I.js → chunk-QJSOZFCZ.js} +2 -2
  43. package/dist/{chunk-V3CHHWOE.cjs → chunk-RRREAOVM.cjs} +4 -4
  44. package/dist/{chunk-V3CHHWOE.cjs.map → chunk-RRREAOVM.cjs.map} +1 -1
  45. package/dist/{chunk-UAKDG62Z.js → chunk-SWE3NPOU.js} +116 -4
  46. package/dist/chunk-SWE3NPOU.js.map +1 -0
  47. package/dist/chunk-TXXNBDQX.cjs +1696 -0
  48. package/dist/chunk-TXXNBDQX.cjs.map +1 -0
  49. package/dist/chunk-UBCFIABU.js +409 -0
  50. package/dist/chunk-UBCFIABU.js.map +1 -0
  51. package/dist/{chunk-RR7F5GUM.js → chunk-X7HXL2SB.js} +941 -189
  52. package/dist/chunk-X7HXL2SB.js.map +1 -0
  53. package/dist/{chunk-PO6A6QQH.cjs → chunk-YOMYSFJU.cjs} +742 -970
  54. package/dist/chunk-YOMYSFJU.cjs.map +1 -0
  55. package/dist/{chunk-FH6F67DN.js → chunk-ZRNHGAQT.js} +17 -6
  56. package/dist/{chunk-FH6F67DN.js.map → chunk-ZRNHGAQT.js.map} +1 -1
  57. package/dist/commands/index.cjs +352 -4
  58. package/dist/commands/index.cjs.map +1 -1
  59. package/dist/commands/index.d.cts +37 -108
  60. package/dist/commands/index.d.ts +37 -108
  61. package/dist/commands/index.js +351 -3
  62. package/dist/commands/index.js.map +1 -1
  63. package/dist/compare/index.cjs +3 -3
  64. package/dist/compare/index.js +2 -2
  65. package/dist/{controller-BIJiNoVs.d.cts → controller-CxXGOEmy.d.cts} +209 -13
  66. package/dist/{controller-BIJiNoVs.d.ts → controller-CxXGOEmy.d.ts} +209 -13
  67. package/dist/export/index.cjs +36 -0
  68. package/dist/export/index.cjs.map +1 -0
  69. package/dist/export/index.d.cts +243 -0
  70. package/dist/export/index.d.ts +243 -0
  71. package/dist/export/index.js +36 -0
  72. package/dist/export/index.js.map +1 -0
  73. package/dist/extensions/index.cjs +54 -6
  74. package/dist/extensions/index.cjs.map +1 -1
  75. package/dist/extensions/index.d.cts +7 -2
  76. package/dist/extensions/index.d.ts +7 -2
  77. package/dist/extensions/index.js +59 -11
  78. package/dist/{index-7a6bHTLy.d.ts → index-B273Zllk.d.ts} +211 -207
  79. package/dist/{index-Csd5qI8u.d.cts → index-jcJwmBYt.d.cts} +211 -207
  80. package/dist/index.cjs +144 -32
  81. package/dist/index.cjs.map +1 -1
  82. package/dist/index.d.cts +49 -13
  83. package/dist/index.d.ts +49 -13
  84. package/dist/index.js +136 -24
  85. package/dist/index.js.map +1 -1
  86. package/dist/registry-CED5C0lA.d.cts +204 -0
  87. package/dist/registry-CED5C0lA.d.ts +204 -0
  88. package/dist/{registry-D32LpIc4.d.cts → registry-D0GADKc7.d.cts} +1 -1
  89. package/dist/{registry-evKTP4ls.d.ts → registry-DhVUZioj.d.ts} +1 -1
  90. package/dist/serializers/index.cjs +4 -4
  91. package/dist/serializers/index.d.cts +2 -1
  92. package/dist/serializers/index.d.ts +2 -1
  93. package/dist/serializers/index.js +3 -3
  94. package/dist/spreadsheet/index.cjs +33 -3
  95. package/dist/spreadsheet/index.cjs.map +1 -1
  96. package/dist/spreadsheet/index.d.cts +106 -3
  97. package/dist/spreadsheet/index.d.ts +106 -3
  98. package/dist/spreadsheet/index.js +32 -2
  99. package/package.json +10 -1
  100. package/dist/chunk-7WISYZFO.cjs.map +0 -1
  101. package/dist/chunk-C7P22VIP.cjs.map +0 -1
  102. package/dist/chunk-ECCCYKGL.js.map +0 -1
  103. package/dist/chunk-IXHSYOVY.js.map +0 -1
  104. package/dist/chunk-PO6A6QQH.cjs.map +0 -1
  105. package/dist/chunk-RR7F5GUM.js.map +0 -1
  106. package/dist/chunk-UAKDG62Z.js.map +0 -1
  107. package/dist/chunk-WSQKHXW7.cjs.map +0 -1
  108. package/dist/chunk-X4N4WUKB.cjs.map +0 -1
  109. package/dist/types-DX4Mh4SL.d.cts +0 -217
  110. package/dist/types-DX4Mh4SL.d.ts +0 -217
  111. /package/dist/{chunk-QGYDWPRM.js.map → chunk-MHEPLBFB.js.map} +0 -0
  112. /package/dist/{chunk-NAXVVS5I.js.map → chunk-QJSOZFCZ.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/editor/editor/packages/core/dist/chunk-3CC7OPUQ.cjs","../src/extensions/paragraph-styles/registry.ts","../src/import/zip.ts"],"names":[],"mappings":"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","file":"/home/runner/work/editor/editor/packages/core/dist/chunk-3CC7OPUQ.cjs","sourcesContent":[null,"// Portions ported from wordcraft/crates/doc/src/styles.rs and wordcraft/crates/doc/src/resolve.rs (MIT OR Apache-2.0, © ArtCraft Team and contributors). See THIRD_PARTY_NOTICES.md.\n\n/** Paragraph styles format whole blocks; character styles format runs of text. */\nexport type StyleKind = \"paragraph\" | \"character\";\n\n/** Character formatting of a style (CSS values). */\nexport interface CharacterFormat {\n fontFamily?: string;\n /** CSS length, e.g. `\"1.5em\"` or `\"18px\"`. */\n fontSize?: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strike?: boolean;\n color?: string;\n backgroundColor?: string;\n letterSpacing?: string;\n textTransform?: \"none\" | \"uppercase\" | \"lowercase\" | \"capitalize\";\n smallCaps?: boolean;\n}\n\n/** Paragraph formatting of a style (CSS values). */\nexport interface ParagraphFormat {\n textAlign?: \"left\" | \"center\" | \"right\" | \"justify\";\n lineHeight?: string;\n spaceBefore?: string;\n spaceAfter?: string;\n indentLeft?: string;\n indentRight?: string;\n indentFirstLine?: string;\n /** CSS border shorthand, e.g. `\"3px solid currentColor\"`. */\n borderLeft?: string;\n paddingLeft?: string;\n backgroundColor?: string;\n}\n\n/** The block node a paragraph style uses (`heading` with `level` for Heading N). */\nexport interface StyleBlock {\n type: string;\n attrs?: Record<string, any>;\n}\n\nexport interface StyleDefinition {\n /** Stable id (`Heading1`): letters, digits, `_` and `-`, starting with a letter. */\n id: string;\n /** Display name (`Heading 1`). */\n name: string;\n kind: StyleKind;\n /** Style this one inherits from; what it sets wins over its base. */\n basedOn?: string | null;\n /** Style of the paragraph after this one when Enter is pressed at its end (paragraph styles). */\n next?: string | null;\n /** Linked style: a paragraph style's character style, or a character style's paragraph style. */\n linked?: string | null;\n paragraph?: ParagraphFormat;\n character?: CharacterFormat;\n /** Block node of a paragraph style. Inherited along `basedOn`; `paragraph` by default. */\n block?: StyleBlock | null;\n /** Gallery order (lower first). */\n priority?: number;\n /** Shown in the styles gallery. */\n quick?: boolean;\n hidden?: boolean;\n /** Built in (cannot be removed). */\n builtin?: boolean;\n}\n\n/** A style with its `basedOn` chain and the defaults merged. */\nexport interface ResolvedStyle {\n id: string;\n paragraph: ParagraphFormat;\n character: CharacterFormat;\n block: StyleBlock;\n /** Id of the style after Enter at the end of a paragraph. */\n next: string;\n}\n\nexport interface StyleDefaults {\n paragraph?: ParagraphFormat;\n character?: CharacterFormat;\n}\n\nexport interface StyleRegistryOptions {\n /** Styles added to (or replacing) the built-in ones. */\n styles?: readonly StyleDefinition[];\n /** Include the built-in styles. Default `true`. */\n builtins?: boolean;\n /** Document defaults, applied below every style. */\n defaults?: StyleDefaults;\n}\n\nexport interface StyleRegistrySnapshot {\n styles: readonly StyleDefinition[];\n defaults: StyleDefaults;\n /** Increases on every change. */\n version: number;\n}\n\n/** Serializable registry content (`registry.toJSON()`). */\nexport interface StyleRegistryJSON {\n styles: StyleDefinition[];\n defaults: StyleDefaults;\n}\n\nexport interface StyleCSSOptions {\n /** Selector the rules are scoped to. Default `.ProseMirror`. */\n scope?: string;\n /**\n * Element selector of blocks that use a style without naming it\n * (`data-style` absent), e.g. `h2` for Heading 2. Return `null` for none.\n */\n tagFor?: (block: StyleBlock) => string | null;\n}\n\n/** Longest `basedOn` chain followed (cycle and depth guard). */\nconst MAX_CHAIN = 32;\nconst STYLE_ID = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;\n/** CSS values that could escape a declaration or load resources are dropped. */\nconst UNSAFE_CSS = /[;{}<>\\\\]|\\/\\*|url\\s*\\(|expression\\s*\\(|@import|javascript:/i;\n\nexport const NORMAL_STYLE_ID = \"Normal\";\n\nconst PREVIEW_PROPERTIES = new Set([\n \"font-family\",\n \"font-weight\",\n \"font-style\",\n \"color\",\n \"text-decoration-line\",\n \"text-transform\",\n \"letter-spacing\",\n \"font-variant-caps\",\n]);\n\n/** Whether `id` is a valid style id. */\nexport function isValidStyleId(id: unknown): id is string {\n return typeof id === \"string\" && STYLE_ID.test(id);\n}\n\nconst MUTED = \"var(--pixerate-style-muted, #6b7280)\";\nconst HEADING_SIZES = [\"2em\", \"1.5em\", \"1.25em\", \"1.1em\", \"1em\", \"0.9em\"];\n\nfunction builtinStyles(): StyleDefinition[] {\n const styles: StyleDefinition[] = [\n {\n id: NORMAL_STYLE_ID,\n name: \"Normal\",\n kind: \"paragraph\",\n block: { type: \"paragraph\" },\n priority: 0,\n quick: true,\n builtin: true,\n },\n {\n id: \"Title\",\n name: \"Title\",\n kind: \"paragraph\",\n basedOn: NORMAL_STYLE_ID,\n next: NORMAL_STYLE_ID,\n linked: \"TitleChar\",\n paragraph: { spaceAfter: \"0.25em\", lineHeight: \"1.15\" },\n character: { fontSize: \"2.5em\", bold: true, letterSpacing: \"-0.01em\" },\n priority: 10,\n quick: true,\n builtin: true,\n },\n {\n id: \"Subtitle\",\n name: \"Subtitle\",\n kind: \"paragraph\",\n basedOn: NORMAL_STYLE_ID,\n next: NORMAL_STYLE_ID,\n linked: \"SubtitleChar\",\n paragraph: { spaceAfter: \"0.75em\" },\n character: { fontSize: \"1.25em\", color: MUTED },\n priority: 11,\n quick: true,\n builtin: true,\n },\n ];\n HEADING_SIZES.forEach((fontSize, i) => {\n const level = i + 1;\n styles.push({\n id: `Heading${level}`,\n name: `Heading ${level}`,\n kind: \"paragraph\",\n basedOn: NORMAL_STYLE_ID,\n next: NORMAL_STYLE_ID,\n linked: `Heading${level}Char`,\n block: { type: \"heading\", attrs: { level } },\n paragraph: { spaceBefore: level <= 2 ? \"1em\" : \"0.75em\", spaceAfter: \"0.25em\" },\n character: { fontSize, bold: true },\n priority: 11 + level,\n quick: level <= 3,\n builtin: true,\n });\n });\n styles.push(\n {\n id: \"Quote\",\n name: \"Quote\",\n kind: \"paragraph\",\n basedOn: NORMAL_STYLE_ID,\n next: NORMAL_STYLE_ID,\n linked: \"QuoteChar\",\n paragraph: { indentLeft: \"1em\", paddingLeft: \"0.75em\", borderLeft: \"3px solid currentColor\" },\n character: { italic: true, color: MUTED },\n priority: 29,\n quick: true,\n builtin: true,\n },\n {\n id: \"Code\",\n name: \"Code\",\n kind: \"paragraph\",\n basedOn: NORMAL_STYLE_ID,\n next: NORMAL_STYLE_ID,\n block: { type: \"codeBlock\" },\n character: {\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, Consolas, monospace\",\n fontSize: \"0.9em\",\n },\n priority: 30,\n quick: true,\n builtin: true,\n },\n {\n id: \"ListParagraph\",\n name: \"List Paragraph\",\n kind: \"paragraph\",\n basedOn: NORMAL_STYLE_ID,\n paragraph: { indentLeft: \"2em\" },\n priority: 34,\n quick: true,\n builtin: true,\n },\n );\n // Linked character styles: their formatting is the paragraph style's.\n const linked = [\"Title\", \"Subtitle\", \"Quote\", ...HEADING_SIZES.map((_, i) => `Heading${i + 1}`)];\n linked.forEach((paragraphId) => {\n const name = styles.find((s) => s.id === paragraphId)!.name;\n styles.push({\n id: `${paragraphId}Char`,\n name: `${name} Char`,\n kind: \"character\",\n linked: paragraphId,\n priority: 99,\n hidden: true,\n builtin: true,\n });\n });\n styles.push(\n {\n id: \"Emphasis\",\n name: \"Emphasis\",\n kind: \"character\",\n character: { italic: true },\n priority: 20,\n quick: true,\n builtin: true,\n },\n {\n id: \"Strong\",\n name: \"Strong\",\n kind: \"character\",\n character: { bold: true },\n priority: 22,\n quick: true,\n builtin: true,\n },\n );\n return styles;\n}\n\n/** The built-in styles: Normal, Title, Subtitle, Heading 1–6, Quote, Code, List Paragraph and character styles. */\nexport const DEFAULT_STYLES: readonly StyleDefinition[] = Object.freeze(builtinStyles());\n\nconst clone = <T>(value: T): T => (value === undefined ? value : JSON.parse(JSON.stringify(value)));\n\n/** Copies only defined values of `patch` over `base`. */\nfunction overlay<T extends object>(base: T, patch: T | undefined | null): T {\n if (!patch) return base;\n const out: Record<string, unknown> = { ...(base as Record<string, unknown>) };\n Object.entries(patch).forEach(([key, value]) => {\n if (value !== undefined && value !== null) out[key] = value;\n });\n return out as T;\n}\n\nfunction sameBlock(a: StyleBlock, type: string, attrs: Record<string, any>): boolean {\n if (a.type !== type) return false;\n return Object.entries(a.attrs ?? {}).every(([key, value]) => attrs[key] === value);\n}\n\n/**\n * Style definitions with `basedOn` inheritance, next-style and linked\n * character/paragraph styles, resolved in cascade order: document defaults →\n * style chain (base first) → direct formatting. Chains are cycle-safe.\n *\n * `subscribe` calls the listener immediately and on every change (Svelte\n * store contract); `getSnapshot` is stable between changes.\n */\nexport class StyleRegistry {\n private styles = new Map<string, StyleDefinition>();\n private defaults: StyleDefaults;\n private version = 0;\n private snapshot: StyleRegistrySnapshot | null = null;\n private listeners = new Set<(snapshot: StyleRegistrySnapshot) => void>();\n\n constructor(options: StyleRegistryOptions = {}) {\n this.defaults = clone(options.defaults ?? {});\n if (options.builtins !== false) DEFAULT_STYLES.forEach((style) => this.styles.set(style.id, clone(style)));\n (options.styles ?? []).forEach((style) => this.put(style));\n }\n\n // -- Reading --------------------------------------------------------------\n\n get(id: string | null | undefined): StyleDefinition | undefined {\n return id ? this.styles.get(id) : undefined;\n }\n\n /** Finds a style by id or display name (case-insensitive). */\n find(nameOrId: string): StyleDefinition | undefined {\n const direct = this.styles.get(nameOrId);\n if (direct) return direct;\n const lower = nameOrId.toLowerCase();\n return this.list().find((style) => style.name.toLowerCase() === lower);\n }\n\n /** All styles (optionally of one kind) in gallery order. */\n list(kind?: StyleKind): StyleDefinition[] {\n return Array.from(this.styles.values())\n .filter((style) => !kind || style.kind === kind)\n .sort((a, b) => (a.priority ?? 99) - (b.priority ?? 99) || a.name.localeCompare(b.name));\n }\n\n /** Styles shown in the gallery (`quick`, not hidden), paragraph styles by default. */\n gallery(kind: StyleKind = \"paragraph\"): StyleDefinition[] {\n return this.list(kind).filter((style) => style.quick && !style.hidden);\n }\n\n /** The `basedOn` chain from the root style down to `id` (cycle-safe, bounded). */\n chain(id: string): StyleDefinition[] {\n const out: StyleDefinition[] = [];\n let current = this.styles.get(id);\n while (current && out.length < MAX_CHAIN && !out.includes(current)) {\n out.push(current);\n current = current.basedOn ? this.styles.get(current.basedOn) : undefined;\n }\n return out.reverse();\n }\n\n /**\n * Resolves a paragraph style: defaults, then each style of the chain (base\n * first). Unknown ids resolve to the defaults in a `paragraph` block.\n */\n resolve(id: string): ResolvedStyle {\n let paragraph = overlay<ParagraphFormat>({}, this.defaults.paragraph);\n let character = overlay<CharacterFormat>({}, this.defaults.character);\n let block: StyleBlock = { type: \"paragraph\" };\n this.chain(id).forEach((style) => {\n if (style.kind !== \"paragraph\") return;\n paragraph = overlay(paragraph, style.paragraph);\n character = overlay(character, style.character);\n if (style.block) block = clone(style.block);\n });\n return { id, paragraph, character, block, next: this.nextStyleId(id) };\n }\n\n /** Character formatting a paragraph style's chain sets (without defaults). */\n private paragraphCharacter(id: string): CharacterFormat {\n let character: CharacterFormat = {};\n this.chain(id).forEach((style) => {\n if (style.kind === \"paragraph\") character = overlay(character, style.character);\n });\n return character;\n }\n\n /**\n * Character formatting of a character style's chain. A style linked to a\n * paragraph style takes that style's character formatting first.\n */\n resolveCharacterStyle(id: string): CharacterFormat {\n let character: CharacterFormat = {};\n this.chain(id).forEach((style) => {\n if (style.kind === \"character\" && style.linked && this.get(style.linked)?.kind === \"paragraph\") {\n character = overlay(character, this.paragraphCharacter(style.linked));\n }\n character = overlay(character, style.character);\n });\n return character;\n }\n\n /**\n * Character formatting of text: defaults → paragraph style chain →\n * character style chain → direct formatting.\n */\n resolveText(input: {\n paragraphStyle?: string | null;\n characterStyle?: string | null;\n direct?: CharacterFormat;\n }): CharacterFormat {\n let character = this.resolve(input.paragraphStyle || NORMAL_STYLE_ID).character;\n if (input.characterStyle) character = overlay(character, this.resolveCharacterStyle(input.characterStyle));\n return overlay(character, input.direct);\n }\n\n /** The style after Enter at the end of a paragraph of `id` (itself when unset or unknown). */\n nextStyleId(id: string): string {\n const next = this.styles.get(id)?.next;\n return next && this.styles.get(next)?.kind === \"paragraph\" ? next : id;\n }\n\n /** The linked character style of a paragraph style, if any. */\n linkedCharacterStyle(id: string): StyleDefinition | undefined {\n const style = this.styles.get(id);\n const linked = style?.linked ? this.styles.get(style.linked) : undefined;\n return style?.kind === \"paragraph\" && linked?.kind === \"character\" ? linked : undefined;\n }\n\n /**\n * The style a block uses when it names none: Normal for paragraphs,\n * Heading N for headings of level N, Code for code blocks (the built-in\n * style whose own `block` matches).\n */\n defaultStyleFor(type: string, attrs: Record<string, any> = {}): string | null {\n if (type === \"paragraph\" && this.styles.get(NORMAL_STYLE_ID)) return NORMAL_STYLE_ID;\n const candidates = this.list(\"paragraph\").filter(\n (style) => style.block && sameBlock(style.block, type, attrs),\n );\n return (candidates.find((s) => s.builtin) ?? candidates[0])?.id ?? null;\n }\n\n /** The style of a block: its `styleId` when known, otherwise the block's default style. */\n styleOfBlock(type: string, attrs: Record<string, any> = {}): string | null {\n const id = attrs.styleId;\n if (id && this.styles.get(id)?.kind === \"paragraph\") return id;\n return this.defaultStyleFor(type, attrs);\n }\n\n getSnapshot = (): StyleRegistrySnapshot => {\n if (!this.snapshot) {\n this.snapshot = Object.freeze({\n styles: Object.freeze(this.list()),\n defaults: this.defaults,\n version: this.version,\n });\n }\n return this.snapshot;\n };\n\n subscribe = (listener: (snapshot: StyleRegistrySnapshot) => void): (() => void) => {\n this.listeners.add(listener);\n listener(this.getSnapshot());\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n toJSON(): StyleRegistryJSON {\n return { styles: clone(Array.from(this.styles.values())), defaults: clone(this.defaults) };\n }\n\n // -- Writing --------------------------------------------------------------\n\n /** Adds or replaces a style. Throws on an invalid id. */\n upsert(style: StyleDefinition): StyleDefinition {\n const stored = this.put(style);\n this.changed();\n return stored;\n }\n\n /** Merges `patch` into a style (formats are merged key by key). Returns `undefined` for unknown ids. */\n update(id: string, patch: Partial<Omit<StyleDefinition, \"id\">>): StyleDefinition | undefined {\n const current = this.styles.get(id);\n if (!current) return undefined;\n const next: StyleDefinition = {\n ...current,\n ...patch,\n id,\n paragraph: patch.paragraph ? { ...current.paragraph, ...patch.paragraph } : current.paragraph,\n character: patch.character ? { ...current.character, ...patch.character } : current.character,\n };\n return this.upsert(next);\n }\n\n /**\n * Removes a style and returns it. Built-in styles cannot be removed. Styles\n * based on it are rebased onto its own base, and `next`/`linked`\n * references to it are dropped.\n */\n remove(id: string): StyleDefinition | undefined {\n const gone = this.styles.get(id);\n if (!gone || gone.builtin) return undefined;\n this.styles.delete(id);\n this.styles.forEach((style, key) => {\n let changed = style;\n if (style.basedOn === id) {\n changed = { ...changed, basedOn: gone.basedOn && gone.basedOn !== key ? gone.basedOn : null };\n }\n if (style.next === id) changed = { ...changed, next: null };\n if (style.linked === id) changed = { ...changed, linked: null };\n if (changed !== style) this.styles.set(key, changed);\n });\n this.changed();\n return gone;\n }\n\n /** Replaces the document defaults. */\n setDefaults(defaults: StyleDefaults): void {\n this.defaults = clone(defaults);\n this.changed();\n }\n\n /** An unused id derived from a display name (`My Style` → `MyStyle`, then `MyStyle1`, …). */\n newId(name: string): string {\n let base = name.replace(/[^A-Za-z0-9_-]+/g, \"\").replace(/^[^A-Za-z]+/, \"\").slice(0, 56);\n if (!base) base = \"Style\";\n if (!this.styles.has(base)) return base;\n for (let i = 1; i < 100000; i++) {\n const id = `${base}${i}`;\n if (!this.styles.has(id)) return id;\n }\n return `${base}${Date.now()}`;\n }\n\n // -- CSS --------------------------------------------------------------------\n\n /** CSS declarations (`property: value`) of a resolved paragraph or character style. */\n cssDeclarations(id: string): Record<string, string> {\n const style = this.styles.get(id);\n if (style?.kind === \"character\") return characterCSS(this.resolveCharacterStyle(id));\n const resolved = this.resolve(id);\n return { ...paragraphCSS(resolved.paragraph), ...characterCSS(resolved.character) };\n }\n\n /**\n * Declarations for previewing a style in a menu or gallery: font family,\n * weight, style, color, decoration, case and letter spacing (no sizes,\n * margins or borders).\n */\n previewDeclarations(id: string): Record<string, string> {\n return Object.fromEntries(\n Object.entries(this.cssDeclarations(id)).filter(([property]) => PREVIEW_PROPERTIES.has(property)),\n );\n }\n\n /**\n * A stylesheet for the styles: `[data-style=\"Id\"]` rules for paragraph\n * styles (plus the plain element of blocks that use their default style,\n * e.g. `h2:not([data-style])`), `[data-char-style=\"Id\"]` for character\n * styles and the defaults on the scope element.\n */\n toCSS(options: StyleCSSOptions = {}): string {\n const scope = options.scope ?? \".ProseMirror\";\n const tagFor = options.tagFor ?? defaultTagFor;\n const rules: string[] = [];\n const rule = (selectors: string[], declarations: Record<string, string>) => {\n const body = Object.entries(declarations)\n .map(([property, value]) => `${property}: ${value};`)\n .join(\" \");\n if (body) rules.push(`${selectors.join(\", \")} { ${body} }`);\n };\n rule([scope], {\n ...paragraphCSS(this.defaults.paragraph ?? {}),\n ...characterCSS(this.defaults.character ?? {}),\n });\n this.list().forEach((style) => {\n if (style.kind === \"character\") {\n rule([`${scope} [data-char-style=\"${style.id}\"]`], this.cssDeclarations(style.id));\n return;\n }\n const selectors = [`${scope} [data-style=\"${style.id}\"]`];\n const block = this.resolve(style.id).block;\n if (this.defaultStyleFor(block.type, block.attrs ?? {}) === style.id) {\n const tag = tagFor(block);\n if (tag) selectors.push(`${scope} ${tag}:not([data-style])`);\n }\n // Defaults already apply to the scope; repeat only what the chain sets.\n const resolved = this.resolve(style.id);\n const own = {\n ...paragraphCSS(withoutDefaults(resolved.paragraph, this.defaults.paragraph)),\n ...characterCSS(withoutDefaults(resolved.character, this.defaults.character)),\n };\n rule(selectors, own);\n });\n return rules.join(\"\\n\");\n }\n\n // -- Internals --------------------------------------------------------------\n\n private put(style: StyleDefinition): StyleDefinition {\n if (!isValidStyleId(style.id)) throw new Error(`Invalid style id: ${String(style.id)}`);\n if (style.kind !== \"paragraph\" && style.kind !== \"character\") {\n throw new Error(`Invalid style kind: ${String(style.kind)}`);\n }\n const stored = clone({ ...style, name: style.name || style.id });\n this.styles.set(style.id, stored);\n return stored;\n }\n\n private changed(): void {\n this.version++;\n this.snapshot = null;\n const snapshot = this.getSnapshot();\n this.listeners.forEach((listener) => {\n try {\n listener(snapshot);\n } catch (err) {\n console.error(\"[StyleRegistry] Error in listener:\", err);\n }\n });\n }\n}\n\nfunction withoutDefaults<T extends object>(format: T, defaults: T | undefined): T {\n if (!defaults) return format;\n const out: Record<string, unknown> = {};\n Object.entries(format).forEach(([key, value]) => {\n if ((defaults as Record<string, unknown>)[key] !== value) out[key] = value;\n });\n return out as T;\n}\n\nfunction defaultTagFor(block: StyleBlock): string | null {\n if (block.type === \"paragraph\") return \"p\";\n if (block.type === \"heading\") {\n const level = Number(block.attrs?.level);\n return level >= 1 && level <= 6 ? `h${level}` : null;\n }\n if (block.type === \"codeBlock\") return \"pre\";\n return null;\n}\n\n/** A CSS value, or `undefined` when it is unsafe or empty. */\nexport function safeCSSValue(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n if (!trimmed || trimmed.length > 200 || UNSAFE_CSS.test(trimmed)) return undefined;\n return trimmed;\n}\n\nfunction paragraphCSS(format: ParagraphFormat): Record<string, string> {\n const out: Record<string, string> = {};\n const set = (property: string, value: unknown) => {\n const safe = safeCSSValue(value);\n if (safe) out[property] = safe;\n };\n set(\"text-align\", format.textAlign);\n set(\"line-height\", format.lineHeight);\n set(\"margin-top\", format.spaceBefore);\n set(\"margin-bottom\", format.spaceAfter);\n set(\"margin-left\", format.indentLeft);\n set(\"margin-right\", format.indentRight);\n set(\"text-indent\", format.indentFirstLine);\n set(\"border-left\", format.borderLeft);\n set(\"padding-left\", format.paddingLeft);\n set(\"background-color\", format.backgroundColor);\n return out;\n}\n\nfunction characterCSS(format: CharacterFormat): Record<string, string> {\n const out: Record<string, string> = {};\n const set = (property: string, value: unknown) => {\n const safe = safeCSSValue(value);\n if (safe) out[property] = safe;\n };\n set(\"font-family\", format.fontFamily);\n set(\"font-size\", format.fontSize);\n if (format.bold !== undefined) out[\"font-weight\"] = format.bold ? \"700\" : \"400\";\n if (format.italic !== undefined) out[\"font-style\"] = format.italic ? \"italic\" : \"normal\";\n const lines = [format.underline && \"underline\", format.strike && \"line-through\"].filter(Boolean);\n if (format.underline !== undefined || format.strike !== undefined) {\n out[\"text-decoration-line\"] = lines.length ? lines.join(\" \") : \"none\";\n }\n set(\"color\", format.color);\n set(\"background-color\", format.backgroundColor);\n set(\"letter-spacing\", format.letterSpacing);\n set(\"text-transform\", format.textTransform);\n if (format.smallCaps !== undefined) out[\"font-variant-caps\"] = format.smallCaps ? \"small-caps\" : \"normal\";\n return out;\n}\n\n/** Creates a style registry with the built-in styles (unless `builtins: false`) and `styles`. */\nexport function createStyleRegistry(options: StyleRegistryOptions | StyleRegistryJSON = {}): StyleRegistry {\n return new StyleRegistry(options as StyleRegistryOptions);\n}\n","/**\n * Minimal, dependency-free ZIP reader used by the DOCX and zipped-export\n * import adapters.\n *\n * - Reads the central directory (including ZIP64 end records and extra\n * fields), so sizes come from the authoritative directory rather than local\n * headers or data descriptors.\n * - Supports stored (method 0) and deflate (method 8) entries; deflate is\n * inflated with the platform `DecompressionStream(\"deflate-raw\")` (modern\n * browsers, Node ≥ 18).\n * - Guards against zip bombs (entry-count and total-uncompressed-size caps,\n * enforced on the bytes actually inflated, not only the declared sizes),\n * path traversal in entry names and encrypted entries.\n * - Verifies CRC-32 checksums of extracted entries.\n */\n\nexport type ZipErrorCode =\n /** Not a ZIP archive, or its directory is truncated / inconsistent. */\n | \"invalid_archive\"\n /** Compression method other than stored/deflate, multi-disk archives, … */\n | \"unsupported_feature\"\n /** The entry is encrypted (general-purpose flag bit 0). */\n | \"encrypted\"\n /** An entry name is absolute or contains `..` segments. */\n | \"unsafe_path\"\n /** More entries than `maxEntries`. */\n | \"too_many_entries\"\n /** Extracting would exceed `maxTotalSize` uncompressed bytes. */\n | \"too_large\"\n /** The entry data is corrupt (bad header, size or CRC mismatch, bad deflate stream). */\n | \"corrupt_entry\"\n /** No entry with the requested name. */\n | \"entry_not_found\"\n /** `DecompressionStream` is unavailable in this environment. */\n | \"unsupported_environment\";\n\nexport class ZipError extends Error {\n readonly code: ZipErrorCode;\n readonly entryName?: string;\n\n constructor(code: ZipErrorCode, message: string, details: { entryName?: string; cause?: unknown } = {}) {\n super(message, details.cause !== undefined ? { cause: details.cause } : undefined);\n this.name = \"ZipError\";\n this.code = code;\n this.entryName = details.entryName;\n }\n}\n\nexport interface ZipEntry {\n /** Entry path with `/` separators (backslashes are normalized). */\n name: string;\n /** Whether the entry is a directory (name ends with `/`). */\n isDirectory: boolean;\n /** Whether the entry is encrypted; reading it throws `ZipError(\"encrypted\")`. */\n encrypted: boolean;\n /** Compression method (0 = stored, 8 = deflate). */\n method: number;\n /** Declared compressed size in bytes. */\n compressedSize: number;\n /** Declared uncompressed size in bytes. */\n size: number;\n /** CRC-32 of the uncompressed data. */\n crc32: number;\n /** Offset of the entry's local file header. */\n localHeaderOffset: number;\n}\n\nexport interface ZipReadOptions {\n /** Maximum number of entries in the central directory (default 10 000). */\n maxEntries?: number;\n /**\n * Maximum number of uncompressed bytes extracted from the archive, summed\n * over every `read` call (default 256 MiB). Enforced while inflating.\n */\n maxTotalSize?: number;\n /**\n * What to do with entries whose names are absolute or contain `..`\n * segments: `\"error\"` (default) rejects the archive, `\"skip\"` leaves them\n * out of `entries`.\n */\n unsafePaths?: \"error\" | \"skip\";\n}\n\nexport const DEFAULT_ZIP_MAX_ENTRIES = 10_000;\nexport const DEFAULT_ZIP_MAX_TOTAL_SIZE = 256 * 1024 * 1024;\n\nconst SIG_EOCD = 0x06054b50;\nconst SIG_ZIP64_EOCD = 0x06064b50;\nconst SIG_ZIP64_LOCATOR = 0x07064b50;\nconst SIG_CENTRAL = 0x02014b50;\nconst SIG_LOCAL = 0x04034b50;\nconst EOCD_SIZE = 22;\nconst MAX_COMMENT = 0xffff;\n\nlet crcTable: Uint32Array | null = null;\n\n/** CRC-32 (IEEE 802.3), as used by ZIP. */\nexport function zipCrc32(data: Uint8Array): number {\n if (!crcTable) {\n crcTable = new Uint32Array(256);\n for (let n = 0; n < 256; n++) {\n let c = n;\n for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;\n crcTable[n] = c >>> 0;\n }\n }\n let crc = 0xffffffff;\n for (let i = 0; i < data.length; i++) crc = crcTable[(crc ^ data[i]) & 0xff] ^ (crc >>> 8);\n return (crc ^ 0xffffffff) >>> 0;\n}\n\nfunction toBytes(data: ArrayBuffer | ArrayBufferView): Uint8Array {\n // Duck-typed so ArrayBuffers from other realms (iframes, jsdom) work too.\n if (ArrayBuffer.isView(data)) return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n return new Uint8Array(data as ArrayBuffer);\n}\n\n/** Whether `name` is absolute, has a drive letter, or contains `..` / NUL. */\nexport function isUnsafeZipPath(name: string): boolean {\n if (!name || name.includes(\"\\0\")) return true;\n const normalized = name.replace(/\\\\/g, \"/\");\n if (normalized.startsWith(\"/\") || /^[a-zA-Z]:/.test(normalized)) return true;\n return normalized.split(\"/\").some((segment) => segment === \"..\");\n}\n\nconst utf8 = new TextDecoder(\"utf-8\");\n\n/** CP437 high half, used for names without the UTF-8 flag. */\nconst CP437_HIGH =\n \"ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ \";\n\nfunction decodeName(bytes: Uint8Array, isUtf8: boolean): string {\n if (isUtf8 || bytes.every((b) => b < 0x80)) return utf8.decode(bytes);\n let out = \"\";\n for (const b of bytes) out += b < 0x80 ? String.fromCharCode(b) : CP437_HIGH[b - 0x80];\n return out;\n}\n\n/**\n * A parsed ZIP archive. Entry data is extracted lazily with {@link read}.\n * Create it with {@link readZip}.\n */\nexport class ZipArchive {\n /** Entries in central-directory order. */\n readonly entries: readonly ZipEntry[];\n private readonly byName = new Map<string, ZipEntry>();\n private extracted = 0;\n\n constructor(\n private readonly bytes: Uint8Array,\n entries: ZipEntry[],\n private readonly maxTotalSize: number,\n ) {\n this.entries = entries;\n entries.forEach((entry) => {\n if (!this.byName.has(entry.name)) this.byName.set(entry.name, entry);\n });\n }\n\n /** Looks up an entry by exact name (a leading `/` is ignored). */\n get(name: string): ZipEntry | undefined {\n return this.byName.get(name.replace(/^\\/+/, \"\"));\n }\n\n has(name: string): boolean {\n return !!this.get(name);\n }\n\n /** Uncompressed bytes extracted so far (counted against `maxTotalSize`). */\n get extractedSize(): number {\n return this.extracted;\n }\n\n /** Extracts an entry's data, verifying its size and CRC-32. */\n async read(entryOrName: ZipEntry | string): Promise<Uint8Array> {\n const entry = typeof entryOrName === \"string\" ? this.get(entryOrName) : entryOrName;\n if (!entry) {\n throw new ZipError(\"entry_not_found\", `ZIP entry \"${String(entryOrName)}\" not found.`, {\n entryName: String(entryOrName),\n });\n }\n const name = entry.name;\n if (entry.encrypted) {\n throw new ZipError(\"encrypted\", `ZIP entry \"${name}\" is encrypted; encrypted archives are not supported.`, {\n entryName: name,\n });\n }\n if (entry.isDirectory) return new Uint8Array(0);\n const remaining = this.maxTotalSize - this.extracted;\n if (entry.size > remaining) {\n throw new ZipError(\n \"too_large\",\n `Extracting \"${name}\" (${entry.size} bytes) would exceed the ${this.maxTotalSize}-byte limit.`,\n { entryName: name },\n );\n }\n\n const { bytes } = this;\n const offset = entry.localHeaderOffset;\n if (offset + 30 > bytes.length || readU32(bytes, offset) !== SIG_LOCAL) {\n throw new ZipError(\"corrupt_entry\", `ZIP entry \"${name}\" has no valid local header.`, { entryName: name });\n }\n const dataStart = offset + 30 + readU16(bytes, offset + 26) + readU16(bytes, offset + 28);\n const dataEnd = dataStart + entry.compressedSize;\n if (dataEnd > bytes.length) {\n throw new ZipError(\"corrupt_entry\", `ZIP entry \"${name}\" is truncated.`, { entryName: name });\n }\n const raw = bytes.subarray(dataStart, dataEnd);\n\n let data: Uint8Array;\n if (entry.method === 0) {\n if (entry.compressedSize !== entry.size) {\n throw new ZipError(\"corrupt_entry\", `Stored ZIP entry \"${name}\" has inconsistent sizes.`, { entryName: name });\n }\n data = raw.slice();\n } else if (entry.method === 8) {\n // Cap at the declared size: more output means a lying header (or a bomb).\n data = await inflateRaw(raw, entry.size, name);\n } else {\n throw new ZipError(\n \"unsupported_feature\",\n `ZIP entry \"${name}\" uses unsupported compression method ${entry.method}; only stored and deflate are supported.`,\n { entryName: name },\n );\n }\n if (data.length !== entry.size) {\n throw new ZipError(\"corrupt_entry\", `ZIP entry \"${name}\" size does not match the directory.`, { entryName: name });\n }\n this.extracted += data.length;\n if (zipCrc32(data) !== entry.crc32) {\n throw new ZipError(\"corrupt_entry\", `ZIP entry \"${name}\" failed its CRC-32 check.`, { entryName: name });\n }\n return data;\n }\n\n /** Extracts an entry and decodes it as UTF-8 (a leading BOM is removed). */\n async readText(entryOrName: ZipEntry | string): Promise<string> {\n const text = utf8.decode(await this.read(entryOrName));\n return text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;\n }\n}\n\nfunction readU16(bytes: Uint8Array, offset: number): number {\n return bytes[offset] | (bytes[offset + 1] << 8);\n}\n\nfunction readU32(bytes: Uint8Array, offset: number): number {\n return (bytes[offset] | (bytes[offset + 1] << 8) | (bytes[offset + 2] << 16) | (bytes[offset + 3] << 24)) >>> 0;\n}\n\nfunction readU64(bytes: Uint8Array, offset: number): number {\n const value = readU32(bytes, offset) + readU32(bytes, offset + 4) * 0x100000000;\n if (!Number.isSafeInteger(value)) {\n throw new ZipError(\"unsupported_feature\", \"ZIP64 value exceeds the supported range.\");\n }\n return value;\n}\n\n/** Inflates a raw deflate stream, failing as soon as output exceeds `limit` bytes. */\nasync function inflateRaw(raw: Uint8Array, limit: number, entryName: string): Promise<Uint8Array> {\n const Stream: typeof DecompressionStream | undefined = (globalThis as any).DecompressionStream;\n if (typeof Stream !== \"function\") {\n throw new ZipError(\n \"unsupported_environment\",\n \"Inflating ZIP entries needs DecompressionStream (modern browsers, Node 18+).\",\n { entryName },\n );\n }\n const stream = new Stream(\"deflate-raw\");\n const writer = stream.writable.getWriter();\n const reader = stream.readable.getReader();\n // Feed the input in slices so output is pulled (and checked) incrementally.\n const CHUNK = 64 * 1024;\n const feeding = (async () => {\n for (let i = 0; i < raw.length; i += CHUNK) await writer.write(raw.subarray(i, i + CHUNK) as unknown as BufferSource);\n await writer.close();\n })();\n feeding.catch(() => {});\n\n const chunks: Uint8Array[] = [];\n let total = 0;\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n total += value.length;\n if (total > limit) {\n throw new ZipError(\n \"corrupt_entry\",\n `ZIP entry \"${entryName}\" inflates beyond its declared size of ${limit} bytes.`,\n { entryName },\n );\n }\n chunks.push(value);\n }\n } catch (error) {\n reader.cancel().catch(() => {});\n writer.abort().catch(() => {});\n if (error instanceof ZipError) throw error;\n throw new ZipError(\"corrupt_entry\", `ZIP entry \"${entryName}\" has an invalid deflate stream.`, {\n entryName,\n cause: error,\n });\n }\n await feeding.catch(() => {});\n const out = new Uint8Array(total);\n let pos = 0;\n for (const chunk of chunks) {\n out.set(chunk, pos);\n pos += chunk.length;\n }\n return out;\n}\n\nfunction findEndOfCentralDirectory(bytes: Uint8Array): number {\n const min = Math.max(0, bytes.length - EOCD_SIZE - MAX_COMMENT);\n for (let i = bytes.length - EOCD_SIZE; i >= min; i--) {\n if (readU32(bytes, i) === SIG_EOCD && i + EOCD_SIZE + readU16(bytes, i + 20) <= bytes.length) return i;\n }\n return -1;\n}\n\n/**\n * Parses a ZIP archive's central directory. Entry data is not extracted until\n * {@link ZipArchive.read} is called. Throws {@link ZipError}.\n */\nexport async function readZip(data: ArrayBuffer | ArrayBufferView, options: ZipReadOptions = {}): Promise<ZipArchive> {\n const bytes = toBytes(data);\n const maxEntries = options.maxEntries ?? DEFAULT_ZIP_MAX_ENTRIES;\n const maxTotalSize = options.maxTotalSize ?? DEFAULT_ZIP_MAX_TOTAL_SIZE;\n\n const eocd = findEndOfCentralDirectory(bytes);\n if (eocd < 0) throw new ZipError(\"invalid_archive\", \"Not a ZIP archive (no end of central directory record).\");\n\n let diskNumber = readU16(bytes, eocd + 4);\n let cdDisk = readU16(bytes, eocd + 6);\n let count = readU16(bytes, eocd + 10);\n let cdSize = readU32(bytes, eocd + 12);\n let cdOffset = readU32(bytes, eocd + 16);\n\n if (count === 0xffff || cdSize === 0xffffffff || cdOffset === 0xffffffff) {\n const locator = eocd - 20;\n if (locator < 0 || readU32(bytes, locator) !== SIG_ZIP64_LOCATOR) {\n throw new ZipError(\"invalid_archive\", \"ZIP64 archive is missing its end of central directory locator.\");\n }\n const record = readU64(bytes, locator + 8);\n if (record + 56 > bytes.length || readU32(bytes, record) !== SIG_ZIP64_EOCD) {\n throw new ZipError(\"invalid_archive\", \"ZIP64 end of central directory record not found.\");\n }\n diskNumber = readU32(bytes, record + 16);\n cdDisk = readU32(bytes, record + 20);\n count = readU64(bytes, record + 32);\n cdSize = readU64(bytes, record + 40);\n cdOffset = readU64(bytes, record + 48);\n }\n if (diskNumber !== 0 || cdDisk !== 0) {\n throw new ZipError(\"unsupported_feature\", \"Multi-disk (spanned) ZIP archives are not supported.\");\n }\n if (count > maxEntries) {\n throw new ZipError(\"too_many_entries\", `ZIP archive has ${count} entries; the limit is ${maxEntries}.`);\n }\n if (cdOffset + cdSize > bytes.length) {\n throw new ZipError(\"invalid_archive\", \"ZIP central directory lies outside the file.\");\n }\n\n const entries: ZipEntry[] = [];\n let p = cdOffset;\n for (let i = 0; i < count; i++) {\n if (p + 46 > bytes.length || readU32(bytes, p) !== SIG_CENTRAL) {\n throw new ZipError(\"invalid_archive\", \"ZIP central directory is corrupt.\");\n }\n const flags = readU16(bytes, p + 8);\n const method = readU16(bytes, p + 10);\n const crc32 = readU32(bytes, p + 16);\n let compressedSize = readU32(bytes, p + 20);\n let size = readU32(bytes, p + 24);\n const nameLength = readU16(bytes, p + 28);\n const extraLength = readU16(bytes, p + 30);\n const commentLength = readU16(bytes, p + 32);\n let localHeaderOffset = readU32(bytes, p + 42);\n const nameStart = p + 46;\n const extraStart = nameStart + nameLength;\n const next = extraStart + extraLength + commentLength;\n if (next > bytes.length) throw new ZipError(\"invalid_archive\", \"ZIP central directory is truncated.\");\n\n // ZIP64 extended information: only the fields that overflowed are present, in order.\n for (let e = extraStart; e + 4 <= extraStart + extraLength; ) {\n const id = readU16(bytes, e);\n const len = readU16(bytes, e + 2);\n if (id === 0x0001) {\n let f = e + 4;\n const end = f + len;\n if (size === 0xffffffff && f + 8 <= end) {\n size = readU64(bytes, f);\n f += 8;\n }\n if (compressedSize === 0xffffffff && f + 8 <= end) {\n compressedSize = readU64(bytes, f);\n f += 8;\n }\n if (localHeaderOffset === 0xffffffff && f + 8 <= end) localHeaderOffset = readU64(bytes, f);\n }\n e += 4 + len;\n }\n\n const rawName = decodeName(bytes.subarray(nameStart, extraStart), (flags & 0x0800) !== 0);\n const name = rawName.replace(/\\\\/g, \"/\");\n p = next;\n if (isUnsafeZipPath(rawName)) {\n if (options.unsafePaths === \"skip\") continue;\n throw new ZipError(\"unsafe_path\", `ZIP entry name \"${rawName}\" is absolute or escapes the archive root.`, {\n entryName: rawName,\n });\n }\n entries.push({\n name,\n isDirectory: name.endsWith(\"/\"),\n encrypted: (flags & 0x0001) !== 0,\n method,\n compressedSize,\n size,\n crc32,\n localHeaderOffset,\n });\n }\n return new ZipArchive(bytes, entries, maxTotalSize);\n}\n"]}
@@ -7,7 +7,7 @@
7
7
 
8
8
 
9
9
 
10
- var _chunkX4N4WUKBcjs = require('./chunk-X4N4WUKB.cjs');
10
+ var _chunkIFHKKVXHcjs = require('./chunk-IFHKKVXH.cjs');
11
11
 
12
12
  // src/compare/diff.ts
13
13
  var EQUAL = 0;
@@ -257,9 +257,9 @@ var _core = require('@tiptap/core');
257
257
 
258
258
  var _model = require('@tiptap/pm/model');
259
259
  var REVIEW_MARK_NAMES = /* @__PURE__ */ new Set([
260
- _chunkX4N4WUKBcjs.INSERTION_MARK_NAME,
261
- _chunkX4N4WUKBcjs.DELETION_MARK_NAME,
262
- _chunkX4N4WUKBcjs.FORMAT_CHANGE_MARK_NAME,
260
+ _chunkIFHKKVXHcjs.INSERTION_MARK_NAME,
261
+ _chunkIFHKKVXHcjs.DELETION_MARK_NAME,
262
+ _chunkIFHKKVXHcjs.FORMAT_CHANGE_MARK_NAME,
263
263
  "comment",
264
264
  "bookmark"
265
265
  ]);
@@ -303,7 +303,7 @@ function lazyAttributes(ctx) {
303
303
  }
304
304
  function stripBlockChange(attrs) {
305
305
  const copy = { ...attrs };
306
- delete copy[_chunkX4N4WUKBcjs.BLOCK_CHANGE_ATTRIBUTE];
306
+ delete copy[_chunkIFHKKVXHcjs.BLOCK_CHANGE_ATTRIBUTE];
307
307
  return copy;
308
308
  }
309
309
  function wrapperOf(node) {
@@ -316,7 +316,7 @@ function filteredAttributes(attrs, ctx) {
316
316
  return stableStringify(
317
317
  Object.fromEntries(
318
318
  Object.entries(_nullishCoalesce(attrs, () => ( {}))).filter(
319
- ([key]) => key !== _chunkX4N4WUKBcjs.BLOCK_CHANGE_ATTRIBUTE && !ctx.ignoredAttributes.has(key)
319
+ ([key]) => key !== _chunkIFHKKVXHcjs.BLOCK_CHANGE_ATTRIBUTE && !ctx.ignoredAttributes.has(key)
320
320
  )
321
321
  )
322
322
  );
@@ -327,7 +327,7 @@ function sameBlock(a, b, ctx) {
327
327
  if (a.wrappers.length !== b.wrappers.length) return false;
328
328
  return a.wrappers.every((w, i) => w.type === b.wrappers[i].type);
329
329
  }
330
- var hasBlockChange = (node) => !!node.type.spec.attrs && _chunkX4N4WUKBcjs.BLOCK_CHANGE_ATTRIBUTE in node.type.spec.attrs;
330
+ var hasBlockChange = (node) => !!node.type.spec.attrs && _chunkIFHKKVXHcjs.BLOCK_CHANGE_ATTRIBUTE in node.type.spec.attrs;
331
331
  var label = (node) => node.type.name;
332
332
  function normalize(text, ctx) {
333
333
  let result = ctx.ignoreWhitespace ? text.replace(/\s+/g, " ") : text;
@@ -380,12 +380,12 @@ function wholeBlock(node, operation, wrappers, attrs, ctx) {
380
380
  previous: snapshot(node, wrappers),
381
381
  operation
382
382
  };
383
- return [node.type.create({ ...node.attrs, [_chunkX4N4WUKBcjs.BLOCK_CHANGE_ATTRIBUTE]: record }, node.content, node.marks)];
383
+ return [node.type.create({ ...node.attrs, [_chunkIFHKKVXHcjs.BLOCK_CHANGE_ATTRIBUTE]: record }, node.content, node.marks)];
384
384
  }
385
385
  const markType = operation === "insert" ? ctx.insertion : ctx.deletion;
386
386
  if (markType && node.type.allowsMarkType(markType) && node.content.size > 0) {
387
387
  ctx.notes.add(
388
- `${verb} ${label(node)} blocks have no "${_chunkX4N4WUKBcjs.BLOCK_CHANGE_ATTRIBUTE}" attribute: only their text is tracked, so an empty block remains when the change is ${operation === "insert" ? "rejected" : "accepted"}.`
388
+ `${verb} ${label(node)} blocks have no "${_chunkIFHKKVXHcjs.BLOCK_CHANGE_ATTRIBUTE}" attribute: only their text is tracked, so an empty block remains when the change is ${operation === "insert" ? "rejected" : "accepted"}.`
389
389
  );
390
390
  return [node.type.create(node.attrs, markInline(node.content, markType.create(attrs())), node.marks)];
391
391
  }
@@ -484,7 +484,7 @@ function formattingOf(marks, ctx) {
484
484
  }
485
485
  function withoutReviewMarks(marks) {
486
486
  return marks.filter(
487
- (mark) => mark.type.name !== _chunkX4N4WUKBcjs.INSERTION_MARK_NAME && mark.type.name !== _chunkX4N4WUKBcjs.DELETION_MARK_NAME && mark.type.name !== _chunkX4N4WUKBcjs.FORMAT_CHANGE_MARK_NAME
487
+ (mark) => mark.type.name !== _chunkIFHKKVXHcjs.INSERTION_MARK_NAME && mark.type.name !== _chunkIFHKKVXHcjs.DELETION_MARK_NAME && mark.type.name !== _chunkIFHKKVXHcjs.FORMAT_CHANGE_MARK_NAME
488
488
  );
489
489
  }
490
490
  function mergeInline(original, revised, parentType, ctx) {
@@ -580,12 +580,12 @@ function mergeTextblocks(original, revised, oPath, rPath, ctx) {
580
580
  if (hasBlockChange(revised)) {
581
581
  const onlyWrappers = ctx.wrapperChange && sameBlock(previous, { ...snapshot(revised, rPath), wrappers: previous.wrappers }, ctx);
582
582
  const base = onlyWrappers ? ctx.wrapperChange() : newAttributes(ctx);
583
- attrs = { ...attrs, [_chunkX4N4WUKBcjs.BLOCK_CHANGE_ATTRIBUTE]: { ...base, previous } };
583
+ attrs = { ...attrs, [_chunkIFHKKVXHcjs.BLOCK_CHANGE_ATTRIBUTE]: { ...base, previous } };
584
584
  } else {
585
585
  ctx.notes.add(`Block changes to ${label(revised)} blocks cannot be tracked.`);
586
586
  }
587
- } else if (_chunkX4N4WUKBcjs.BLOCK_CHANGE_ATTRIBUTE in attrs) {
588
- attrs[_chunkX4N4WUKBcjs.BLOCK_CHANGE_ATTRIBUTE] = null;
587
+ } else if (_chunkIFHKKVXHcjs.BLOCK_CHANGE_ATTRIBUTE in attrs) {
588
+ attrs[_chunkIFHKKVXHcjs.BLOCK_CHANGE_ATTRIBUTE] = null;
589
589
  }
590
590
  const type = revised.type;
591
591
  const inlineTracking = !!ctx.insertion && !!ctx.deletion && type.allowsMarkType(ctx.insertion) && type.allowsMarkType(ctx.deletion);
@@ -679,7 +679,7 @@ function detectMovedBlocks(children, ctx) {
679
679
  const keyOf = (node) => `${node.type.name}\0${filteredAttributes(node.attrs, ctx)}\0${stableStringify(node.content.toJSON())}`;
680
680
  const candidates = /* @__PURE__ */ new Map();
681
681
  children.forEach((node, index) => {
682
- const operation = _optionalChain([node, 'access', _2 => _2.attrs, 'optionalAccess', _3 => _3[_chunkX4N4WUKBcjs.BLOCK_CHANGE_ATTRIBUTE], 'optionalAccess', _4 => _4.operation]);
682
+ const operation = _optionalChain([node, 'access', _2 => _2.attrs, 'optionalAccess', _3 => _3[_chunkIFHKKVXHcjs.BLOCK_CHANGE_ATTRIBUTE], 'optionalAccess', _4 => _4.operation]);
683
683
  if (!operation || !node.isTextblock || !node.textContent.trim()) return;
684
684
  if (!node.type.allowsMarkType(ctx.insertion) || !node.type.allowsMarkType(ctx.deletion)) return;
685
685
  const key = keyOf(node);
@@ -691,11 +691,11 @@ function detectMovedBlocks(children, ctx) {
691
691
  candidates.forEach(({ del, ins }) => {
692
692
  if (del.length !== 1 || ins.length !== 1) return;
693
693
  const attrs = newAttributes(ctx);
694
- const moved = { ...attrs, [_chunkX4N4WUKBcjs.MOVE_ID_ATTRIBUTE]: attrs.changeId };
694
+ const moved = { ...attrs, [_chunkIFHKKVXHcjs.MOVE_ID_ATTRIBUTE]: attrs.changeId };
695
695
  const relink = (index, markType) => {
696
696
  const node = out[index];
697
697
  out[index] = node.type.create(
698
- { ...node.attrs, [_chunkX4N4WUKBcjs.BLOCK_CHANGE_ATTRIBUTE]: null },
698
+ { ...node.attrs, [_chunkIFHKKVXHcjs.BLOCK_CHANGE_ATTRIBUTE]: null },
699
699
  markInline(node.content, markType.create(moved)),
700
700
  node.marks
701
701
  );
@@ -714,7 +714,7 @@ function summarize(doc, notes) {
714
714
  moves: 0,
715
715
  notHonoured: [...notes]
716
716
  };
717
- _chunkX4N4WUKBcjs.getTrackedChanges.call(void 0, doc).forEach((change) => {
717
+ _chunkIFHKKVXHcjs.getTrackedChanges.call(void 0, doc).forEach((change) => {
718
718
  if (change.type === "move") summary.moves++;
719
719
  else if (change.type === "insertion" || _optionalChain([change, 'access', _5 => _5.block, 'optionalAccess', _6 => _6.operation]) === "insert") summary.insertions++;
720
720
  else if (change.type === "deletion" || _optionalChain([change, 'access', _7 => _7.block, 'optionalAccess', _8 => _8.operation]) === "delete") summary.deletions++;
@@ -730,7 +730,7 @@ function compareDocuments(original, revised, options = {}) {
730
730
  schema,
731
731
  author: _nullishCoalesce(options.author, () => ( { id: "compare", name: "Compare" })),
732
732
  createdAt: toTime(options.date),
733
- generateId: _nullishCoalesce(options.generateId, () => ( (() => _chunkX4N4WUKBcjs.createReviewId.call(void 0, "change")))),
733
+ generateId: _nullishCoalesce(options.generateId, () => ( (() => _chunkIFHKKVXHcjs.createReviewId.call(void 0, "change")))),
734
734
  granularity: _nullishCoalesce(options.granularity, () => ( "word")),
735
735
  ignoreCase: !!options.ignoreCase,
736
736
  ignoreWhitespace: !!options.ignoreWhitespace,
@@ -738,9 +738,9 @@ function compareDocuments(original, revised, options = {}) {
738
738
  maxCharDiff: _nullishCoalesce(options.maxCharDiff, () => ( 2e3)),
739
739
  ignoredMarks: new Set(_nullishCoalesce(options.ignoredMarks, () => ( []))),
740
740
  ignoredAttributes: new Set(_nullishCoalesce(options.ignoredBlockAttributes, () => ( ["id"]))),
741
- insertion: schema.marks[_chunkX4N4WUKBcjs.INSERTION_MARK_NAME],
742
- deletion: schema.marks[_chunkX4N4WUKBcjs.DELETION_MARK_NAME],
743
- format: schema.marks[_chunkX4N4WUKBcjs.FORMAT_CHANGE_MARK_NAME],
741
+ insertion: schema.marks[_chunkIFHKKVXHcjs.INSERTION_MARK_NAME],
742
+ deletion: schema.marks[_chunkIFHKKVXHcjs.DELETION_MARK_NAME],
743
+ format: schema.marks[_chunkIFHKKVXHcjs.FORMAT_CHANGE_MARK_NAME],
744
744
  notes: /* @__PURE__ */ new Set(),
745
745
  keys: /* @__PURE__ */ new Map(),
746
746
  wrapperChange: null
@@ -753,9 +753,9 @@ function compareDocuments(original, revised, options = {}) {
753
753
  }
754
754
  const prepare = (source) => {
755
755
  const doc2 = toNode(source, schema);
756
- if (_chunkX4N4WUKBcjs.getTrackedChanges.call(void 0, doc2).length === 0) return doc2;
756
+ if (_chunkIFHKKVXHcjs.getTrackedChanges.call(void 0, doc2).length === 0) return doc2;
757
757
  ctx.notes.add("Tracked changes already in the documents were accepted before comparing.");
758
- return _chunkX4N4WUKBcjs.resolveTrackedChanges.call(void 0, doc2, "accepted");
758
+ return _chunkIFHKKVXHcjs.resolveTrackedChanges.call(void 0, doc2, "accepted");
759
759
  };
760
760
  const a = prepare(original);
761
761
  const b = prepare(revised);
@@ -780,4 +780,4 @@ function compareHtml(originalHtml, revisedHtml, options) {
780
780
 
781
781
 
782
782
  exports.diffSequences = diffSequences; exports.diffChanges = diffChanges; exports.compareDocuments = compareDocuments; exports.compareHtml = compareHtml;
783
- //# sourceMappingURL=chunk-AL6JMGWW.cjs.map
783
+ //# sourceMappingURL=chunk-CS6NZWWA.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/editor/editor/packages/core/dist/chunk-AL6JMGWW.cjs","../src/compare/diff.ts","../src/compare/documents.ts"],"names":["x","y","k","i","j"],"mappings":"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","file":"/home/runner/work/editor/editor/packages/core/dist/chunk-AL6JMGWW.cjs","sourcesContent":[null,"// Portions ported from pdfcraft/crates/compare/src/lib.rs (MIT OR Apache-2.0, © ArtCraft Team and contributors). See THIRD_PARTY_NOTICES.md.\n\n/**\n * Generic sequence diff: common prefix/suffix stripping, Myers' O((N+M)·D)\n * algorithm for small segments and patience anchors (items unique on both\n * sides, longest increasing subsequence) to split long ones. Dependency-free.\n */\n\nexport type DiffOpType = \"equal\" | \"delete\" | \"insert\";\n\n/** A run of consecutive operations of one type. */\nexport interface DiffRun {\n type: DiffOpType;\n /** Start index in `a` (for `insert`, where the items go in `a`). */\n aIndex: number;\n /** Start index in `b` (for `delete`, where the items were in `b`). */\n bIndex: number;\n length: number;\n}\n\n/** A change: a deleted range of `a`, an inserted range of `b`, or both (replaced). */\nexport interface DiffChange {\n kind: \"inserted\" | \"deleted\" | \"replaced\";\n aStart: number;\n aEnd: number;\n bStart: number;\n bEnd: number;\n}\n\nexport interface DiffSequencesOptions<T> {\n /**\n * Key of an item: items with the same key are equal. Defaults to the item\n * itself for strings, numbers and booleans, and `JSON.stringify` otherwise.\n * Keys enable patience anchors for long inputs.\n */\n hash?: (item: T) => string | number | boolean;\n /**\n * Custom equality. Without `hash`, segments longer than `direct` are only\n * diffed while the edit distance stays below `direct`, otherwise replaced.\n */\n equals?: (a: T, b: T) => boolean;\n /**\n * Segments with more items (both sides together) are split at anchors\n * first so Myers' saved frontiers (O(D²) memory) stay small. Default 3000.\n */\n direct?: number;\n /** Maximum anchor recursion depth before a long segment is replaced whole. Default 8. */\n maxDepth?: number;\n}\n\nconst EQUAL = 0;\nconst DELETE = 1;\nconst INSERT = 2;\n\ntype Eq = (i: number, j: number) => boolean;\n\nfunction pushRepeat(out: number[], op: number, count: number): void {\n for (let i = 0; i < count; i++) out.push(op);\n}\n\n/**\n * Myers' diff of a[aLo..aHi) and b[bLo..bHi). Returns false (and emits\n * nothing) when the edit distance exceeds `maxD`.\n */\nfunction myers(\n aLo: number,\n aHi: number,\n bLo: number,\n bHi: number,\n eq: Eq,\n out: number[],\n maxD: number,\n): boolean {\n const n = aHi - aLo;\n const m = bHi - bLo;\n if (n === 0 || m === 0) {\n pushRepeat(out, DELETE, n);\n pushRepeat(out, INSERT, m);\n return true;\n }\n const max = n + m;\n const off = max + 1;\n const v = new Int32Array(2 * max + 3);\n // Frontier d only spans diagonals -d..d: save just that slice.\n const trace: Int32Array[] = [];\n const limit = Math.min(max, maxD);\n let found = false;\n outer: for (let d = 0; d <= limit; d++) {\n trace.push(v.slice(Math.max(off - d - 1, 0), off + d + 2));\n for (let k = -d; k <= d; k += 2) {\n const i = k + off;\n let x = k === -d || (k !== d && v[i - 1] < v[i + 1]) ? v[i + 1] : v[i - 1] + 1;\n let y = x - k;\n while (x < n && y < m && eq(aLo + x, bLo + y)) {\n x++;\n y++;\n }\n v[i] = x;\n if (x >= n && y >= m) {\n found = true;\n break outer;\n }\n }\n }\n if (!found) return false;\n\n // Walk back through the saved frontiers.\n const ops: number[] = [];\n let x = n;\n let y = m;\n for (let d = trace.length - 1; d >= 0; d--) {\n const frontier = trace[d];\n const base = Math.max(off - d - 1, 0);\n const at = (k: number) => frontier[k + off - base];\n const k = x - y;\n const prevK = k === -d || (k !== d && at(k - 1) < at(k + 1)) ? k + 1 : k - 1;\n const prevX = at(prevK);\n const prevY = prevX - prevK;\n while (x > prevX && y > prevY) {\n ops.push(EQUAL);\n x--;\n y--;\n }\n if (d > 0) ops.push(x === prevX ? INSERT : DELETE);\n x = prevX;\n y = prevY;\n }\n for (let i = ops.length - 1; i >= 0; i--) out.push(ops[i]);\n return true;\n}\n\n/**\n * Patience anchors: items that occur once on each side, in an order both\n * sides agree on (the longest increasing subsequence of their positions).\n */\nfunction anchors(\n ids: { a: Int32Array; b: Int32Array },\n aLo: number,\n aHi: number,\n bLo: number,\n bHi: number,\n): [number, number][] {\n const count = new Map<number, [number, number, number, number]>();\n for (let i = aLo; i < aHi; i++) {\n const id = ids.a[i];\n const entry = count.get(id);\n if (entry) {\n entry[0]++;\n } else {\n count.set(id, [1, 0, i, -1]);\n }\n }\n for (let j = bLo; j < bHi; j++) {\n const entry = count.get(ids.b[j]);\n if (entry) {\n entry[1]++;\n entry[3] = j;\n }\n }\n const pairs: [number, number][] = [];\n count.forEach((entry) => {\n if (entry[0] === 1 && entry[1] === 1) pairs.push([entry[2], entry[3]]);\n });\n pairs.sort((p, q) => p[0] - q[0]);\n // LIS on the b positions (patience sorting with back links).\n const tails: number[] = [];\n const prev = new Int32Array(pairs.length).fill(-1);\n for (let k = 0; k < pairs.length; k++) {\n const y = pairs[k][1];\n let lo = 0;\n let hi = tails.length;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (pairs[tails[mid]][1] < y) lo = mid + 1;\n else hi = mid;\n }\n if (lo > 0) prev[k] = tails[lo - 1];\n if (lo === tails.length) tails.push(k);\n else tails[lo] = k;\n }\n const result: [number, number][] = [];\n let k = tails.length ? tails[tails.length - 1] : -1;\n while (k !== -1) {\n result.push(pairs[k]);\n k = prev[k];\n }\n return result.reverse();\n}\n\ninterface DiffContext {\n eq: Eq;\n ids: { a: Int32Array; b: Int32Array } | null;\n direct: number;\n maxDepth: number;\n}\n\nfunction diffRange(\n ctx: DiffContext,\n aLo: number,\n aHi: number,\n bLo: number,\n bHi: number,\n out: number[],\n depth: number,\n): void {\n const { eq } = ctx;\n let prefix = 0;\n while (aLo + prefix < aHi && bLo + prefix < bHi && eq(aLo + prefix, bLo + prefix)) prefix++;\n let suffix = 0;\n while (\n aHi - suffix > aLo + prefix &&\n bHi - suffix > bLo + prefix &&\n eq(aHi - suffix - 1, bHi - suffix - 1)\n ) {\n suffix++;\n }\n pushRepeat(out, EQUAL, prefix);\n const ma = aLo + prefix;\n const mb = bLo + prefix;\n const ea = aHi - suffix;\n const eb = bHi - suffix;\n const replace = () => {\n pushRepeat(out, DELETE, ea - ma);\n pushRepeat(out, INSERT, eb - mb);\n };\n\n if (ea - ma + (eb - mb) <= ctx.direct) {\n myers(ma, ea, mb, eb, eq, out, Infinity);\n } else if (!ctx.ids) {\n // No keys, so no anchors: bounded Myers, else one replacement.\n if (!myers(ma, ea, mb, eb, eq, out, ctx.direct)) replace();\n } else {\n const found = depth >= ctx.maxDepth ? [] : anchors(ctx.ids, ma, ea, mb, eb);\n if (found.length === 0) {\n // A long stretch with nothing unique in common: one replacement.\n replace();\n } else {\n let i = ma;\n let j = mb;\n for (const [x, y] of found) {\n diffRange(ctx, i, x, j, y, out, depth + 1);\n out.push(EQUAL);\n i = x + 1;\n j = y + 1;\n }\n diffRange(ctx, i, ea, j, eb, out, depth + 1);\n }\n }\n pushRepeat(out, EQUAL, suffix);\n}\n\nconst defaultHash = (item: unknown): string | number | boolean =>\n typeof item === \"string\" || typeof item === \"number\" || typeof item === \"boolean\"\n ? item\n : JSON.stringify(item);\n\n/**\n * Diffs two sequences and returns the edit script as runs of equal, deleted\n * and inserted items, in order. Within a changed stretch deletions come\n * before insertions. The script is minimal for segments up to `direct`\n * items; longer inputs are split at patience anchors (bounded work).\n */\nexport function diffSequences<T>(\n a: readonly T[],\n b: readonly T[],\n options: DiffSequencesOptions<T> = {},\n): DiffRun[] {\n const direct = Math.max(2, options.direct ?? 3000);\n const maxDepth = options.maxDepth ?? 8;\n let ids: { a: Int32Array; b: Int32Array } | null = null;\n let eq: Eq;\n if (options.equals && !options.hash) {\n const equals = options.equals;\n eq = (i, j) => equals(a[i], b[j]);\n } else {\n const hash = options.hash ?? (defaultHash as (item: T) => string | number | boolean);\n const table = new Map<string | number | boolean, number>();\n const idOf = (item: T) => {\n const key = hash(item);\n let id = table.get(key);\n if (id === undefined) {\n id = table.size;\n table.set(key, id);\n }\n return id;\n };\n ids = { a: Int32Array.from(a, idOf), b: Int32Array.from(b, idOf) };\n const { a: ia, b: ib } = ids;\n eq = (i, j) => ia[i] === ib[j];\n }\n\n const ops: number[] = [];\n diffRange({ eq, ids, direct, maxDepth }, 0, a.length, 0, b.length, ops, 0);\n\n // Group into runs, deletions first within each changed stretch.\n const runs: DiffRun[] = [];\n const push = (type: DiffOpType, aIndex: number, bIndex: number, length: number) => {\n if (length === 0) return;\n const last = runs[runs.length - 1];\n if (last && last.type === type) {\n last.length += length;\n } else {\n runs.push({ type, aIndex, bIndex, length });\n }\n };\n let i = 0;\n let j = 0;\n let k = 0;\n while (k < ops.length) {\n if (ops[k] === EQUAL) {\n let n = 0;\n while (k < ops.length && ops[k] === EQUAL) {\n n++;\n k++;\n }\n push(\"equal\", i, j, n);\n i += n;\n j += n;\n continue;\n }\n let dels = 0;\n let inss = 0;\n while (k < ops.length && ops[k] !== EQUAL) {\n if (ops[k] === DELETE) dels++;\n else inss++;\n k++;\n }\n push(\"delete\", i, j, dels);\n push(\"insert\", i + dels, j, inss);\n i += dels;\n j += inss;\n }\n return runs;\n}\n\n/** Groups an edit script into inserted, deleted and replaced ranges. */\nexport function diffChanges<T>(\n a: readonly T[],\n b: readonly T[],\n options: DiffSequencesOptions<T> = {},\n): DiffChange[] {\n const changes: DiffChange[] = [];\n let current: DiffChange | null = null;\n for (const run of diffSequences(a, b, options)) {\n if (run.type === \"equal\") {\n current = null;\n continue;\n }\n if (!current) {\n current = {\n kind: run.type === \"delete\" ? \"deleted\" : \"inserted\",\n aStart: run.aIndex,\n aEnd: run.aIndex,\n bStart: run.bIndex,\n bEnd: run.bIndex,\n };\n changes.push(current);\n }\n if (run.type === \"delete\") {\n current.aEnd = run.aIndex + run.length;\n } else {\n current.bEnd = run.bIndex + run.length;\n }\n if (current.aEnd > current.aStart && current.bEnd > current.bStart) current.kind = \"replaced\";\n }\n return changes;\n}\n","// Portions ported from wordcraft/crates/engine/src/cmd/tools.rs (MIT OR Apache-2.0, © ArtCraft Team and contributors). See THIRD_PARTY_NOTICES.md.\n\nimport { createDocument } from \"@tiptap/core\";\nimport {\n Fragment,\n Mark as ProsemirrorMark,\n type MarkType,\n type Node as ProsemirrorNode,\n type Schema,\n} from \"@tiptap/pm/model\";\nimport {\n BLOCK_CHANGE_ATTRIBUTE,\n DELETION_MARK_NAME,\n FORMAT_CHANGE_MARK_NAME,\n INSERTION_MARK_NAME,\n MOVE_ID_ATTRIBUTE,\n getTrackedChanges,\n resolveTrackedChanges,\n type TrackedBlockChangeAttributes,\n type TrackedBlockOperation,\n type TrackedBlockSnapshot,\n type TrackedChangeAttributes,\n type TrackedMark,\n} from \"../extensions/track-changes\";\nimport { createReviewId, type ReviewAuthor } from \"../extensions/comment-store\";\nimport { diffSequences } from \"./diff\";\n\n/** A document to compare: a ProseMirror node, its JSON, or HTML (needs a DOM). */\nexport type CompareSource = ProsemirrorNode | Record<string, any> | string;\n\nexport interface CompareDocumentsOptions {\n /** Schema of the documents. Required unless both sources are ProseMirror nodes. */\n schema?: Schema;\n /** Author recorded on every change. Default `{ id: \"compare\", name: \"Compare\" }`. */\n author?: ReviewAuthor;\n /** Time recorded on every change (`createdAt`). Default now. */\n date?: number | Date | string;\n /** Compare changed paragraphs word by word (default) or character by character. */\n granularity?: \"word\" | \"char\";\n /** Treat text differing only in case as equal (the revised text is kept). */\n ignoreCase?: boolean;\n /** Treat runs of white space as equal (the revised text is kept). */\n ignoreWhitespace?: boolean;\n /** Record formatting differences of equal text as `formatChange` marks. Default `true`. */\n formatting?: boolean;\n /** Change id generator. */\n generateId?: () => string;\n /** Marks not compared as formatting (in addition to review marks, comments and bookmarks). */\n ignoredMarks?: string[];\n /** Node attributes ignored when comparing blocks. Default `[\"id\"]`. */\n ignoredBlockAttributes?: string[];\n /**\n * Paragraphs longer than this (in characters) are compared by words even\n * at `granularity: \"char\"`. Default 2000.\n */\n maxCharDiff?: number;\n /**\n * Record a top-level paragraph that was deleted in one place and inserted,\n * identical, elsewhere as a tracked move (`type: \"move\"`) instead of a\n * whole-block deletion and insertion. Only paragraphs whose content occurs\n * once among the deleted and once among the inserted blocks are paired.\n * Default `false`.\n */\n detectMoves?: boolean;\n}\n\nexport interface CompareSummary {\n /** Inserted text runs and inserted block runs. */\n insertions: number;\n /** Deleted text runs and deleted block runs. */\n deletions: number;\n /** Formatting changes of equal text. */\n formatChanges: number;\n /** Block type, attribute and wrapping changes. */\n blockChanges: number;\n /** Moved paragraphs (with `detectMoves`). */\n moves: number;\n /** Differences the result could not represent as tracked changes. */\n notHonoured: string[];\n}\n\nexport interface CompareDocumentsResult {\n /**\n * The revised document with the differences as tracked changes: accepting\n * all changes yields the revised document, rejecting all the original.\n */\n doc: ProsemirrorNode;\n summary: CompareSummary;\n}\n\n/** Marks that are never compared as formatting. */\nconst REVIEW_MARK_NAMES = new Set([\n INSERTION_MARK_NAME,\n DELETION_MARK_NAME,\n FORMAT_CHANGE_MARK_NAME,\n \"comment\",\n \"bookmark\",\n]);\n\n/** Container types that pair with each other (a list whose type changed). */\nconst LIST_TYPES = new Set([\"bulletList\", \"orderedList\"]);\n\nconst OBJECT_REPLACEMENT = \"\";\n\ntype Wrapper = TrackedBlockSnapshot[\"wrappers\"][number];\n\ninterface Unit {\n /** One code point, or \"\" for an inline leaf node. */\n text: string;\n node: ProsemirrorNode | null;\n marks: readonly ProsemirrorMark[];\n}\n\ninterface Context {\n schema: Schema;\n author: ReviewAuthor;\n createdAt: number;\n generateId: () => string;\n granularity: \"word\" | \"char\";\n ignoreCase: boolean;\n ignoreWhitespace: boolean;\n formatting: boolean;\n maxCharDiff: number;\n ignoredMarks: Set<string>;\n ignoredAttributes: Set<string>;\n insertion?: MarkType;\n deletion?: MarkType;\n format?: MarkType;\n notes: Set<string>;\n keys: Map<ProsemirrorNode, string>;\n /** Shared change of the textblocks inside a container whose type changed. */\n wrapperChange: (() => TrackedChangeAttributes) | null;\n}\n\nfunction stableStringify(value: unknown): string {\n if (value === undefined) return \"null\";\n if (value === null || typeof value !== \"object\") return JSON.stringify(value);\n if (Array.isArray(value)) return `[${value.map(stableStringify).join(\",\")}]`;\n const keys = Object.keys(value as object).sort();\n return `{${keys\n .map((key) => `${JSON.stringify(key)}:${stableStringify((value as any)[key])}`)\n .join(\",\")}}`;\n}\n\nfunction toTime(date: CompareDocumentsOptions[\"date\"]): number {\n if (date instanceof Date) return date.getTime();\n if (typeof date === \"string\") {\n const time = Date.parse(date);\n return Number.isNaN(time) ? Date.now() : time;\n }\n return typeof date === \"number\" ? date : Date.now();\n}\n\nfunction toNode(source: CompareSource, schema: Schema): ProsemirrorNode {\n if (typeof source === \"string\") return createDocument(source, schema);\n if (typeof (source as ProsemirrorNode).descendants === \"function\") {\n const node = source as ProsemirrorNode;\n return node.type.schema === schema ? node : schema.nodeFromJSON(node.toJSON());\n }\n return schema.nodeFromJSON(source);\n}\n\nfunction newAttributes(ctx: Context): TrackedChangeAttributes {\n return {\n changeId: ctx.generateId(),\n authorId: ctx.author.id,\n authorName: ctx.author.name,\n authorColor: ctx.author.color ?? null,\n createdAt: ctx.createdAt,\n };\n}\n\n/** Lazily created attributes shared by one run of changes. */\nfunction lazyAttributes(ctx: Context): () => TrackedChangeAttributes {\n let attrs: TrackedChangeAttributes | null = null;\n return () => (attrs = attrs ?? newAttributes(ctx));\n}\n\nfunction stripBlockChange(attrs: Record<string, any>): Record<string, any> {\n const copy = { ...attrs };\n delete copy[BLOCK_CHANGE_ATTRIBUTE];\n return copy;\n}\n\nfunction wrapperOf(node: ProsemirrorNode): Wrapper {\n return { type: node.type.name, attrs: stripBlockChange(node.attrs) };\n}\n\nfunction snapshot(node: ProsemirrorNode, wrappers: Wrapper[]): TrackedBlockSnapshot {\n return { type: node.type.name, attrs: stripBlockChange(node.attrs), wrappers };\n}\n\nfunction filteredAttributes(attrs: Record<string, any>, ctx: Context): string {\n return stableStringify(\n Object.fromEntries(\n Object.entries(attrs ?? {}).filter(\n ([key]) => key !== BLOCK_CHANGE_ATTRIBUTE && !ctx.ignoredAttributes.has(key),\n ),\n ),\n );\n}\n\n/** Mirrors the tracker's block comparison: type, attributes and wrapper types. */\nfunction sameBlock(a: TrackedBlockSnapshot, b: TrackedBlockSnapshot, ctx: Context): boolean {\n if (a.type !== b.type) return false;\n if (filteredAttributes(a.attrs, ctx) !== filteredAttributes(b.attrs, ctx)) return false;\n if (a.wrappers.length !== b.wrappers.length) return false;\n return a.wrappers.every((w, i) => w.type === b.wrappers[i].type);\n}\n\nconst hasBlockChange = (node: ProsemirrorNode) =>\n !!node.type.spec.attrs && BLOCK_CHANGE_ATTRIBUTE in node.type.spec.attrs;\n\nconst label = (node: ProsemirrorNode) => node.type.name;\n\n// ---------------------------------------------------------------------------\n// Keys\n// ---------------------------------------------------------------------------\n\nfunction normalize(text: string, ctx: Context): string {\n let result = ctx.ignoreWhitespace ? text.replace(/\\s+/g, \" \") : text;\n if (ctx.ignoreCase) result = result.toLowerCase();\n return result;\n}\n\nfunction leafKey(node: ProsemirrorNode): string {\n return `${node.type.name}${stableStringify(stripBlockChange(node.attrs))}`;\n}\n\nfunction group(node: ProsemirrorNode): string {\n return LIST_TYPES.has(node.type.name) ? \"list\" : node.type.name;\n}\n\n/** Block key: textblocks by their (normalized) text only, so type changes pair up. */\nfunction blockKey(node: ProsemirrorNode, ctx: Context): string {\n const cached = ctx.keys.get(node);\n if (cached !== undefined) return cached;\n let key: string;\n if (node.isTextblock) {\n let text = \"\";\n node.forEach((child) => {\n text += child.isText ? child.text : `${OBJECT_REPLACEMENT}${leafKey(child)}${OBJECT_REPLACEMENT}`;\n });\n text = normalize(text, ctx);\n key = `T\\u0000${ctx.ignoreWhitespace ? text.trim() : text}`;\n } else if (node.isLeaf) {\n key = `A\\u0000${leafKey(node)}`;\n } else {\n const parts: string[] = [];\n node.forEach((child) => parts.push(blockKey(child, ctx)));\n key = `C\\u0000${group(node)}\\u0000${parts.join(\"\\u0001\")}\\u0002`;\n }\n ctx.keys.set(node, key);\n return key;\n}\n\nfunction compatible(a: ProsemirrorNode, b: ProsemirrorNode): boolean {\n if (a.isTextblock || b.isTextblock) return a.isTextblock && b.isTextblock;\n if (a.isLeaf || b.isLeaf) return a.isLeaf && b.isLeaf && a.type === b.type;\n return group(a) === group(b);\n}\n\n// ---------------------------------------------------------------------------\n// Whole blocks\n// ---------------------------------------------------------------------------\n\nfunction markInline(\n content: Fragment,\n mark: ProsemirrorMark,\n): Fragment {\n const nodes: ProsemirrorNode[] = [];\n content.forEach((child) => nodes.push(child.mark(mark.addToSet(child.marks))));\n return Fragment.from(nodes);\n}\n\n/**\n * A block deleted or inserted as a whole: every textblock inside gets a\n * `blockChange` record with the operation (one change id per run).\n */\nfunction wholeBlock(\n node: ProsemirrorNode,\n operation: TrackedBlockOperation,\n wrappers: Wrapper[],\n attrs: () => TrackedChangeAttributes,\n ctx: Context,\n): ProsemirrorNode[] {\n const verb = operation === \"insert\" ? \"Inserted\" : \"Deleted\";\n if (node.isTextblock) {\n if (hasBlockChange(node)) {\n const record: TrackedBlockChangeAttributes = {\n ...attrs(),\n previous: snapshot(node, wrappers),\n operation,\n };\n return [node.type.create({ ...node.attrs, [BLOCK_CHANGE_ATTRIBUTE]: record }, node.content, node.marks)];\n }\n // No block record: fall back to marking the text.\n const markType = operation === \"insert\" ? ctx.insertion : ctx.deletion;\n if (markType && node.type.allowsMarkType(markType) && node.content.size > 0) {\n ctx.notes.add(\n `${verb} ${label(node)} blocks have no \"${BLOCK_CHANGE_ATTRIBUTE}\" attribute: only their text is tracked, so an empty block remains when the change is ${operation === \"insert\" ? \"rejected\" : \"accepted\"}.`,\n );\n return [node.type.create(node.attrs, markInline(node.content, markType.create(attrs())), node.marks)];\n }\n ctx.notes.add(`${verb} ${label(node)} blocks cannot be tracked.`);\n return operation === \"insert\" ? [node] : [];\n }\n if (node.isLeaf) {\n ctx.notes.add(`${verb} ${label(node)} blocks cannot be tracked.`);\n return operation === \"insert\" ? [node] : [];\n }\n const inner = [...wrappers, wrapperOf(node)];\n const children: ProsemirrorNode[] = [];\n node.forEach((child) => children.push(...wholeBlock(child, operation, inner, attrs, ctx)));\n try {\n return [node.type.createChecked(node.attrs, children, node.marks)];\n } catch {\n ctx.notes.add(`${verb} ${label(node)} blocks cannot be tracked.`);\n return operation === \"insert\" ? [node] : [];\n }\n}\n\n// ---------------------------------------------------------------------------\n// Inline comparison\n// ---------------------------------------------------------------------------\n\nfunction units(node: ProsemirrorNode): Unit[] {\n const result: Unit[] = [];\n node.forEach((child) => {\n if (child.isText) {\n for (const ch of child.text ?? \"\") result.push({ text: ch, node: null, marks: child.marks });\n } else {\n result.push({ text: \"\", node: child, marks: child.marks });\n }\n });\n return result;\n}\n\nconst SPACE = /\\s/u;\nconst WORD = /[\\p{L}\\p{N}\\p{M}_]/u;\n\nconst isSpace = (u: Unit) => !u.node && SPACE.test(u.text);\nconst isWord = (u: Unit) => !u.node && WORD.test(u.text);\n\n/** Token ranges: words, white space runs and single symbols, or characters. */\nfunction tokenize(list: Unit[], chars: boolean): [number, number][] {\n const tokens: [number, number][] = [];\n if (chars) {\n for (let i = 0; i < list.length; i++) tokens.push([i, i + 1]);\n return tokens;\n }\n let i = 0;\n while (i < list.length) {\n const start = i;\n const unit = list[i];\n if (isSpace(unit)) {\n while (i < list.length && isSpace(list[i])) i++;\n } else if (isWord(unit)) {\n while (i < list.length && isWord(list[i])) i++;\n } else {\n i++;\n }\n tokens.push([start, i]);\n }\n return tokens;\n}\n\ntype Stretch =\n | { type: \"equal\"; aIndex: number; bIndex: number; length: number }\n | { type: \"change\"; aFrom: number; aTo: number; bFrom: number; bTo: number };\n\n/**\n * Groups token runs into equal stretches and changes. White space alone\n * between two changes joins them, so \"a b\" → \"x y\" reads as one\n * replacement instead of alternating deletions and insertions.\n */\nfunction stretches(runs: ReturnType<typeof diffSequences>, list: Unit[], tokens: [number, number][]): Stretch[] {\n const spaceOnly = (bIndex: number, length: number) => {\n for (let t = bIndex; t < bIndex + length; t++) {\n const [from, to] = tokens[t];\n for (let k = from; k < to; k++) if (!isSpace(list[k])) return false;\n }\n return true;\n };\n const result: Stretch[] = [];\n runs.forEach((run, index) => {\n const prev = runs[index - 1];\n const next = runs[index + 1];\n const absorbed =\n run.type === \"equal\" &&\n prev &&\n next &&\n prev.type !== \"equal\" &&\n next.type !== \"equal\" &&\n spaceOnly(run.bIndex, run.length);\n if (run.type === \"equal\" && !absorbed) {\n result.push({ type: \"equal\", aIndex: run.aIndex, bIndex: run.bIndex, length: run.length });\n return;\n }\n let last = result[result.length - 1];\n if (!last || last.type !== \"change\") {\n last = { type: \"change\", aFrom: run.aIndex, aTo: run.aIndex, bFrom: run.bIndex, bTo: run.bIndex };\n result.push(last);\n }\n if (run.type !== \"insert\") last.aTo = run.aIndex + run.length;\n if (run.type !== \"delete\") last.bTo = run.bIndex + run.length;\n });\n return result;\n}\n\nfunction tokenKey(list: Unit[], [from, to]: [number, number], ctx: Context): string {\n let text = \"\";\n for (let i = from; i < to; i++) {\n const unit = list[i];\n text += unit.node ? `${OBJECT_REPLACEMENT}${leafKey(unit.node)}${OBJECT_REPLACEMENT}` : unit.text;\n }\n return normalize(text, ctx);\n}\n\nfunction formattingOf(marks: readonly ProsemirrorMark[], ctx: Context): ProsemirrorMark[] {\n return marks.filter(\n (mark) => !REVIEW_MARK_NAMES.has(mark.type.name) && !ctx.ignoredMarks.has(mark.type.name),\n );\n}\n\nfunction withoutReviewMarks(marks: readonly ProsemirrorMark[]): readonly ProsemirrorMark[] {\n return marks.filter(\n (mark) =>\n mark.type.name !== INSERTION_MARK_NAME &&\n mark.type.name !== DELETION_MARK_NAME &&\n mark.type.name !== FORMAT_CHANGE_MARK_NAME,\n );\n}\n\n/**\n * Merges the inline content of two paired textblocks: equal tokens keep the\n * revised text (with `formatChange` where formatting differs), deleted\n * tokens are re-inserted with the `deletion` mark before inserted tokens.\n */\nfunction mergeInline(\n original: ProsemirrorNode,\n revised: ProsemirrorNode,\n parentType: ProsemirrorNode[\"type\"],\n ctx: Context,\n): Fragment {\n const a = units(original);\n const b = units(revised);\n let chars = ctx.granularity === \"char\";\n if (chars && Math.max(a.length, b.length) > ctx.maxCharDiff) {\n chars = false;\n ctx.notes.add(\n `Paragraphs longer than ${ctx.maxCharDiff} characters were compared by words instead of characters.`,\n );\n }\n const ta = tokenize(a, chars);\n const tb = tokenize(b, chars);\n const runs = diffSequences(\n ta.map((t) => tokenKey(a, t, ctx)),\n tb.map((t) => tokenKey(b, t, ctx)),\n );\n\n const format = ctx.formatting && ctx.format && parentType.allowsMarkType(ctx.format) ? ctx.format : null;\n const out: Unit[] = [];\n let formatRun: { attrs: TrackedChangeAttributes; key: string } | null = null;\n\n const emit = (\n source: Unit[],\n tokens: [number, number][],\n from: number,\n to: number,\n markType: MarkType,\n ) => {\n if (to <= from) return;\n const mark = markType.create(newAttributes(ctx));\n for (let k = tokens[from][0]; k < tokens[to - 1][1]; k++) {\n const unit = source[k];\n out.push({ ...unit, marks: mark.addToSet(withoutReviewMarks(unit.marks)) });\n }\n };\n\n for (const run of stretches(runs, b, tb)) {\n if (run.type === \"equal\") {\n for (let t = 0; t < run.length; t++) {\n const [aFrom, aTo] = ta[run.aIndex + t];\n const [bFrom, bTo] = tb[run.bIndex + t];\n for (let k = bFrom; k < bTo; k++) {\n const unit = b[k];\n const before = a[Math.min(aFrom + (k - bFrom), aTo - 1)];\n const marks = withoutReviewMarks(unit.marks);\n if (!format) {\n formatRun = null;\n out.push({ ...unit, marks });\n continue;\n }\n const oldFormat = formattingOf(before.marks, ctx);\n const newFormat = formattingOf(unit.marks, ctx);\n if (ProsemirrorMark.sameSet(oldFormat, newFormat)) {\n formatRun = null;\n out.push({ ...unit, marks });\n continue;\n }\n const beforeJSON = oldFormat.map((m) => m.toJSON() as TrackedMark);\n const afterJSON = newFormat.map((m) => m.toJSON() as TrackedMark);\n const key = stableStringify([beforeJSON, afterJSON]);\n if (!formatRun || formatRun.key !== key) formatRun = { attrs: newAttributes(ctx), key };\n const mark = format.create({ ...formatRun.attrs, before: beforeJSON, after: afterJSON });\n out.push({ ...unit, marks: mark.addToSet(marks) });\n }\n }\n continue;\n }\n formatRun = null;\n emit(a, ta, run.aFrom, run.aTo, ctx.deletion!);\n emit(b, tb, run.bFrom, run.bTo, ctx.insertion!);\n }\n\n const nodes: ProsemirrorNode[] = [];\n let i = 0;\n while (i < out.length) {\n const unit = out[i];\n if (unit.node) {\n nodes.push(unit.node.mark(unit.marks));\n i++;\n continue;\n }\n let text = unit.text;\n let j = i + 1;\n while (j < out.length && !out[j].node && ProsemirrorMark.sameSet(out[j].marks, unit.marks)) {\n text += out[j].text;\n j++;\n }\n nodes.push(ctx.schema.text(text, unit.marks));\n i = j;\n }\n return Fragment.from(nodes);\n}\n\n// ---------------------------------------------------------------------------\n// Blocks\n// ---------------------------------------------------------------------------\n\nfunction mergeTextblocks(\n original: ProsemirrorNode,\n revised: ProsemirrorNode,\n oPath: Wrapper[],\n rPath: Wrapper[],\n ctx: Context,\n): ProsemirrorNode[] {\n const replaceWhole = () => [\n ...wholeBlock(original, \"delete\", rPath, lazyAttributes(ctx), ctx),\n ...wholeBlock(revised, \"insert\", rPath, lazyAttributes(ctx), ctx),\n ];\n\n let attrs: Record<string, any> = { ...revised.attrs };\n const previous = snapshot(original, oPath);\n if (!sameBlock(previous, snapshot(revised, rPath), ctx)) {\n if (hasBlockChange(revised)) {\n // Only the wrappers changed (e.g. bulleted → numbered list): one change per container.\n const onlyWrappers =\n ctx.wrapperChange &&\n sameBlock(previous, { ...snapshot(revised, rPath), wrappers: previous.wrappers }, ctx);\n const base = onlyWrappers ? ctx.wrapperChange!() : newAttributes(ctx);\n attrs = { ...attrs, [BLOCK_CHANGE_ATTRIBUTE]: { ...base, previous } };\n } else {\n ctx.notes.add(`Block changes to ${label(revised)} blocks cannot be tracked.`);\n }\n } else if (BLOCK_CHANGE_ATTRIBUTE in attrs) {\n attrs[BLOCK_CHANGE_ATTRIBUTE] = null;\n }\n\n const type = revised.type;\n const inlineTracking =\n !!ctx.insertion &&\n !!ctx.deletion &&\n type.allowsMarkType(ctx.insertion) &&\n type.allowsMarkType(ctx.deletion);\n if (!inlineTracking) {\n // e.g. code blocks in a headless schema: equal text keeps the block,\n // anything else is replaced whole.\n if (!original.content.eq(revised.content)) return replaceWhole();\n return [type.create(attrs, revised.content, revised.marks)];\n }\n const content = mergeInline(original, revised, type, ctx);\n if (!type.validContent(content)) {\n ctx.notes.add(`Changes between ${label(original)} and ${label(revised)} blocks were tracked as whole-block replacements.`);\n return replaceWhole();\n }\n return [type.create(attrs, content, revised.marks)];\n}\n\nfunction mergePair(\n original: ProsemirrorNode,\n revised: ProsemirrorNode,\n oPath: Wrapper[],\n rPath: Wrapper[],\n ctx: Context,\n): ProsemirrorNode[] {\n if (original.isTextblock) return mergeTextblocks(original, revised, oPath, rPath, ctx);\n const replaceWhole = () => [\n ...wholeBlock(original, \"delete\", rPath, lazyAttributes(ctx), ctx),\n ...wholeBlock(revised, \"insert\", rPath, lazyAttributes(ctx), ctx),\n ];\n if (original.isLeaf) {\n return original.eq(revised) ? [revised] : replaceWhole();\n }\n if (\n original.type === revised.type &&\n filteredAttributes(original.attrs, ctx) !== filteredAttributes(revised.attrs, ctx)\n ) {\n ctx.notes.add(`Attribute changes of ${label(revised)} nodes are not tracked.`);\n }\n const outer = ctx.wrapperChange;\n if (original.type !== revised.type) ctx.wrapperChange = lazyAttributes(ctx);\n let children: ProsemirrorNode[];\n try {\n children = compareChildren(\n original,\n revised,\n [...oPath, wrapperOf(original)],\n [...rPath, wrapperOf(revised)],\n ctx,\n );\n } finally {\n ctx.wrapperChange = outer;\n }\n try {\n return [revised.type.createChecked(revised.attrs, children, revised.marks)];\n } catch {\n ctx.notes.add(`Changes inside ${label(revised)} nodes were tracked as whole-block replacements.`);\n return replaceWhole();\n }\n}\n\nfunction compareChildren(\n original: ProsemirrorNode,\n revised: ProsemirrorNode,\n oPath: Wrapper[],\n rPath: Wrapper[],\n ctx: Context,\n): ProsemirrorNode[] {\n const a: ProsemirrorNode[] = [];\n const b: ProsemirrorNode[] = [];\n original.forEach((child) => a.push(child));\n revised.forEach((child) => b.push(child));\n const runs = diffSequences(a, b, { hash: (node) => blockKey(node, ctx) });\n const out: ProsemirrorNode[] = [];\n\n for (let r = 0; r < runs.length; r++) {\n const run = runs[r];\n if (run.type === \"equal\") {\n for (let t = 0; t < run.length; t++) {\n out.push(...mergePair(a[run.aIndex + t], b[run.bIndex + t], oPath, rPath, ctx));\n }\n continue;\n }\n // A run of deletions and insertions: the i-th deleted block pairs with\n // the i-th inserted one when they are alike; the rest are whole.\n let dels: ProsemirrorNode[] = [];\n let inss: ProsemirrorNode[] = [];\n if (run.type === \"delete\") {\n dels = a.slice(run.aIndex, run.aIndex + run.length);\n const next = runs[r + 1];\n if (next?.type === \"insert\") {\n inss = b.slice(next.bIndex, next.bIndex + next.length);\n r++;\n }\n } else {\n inss = b.slice(run.bIndex, run.bIndex + run.length);\n }\n const deleted = lazyAttributes(ctx);\n const inserted = lazyAttributes(ctx);\n for (let x = 0; x < Math.max(dels.length, inss.length); x++) {\n const del = dels[x];\n const ins = inss[x];\n if (del && ins && compatible(del, ins)) {\n out.push(...mergePair(del, ins, oPath, rPath, ctx));\n continue;\n }\n if (del) out.push(...wholeBlock(del, \"delete\", rPath, deleted, ctx));\n if (ins) out.push(...wholeBlock(ins, \"insert\", rPath, inserted, ctx));\n }\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Moves\n// ---------------------------------------------------------------------------\n\n/**\n * Pairs top-level paragraphs deleted as a whole with identical paragraphs\n * inserted as a whole elsewhere, and records each pair as a move: the\n * source's text gets the deletion mark and the destination's the insertion\n * mark, both with the same move id (accepting or rejecting removes the\n * emptied block). Ambiguous content (several identical candidates) is left\n * as whole-block changes.\n */\nfunction detectMovedBlocks(children: ProsemirrorNode[], ctx: Context): ProsemirrorNode[] {\n const keyOf = (node: ProsemirrorNode) =>\n `${node.type.name}\\u0000${filteredAttributes(node.attrs, ctx)}\\u0000${stableStringify(node.content.toJSON())}`;\n const candidates = new Map<string, { del: number[]; ins: number[] }>();\n children.forEach((node, index) => {\n const operation = (node.attrs?.[BLOCK_CHANGE_ATTRIBUTE] as TrackedBlockChangeAttributes | null)\n ?.operation;\n if (!operation || !node.isTextblock || !node.textContent.trim()) return;\n if (!node.type.allowsMarkType(ctx.insertion!) || !node.type.allowsMarkType(ctx.deletion!)) return;\n const key = keyOf(node);\n const entry = candidates.get(key) ?? { del: [], ins: [] };\n (operation === \"delete\" ? entry.del : entry.ins).push(index);\n candidates.set(key, entry);\n });\n const out = [...children];\n candidates.forEach(({ del, ins }) => {\n if (del.length !== 1 || ins.length !== 1) return;\n const attrs = newAttributes(ctx);\n const moved = { ...attrs, [MOVE_ID_ATTRIBUTE]: attrs.changeId };\n const relink = (index: number, markType: MarkType) => {\n const node = out[index];\n out[index] = node.type.create(\n { ...node.attrs, [BLOCK_CHANGE_ATTRIBUTE]: null },\n markInline(node.content, markType.create(moved)),\n node.marks,\n );\n };\n relink(del[0], ctx.deletion!);\n relink(ins[0], ctx.insertion!);\n });\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nfunction summarize(doc: ProsemirrorNode, notes: Set<string>): CompareSummary {\n const summary: CompareSummary = {\n insertions: 0,\n deletions: 0,\n formatChanges: 0,\n blockChanges: 0,\n moves: 0,\n notHonoured: [...notes],\n };\n getTrackedChanges(doc).forEach((change) => {\n if (change.type === \"move\") summary.moves++;\n else if (change.type === \"insertion\" || change.block?.operation === \"insert\") summary.insertions++;\n else if (change.type === \"deletion\" || change.block?.operation === \"delete\") summary.deletions++;\n else if (change.type === \"format\") summary.formatChanges++;\n else summary.blockChanges++;\n });\n return summary;\n}\n\n/**\n * Compares two documents and returns the revised document with the\n * differences as tracked changes (`insertion`/`deletion`/`formatChange`\n * marks and `blockChange` records), plus a summary.\n *\n * Blocks are matched by their text (Myers diff with patience anchors); in a\n * run of changed blocks the i-th deleted block is paired with the i-th\n * inserted one and compared word by word (or by character), while unpaired\n * blocks are recorded as whole-block insertions/deletions. Equal text is\n * compared for formatting, and type/attribute/wrapping changes become\n * `blockChange` records. Without ignore options, accepting all changes\n * yields the revised document and rejecting all yields the original.\n *\n * The schema needs the `TrackChanges` extension (marks and the\n * `blockChange` attribute). Existing tracked changes in either document are\n * accepted first.\n */\nexport function compareDocuments(\n original: CompareSource,\n revised: CompareSource,\n options: CompareDocumentsOptions = {},\n): CompareDocumentsResult {\n const schema =\n options.schema ??\n (typeof (original as ProsemirrorNode)?.descendants === \"function\"\n ? (original as ProsemirrorNode).type.schema\n : typeof (revised as ProsemirrorNode)?.descendants === \"function\"\n ? (revised as ProsemirrorNode).type.schema\n : null);\n if (!schema) throw new Error(\"compareDocuments: `schema` is required for JSON or HTML sources.\");\n\n const ctx: Context = {\n schema,\n author: options.author ?? { id: \"compare\", name: \"Compare\" },\n createdAt: toTime(options.date),\n generateId: options.generateId ?? (() => createReviewId(\"change\")),\n granularity: options.granularity ?? \"word\",\n ignoreCase: !!options.ignoreCase,\n ignoreWhitespace: !!options.ignoreWhitespace,\n formatting: options.formatting !== false,\n maxCharDiff: options.maxCharDiff ?? 2000,\n ignoredMarks: new Set(options.ignoredMarks ?? []),\n ignoredAttributes: new Set(options.ignoredBlockAttributes ?? [\"id\"]),\n insertion: schema.marks[INSERTION_MARK_NAME],\n deletion: schema.marks[DELETION_MARK_NAME],\n format: schema.marks[FORMAT_CHANGE_MARK_NAME],\n notes: new Set(),\n keys: new Map(),\n wrapperChange: null,\n };\n if (!ctx.insertion || !ctx.deletion) {\n throw new Error(\"compareDocuments: the schema needs the TrackChanges extension (insertion/deletion marks).\");\n }\n if (ctx.formatting && !ctx.format) {\n ctx.notes.add(\"Formatting differences cannot be tracked: the schema has no formatChange mark.\");\n }\n\n const prepare = (source: CompareSource) => {\n const doc = toNode(source, schema);\n if (getTrackedChanges(doc).length === 0) return doc;\n ctx.notes.add(\"Tracked changes already in the documents were accepted before comparing.\");\n return resolveTrackedChanges(doc, \"accepted\");\n };\n const a = prepare(original);\n const b = prepare(revised);\n\n let children = compareChildren(a, b, [], [], ctx);\n if (options.detectMoves) children = detectMovedBlocks(children, ctx);\n let doc: ProsemirrorNode;\n try {\n doc = b.type.createChecked(b.attrs, children, b.marks);\n } catch {\n doc = b.type.createAndFill(b.attrs, children, b.marks) ?? b;\n ctx.notes.add(\"The compared document had to be repaired to fit the schema.\");\n }\n return { doc, summary: summarize(doc, ctx.notes) };\n}\n\n/** `compareDocuments` for two HTML strings (needs a DOM, like `setContent`). */\nexport function compareHtml(\n originalHtml: string,\n revisedHtml: string,\n options: CompareDocumentsOptions & { schema: Schema },\n): CompareDocumentsResult {\n return compareDocuments(originalHtml, revisedHtml, options);\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/editor/editor/packages/core/dist/chunk-CS6NZWWA.cjs","../src/compare/diff.ts","../src/compare/documents.ts"],"names":["x","y","k","i","j"],"mappings":"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","file":"/home/runner/work/editor/editor/packages/core/dist/chunk-CS6NZWWA.cjs","sourcesContent":[null,"// Portions ported from pdfcraft/crates/compare/src/lib.rs (MIT OR Apache-2.0, © ArtCraft Team and contributors). See THIRD_PARTY_NOTICES.md.\n\n/**\n * Generic sequence diff: common prefix/suffix stripping, Myers' O((N+M)·D)\n * algorithm for small segments and patience anchors (items unique on both\n * sides, longest increasing subsequence) to split long ones. Dependency-free.\n */\n\nexport type DiffOpType = \"equal\" | \"delete\" | \"insert\";\n\n/** A run of consecutive operations of one type. */\nexport interface DiffRun {\n type: DiffOpType;\n /** Start index in `a` (for `insert`, where the items go in `a`). */\n aIndex: number;\n /** Start index in `b` (for `delete`, where the items were in `b`). */\n bIndex: number;\n length: number;\n}\n\n/** A change: a deleted range of `a`, an inserted range of `b`, or both (replaced). */\nexport interface DiffChange {\n kind: \"inserted\" | \"deleted\" | \"replaced\";\n aStart: number;\n aEnd: number;\n bStart: number;\n bEnd: number;\n}\n\nexport interface DiffSequencesOptions<T> {\n /**\n * Key of an item: items with the same key are equal. Defaults to the item\n * itself for strings, numbers and booleans, and `JSON.stringify` otherwise.\n * Keys enable patience anchors for long inputs.\n */\n hash?: (item: T) => string | number | boolean;\n /**\n * Custom equality. Without `hash`, segments longer than `direct` are only\n * diffed while the edit distance stays below `direct`, otherwise replaced.\n */\n equals?: (a: T, b: T) => boolean;\n /**\n * Segments with more items (both sides together) are split at anchors\n * first so Myers' saved frontiers (O(D²) memory) stay small. Default 3000.\n */\n direct?: number;\n /** Maximum anchor recursion depth before a long segment is replaced whole. Default 8. */\n maxDepth?: number;\n}\n\nconst EQUAL = 0;\nconst DELETE = 1;\nconst INSERT = 2;\n\ntype Eq = (i: number, j: number) => boolean;\n\nfunction pushRepeat(out: number[], op: number, count: number): void {\n for (let i = 0; i < count; i++) out.push(op);\n}\n\n/**\n * Myers' diff of a[aLo..aHi) and b[bLo..bHi). Returns false (and emits\n * nothing) when the edit distance exceeds `maxD`.\n */\nfunction myers(\n aLo: number,\n aHi: number,\n bLo: number,\n bHi: number,\n eq: Eq,\n out: number[],\n maxD: number,\n): boolean {\n const n = aHi - aLo;\n const m = bHi - bLo;\n if (n === 0 || m === 0) {\n pushRepeat(out, DELETE, n);\n pushRepeat(out, INSERT, m);\n return true;\n }\n const max = n + m;\n const off = max + 1;\n const v = new Int32Array(2 * max + 3);\n // Frontier d only spans diagonals -d..d: save just that slice.\n const trace: Int32Array[] = [];\n const limit = Math.min(max, maxD);\n let found = false;\n outer: for (let d = 0; d <= limit; d++) {\n trace.push(v.slice(Math.max(off - d - 1, 0), off + d + 2));\n for (let k = -d; k <= d; k += 2) {\n const i = k + off;\n let x = k === -d || (k !== d && v[i - 1] < v[i + 1]) ? v[i + 1] : v[i - 1] + 1;\n let y = x - k;\n while (x < n && y < m && eq(aLo + x, bLo + y)) {\n x++;\n y++;\n }\n v[i] = x;\n if (x >= n && y >= m) {\n found = true;\n break outer;\n }\n }\n }\n if (!found) return false;\n\n // Walk back through the saved frontiers.\n const ops: number[] = [];\n let x = n;\n let y = m;\n for (let d = trace.length - 1; d >= 0; d--) {\n const frontier = trace[d];\n const base = Math.max(off - d - 1, 0);\n const at = (k: number) => frontier[k + off - base];\n const k = x - y;\n const prevK = k === -d || (k !== d && at(k - 1) < at(k + 1)) ? k + 1 : k - 1;\n const prevX = at(prevK);\n const prevY = prevX - prevK;\n while (x > prevX && y > prevY) {\n ops.push(EQUAL);\n x--;\n y--;\n }\n if (d > 0) ops.push(x === prevX ? INSERT : DELETE);\n x = prevX;\n y = prevY;\n }\n for (let i = ops.length - 1; i >= 0; i--) out.push(ops[i]);\n return true;\n}\n\n/**\n * Patience anchors: items that occur once on each side, in an order both\n * sides agree on (the longest increasing subsequence of their positions).\n */\nfunction anchors(\n ids: { a: Int32Array; b: Int32Array },\n aLo: number,\n aHi: number,\n bLo: number,\n bHi: number,\n): [number, number][] {\n const count = new Map<number, [number, number, number, number]>();\n for (let i = aLo; i < aHi; i++) {\n const id = ids.a[i];\n const entry = count.get(id);\n if (entry) {\n entry[0]++;\n } else {\n count.set(id, [1, 0, i, -1]);\n }\n }\n for (let j = bLo; j < bHi; j++) {\n const entry = count.get(ids.b[j]);\n if (entry) {\n entry[1]++;\n entry[3] = j;\n }\n }\n const pairs: [number, number][] = [];\n count.forEach((entry) => {\n if (entry[0] === 1 && entry[1] === 1) pairs.push([entry[2], entry[3]]);\n });\n pairs.sort((p, q) => p[0] - q[0]);\n // LIS on the b positions (patience sorting with back links).\n const tails: number[] = [];\n const prev = new Int32Array(pairs.length).fill(-1);\n for (let k = 0; k < pairs.length; k++) {\n const y = pairs[k][1];\n let lo = 0;\n let hi = tails.length;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (pairs[tails[mid]][1] < y) lo = mid + 1;\n else hi = mid;\n }\n if (lo > 0) prev[k] = tails[lo - 1];\n if (lo === tails.length) tails.push(k);\n else tails[lo] = k;\n }\n const result: [number, number][] = [];\n let k = tails.length ? tails[tails.length - 1] : -1;\n while (k !== -1) {\n result.push(pairs[k]);\n k = prev[k];\n }\n return result.reverse();\n}\n\ninterface DiffContext {\n eq: Eq;\n ids: { a: Int32Array; b: Int32Array } | null;\n direct: number;\n maxDepth: number;\n}\n\nfunction diffRange(\n ctx: DiffContext,\n aLo: number,\n aHi: number,\n bLo: number,\n bHi: number,\n out: number[],\n depth: number,\n): void {\n const { eq } = ctx;\n let prefix = 0;\n while (aLo + prefix < aHi && bLo + prefix < bHi && eq(aLo + prefix, bLo + prefix)) prefix++;\n let suffix = 0;\n while (\n aHi - suffix > aLo + prefix &&\n bHi - suffix > bLo + prefix &&\n eq(aHi - suffix - 1, bHi - suffix - 1)\n ) {\n suffix++;\n }\n pushRepeat(out, EQUAL, prefix);\n const ma = aLo + prefix;\n const mb = bLo + prefix;\n const ea = aHi - suffix;\n const eb = bHi - suffix;\n const replace = () => {\n pushRepeat(out, DELETE, ea - ma);\n pushRepeat(out, INSERT, eb - mb);\n };\n\n if (ea - ma + (eb - mb) <= ctx.direct) {\n myers(ma, ea, mb, eb, eq, out, Infinity);\n } else if (!ctx.ids) {\n // No keys, so no anchors: bounded Myers, else one replacement.\n if (!myers(ma, ea, mb, eb, eq, out, ctx.direct)) replace();\n } else {\n const found = depth >= ctx.maxDepth ? [] : anchors(ctx.ids, ma, ea, mb, eb);\n if (found.length === 0) {\n // A long stretch with nothing unique in common: one replacement.\n replace();\n } else {\n let i = ma;\n let j = mb;\n for (const [x, y] of found) {\n diffRange(ctx, i, x, j, y, out, depth + 1);\n out.push(EQUAL);\n i = x + 1;\n j = y + 1;\n }\n diffRange(ctx, i, ea, j, eb, out, depth + 1);\n }\n }\n pushRepeat(out, EQUAL, suffix);\n}\n\nconst defaultHash = (item: unknown): string | number | boolean =>\n typeof item === \"string\" || typeof item === \"number\" || typeof item === \"boolean\"\n ? item\n : JSON.stringify(item);\n\n/**\n * Diffs two sequences and returns the edit script as runs of equal, deleted\n * and inserted items, in order. Within a changed stretch deletions come\n * before insertions. The script is minimal for segments up to `direct`\n * items; longer inputs are split at patience anchors (bounded work).\n */\nexport function diffSequences<T>(\n a: readonly T[],\n b: readonly T[],\n options: DiffSequencesOptions<T> = {},\n): DiffRun[] {\n const direct = Math.max(2, options.direct ?? 3000);\n const maxDepth = options.maxDepth ?? 8;\n let ids: { a: Int32Array; b: Int32Array } | null = null;\n let eq: Eq;\n if (options.equals && !options.hash) {\n const equals = options.equals;\n eq = (i, j) => equals(a[i], b[j]);\n } else {\n const hash = options.hash ?? (defaultHash as (item: T) => string | number | boolean);\n const table = new Map<string | number | boolean, number>();\n const idOf = (item: T) => {\n const key = hash(item);\n let id = table.get(key);\n if (id === undefined) {\n id = table.size;\n table.set(key, id);\n }\n return id;\n };\n ids = { a: Int32Array.from(a, idOf), b: Int32Array.from(b, idOf) };\n const { a: ia, b: ib } = ids;\n eq = (i, j) => ia[i] === ib[j];\n }\n\n const ops: number[] = [];\n diffRange({ eq, ids, direct, maxDepth }, 0, a.length, 0, b.length, ops, 0);\n\n // Group into runs, deletions first within each changed stretch.\n const runs: DiffRun[] = [];\n const push = (type: DiffOpType, aIndex: number, bIndex: number, length: number) => {\n if (length === 0) return;\n const last = runs[runs.length - 1];\n if (last && last.type === type) {\n last.length += length;\n } else {\n runs.push({ type, aIndex, bIndex, length });\n }\n };\n let i = 0;\n let j = 0;\n let k = 0;\n while (k < ops.length) {\n if (ops[k] === EQUAL) {\n let n = 0;\n while (k < ops.length && ops[k] === EQUAL) {\n n++;\n k++;\n }\n push(\"equal\", i, j, n);\n i += n;\n j += n;\n continue;\n }\n let dels = 0;\n let inss = 0;\n while (k < ops.length && ops[k] !== EQUAL) {\n if (ops[k] === DELETE) dels++;\n else inss++;\n k++;\n }\n push(\"delete\", i, j, dels);\n push(\"insert\", i + dels, j, inss);\n i += dels;\n j += inss;\n }\n return runs;\n}\n\n/** Groups an edit script into inserted, deleted and replaced ranges. */\nexport function diffChanges<T>(\n a: readonly T[],\n b: readonly T[],\n options: DiffSequencesOptions<T> = {},\n): DiffChange[] {\n const changes: DiffChange[] = [];\n let current: DiffChange | null = null;\n for (const run of diffSequences(a, b, options)) {\n if (run.type === \"equal\") {\n current = null;\n continue;\n }\n if (!current) {\n current = {\n kind: run.type === \"delete\" ? \"deleted\" : \"inserted\",\n aStart: run.aIndex,\n aEnd: run.aIndex,\n bStart: run.bIndex,\n bEnd: run.bIndex,\n };\n changes.push(current);\n }\n if (run.type === \"delete\") {\n current.aEnd = run.aIndex + run.length;\n } else {\n current.bEnd = run.bIndex + run.length;\n }\n if (current.aEnd > current.aStart && current.bEnd > current.bStart) current.kind = \"replaced\";\n }\n return changes;\n}\n","// Portions ported from wordcraft/crates/engine/src/cmd/tools.rs (MIT OR Apache-2.0, © ArtCraft Team and contributors). See THIRD_PARTY_NOTICES.md.\n\nimport { createDocument } from \"@tiptap/core\";\nimport {\n Fragment,\n Mark as ProsemirrorMark,\n type MarkType,\n type Node as ProsemirrorNode,\n type Schema,\n} from \"@tiptap/pm/model\";\nimport {\n BLOCK_CHANGE_ATTRIBUTE,\n DELETION_MARK_NAME,\n FORMAT_CHANGE_MARK_NAME,\n INSERTION_MARK_NAME,\n MOVE_ID_ATTRIBUTE,\n getTrackedChanges,\n resolveTrackedChanges,\n type TrackedBlockChangeAttributes,\n type TrackedBlockOperation,\n type TrackedBlockSnapshot,\n type TrackedChangeAttributes,\n type TrackedMark,\n} from \"../extensions/track-changes\";\nimport { createReviewId, type ReviewAuthor } from \"../extensions/comment-store\";\nimport { diffSequences } from \"./diff\";\n\n/** A document to compare: a ProseMirror node, its JSON, or HTML (needs a DOM). */\nexport type CompareSource = ProsemirrorNode | Record<string, any> | string;\n\nexport interface CompareDocumentsOptions {\n /** Schema of the documents. Required unless both sources are ProseMirror nodes. */\n schema?: Schema;\n /** Author recorded on every change. Default `{ id: \"compare\", name: \"Compare\" }`. */\n author?: ReviewAuthor;\n /** Time recorded on every change (`createdAt`). Default now. */\n date?: number | Date | string;\n /** Compare changed paragraphs word by word (default) or character by character. */\n granularity?: \"word\" | \"char\";\n /** Treat text differing only in case as equal (the revised text is kept). */\n ignoreCase?: boolean;\n /** Treat runs of white space as equal (the revised text is kept). */\n ignoreWhitespace?: boolean;\n /** Record formatting differences of equal text as `formatChange` marks. Default `true`. */\n formatting?: boolean;\n /** Change id generator. */\n generateId?: () => string;\n /** Marks not compared as formatting (in addition to review marks, comments and bookmarks). */\n ignoredMarks?: string[];\n /** Node attributes ignored when comparing blocks. Default `[\"id\"]`. */\n ignoredBlockAttributes?: string[];\n /**\n * Paragraphs longer than this (in characters) are compared by words even\n * at `granularity: \"char\"`. Default 2000.\n */\n maxCharDiff?: number;\n /**\n * Record a top-level paragraph that was deleted in one place and inserted,\n * identical, elsewhere as a tracked move (`type: \"move\"`) instead of a\n * whole-block deletion and insertion. Only paragraphs whose content occurs\n * once among the deleted and once among the inserted blocks are paired.\n * Default `false`.\n */\n detectMoves?: boolean;\n}\n\nexport interface CompareSummary {\n /** Inserted text runs and inserted block runs. */\n insertions: number;\n /** Deleted text runs and deleted block runs. */\n deletions: number;\n /** Formatting changes of equal text. */\n formatChanges: number;\n /** Block type, attribute and wrapping changes. */\n blockChanges: number;\n /** Moved paragraphs (with `detectMoves`). */\n moves: number;\n /** Differences the result could not represent as tracked changes. */\n notHonoured: string[];\n}\n\nexport interface CompareDocumentsResult {\n /**\n * The revised document with the differences as tracked changes: accepting\n * all changes yields the revised document, rejecting all the original.\n */\n doc: ProsemirrorNode;\n summary: CompareSummary;\n}\n\n/** Marks that are never compared as formatting. */\nconst REVIEW_MARK_NAMES = new Set([\n INSERTION_MARK_NAME,\n DELETION_MARK_NAME,\n FORMAT_CHANGE_MARK_NAME,\n \"comment\",\n \"bookmark\",\n]);\n\n/** Container types that pair with each other (a list whose type changed). */\nconst LIST_TYPES = new Set([\"bulletList\", \"orderedList\"]);\n\nconst OBJECT_REPLACEMENT = \"\";\n\ntype Wrapper = TrackedBlockSnapshot[\"wrappers\"][number];\n\ninterface Unit {\n /** One code point, or \"\" for an inline leaf node. */\n text: string;\n node: ProsemirrorNode | null;\n marks: readonly ProsemirrorMark[];\n}\n\ninterface Context {\n schema: Schema;\n author: ReviewAuthor;\n createdAt: number;\n generateId: () => string;\n granularity: \"word\" | \"char\";\n ignoreCase: boolean;\n ignoreWhitespace: boolean;\n formatting: boolean;\n maxCharDiff: number;\n ignoredMarks: Set<string>;\n ignoredAttributes: Set<string>;\n insertion?: MarkType;\n deletion?: MarkType;\n format?: MarkType;\n notes: Set<string>;\n keys: Map<ProsemirrorNode, string>;\n /** Shared change of the textblocks inside a container whose type changed. */\n wrapperChange: (() => TrackedChangeAttributes) | null;\n}\n\nfunction stableStringify(value: unknown): string {\n if (value === undefined) return \"null\";\n if (value === null || typeof value !== \"object\") return JSON.stringify(value);\n if (Array.isArray(value)) return `[${value.map(stableStringify).join(\",\")}]`;\n const keys = Object.keys(value as object).sort();\n return `{${keys\n .map((key) => `${JSON.stringify(key)}:${stableStringify((value as any)[key])}`)\n .join(\",\")}}`;\n}\n\nfunction toTime(date: CompareDocumentsOptions[\"date\"]): number {\n if (date instanceof Date) return date.getTime();\n if (typeof date === \"string\") {\n const time = Date.parse(date);\n return Number.isNaN(time) ? Date.now() : time;\n }\n return typeof date === \"number\" ? date : Date.now();\n}\n\nfunction toNode(source: CompareSource, schema: Schema): ProsemirrorNode {\n if (typeof source === \"string\") return createDocument(source, schema);\n if (typeof (source as ProsemirrorNode).descendants === \"function\") {\n const node = source as ProsemirrorNode;\n return node.type.schema === schema ? node : schema.nodeFromJSON(node.toJSON());\n }\n return schema.nodeFromJSON(source);\n}\n\nfunction newAttributes(ctx: Context): TrackedChangeAttributes {\n return {\n changeId: ctx.generateId(),\n authorId: ctx.author.id,\n authorName: ctx.author.name,\n authorColor: ctx.author.color ?? null,\n createdAt: ctx.createdAt,\n };\n}\n\n/** Lazily created attributes shared by one run of changes. */\nfunction lazyAttributes(ctx: Context): () => TrackedChangeAttributes {\n let attrs: TrackedChangeAttributes | null = null;\n return () => (attrs = attrs ?? newAttributes(ctx));\n}\n\nfunction stripBlockChange(attrs: Record<string, any>): Record<string, any> {\n const copy = { ...attrs };\n delete copy[BLOCK_CHANGE_ATTRIBUTE];\n return copy;\n}\n\nfunction wrapperOf(node: ProsemirrorNode): Wrapper {\n return { type: node.type.name, attrs: stripBlockChange(node.attrs) };\n}\n\nfunction snapshot(node: ProsemirrorNode, wrappers: Wrapper[]): TrackedBlockSnapshot {\n return { type: node.type.name, attrs: stripBlockChange(node.attrs), wrappers };\n}\n\nfunction filteredAttributes(attrs: Record<string, any>, ctx: Context): string {\n return stableStringify(\n Object.fromEntries(\n Object.entries(attrs ?? {}).filter(\n ([key]) => key !== BLOCK_CHANGE_ATTRIBUTE && !ctx.ignoredAttributes.has(key),\n ),\n ),\n );\n}\n\n/** Mirrors the tracker's block comparison: type, attributes and wrapper types. */\nfunction sameBlock(a: TrackedBlockSnapshot, b: TrackedBlockSnapshot, ctx: Context): boolean {\n if (a.type !== b.type) return false;\n if (filteredAttributes(a.attrs, ctx) !== filteredAttributes(b.attrs, ctx)) return false;\n if (a.wrappers.length !== b.wrappers.length) return false;\n return a.wrappers.every((w, i) => w.type === b.wrappers[i].type);\n}\n\nconst hasBlockChange = (node: ProsemirrorNode) =>\n !!node.type.spec.attrs && BLOCK_CHANGE_ATTRIBUTE in node.type.spec.attrs;\n\nconst label = (node: ProsemirrorNode) => node.type.name;\n\n// ---------------------------------------------------------------------------\n// Keys\n// ---------------------------------------------------------------------------\n\nfunction normalize(text: string, ctx: Context): string {\n let result = ctx.ignoreWhitespace ? text.replace(/\\s+/g, \" \") : text;\n if (ctx.ignoreCase) result = result.toLowerCase();\n return result;\n}\n\nfunction leafKey(node: ProsemirrorNode): string {\n return `${node.type.name}${stableStringify(stripBlockChange(node.attrs))}`;\n}\n\nfunction group(node: ProsemirrorNode): string {\n return LIST_TYPES.has(node.type.name) ? \"list\" : node.type.name;\n}\n\n/** Block key: textblocks by their (normalized) text only, so type changes pair up. */\nfunction blockKey(node: ProsemirrorNode, ctx: Context): string {\n const cached = ctx.keys.get(node);\n if (cached !== undefined) return cached;\n let key: string;\n if (node.isTextblock) {\n let text = \"\";\n node.forEach((child) => {\n text += child.isText ? child.text : `${OBJECT_REPLACEMENT}${leafKey(child)}${OBJECT_REPLACEMENT}`;\n });\n text = normalize(text, ctx);\n key = `T\\u0000${ctx.ignoreWhitespace ? text.trim() : text}`;\n } else if (node.isLeaf) {\n key = `A\\u0000${leafKey(node)}`;\n } else {\n const parts: string[] = [];\n node.forEach((child) => parts.push(blockKey(child, ctx)));\n key = `C\\u0000${group(node)}\\u0000${parts.join(\"\\u0001\")}\\u0002`;\n }\n ctx.keys.set(node, key);\n return key;\n}\n\nfunction compatible(a: ProsemirrorNode, b: ProsemirrorNode): boolean {\n if (a.isTextblock || b.isTextblock) return a.isTextblock && b.isTextblock;\n if (a.isLeaf || b.isLeaf) return a.isLeaf && b.isLeaf && a.type === b.type;\n return group(a) === group(b);\n}\n\n// ---------------------------------------------------------------------------\n// Whole blocks\n// ---------------------------------------------------------------------------\n\nfunction markInline(\n content: Fragment,\n mark: ProsemirrorMark,\n): Fragment {\n const nodes: ProsemirrorNode[] = [];\n content.forEach((child) => nodes.push(child.mark(mark.addToSet(child.marks))));\n return Fragment.from(nodes);\n}\n\n/**\n * A block deleted or inserted as a whole: every textblock inside gets a\n * `blockChange` record with the operation (one change id per run).\n */\nfunction wholeBlock(\n node: ProsemirrorNode,\n operation: TrackedBlockOperation,\n wrappers: Wrapper[],\n attrs: () => TrackedChangeAttributes,\n ctx: Context,\n): ProsemirrorNode[] {\n const verb = operation === \"insert\" ? \"Inserted\" : \"Deleted\";\n if (node.isTextblock) {\n if (hasBlockChange(node)) {\n const record: TrackedBlockChangeAttributes = {\n ...attrs(),\n previous: snapshot(node, wrappers),\n operation,\n };\n return [node.type.create({ ...node.attrs, [BLOCK_CHANGE_ATTRIBUTE]: record }, node.content, node.marks)];\n }\n // No block record: fall back to marking the text.\n const markType = operation === \"insert\" ? ctx.insertion : ctx.deletion;\n if (markType && node.type.allowsMarkType(markType) && node.content.size > 0) {\n ctx.notes.add(\n `${verb} ${label(node)} blocks have no \"${BLOCK_CHANGE_ATTRIBUTE}\" attribute: only their text is tracked, so an empty block remains when the change is ${operation === \"insert\" ? \"rejected\" : \"accepted\"}.`,\n );\n return [node.type.create(node.attrs, markInline(node.content, markType.create(attrs())), node.marks)];\n }\n ctx.notes.add(`${verb} ${label(node)} blocks cannot be tracked.`);\n return operation === \"insert\" ? [node] : [];\n }\n if (node.isLeaf) {\n ctx.notes.add(`${verb} ${label(node)} blocks cannot be tracked.`);\n return operation === \"insert\" ? [node] : [];\n }\n const inner = [...wrappers, wrapperOf(node)];\n const children: ProsemirrorNode[] = [];\n node.forEach((child) => children.push(...wholeBlock(child, operation, inner, attrs, ctx)));\n try {\n return [node.type.createChecked(node.attrs, children, node.marks)];\n } catch {\n ctx.notes.add(`${verb} ${label(node)} blocks cannot be tracked.`);\n return operation === \"insert\" ? [node] : [];\n }\n}\n\n// ---------------------------------------------------------------------------\n// Inline comparison\n// ---------------------------------------------------------------------------\n\nfunction units(node: ProsemirrorNode): Unit[] {\n const result: Unit[] = [];\n node.forEach((child) => {\n if (child.isText) {\n for (const ch of child.text ?? \"\") result.push({ text: ch, node: null, marks: child.marks });\n } else {\n result.push({ text: \"\", node: child, marks: child.marks });\n }\n });\n return result;\n}\n\nconst SPACE = /\\s/u;\nconst WORD = /[\\p{L}\\p{N}\\p{M}_]/u;\n\nconst isSpace = (u: Unit) => !u.node && SPACE.test(u.text);\nconst isWord = (u: Unit) => !u.node && WORD.test(u.text);\n\n/** Token ranges: words, white space runs and single symbols, or characters. */\nfunction tokenize(list: Unit[], chars: boolean): [number, number][] {\n const tokens: [number, number][] = [];\n if (chars) {\n for (let i = 0; i < list.length; i++) tokens.push([i, i + 1]);\n return tokens;\n }\n let i = 0;\n while (i < list.length) {\n const start = i;\n const unit = list[i];\n if (isSpace(unit)) {\n while (i < list.length && isSpace(list[i])) i++;\n } else if (isWord(unit)) {\n while (i < list.length && isWord(list[i])) i++;\n } else {\n i++;\n }\n tokens.push([start, i]);\n }\n return tokens;\n}\n\ntype Stretch =\n | { type: \"equal\"; aIndex: number; bIndex: number; length: number }\n | { type: \"change\"; aFrom: number; aTo: number; bFrom: number; bTo: number };\n\n/**\n * Groups token runs into equal stretches and changes. White space alone\n * between two changes joins them, so \"a b\" → \"x y\" reads as one\n * replacement instead of alternating deletions and insertions.\n */\nfunction stretches(runs: ReturnType<typeof diffSequences>, list: Unit[], tokens: [number, number][]): Stretch[] {\n const spaceOnly = (bIndex: number, length: number) => {\n for (let t = bIndex; t < bIndex + length; t++) {\n const [from, to] = tokens[t];\n for (let k = from; k < to; k++) if (!isSpace(list[k])) return false;\n }\n return true;\n };\n const result: Stretch[] = [];\n runs.forEach((run, index) => {\n const prev = runs[index - 1];\n const next = runs[index + 1];\n const absorbed =\n run.type === \"equal\" &&\n prev &&\n next &&\n prev.type !== \"equal\" &&\n next.type !== \"equal\" &&\n spaceOnly(run.bIndex, run.length);\n if (run.type === \"equal\" && !absorbed) {\n result.push({ type: \"equal\", aIndex: run.aIndex, bIndex: run.bIndex, length: run.length });\n return;\n }\n let last = result[result.length - 1];\n if (!last || last.type !== \"change\") {\n last = { type: \"change\", aFrom: run.aIndex, aTo: run.aIndex, bFrom: run.bIndex, bTo: run.bIndex };\n result.push(last);\n }\n if (run.type !== \"insert\") last.aTo = run.aIndex + run.length;\n if (run.type !== \"delete\") last.bTo = run.bIndex + run.length;\n });\n return result;\n}\n\nfunction tokenKey(list: Unit[], [from, to]: [number, number], ctx: Context): string {\n let text = \"\";\n for (let i = from; i < to; i++) {\n const unit = list[i];\n text += unit.node ? `${OBJECT_REPLACEMENT}${leafKey(unit.node)}${OBJECT_REPLACEMENT}` : unit.text;\n }\n return normalize(text, ctx);\n}\n\nfunction formattingOf(marks: readonly ProsemirrorMark[], ctx: Context): ProsemirrorMark[] {\n return marks.filter(\n (mark) => !REVIEW_MARK_NAMES.has(mark.type.name) && !ctx.ignoredMarks.has(mark.type.name),\n );\n}\n\nfunction withoutReviewMarks(marks: readonly ProsemirrorMark[]): readonly ProsemirrorMark[] {\n return marks.filter(\n (mark) =>\n mark.type.name !== INSERTION_MARK_NAME &&\n mark.type.name !== DELETION_MARK_NAME &&\n mark.type.name !== FORMAT_CHANGE_MARK_NAME,\n );\n}\n\n/**\n * Merges the inline content of two paired textblocks: equal tokens keep the\n * revised text (with `formatChange` where formatting differs), deleted\n * tokens are re-inserted with the `deletion` mark before inserted tokens.\n */\nfunction mergeInline(\n original: ProsemirrorNode,\n revised: ProsemirrorNode,\n parentType: ProsemirrorNode[\"type\"],\n ctx: Context,\n): Fragment {\n const a = units(original);\n const b = units(revised);\n let chars = ctx.granularity === \"char\";\n if (chars && Math.max(a.length, b.length) > ctx.maxCharDiff) {\n chars = false;\n ctx.notes.add(\n `Paragraphs longer than ${ctx.maxCharDiff} characters were compared by words instead of characters.`,\n );\n }\n const ta = tokenize(a, chars);\n const tb = tokenize(b, chars);\n const runs = diffSequences(\n ta.map((t) => tokenKey(a, t, ctx)),\n tb.map((t) => tokenKey(b, t, ctx)),\n );\n\n const format = ctx.formatting && ctx.format && parentType.allowsMarkType(ctx.format) ? ctx.format : null;\n const out: Unit[] = [];\n let formatRun: { attrs: TrackedChangeAttributes; key: string } | null = null;\n\n const emit = (\n source: Unit[],\n tokens: [number, number][],\n from: number,\n to: number,\n markType: MarkType,\n ) => {\n if (to <= from) return;\n const mark = markType.create(newAttributes(ctx));\n for (let k = tokens[from][0]; k < tokens[to - 1][1]; k++) {\n const unit = source[k];\n out.push({ ...unit, marks: mark.addToSet(withoutReviewMarks(unit.marks)) });\n }\n };\n\n for (const run of stretches(runs, b, tb)) {\n if (run.type === \"equal\") {\n for (let t = 0; t < run.length; t++) {\n const [aFrom, aTo] = ta[run.aIndex + t];\n const [bFrom, bTo] = tb[run.bIndex + t];\n for (let k = bFrom; k < bTo; k++) {\n const unit = b[k];\n const before = a[Math.min(aFrom + (k - bFrom), aTo - 1)];\n const marks = withoutReviewMarks(unit.marks);\n if (!format) {\n formatRun = null;\n out.push({ ...unit, marks });\n continue;\n }\n const oldFormat = formattingOf(before.marks, ctx);\n const newFormat = formattingOf(unit.marks, ctx);\n if (ProsemirrorMark.sameSet(oldFormat, newFormat)) {\n formatRun = null;\n out.push({ ...unit, marks });\n continue;\n }\n const beforeJSON = oldFormat.map((m) => m.toJSON() as TrackedMark);\n const afterJSON = newFormat.map((m) => m.toJSON() as TrackedMark);\n const key = stableStringify([beforeJSON, afterJSON]);\n if (!formatRun || formatRun.key !== key) formatRun = { attrs: newAttributes(ctx), key };\n const mark = format.create({ ...formatRun.attrs, before: beforeJSON, after: afterJSON });\n out.push({ ...unit, marks: mark.addToSet(marks) });\n }\n }\n continue;\n }\n formatRun = null;\n emit(a, ta, run.aFrom, run.aTo, ctx.deletion!);\n emit(b, tb, run.bFrom, run.bTo, ctx.insertion!);\n }\n\n const nodes: ProsemirrorNode[] = [];\n let i = 0;\n while (i < out.length) {\n const unit = out[i];\n if (unit.node) {\n nodes.push(unit.node.mark(unit.marks));\n i++;\n continue;\n }\n let text = unit.text;\n let j = i + 1;\n while (j < out.length && !out[j].node && ProsemirrorMark.sameSet(out[j].marks, unit.marks)) {\n text += out[j].text;\n j++;\n }\n nodes.push(ctx.schema.text(text, unit.marks));\n i = j;\n }\n return Fragment.from(nodes);\n}\n\n// ---------------------------------------------------------------------------\n// Blocks\n// ---------------------------------------------------------------------------\n\nfunction mergeTextblocks(\n original: ProsemirrorNode,\n revised: ProsemirrorNode,\n oPath: Wrapper[],\n rPath: Wrapper[],\n ctx: Context,\n): ProsemirrorNode[] {\n const replaceWhole = () => [\n ...wholeBlock(original, \"delete\", rPath, lazyAttributes(ctx), ctx),\n ...wholeBlock(revised, \"insert\", rPath, lazyAttributes(ctx), ctx),\n ];\n\n let attrs: Record<string, any> = { ...revised.attrs };\n const previous = snapshot(original, oPath);\n if (!sameBlock(previous, snapshot(revised, rPath), ctx)) {\n if (hasBlockChange(revised)) {\n // Only the wrappers changed (e.g. bulleted → numbered list): one change per container.\n const onlyWrappers =\n ctx.wrapperChange &&\n sameBlock(previous, { ...snapshot(revised, rPath), wrappers: previous.wrappers }, ctx);\n const base = onlyWrappers ? ctx.wrapperChange!() : newAttributes(ctx);\n attrs = { ...attrs, [BLOCK_CHANGE_ATTRIBUTE]: { ...base, previous } };\n } else {\n ctx.notes.add(`Block changes to ${label(revised)} blocks cannot be tracked.`);\n }\n } else if (BLOCK_CHANGE_ATTRIBUTE in attrs) {\n attrs[BLOCK_CHANGE_ATTRIBUTE] = null;\n }\n\n const type = revised.type;\n const inlineTracking =\n !!ctx.insertion &&\n !!ctx.deletion &&\n type.allowsMarkType(ctx.insertion) &&\n type.allowsMarkType(ctx.deletion);\n if (!inlineTracking) {\n // e.g. code blocks in a headless schema: equal text keeps the block,\n // anything else is replaced whole.\n if (!original.content.eq(revised.content)) return replaceWhole();\n return [type.create(attrs, revised.content, revised.marks)];\n }\n const content = mergeInline(original, revised, type, ctx);\n if (!type.validContent(content)) {\n ctx.notes.add(`Changes between ${label(original)} and ${label(revised)} blocks were tracked as whole-block replacements.`);\n return replaceWhole();\n }\n return [type.create(attrs, content, revised.marks)];\n}\n\nfunction mergePair(\n original: ProsemirrorNode,\n revised: ProsemirrorNode,\n oPath: Wrapper[],\n rPath: Wrapper[],\n ctx: Context,\n): ProsemirrorNode[] {\n if (original.isTextblock) return mergeTextblocks(original, revised, oPath, rPath, ctx);\n const replaceWhole = () => [\n ...wholeBlock(original, \"delete\", rPath, lazyAttributes(ctx), ctx),\n ...wholeBlock(revised, \"insert\", rPath, lazyAttributes(ctx), ctx),\n ];\n if (original.isLeaf) {\n return original.eq(revised) ? [revised] : replaceWhole();\n }\n if (\n original.type === revised.type &&\n filteredAttributes(original.attrs, ctx) !== filteredAttributes(revised.attrs, ctx)\n ) {\n ctx.notes.add(`Attribute changes of ${label(revised)} nodes are not tracked.`);\n }\n const outer = ctx.wrapperChange;\n if (original.type !== revised.type) ctx.wrapperChange = lazyAttributes(ctx);\n let children: ProsemirrorNode[];\n try {\n children = compareChildren(\n original,\n revised,\n [...oPath, wrapperOf(original)],\n [...rPath, wrapperOf(revised)],\n ctx,\n );\n } finally {\n ctx.wrapperChange = outer;\n }\n try {\n return [revised.type.createChecked(revised.attrs, children, revised.marks)];\n } catch {\n ctx.notes.add(`Changes inside ${label(revised)} nodes were tracked as whole-block replacements.`);\n return replaceWhole();\n }\n}\n\nfunction compareChildren(\n original: ProsemirrorNode,\n revised: ProsemirrorNode,\n oPath: Wrapper[],\n rPath: Wrapper[],\n ctx: Context,\n): ProsemirrorNode[] {\n const a: ProsemirrorNode[] = [];\n const b: ProsemirrorNode[] = [];\n original.forEach((child) => a.push(child));\n revised.forEach((child) => b.push(child));\n const runs = diffSequences(a, b, { hash: (node) => blockKey(node, ctx) });\n const out: ProsemirrorNode[] = [];\n\n for (let r = 0; r < runs.length; r++) {\n const run = runs[r];\n if (run.type === \"equal\") {\n for (let t = 0; t < run.length; t++) {\n out.push(...mergePair(a[run.aIndex + t], b[run.bIndex + t], oPath, rPath, ctx));\n }\n continue;\n }\n // A run of deletions and insertions: the i-th deleted block pairs with\n // the i-th inserted one when they are alike; the rest are whole.\n let dels: ProsemirrorNode[] = [];\n let inss: ProsemirrorNode[] = [];\n if (run.type === \"delete\") {\n dels = a.slice(run.aIndex, run.aIndex + run.length);\n const next = runs[r + 1];\n if (next?.type === \"insert\") {\n inss = b.slice(next.bIndex, next.bIndex + next.length);\n r++;\n }\n } else {\n inss = b.slice(run.bIndex, run.bIndex + run.length);\n }\n const deleted = lazyAttributes(ctx);\n const inserted = lazyAttributes(ctx);\n for (let x = 0; x < Math.max(dels.length, inss.length); x++) {\n const del = dels[x];\n const ins = inss[x];\n if (del && ins && compatible(del, ins)) {\n out.push(...mergePair(del, ins, oPath, rPath, ctx));\n continue;\n }\n if (del) out.push(...wholeBlock(del, \"delete\", rPath, deleted, ctx));\n if (ins) out.push(...wholeBlock(ins, \"insert\", rPath, inserted, ctx));\n }\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Moves\n// ---------------------------------------------------------------------------\n\n/**\n * Pairs top-level paragraphs deleted as a whole with identical paragraphs\n * inserted as a whole elsewhere, and records each pair as a move: the\n * source's text gets the deletion mark and the destination's the insertion\n * mark, both with the same move id (accepting or rejecting removes the\n * emptied block). Ambiguous content (several identical candidates) is left\n * as whole-block changes.\n */\nfunction detectMovedBlocks(children: ProsemirrorNode[], ctx: Context): ProsemirrorNode[] {\n const keyOf = (node: ProsemirrorNode) =>\n `${node.type.name}\\u0000${filteredAttributes(node.attrs, ctx)}\\u0000${stableStringify(node.content.toJSON())}`;\n const candidates = new Map<string, { del: number[]; ins: number[] }>();\n children.forEach((node, index) => {\n const operation = (node.attrs?.[BLOCK_CHANGE_ATTRIBUTE] as TrackedBlockChangeAttributes | null)\n ?.operation;\n if (!operation || !node.isTextblock || !node.textContent.trim()) return;\n if (!node.type.allowsMarkType(ctx.insertion!) || !node.type.allowsMarkType(ctx.deletion!)) return;\n const key = keyOf(node);\n const entry = candidates.get(key) ?? { del: [], ins: [] };\n (operation === \"delete\" ? entry.del : entry.ins).push(index);\n candidates.set(key, entry);\n });\n const out = [...children];\n candidates.forEach(({ del, ins }) => {\n if (del.length !== 1 || ins.length !== 1) return;\n const attrs = newAttributes(ctx);\n const moved = { ...attrs, [MOVE_ID_ATTRIBUTE]: attrs.changeId };\n const relink = (index: number, markType: MarkType) => {\n const node = out[index];\n out[index] = node.type.create(\n { ...node.attrs, [BLOCK_CHANGE_ATTRIBUTE]: null },\n markInline(node.content, markType.create(moved)),\n node.marks,\n );\n };\n relink(del[0], ctx.deletion!);\n relink(ins[0], ctx.insertion!);\n });\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nfunction summarize(doc: ProsemirrorNode, notes: Set<string>): CompareSummary {\n const summary: CompareSummary = {\n insertions: 0,\n deletions: 0,\n formatChanges: 0,\n blockChanges: 0,\n moves: 0,\n notHonoured: [...notes],\n };\n getTrackedChanges(doc).forEach((change) => {\n if (change.type === \"move\") summary.moves++;\n else if (change.type === \"insertion\" || change.block?.operation === \"insert\") summary.insertions++;\n else if (change.type === \"deletion\" || change.block?.operation === \"delete\") summary.deletions++;\n else if (change.type === \"format\") summary.formatChanges++;\n else summary.blockChanges++;\n });\n return summary;\n}\n\n/**\n * Compares two documents and returns the revised document with the\n * differences as tracked changes (`insertion`/`deletion`/`formatChange`\n * marks and `blockChange` records), plus a summary.\n *\n * Blocks are matched by their text (Myers diff with patience anchors); in a\n * run of changed blocks the i-th deleted block is paired with the i-th\n * inserted one and compared word by word (or by character), while unpaired\n * blocks are recorded as whole-block insertions/deletions. Equal text is\n * compared for formatting, and type/attribute/wrapping changes become\n * `blockChange` records. Without ignore options, accepting all changes\n * yields the revised document and rejecting all yields the original.\n *\n * The schema needs the `TrackChanges` extension (marks and the\n * `blockChange` attribute). Existing tracked changes in either document are\n * accepted first.\n */\nexport function compareDocuments(\n original: CompareSource,\n revised: CompareSource,\n options: CompareDocumentsOptions = {},\n): CompareDocumentsResult {\n const schema =\n options.schema ??\n (typeof (original as ProsemirrorNode)?.descendants === \"function\"\n ? (original as ProsemirrorNode).type.schema\n : typeof (revised as ProsemirrorNode)?.descendants === \"function\"\n ? (revised as ProsemirrorNode).type.schema\n : null);\n if (!schema) throw new Error(\"compareDocuments: `schema` is required for JSON or HTML sources.\");\n\n const ctx: Context = {\n schema,\n author: options.author ?? { id: \"compare\", name: \"Compare\" },\n createdAt: toTime(options.date),\n generateId: options.generateId ?? (() => createReviewId(\"change\")),\n granularity: options.granularity ?? \"word\",\n ignoreCase: !!options.ignoreCase,\n ignoreWhitespace: !!options.ignoreWhitespace,\n formatting: options.formatting !== false,\n maxCharDiff: options.maxCharDiff ?? 2000,\n ignoredMarks: new Set(options.ignoredMarks ?? []),\n ignoredAttributes: new Set(options.ignoredBlockAttributes ?? [\"id\"]),\n insertion: schema.marks[INSERTION_MARK_NAME],\n deletion: schema.marks[DELETION_MARK_NAME],\n format: schema.marks[FORMAT_CHANGE_MARK_NAME],\n notes: new Set(),\n keys: new Map(),\n wrapperChange: null,\n };\n if (!ctx.insertion || !ctx.deletion) {\n throw new Error(\"compareDocuments: the schema needs the TrackChanges extension (insertion/deletion marks).\");\n }\n if (ctx.formatting && !ctx.format) {\n ctx.notes.add(\"Formatting differences cannot be tracked: the schema has no formatChange mark.\");\n }\n\n const prepare = (source: CompareSource) => {\n const doc = toNode(source, schema);\n if (getTrackedChanges(doc).length === 0) return doc;\n ctx.notes.add(\"Tracked changes already in the documents were accepted before comparing.\");\n return resolveTrackedChanges(doc, \"accepted\");\n };\n const a = prepare(original);\n const b = prepare(revised);\n\n let children = compareChildren(a, b, [], [], ctx);\n if (options.detectMoves) children = detectMovedBlocks(children, ctx);\n let doc: ProsemirrorNode;\n try {\n doc = b.type.createChecked(b.attrs, children, b.marks);\n } catch {\n doc = b.type.createAndFill(b.attrs, children, b.marks) ?? b;\n ctx.notes.add(\"The compared document had to be repaired to fit the schema.\");\n }\n return { doc, summary: summarize(doc, ctx.notes) };\n}\n\n/** `compareDocuments` for two HTML strings (needs a DOM, like `setContent`). */\nexport function compareHtml(\n originalHtml: string,\n revisedHtml: string,\n options: CompareDocumentsOptions & { schema: Schema },\n): CompareDocumentsResult {\n return compareDocuments(originalHtml, revisedHtml, options);\n}\n"]}