@stll/folio-core 0.58.5 → 0.59.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.
- package/dist/ai-edits/apply.d.ts +11 -12
- package/dist/ai-edits/apply.js +179 -168
- package/dist/ai-edits/headless.d.ts +15 -13
- package/dist/ai-edits/headless.js +40 -13
- package/dist/ai-edits/index.d.ts +3 -3
- package/dist/ai-edits/newListNumbering.d.ts +3 -9
- package/dist/ai-edits/newListNumbering.js +36 -41
- package/dist/ai-edits/referenceClassification.d.ts +22 -0
- package/dist/ai-edits/referenceClassification.js +21 -0
- package/dist/ai-edits/snapshot.js +39 -40
- package/dist/ai-edits/types.d.ts +24 -32
- package/dist/compare/column-alignment.d.ts +4 -4
- package/dist/compare/compare.d.ts +3 -7
- package/dist/compare/compare.js +25 -27
- package/dist/compare/content-alignment.d.ts +9 -9
- package/dist/compare/content-types.d.ts +23 -10
- package/dist/compare/content-types.js +14 -0
- package/dist/compare/content.d.ts +16 -17
- package/dist/compare/content.js +30 -7
- package/dist/compare/formatting.d.ts +3 -3
- package/dist/compare/import-style-closure.d.ts +22 -0
- package/dist/compare/import-style-closure.js +33 -0
- package/dist/compare/inserted-resource-snapshot.d.ts +15 -0
- package/dist/compare/inserted-resource-snapshot.js +63 -0
- package/dist/compare/plan.js +20 -13
- package/dist/compare/scenario.js +12 -2
- package/dist/compare/style-resources.d.ts +8 -2
- package/dist/compare/style-resources.js +63 -14
- package/dist/compare/verification.d.ts +15 -3
- package/dist/compare/verification.js +47 -8
- package/dist/compat/eigenpal.d.ts +4 -4
- package/dist/controller/canonicalListRendering.js +13 -22
- package/dist/controller/canonicalPublicOperations.js +1 -1
- package/dist/controller/canonicalStructure.js +45 -21
- package/dist/document-operations.d.ts +4 -9
- package/dist/document-operations.js +45 -41
- package/dist/docx/attributeRemainder.d.ts +1 -1
- package/dist/docx/index.d.ts +1 -1
- package/dist/docx/listMarkerComputation.js +9 -14
- package/dist/docx/listTemplate.d.ts +22 -0
- package/dist/docx/listTemplate.js +40 -0
- package/dist/docx/numberingParser.js +2 -2
- package/dist/docx/numberingReferenceNormalization.js +3 -3
- package/dist/docx/paragraphParser.js +3 -4
- package/dist/docx/rezip.js +2 -2
- package/dist/docx/server/materializeYjsDocx.js +2 -2
- package/dist/docx/server/migrateYjsAttrSchema.js +5 -5
- package/dist/generated/text_shaper.js +8 -4
- package/dist/generated/text_shaper_bg.wasm +0 -0
- package/dist/index.d.ts +4 -4
- package/dist/internal/paragraphFormattingSerialization.d.ts +1 -8
- package/dist/internal/paragraphFormattingSerialization.js +6 -20
- package/dist/layout-bridge/convert/flowConversionShared.d.ts +1 -1
- package/dist/layout-bridge/convert/listMarkers.d.ts +1 -2
- package/dist/layout-bridge/convert/listMarkers.js +3 -11
- package/dist/layout-bridge/convert/paragraphAttrs.d.ts +1 -1
- package/dist/layout-bridge/convert/paragraphAttrs.js +8 -4
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +2 -1
- package/dist/layout-bridge/convert/toFlowBlocks.js +2 -1
- package/dist/markdown/renderParagraph.js +29 -3
- package/dist/prosemirror/commands/comments.js +5 -32
- package/dist/prosemirror/commands/paragraphBookmarkJoin.d.ts +7 -1
- package/dist/prosemirror/commands/paragraphBookmarkJoin.js +35 -1
- package/dist/prosemirror/commands/propertyChangeScope.js +6 -0
- package/dist/prosemirror/commands/resolveParagraphProperties.js +10 -5
- package/dist/prosemirror/conversion/fromProseDoc.js +23 -9
- package/dist/prosemirror/conversion/toProseDoc.js +31 -7
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +29 -14
- package/dist/prosemirror/extensions/features/ListExtension.js +51 -21
- package/dist/prosemirror/listInstanceReferences.js +21 -15
- package/dist/prosemirror/listLabels.d.ts +4 -3
- package/dist/prosemirror/listLabels.js +18 -51
- package/dist/prosemirror/listMarker.d.ts +2 -19
- package/dist/prosemirror/listMarker.js +28 -57
- package/dist/prosemirror/listNumbering.js +16 -6
- package/dist/prosemirror/listRendering.d.ts +4 -3
- package/dist/prosemirror/listRendering.js +22 -3
- package/dist/prosemirror/listRenderingAttrs.d.ts +2 -1
- package/dist/prosemirror/listRenderingAttrs.js +6 -11
- package/dist/prosemirror/numberedRefFields.js +9 -5
- package/dist/prosemirror/numberingAttr.d.ts +19 -1
- package/dist/prosemirror/numberingAttr.js +16 -2
- package/dist/prosemirror/paragraphIndentation.js +5 -2
- package/dist/prosemirror/paragraphMarkJoin.js +17 -3
- package/dist/prosemirror/paragraphPropertyCarry.js +5 -6
- package/dist/prosemirror/plugins/transactionInvariants.js +6 -2
- package/dist/prosemirror/schema/nodes.d.ts +2 -1
- package/dist/prosemirror/selectionState.js +5 -1
- package/dist/prosemirror/storyListNumbering.js +11 -12
- package/dist/prosemirror/styles/paragraphStyleCascade.js +2 -6
- package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +11 -4
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +28 -18
- package/dist/prosemirror/yjsDocumentMetadata.d.ts +9 -3
- package/dist/prosemirror/yjsDocumentMetadata.js +42 -10
- package/dist/redline.d.ts +17 -1
- package/dist/redline.js +118 -57
- package/dist/server.d.ts +3 -3
- package/dist/server.js +2 -2
- package/dist/version-comparison.d.ts +1 -2
- package/dist/version-comparison.js +1 -2
- package/package.json +4 -3
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { FONT_THEME_VALUES } from "../types/documentEnumValues.js";
|
|
2
2
|
import { expectFontFamilyMarkAttrs, expectFontSizeMarkAttrs, expectHighlightMarkAttrs, expectParagraphAttrs, expectStrikeMarkAttrs, expectTextColorMarkAttrs, expectUnderlineMarkAttrs } from "./attrs/index.js";
|
|
3
3
|
import { resolveListState } from "./listState.js";
|
|
4
|
+
import { effectiveParagraphNumbering, paragraphNumberingSourcesFromBoundary } from "./numberingAttr.js";
|
|
4
5
|
import { directionIsRtl } from "./paragraphDirection.js";
|
|
5
6
|
import { getDocumentNumbering } from "./plugins/documentNumbering.js";
|
|
6
7
|
import { collectMarksInRange } from "./selectionMarks.js";
|
|
@@ -46,7 +47,10 @@ function extractSelectionSnapshot(state) {
|
|
|
46
47
|
styleId,
|
|
47
48
|
startParagraphIndex,
|
|
48
49
|
endParagraphIndex,
|
|
49
|
-
listState: resolveListState(getDocumentNumbering(state),
|
|
50
|
+
listState: resolveListState(getDocumentNumbering(state), effectiveParagraphNumbering(paragraphNumberingSourcesFromBoundary({
|
|
51
|
+
numPr: paragraphAttrs?.numPr,
|
|
52
|
+
numPrFromStyle: paragraphAttrs?.numPrFromStyle
|
|
53
|
+
})))
|
|
50
54
|
};
|
|
51
55
|
}
|
|
52
56
|
/** Compatibility entry point used by existing React and Vue integrations. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createNumberingIdAllocator } from "../docx/numberingIds.js";
|
|
2
2
|
import { getCachedNumberingMap, isBulletLevel } from "../docx/numberingParser.js";
|
|
3
|
-
import {
|
|
3
|
+
import { paragraphNumberingReference } from "../docx/numberingReference.js";
|
|
4
4
|
import { expectParagraphAttrs } from "./attrs/index.js";
|
|
5
5
|
import { completeNumberingForDoc, paragraphListReferences } from "./listInstanceReferences.js";
|
|
6
6
|
import { paragraphNumberingAttr } from "./numberingAttr.js";
|
|
@@ -8,13 +8,12 @@ import { getPackageNumberingDefinitions } from "./plugins/documentNumbering.js";
|
|
|
8
8
|
import { Transform } from "prosemirror-transform";
|
|
9
9
|
//#region src/prosemirror/storyListNumbering.ts
|
|
10
10
|
const remappedNumPr = (numPr, numIds) => {
|
|
11
|
-
|
|
12
|
-
const next =
|
|
11
|
+
if (numPr?.kind !== "reference") return numPr;
|
|
12
|
+
const next = numIds.get(numPr.numId);
|
|
13
13
|
if (next === void 0) return numPr;
|
|
14
|
-
|
|
15
|
-
return paragraphNumberingAttr(paragraphNumberingReference(ilvl === void 0 ? { numId: next } : {
|
|
14
|
+
return paragraphNumberingAttr(paragraphNumberingReference(numPr.ilvl === void 0 ? { numId: next } : {
|
|
16
15
|
numId: next,
|
|
17
|
-
ilvl
|
|
16
|
+
ilvl: numPr.ilvl
|
|
18
17
|
}));
|
|
19
18
|
};
|
|
20
19
|
const remappedAbstractNumId = (abstractNumId, remap) => {
|
|
@@ -47,10 +46,10 @@ const storyListNumbering = (state, numbering) => {
|
|
|
47
46
|
const abstractId = change.previousFormatting?.listAbstractNumId;
|
|
48
47
|
if (typeof abstractId === "number") existingAbstractNumIds.add(abstractId);
|
|
49
48
|
}
|
|
50
|
-
const
|
|
51
|
-
if (
|
|
52
|
-
const level = definedMap.getLevel(numId,
|
|
53
|
-
if (!(level !== null && isBulletLevel(level) === (attrs.listIsBullet === true) && (attrs.listAbstractNumId ?? void 0) === (definedMap.getAbstractNumId(numId) ?? void 0))) colliding.add(numId);
|
|
49
|
+
const statedNumbering = attrs.numPr;
|
|
50
|
+
if (statedNumbering?.kind === "reference" && !storyBase.has(statedNumbering.numId) && definedMap?.hasNumbering(statedNumbering.numId)) {
|
|
51
|
+
const level = definedMap.getLevel(statedNumbering.numId, statedNumbering.ilvl ?? 0);
|
|
52
|
+
if (!(level !== null && isBulletLevel(level) === (attrs.listIsBullet === true) && (attrs.listAbstractNumId ?? void 0) === (definedMap.getAbstractNumId(statedNumbering.numId) ?? void 0))) colliding.add(statedNumbering.numId);
|
|
54
53
|
}
|
|
55
54
|
return false;
|
|
56
55
|
});
|
|
@@ -69,11 +68,11 @@ const storyListNumbering = (state, numbering) => {
|
|
|
69
68
|
state.doc.descendants((node, pos) => {
|
|
70
69
|
if (node.type.name !== "paragraph") return true;
|
|
71
70
|
const attrs = expectParagraphAttrs(node);
|
|
72
|
-
const numId =
|
|
71
|
+
const numId = attrs.numPr?.kind === "reference" ? attrs.numPr.numId : void 0;
|
|
73
72
|
const moves = numId !== void 0 && remap.numIds.has(numId);
|
|
74
73
|
const changes = attrs._propertyChanges?.map((change) => {
|
|
75
74
|
const previous = change.previousFormatting;
|
|
76
|
-
const previousNumId =
|
|
75
|
+
const previousNumId = previous?.numPr?.kind === "reference" ? previous.numPr.numId : void 0;
|
|
77
76
|
if (!previous || previousNumId === void 0 || !remap.numIds.has(previousNumId)) return change;
|
|
78
77
|
return {
|
|
79
78
|
...change,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { paragraphNumberingReferenceId } from "../../docx/numberingReference.js";
|
|
2
2
|
import { mergeParagraphFormatting, mergeParagraphTabStops } from "../../utils/paragraphFormattingMerge.js";
|
|
3
3
|
import { mergeTextFormatting } from "../../utils/textFormattingMerge.js";
|
|
4
4
|
import { paragraphNumberingAttr } from "../numberingAttr.js";
|
|
@@ -103,11 +103,7 @@ function paragraphStyleCascadeAttrs({ styleId, formatting, styleResolver, tableP
|
|
|
103
103
|
set("direction", directionFromBidi(formatting?.bidi ?? stylePpr?.bidi));
|
|
104
104
|
set("defaultTextFormatting", resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolver, { includeParagraphMarkRunProperties }));
|
|
105
105
|
const styleNumbering = stylePpr?.numPr;
|
|
106
|
-
if (styleNumbering?.kind === "reference" && (formatting?.numPr === void 0 || formatting.numPr.kind === "levelOnly"))
|
|
107
|
-
const merged = mergeParagraphNumbering(styleNumbering, formatting?.numPr);
|
|
108
|
-
if (merged !== void 0) attrs.numPr = paragraphNumberingAttr(merged);
|
|
109
|
-
attrs.numPrFromStyle = paragraphNumberingAttr(styleNumbering);
|
|
110
|
-
}
|
|
106
|
+
if (styleNumbering?.kind === "reference" && (formatting?.numPr === void 0 || formatting.numPr.kind === "levelOnly")) attrs.numPrFromStyle = paragraphNumberingAttr(styleNumbering);
|
|
111
107
|
return {
|
|
112
108
|
attrs,
|
|
113
109
|
stylePpr
|
|
@@ -4,6 +4,16 @@ import { ResolvedParagraphStyle } from "./styleResolver.js";
|
|
|
4
4
|
import { NumberingMap } from "../../docx/numberingParser.js";
|
|
5
5
|
import { DirectParagraphIndentation } from "../paragraphIndentation.js";
|
|
6
6
|
//#region src/prosemirror/styles/resolvedStyleAttrs.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* Shared helper for projecting a resolved paragraph style onto ProseMirror
|
|
9
|
+
* paragraph node attrs.
|
|
10
|
+
*
|
|
11
|
+
* Both `applyStyle` (toolbar style picker) and the Enter handler's
|
|
12
|
+
* next-style switch need to write the same set of style-controlled attrs.
|
|
13
|
+
* Keeping the projection in one place ensures the two paths stay in sync —
|
|
14
|
+
* a style applied via the picker and a style applied on Enter produce
|
|
15
|
+
* identical paragraph attrs.
|
|
16
|
+
*/
|
|
7
17
|
type ResolvedStyleIdentity = {
|
|
8
18
|
styleId: string;
|
|
9
19
|
styleName?: string;
|
|
@@ -59,9 +69,6 @@ declare function listIndentationProvenancePatch({ direct, styleFormatting, numbe
|
|
|
59
69
|
*/
|
|
60
70
|
declare function listLevelIndentRemovalPatch(attrs: Readonly<ParagraphAttrs>, numbering: NumberingMap | null | undefined): ParagraphAttrsPatch;
|
|
61
71
|
/** Recompute every level-dependent attr when a paragraph changes list level. */
|
|
62
|
-
declare function listLevelAttrPatch(attrs: Pick<ParagraphAttrs, "listImplicitChildLevelAdvances" | "_originalFormatting" | "_resolvedFormatting" | "_styleResolvedFormatting" | "numPr" | "numPrFromStyle" | "indentLeft" | "indentRight" | "indentFirstLine" | "hangingIndent">,
|
|
63
|
-
numId: number;
|
|
64
|
-
ilvl: number;
|
|
65
|
-
}, numbering: NumberingMap | null | undefined): ParagraphAttrsPatch;
|
|
72
|
+
declare function listLevelAttrPatch(attrs: Pick<ParagraphAttrs, "listImplicitChildLevelAdvances" | "_originalFormatting" | "_resolvedFormatting" | "_styleResolvedFormatting" | "numPr" | "numPrFromStyle" | "indentLeft" | "indentRight" | "indentFirstLine" | "hangingIndent">, ilvl: number, numbering: NumberingMap | null | undefined): ParagraphAttrsPatch;
|
|
66
73
|
//#endregion
|
|
67
74
|
export { listAttrsFromNumbering, listAttrsFromResolvedStyle, listIndentationProvenancePatch, listLevelAttrPatch, listLevelIndentRemovalPatch, paragraphAttrsFromResolvedStyle };
|
|
@@ -4,21 +4,12 @@ import { tableOfContentsStyleLevel } from "../../utils/tableOfContentsStyle.js";
|
|
|
4
4
|
import { setAutospacingBaseValue } from "../autospacingBase.js";
|
|
5
5
|
import { CLEARED_LIST_RENDERING_ATTRS } from "../listMarker.js";
|
|
6
6
|
import { listRenderingAttrPatch } from "../listRenderingAttrs.js";
|
|
7
|
-
import { paragraphNumberingAttr } from "../numberingAttr.js";
|
|
7
|
+
import { effectiveParagraphNumbering, effectiveParagraphNumberingReference, paragraphNumberingAttr, paragraphNumberingSourcesFromBoundary } from "../numberingAttr.js";
|
|
8
8
|
import { styleResolvedParagraphFormatting } from "../paragraphFormattingProvenance.js";
|
|
9
9
|
import { directParagraphIndentation, paragraphIndentationAttrPatch, paragraphIndentationFromFormatting, withDirectParagraphIndentation } from "../paragraphIndentation.js";
|
|
10
|
+
import { panic } from "better-result";
|
|
10
11
|
//#region src/prosemirror/styles/resolvedStyleAttrs.ts
|
|
11
12
|
/**
|
|
12
|
-
* Shared helper for projecting a resolved paragraph style onto ProseMirror
|
|
13
|
-
* paragraph node attrs.
|
|
14
|
-
*
|
|
15
|
-
* Both `applyStyle` (toolbar style picker) and the Enter handler's
|
|
16
|
-
* next-style switch need to write the same set of style-controlled attrs.
|
|
17
|
-
* Keeping the projection in one place ensures the two paths stay in sync —
|
|
18
|
-
* a style applied via the picker and a style applied on Enter produce
|
|
19
|
-
* identical paragraph attrs.
|
|
20
|
-
*/
|
|
21
|
-
/**
|
|
22
13
|
* The paragraph attrs a style definition controls. Applying a style resets
|
|
23
14
|
* every one of these to the style's value (or `null` to clear), so a prior
|
|
24
15
|
* style's properties (e.g. a heading's spacing) never leak through. Returns
|
|
@@ -82,10 +73,13 @@ function listAttrsFromResolvedStyle(resolved, numbering) {
|
|
|
82
73
|
const numPr = resolved.paragraphFormatting?.numPr;
|
|
83
74
|
if (numPr?.kind !== "reference") return null;
|
|
84
75
|
const { numId, ilvl = 0 } = numPr;
|
|
85
|
-
const attrs =
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
76
|
+
const attrs = {
|
|
77
|
+
...listAttrsFromNumbering({
|
|
78
|
+
numId,
|
|
79
|
+
ilvl
|
|
80
|
+
}, numbering),
|
|
81
|
+
numPr: null
|
|
82
|
+
};
|
|
89
83
|
attrs.numPrFromStyle = paragraphNumberingAttr(paragraphNumberingReference({
|
|
90
84
|
numId,
|
|
91
85
|
ilvl
|
|
@@ -173,7 +167,10 @@ function listIndentationProvenancePatch({ direct, styleFormatting, numberingSour
|
|
|
173
167
|
* {@link listLevelIndentAttrPatch}.
|
|
174
168
|
*/
|
|
175
169
|
function listLevelIndentRemovalPatch(attrs, numbering) {
|
|
176
|
-
if (
|
|
170
|
+
if (effectiveParagraphNumbering(paragraphNumberingSourcesFromBoundary({
|
|
171
|
+
numPr: attrs.numPr,
|
|
172
|
+
numPrFromStyle: attrs.numPrFromStyle
|
|
173
|
+
}))?.kind !== "reference") return {};
|
|
177
174
|
const direct = directParagraphIndentation(attrs);
|
|
178
175
|
return {
|
|
179
176
|
...listIndentationProvenancePatch({
|
|
@@ -187,15 +184,28 @@ function listLevelIndentRemovalPatch(attrs, numbering) {
|
|
|
187
184
|
};
|
|
188
185
|
}
|
|
189
186
|
/** Recompute every level-dependent attr when a paragraph changes list level. */
|
|
190
|
-
function listLevelAttrPatch(attrs,
|
|
187
|
+
function listLevelAttrPatch(attrs, ilvl, numbering) {
|
|
188
|
+
const reference = effectiveParagraphNumberingReference(paragraphNumberingSourcesFromBoundary({
|
|
189
|
+
numPr: attrs.numPr,
|
|
190
|
+
numPrFromStyle: attrs.numPrFromStyle
|
|
191
|
+
}));
|
|
192
|
+
if (reference === void 0) panic("Cannot change list level without an effective numbering reference");
|
|
193
|
+
const numPr = {
|
|
194
|
+
numId: reference.numId,
|
|
195
|
+
ilvl
|
|
196
|
+
};
|
|
191
197
|
const direct = directParagraphIndentation(attrs);
|
|
192
198
|
return {
|
|
193
199
|
...listAttrsFromNumbering(numPr, numbering),
|
|
200
|
+
...attrs.numPr?.kind !== "reference" && attrs.numPrFromStyle?.kind === "reference" ? { numPr: paragraphNumberingAttr({
|
|
201
|
+
kind: "levelOnly",
|
|
202
|
+
ilvl: numPr.ilvl
|
|
203
|
+
}) } : {},
|
|
194
204
|
listImplicitChildLevelAdvances: attrs.listImplicitChildLevelAdvances ?? null,
|
|
195
205
|
...listIndentationProvenancePatch({
|
|
196
206
|
direct,
|
|
197
207
|
styleFormatting: attrs._styleResolvedFormatting,
|
|
198
|
-
numberingSource: attrs.numPrFromStyle == null ? "paragraph" : "style",
|
|
208
|
+
numberingSource: attrs.numPr?.kind === "reference" || attrs.numPrFromStyle == null ? "paragraph" : "style",
|
|
199
209
|
numPr,
|
|
200
210
|
numbering
|
|
201
211
|
}),
|
|
@@ -8,20 +8,26 @@ import * as Y from "yjs";
|
|
|
8
8
|
*/
|
|
9
9
|
type AttrSchemaMigrationStep = (fragment: Y.XmlFragment) => number;
|
|
10
10
|
/** Every attr-schema version this build reads, oldest first, with no gaps. */
|
|
11
|
-
declare const FOLIO_YJS_ATTR_SCHEMA_VERSIONS: readonly [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
|
|
11
|
+
declare const FOLIO_YJS_ATTR_SCHEMA_VERSIONS: readonly [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
|
|
12
12
|
/** An attr-schema version this build can read. */
|
|
13
13
|
type FolioYjsAttrSchemaVersion = (typeof FOLIO_YJS_ATTR_SCHEMA_VERSIONS)[number];
|
|
14
14
|
/**
|
|
15
15
|
* The attr-schema version this build writes. Derived against the migration map
|
|
16
16
|
* so the constant and the map cannot disagree.
|
|
17
17
|
*/
|
|
18
|
-
declare const FOLIO_YJS_ATTR_SCHEMA_VERSION =
|
|
18
|
+
declare const FOLIO_YJS_ATTR_SCHEMA_VERSION = 13;
|
|
19
19
|
declare const FolioYjsNoteReferenceSchemaError_base: import("better-result").TaggedErrorClass<"FolioYjsNoteReferenceSchemaError">;
|
|
20
20
|
declare class FolioYjsNoteReferenceSchemaError extends FolioYjsNoteReferenceSchemaError_base<{
|
|
21
21
|
message: string;
|
|
22
22
|
schemaVersion: FolioYjsAttrSchemaVersion;
|
|
23
23
|
requiredSchemaVersion: FolioYjsAttrSchemaVersion;
|
|
24
24
|
}> {}
|
|
25
|
+
declare const FolioYjsNumberingSourceSchemaError_base: import("better-result").TaggedErrorClass<"FolioYjsNumberingSourceSchemaError">;
|
|
26
|
+
declare class FolioYjsNumberingSourceSchemaError extends FolioYjsNumberingSourceSchemaError_base<{
|
|
27
|
+
message: string;
|
|
28
|
+
schemaVersion: FolioYjsAttrSchemaVersion;
|
|
29
|
+
requiredSchemaVersion: FolioYjsAttrSchemaVersion;
|
|
30
|
+
}> {}
|
|
25
31
|
/**
|
|
26
32
|
* The steps that carry a snapshot written under `fromVersion` up to
|
|
27
33
|
* {@link FOLIO_YJS_ATTR_SCHEMA_VERSION}, in order. Empty when the snapshot is
|
|
@@ -76,4 +82,4 @@ declare const writeYjsDocumentMetadata: (ydoc: Y.Doc, document: Node) => void;
|
|
|
76
82
|
declare const readYjsParagraphSourceContract: (ydoc: Y.Doc) => string | null;
|
|
77
83
|
declare const withParagraphSourceContract: (document: Node, contract: string) => Node;
|
|
78
84
|
//#endregion
|
|
79
|
-
export { FOLIO_YJS_ATTR_SCHEMA_VERSION, FolioYjsAttrSchemaVersion, FolioYjsAttrSchemaVersionError, FolioYjsNoteReferenceSchemaError, applyAttrSchemaMigrations, attrSchemaMigrationSteps, proseDocumentParagraphSourceContract, readYjsAttrSchemaVersion, readYjsParagraphSourceContract, withParagraphSourceContract, writeYjsAttrSchemaVersion, writeYjsDocumentMetadata };
|
|
85
|
+
export { FOLIO_YJS_ATTR_SCHEMA_VERSION, FolioYjsAttrSchemaVersion, FolioYjsAttrSchemaVersionError, FolioYjsNoteReferenceSchemaError, FolioYjsNumberingSourceSchemaError, applyAttrSchemaMigrations, attrSchemaMigrationSteps, proseDocumentParagraphSourceContract, readYjsAttrSchemaVersion, readYjsParagraphSourceContract, withParagraphSourceContract, writeYjsAttrSchemaVersion, writeYjsDocumentMetadata };
|
|
@@ -475,7 +475,8 @@ const FOLIO_YJS_ATTR_SCHEMA_VERSIONS = [
|
|
|
475
475
|
9,
|
|
476
476
|
10,
|
|
477
477
|
11,
|
|
478
|
-
12
|
|
478
|
+
12,
|
|
479
|
+
13
|
|
479
480
|
];
|
|
480
481
|
/**
|
|
481
482
|
* The one place a persisted attr-shape change is decided.
|
|
@@ -500,14 +501,44 @@ const ATTR_SCHEMA_MIGRATIONS = {
|
|
|
500
501
|
9: dropUnstatedPlaceholderFlags,
|
|
501
502
|
10: renamePageBreakRunOwnerMarkAttr,
|
|
502
503
|
11: stampMarkerOnly,
|
|
503
|
-
12:
|
|
504
|
+
12: stampMarkerOnly,
|
|
505
|
+
13: "current"
|
|
504
506
|
};
|
|
505
507
|
/**
|
|
506
508
|
* The attr-schema version this build writes. Derived against the migration map
|
|
507
509
|
* so the constant and the map cannot disagree.
|
|
508
510
|
*/
|
|
509
|
-
const FOLIO_YJS_ATTR_SCHEMA_VERSION =
|
|
511
|
+
const FOLIO_YJS_ATTR_SCHEMA_VERSION = 13;
|
|
510
512
|
var FolioYjsNoteReferenceSchemaError = class extends TaggedError("FolioYjsNoteReferenceSchemaError") {};
|
|
513
|
+
var FolioYjsNumberingSourceSchemaError = class extends TaggedError("FolioYjsNumberingSourceSchemaError") {};
|
|
514
|
+
/** Older snapshots can hold a resolved style reference where a stated override belongs. */
|
|
515
|
+
const requireStatedNumberingSources = (fragment, schemaVersion) => {
|
|
516
|
+
if (schemaVersion === 13) return;
|
|
517
|
+
const pending = [];
|
|
518
|
+
const visit = (node) => {
|
|
519
|
+
if ("getAttributes" in node) pending.push(node.getAttributes());
|
|
520
|
+
for (const child of node.toArray()) if (typeof child !== "string" && !isXmlText(child) && "toArray" in child) visit(child);
|
|
521
|
+
};
|
|
522
|
+
visit(fragment);
|
|
523
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
524
|
+
while (pending.length > 0) {
|
|
525
|
+
const value = pending.pop();
|
|
526
|
+
if (typeof value !== "object" || value === null || seen.has(value)) continue;
|
|
527
|
+
seen.add(value);
|
|
528
|
+
if (Array.isArray(value)) {
|
|
529
|
+
for (const entry of value) pending.push(entry);
|
|
530
|
+
continue;
|
|
531
|
+
}
|
|
532
|
+
if (!isRecord(value)) continue;
|
|
533
|
+
const numbering = value["numPr"];
|
|
534
|
+
if (isRecord(value["numPrFromStyle"]) && isRecord(numbering) && (numbering["kind"] === "reference" || "numId" in numbering)) throw new FolioYjsNumberingSourceSchemaError({
|
|
535
|
+
schemaVersion,
|
|
536
|
+
requiredSchemaVersion: 13,
|
|
537
|
+
message: `Yjs schema ${schemaVersion} has ambiguous numbering ownership; schema 13 requires stated numbering overrides. Rebuild the collaboration state from the saved DOCX.`
|
|
538
|
+
});
|
|
539
|
+
for (const entry of Object.values(value)) pending.push(entry);
|
|
540
|
+
}
|
|
541
|
+
};
|
|
511
542
|
/** Check before any migration mutates the snapshot or any PM builder can drop text. */
|
|
512
543
|
const requireNoteOccurrenceAttribution = (fragment, schemaVersion) => {
|
|
513
544
|
const visit = (node) => {
|
|
@@ -524,8 +555,8 @@ const requireNoteOccurrenceAttribution = (fragment, schemaVersion) => {
|
|
|
524
555
|
if (isRecord(reference) && isNoteReferenceOccurrenceId(reference["occurrenceId"])) continue;
|
|
525
556
|
throw new FolioYjsNoteReferenceSchemaError({
|
|
526
557
|
schemaVersion,
|
|
527
|
-
requiredSchemaVersion:
|
|
528
|
-
message: `Yjs schema ${schemaVersion} has unattributed note references; schema
|
|
558
|
+
requiredSchemaVersion: 13,
|
|
559
|
+
message: `Yjs schema ${schemaVersion} has unattributed note references; schema 13 requires occurrence identities. Rebuild the collaboration state from the saved DOCX.`
|
|
529
560
|
});
|
|
530
561
|
}
|
|
531
562
|
}
|
|
@@ -557,7 +588,8 @@ const attrSchemaMigrationSteps = (fromVersion) => FOLIO_YJS_ATTR_SCHEMA_VERSIONS
|
|
|
557
588
|
*/
|
|
558
589
|
const applyAttrSchemaMigrations = (ydoc, fragment, fromVersion) => {
|
|
559
590
|
requireNoteOccurrenceAttribution(fragment, fromVersion);
|
|
560
|
-
|
|
591
|
+
requireStatedNumberingSources(fragment, fromVersion);
|
|
592
|
+
if (fromVersion === 13) return 0;
|
|
561
593
|
let rewritten = 0;
|
|
562
594
|
ydoc.transact(() => {
|
|
563
595
|
for (const step of attrSchemaMigrationSteps(fromVersion)) rewritten += step(fragment);
|
|
@@ -567,7 +599,7 @@ const applyAttrSchemaMigrations = (ydoc, fragment, fromVersion) => {
|
|
|
567
599
|
};
|
|
568
600
|
/** Raised when a snapshot's attr-schema marker is ahead of the running code. */
|
|
569
601
|
var FolioYjsAttrSchemaVersionError = class extends TaggedError("FolioYjsAttrSchemaVersionError") {};
|
|
570
|
-
const isReadableVersion = (marker) => typeof marker === "number" && Number.isInteger(marker) && marker >= 0 && marker <=
|
|
602
|
+
const isReadableVersion = (marker) => typeof marker === "number" && Number.isInteger(marker) && marker >= 0 && marker <= 13;
|
|
571
603
|
/**
|
|
572
604
|
* The attr-schema version a collaboration document was written under.
|
|
573
605
|
*
|
|
@@ -585,7 +617,7 @@ const readYjsAttrSchemaVersion = (ydoc) => {
|
|
|
585
617
|
return Result.err(new FolioYjsAttrSchemaVersionError({
|
|
586
618
|
marker,
|
|
587
619
|
message: "The collaboration snapshot was written by a newer Folio attr schema than this build reads.",
|
|
588
|
-
supportedVersion:
|
|
620
|
+
supportedVersion: 13
|
|
589
621
|
}));
|
|
590
622
|
};
|
|
591
623
|
const proseDocumentParagraphSourceContract = (document) => {
|
|
@@ -593,7 +625,7 @@ const proseDocumentParagraphSourceContract = (document) => {
|
|
|
593
625
|
};
|
|
594
626
|
/** Stamp the attr-schema version of the build that wrote the current fragment. */
|
|
595
627
|
const writeYjsAttrSchemaVersion = (ydoc) => {
|
|
596
|
-
ydoc.getMap(FOLIO_YJS_METADATA_MAP_NAME).set(ATTR_SCHEMA_VERSION_KEY,
|
|
628
|
+
ydoc.getMap(FOLIO_YJS_METADATA_MAP_NAME).set(ATTR_SCHEMA_VERSION_KEY, 13);
|
|
597
629
|
};
|
|
598
630
|
/**
|
|
599
631
|
* Write both metadata bindings for a freshly seeded collaboration document.
|
|
@@ -618,4 +650,4 @@ const withParagraphSourceContract = (document, contract) => {
|
|
|
618
650
|
}, document.content, document.marks);
|
|
619
651
|
};
|
|
620
652
|
//#endregion
|
|
621
|
-
export { FOLIO_YJS_ATTR_SCHEMA_VERSION, FolioYjsAttrSchemaVersionError, FolioYjsNoteReferenceSchemaError, applyAttrSchemaMigrations, attrSchemaMigrationSteps, proseDocumentParagraphSourceContract, readYjsAttrSchemaVersion, readYjsParagraphSourceContract, withParagraphSourceContract, writeYjsAttrSchemaVersion, writeYjsDocumentMetadata };
|
|
653
|
+
export { FOLIO_YJS_ATTR_SCHEMA_VERSION, FolioYjsAttrSchemaVersionError, FolioYjsNoteReferenceSchemaError, FolioYjsNumberingSourceSchemaError, applyAttrSchemaMigrations, attrSchemaMigrationSteps, proseDocumentParagraphSourceContract, readYjsAttrSchemaVersion, readYjsParagraphSourceContract, withParagraphSourceContract, writeYjsAttrSchemaVersion, writeYjsDocumentMetadata };
|
package/dist/redline.d.ts
CHANGED
|
@@ -20,6 +20,12 @@ declare class InvalidGenerateRedlineDocxOptionsError extends InvalidGenerateRedl
|
|
|
20
20
|
option: "baseView" | "revisedView";
|
|
21
21
|
receivedValue: unknown;
|
|
22
22
|
}> {}
|
|
23
|
+
declare const GenerateRedlineDocxResourceImportError_base: import("better-result").TaggedErrorClass<"GenerateRedlineDocxResourceImportError">;
|
|
24
|
+
/** Raised before body operations when revised resources cannot be imported atomically. */
|
|
25
|
+
declare class GenerateRedlineDocxResourceImportError extends GenerateRedlineDocxResourceImportError_base<{
|
|
26
|
+
message: string;
|
|
27
|
+
detail: string;
|
|
28
|
+
}> {}
|
|
23
29
|
/** A document story that could not be paired across the two input packages. */
|
|
24
30
|
type GenerateRedlineUnprocessedStory = {
|
|
25
31
|
/** Story in the base package, or `null` when it exists only in the revision. */
|
|
@@ -29,6 +35,14 @@ type GenerateRedlineUnprocessedStory = {
|
|
|
29
35
|
/** Why the story could not be represented in the generated redline. */
|
|
30
36
|
reason: "missing-base-story" | "missing-revised-story";
|
|
31
37
|
};
|
|
38
|
+
/** A source-undefined style cleared so it cannot acquire unrelated base meaning. */
|
|
39
|
+
type GenerateRedlineReferenceWarning = {
|
|
40
|
+
/** Position in the revised story's ProseMirror projection. */
|
|
41
|
+
paragraphPosition: number;
|
|
42
|
+
story: FolioDocumentStoryHandle;
|
|
43
|
+
kind: "style";
|
|
44
|
+
id: string;
|
|
45
|
+
};
|
|
32
46
|
/** Result of {@link generateRedlineDocx}. */
|
|
33
47
|
type GenerateRedlineDocxResult = {
|
|
34
48
|
/** The base package with generated tracked changes. */
|
|
@@ -37,6 +51,8 @@ type GenerateRedlineDocxResult = {
|
|
|
37
51
|
applied: FolioAIEditAppliedOperation[];
|
|
38
52
|
/** Block operations that could not be applied. */
|
|
39
53
|
skipped: FolioAIEditSkippedOperation[];
|
|
54
|
+
/** Undefined source references cleared to avoid binding to a base definition. */
|
|
55
|
+
referenceWarnings: GenerateRedlineReferenceWarning[];
|
|
40
56
|
/** Package parts that could not be represented as story-scoped text edits. */
|
|
41
57
|
unprocessedStories: GenerateRedlineUnprocessedStory[];
|
|
42
58
|
/** Privacy transforms applied to the generated package. */
|
|
@@ -45,4 +61,4 @@ type GenerateRedlineDocxResult = {
|
|
|
45
61
|
/** Compare two buffers and return tracked changes for every matched editable story. */
|
|
46
62
|
declare const generateRedlineDocx: (base: ArrayBuffer, revised: ArrayBuffer, options?: GenerateRedlineDocxOptions) => Promise<GenerateRedlineDocxResult>;
|
|
47
63
|
//#endregion
|
|
48
|
-
export { GenerateRedlineDocxOptions, GenerateRedlineDocxResult, GenerateRedlineUnprocessedStory, InvalidGenerateRedlineDocxOptionsError, generateRedlineDocx };
|
|
64
|
+
export { GenerateRedlineDocxOptions, GenerateRedlineDocxResourceImportError, GenerateRedlineDocxResult, GenerateRedlineReferenceWarning, GenerateRedlineUnprocessedStory, InvalidGenerateRedlineDocxOptionsError, generateRedlineDocx };
|
package/dist/redline.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { FolioDocxReviewer, getFolioDocxComparisonAccess, isFolioResolvedReviewedView } from "./ai-edits/headless.js";
|
|
2
|
+
import { classifyResourceReference } from "./ai-edits/referenceClassification.js";
|
|
2
3
|
import { createFolioAITextRangeHandle, trailingBodyBlockId } from "./ai-edits/snapshot.js";
|
|
3
4
|
import { createScopedWordDiffOptions } from "./ai-edits/word-diff.js";
|
|
4
5
|
import { FolioContentInlinePresentationProjectionError } from "./compare/content.js";
|
|
5
6
|
import { inlineFormattingSegments } from "./compare/formatting.js";
|
|
7
|
+
import { importStyleClosureWithNumbering } from "./compare/import-style-closure.js";
|
|
8
|
+
import { createInsertedResourceProjection, rebindInsertedResourceBlocks } from "./compare/inserted-resource-snapshot.js";
|
|
6
9
|
import "./document-operations.js";
|
|
7
10
|
import { pairFolioDocumentStories } from "./document-stories.js";
|
|
8
11
|
import { resolveFolioDocumentPrivacyTransforms, rewriteDocxMetadataPrivacy } from "./docx/metadataPrivacy.js";
|
|
@@ -23,6 +26,8 @@ import { TaggedError, panic } from "better-result";
|
|
|
23
26
|
*/
|
|
24
27
|
/** Raised when a resolved input view is not `"original"` or `"final"`. */
|
|
25
28
|
var InvalidGenerateRedlineDocxOptionsError = class extends TaggedError("InvalidGenerateRedlineDocxOptionsError") {};
|
|
29
|
+
/** Raised before body operations when revised resources cannot be imported atomically. */
|
|
30
|
+
var GenerateRedlineDocxResourceImportError = class extends TaggedError("GenerateRedlineDocxResourceImportError") {};
|
|
26
31
|
const nextBaseBlockIdByIndex = (events) => {
|
|
27
32
|
const nextIds = Array.from({ length: events.length });
|
|
28
33
|
let nextId = null;
|
|
@@ -136,68 +141,83 @@ const statedOrCleared = (revised, anchor) => revised ?? (anchor === void 0 ? voi
|
|
|
136
141
|
* beside a list item stays plain.
|
|
137
142
|
*/
|
|
138
143
|
const insertedParagraphProperties = (block, anchor) => {
|
|
144
|
+
const paragraph = paragraphBlockOf(block);
|
|
145
|
+
if (paragraph === void 0) return {};
|
|
146
|
+
const anchorParagraph = anchor === void 0 ? void 0 : paragraphBlockOf(anchor);
|
|
139
147
|
const properties = {};
|
|
140
|
-
const styleId = statedOrCleared(
|
|
148
|
+
const styleId = statedOrCleared(paragraph.styleId, anchorParagraph?.styleId);
|
|
141
149
|
if (styleId !== void 0) properties.styleId = styleId;
|
|
142
|
-
const alignment = statedOrCleared(
|
|
150
|
+
const alignment = statedOrCleared(paragraph.directAlignment, anchorParagraph?.directAlignment);
|
|
143
151
|
if (alignment !== void 0) properties.alignment = alignment;
|
|
144
|
-
const spacing = statedOrCleared(
|
|
152
|
+
const spacing = statedOrCleared(paragraph.directSpacing, anchorParagraph?.directSpacing);
|
|
145
153
|
if (spacing !== void 0) properties.spacing = spacing;
|
|
146
|
-
const indentation = statedOrCleared(
|
|
154
|
+
const indentation = statedOrCleared(paragraph.directIndentation, anchorParagraph?.directIndentation);
|
|
147
155
|
if (indentation !== void 0) properties.indentation = indentation;
|
|
148
|
-
|
|
149
|
-
properties.numbering = block.listReference ?? null;
|
|
150
|
-
properties.listLevel = block.listLevel ?? null;
|
|
151
|
-
} else if (block.listLevel !== void 0) properties.listLevel = block.listLevel;
|
|
156
|
+
properties.numbering = paragraph.statedNumbering;
|
|
152
157
|
return properties;
|
|
153
158
|
};
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
159
|
+
const paragraphBlockOf = (block) => {
|
|
160
|
+
switch (block.kind) {
|
|
161
|
+
case "paragraph":
|
|
162
|
+
case "heading":
|
|
163
|
+
case "listItem": return block;
|
|
164
|
+
case "diagnostic": return;
|
|
165
|
+
default: return panic("Unhandled redline block kind", { block });
|
|
166
|
+
}
|
|
158
167
|
};
|
|
159
168
|
/** The `w:numId`s whose `w:num` and abstract definition both exist. */
|
|
160
169
|
const definedNumIds = (numbering) => {
|
|
161
170
|
const abstractIds = new Set(numbering?.abstractNums.map((entry) => entry.abstractNumId));
|
|
162
171
|
return new Set((numbering?.nums ?? []).filter((entry) => abstractIds.has(entry.abstractNumId)).map((entry) => entry.numId));
|
|
163
172
|
};
|
|
164
|
-
/**
|
|
165
|
-
|
|
166
|
-
* The redline is the base package, where the revised version's `w:numId` may
|
|
167
|
-
* name nothing, or another list: the referenced definitions are copied in,
|
|
168
|
-
* under a fresh id wherever the base uses that one for different numbering.
|
|
169
|
-
* A reference the revised package cannot resolve shows no number there
|
|
170
|
-
* either, and is inserted without one.
|
|
171
|
-
*/
|
|
172
|
-
const bindInsertedNumbering = (baseReviewer, revisedReviewer, operationsByStory) => {
|
|
173
|
-
const baseAccess = getFolioDocxComparisonAccess(baseReviewer);
|
|
173
|
+
/** Unresolvable source references have no visible list; retain only importable resources. */
|
|
174
|
+
const insertedNumberingReferences = (revisedReviewer, snapshots) => {
|
|
174
175
|
const revisedNumbering = getFolioDocxComparisonAccess(revisedReviewer).numberingDefinitions();
|
|
175
176
|
const resolvable = definedNumIds(revisedNumbering);
|
|
176
|
-
|
|
177
|
-
const
|
|
178
|
-
return
|
|
179
|
-
}));
|
|
180
|
-
const remapped = baseAccess.planTargetNumberingReferences(revisedNumbering, references) ?? panic("Resolvable revised numbering references could not be planned");
|
|
181
|
-
baseAccess.stageTargetNumbering(revisedNumbering, references, remapped);
|
|
182
|
-
const defined = definedNumIds(baseAccess.numberingDefinitions());
|
|
183
|
-
return operationsByStory.map((operations) => operations.map((operation) => {
|
|
184
|
-
const numbering = insertedNumbering(operation);
|
|
185
|
-
if (numbering === null) return operation;
|
|
186
|
-
const numId = remapped.get(numbering.numId) ?? numbering.numId;
|
|
187
|
-
if (!resolvable.has(numbering.numId) || !defined.has(numId)) return {
|
|
188
|
-
...operation,
|
|
189
|
-
numbering: null,
|
|
190
|
-
listLevel: null
|
|
191
|
-
};
|
|
192
|
-
return {
|
|
193
|
-
...operation,
|
|
194
|
-
numbering: {
|
|
195
|
-
numId,
|
|
196
|
-
level: numbering.level
|
|
197
|
-
}
|
|
198
|
-
};
|
|
177
|
+
return snapshots.flatMap((snapshot) => snapshot.blocks.flatMap((block) => {
|
|
178
|
+
const reference = paragraphBlockOf(block)?.listReference;
|
|
179
|
+
return reference && resolvable.has(reference.numId) ? [reference] : [];
|
|
199
180
|
}));
|
|
200
181
|
};
|
|
182
|
+
const prepareInsertedReferences = ({ original, rebound, sourceStyles, destinationStyles, paragraphPosition, story }) => {
|
|
183
|
+
const source = paragraphBlockOf(original);
|
|
184
|
+
const imported = paragraphBlockOf(rebound);
|
|
185
|
+
const warnings = [];
|
|
186
|
+
if (source === void 0 || imported === void 0) return {
|
|
187
|
+
block: rebound,
|
|
188
|
+
warnings
|
|
189
|
+
};
|
|
190
|
+
let block = { ...imported };
|
|
191
|
+
if (source.styleId !== void 0) {
|
|
192
|
+
const disposition = classifyResourceReference({
|
|
193
|
+
kind: "style",
|
|
194
|
+
id: source.styleId,
|
|
195
|
+
sourceDefines: (id) => sourceStyles.has(id),
|
|
196
|
+
destinationDefines: (id) => destinationStyles.has(id)
|
|
197
|
+
});
|
|
198
|
+
if (disposition !== "sourceDefined") block = { ...source };
|
|
199
|
+
if (disposition === "destinationCollision") {
|
|
200
|
+
delete block.styleId;
|
|
201
|
+
warnings.push({
|
|
202
|
+
kind: "style",
|
|
203
|
+
id: source.styleId,
|
|
204
|
+
paragraphPosition,
|
|
205
|
+
story
|
|
206
|
+
});
|
|
207
|
+
} else if (disposition === "unknown") block.styleId = source.styleId;
|
|
208
|
+
}
|
|
209
|
+
if (source.statedNumbering.kind === "reference") {
|
|
210
|
+
block.statedNumbering = imported.statedNumbering;
|
|
211
|
+
if (imported.listReference === void 0) delete block.listReference;
|
|
212
|
+
else block.listReference = imported.listReference;
|
|
213
|
+
if (imported.displayLabel === void 0) delete block.displayLabel;
|
|
214
|
+
else block.displayLabel = imported.displayLabel;
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
block,
|
|
218
|
+
warnings
|
|
219
|
+
};
|
|
220
|
+
};
|
|
201
221
|
const resolveInputView = (value, option) => {
|
|
202
222
|
if (value === void 0) return "final";
|
|
203
223
|
if (!isFolioResolvedReviewedView(value)) throw new InvalidGenerateRedlineDocxOptionsError({
|
|
@@ -221,6 +241,10 @@ const generateRedlineDocx = async (base, revised, options = {}) => {
|
|
|
221
241
|
})) panic("A listed base story could not be resolved");
|
|
222
242
|
const applied = [];
|
|
223
243
|
const skipped = [];
|
|
244
|
+
const referenceWarnings = [];
|
|
245
|
+
const baseAccess = getFolioDocxComparisonAccess(baseReviewer);
|
|
246
|
+
const sourceAccess = getFolioDocxComparisonAccess(revisedReviewer);
|
|
247
|
+
const sourceStyles = new Set(sourceAccess.styleDefinitions()?.styles.map(({ styleId }) => styleId));
|
|
224
248
|
const unprocessedStories = [];
|
|
225
249
|
const wordDiff = createScopedWordDiffOptions({});
|
|
226
250
|
let operationSequence = 0;
|
|
@@ -250,21 +274,57 @@ const generateRedlineDocx = async (base, revised, options = {}) => {
|
|
|
250
274
|
view: revisedView
|
|
251
275
|
})?.snapshot;
|
|
252
276
|
if (!baseSnapshot || !revisedSnapshot) panic("A matched document story could not be read");
|
|
253
|
-
const operations = buildRedlineOperations({
|
|
254
|
-
baseSnapshot,
|
|
255
|
-
revisedBlocks: revisedSnapshot.blocks,
|
|
256
|
-
nextOperationId
|
|
257
|
-
});
|
|
258
|
-
if (operations.length === 0) continue;
|
|
259
277
|
plannedStories.push({
|
|
260
278
|
story: pair.baseStory,
|
|
261
279
|
snapshot: baseSnapshot,
|
|
262
|
-
|
|
280
|
+
revisedSnapshot,
|
|
281
|
+
inserted: createInsertedResourceProjection({
|
|
282
|
+
base: baseSnapshot,
|
|
283
|
+
revised: revisedSnapshot
|
|
284
|
+
})
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
const insertedSnapshots = plannedStories.map(({ inserted }) => inserted.snapshot);
|
|
288
|
+
const numberingReferences = insertedNumberingReferences(revisedReviewer, insertedSnapshots);
|
|
289
|
+
const resources = importStyleClosureWithNumbering({
|
|
290
|
+
destination: baseReviewer,
|
|
291
|
+
source: revisedReviewer,
|
|
292
|
+
snapshots: insertedSnapshots,
|
|
293
|
+
importedHeaderFooterSnapshots: insertedSnapshots,
|
|
294
|
+
numberingReferences
|
|
295
|
+
});
|
|
296
|
+
const { styleImport } = resources;
|
|
297
|
+
if (styleImport.status === "unalignable" || resources.numberingStage === "conflict") {
|
|
298
|
+
const detail = styleImport.status === "unalignable" ? styleImport.detail : `target numbering references ${numberingReferences.map(({ numId, level }) => `${numId}:${level}`).join(", ")} cannot be imported without changing existing references`;
|
|
299
|
+
throw new GenerateRedlineDocxResourceImportError({
|
|
300
|
+
message: `The revised style/numbering closure cannot be imported: ${detail}`,
|
|
301
|
+
detail
|
|
263
302
|
});
|
|
264
303
|
}
|
|
265
|
-
const
|
|
266
|
-
for (const [index, { story, snapshot }] of plannedStories.entries()) {
|
|
267
|
-
const
|
|
304
|
+
const destinationStyles = new Set(baseAccess.styleDefinitions()?.styles.map(({ styleId }) => styleId));
|
|
305
|
+
for (const [index, { story, snapshot, revisedSnapshot, inserted }] of plannedStories.entries()) {
|
|
306
|
+
const insertedById = rebindInsertedResourceBlocks(inserted, resources.snapshots.at(index) ?? panic("A redline resource import lost its snapshot"));
|
|
307
|
+
const originalBlocksById = new Map(revisedSnapshot.blocks.map((block) => [block.id, block]));
|
|
308
|
+
for (const [id, imported] of insertedById) {
|
|
309
|
+
const original = originalBlocksById.get(id) ?? panic("A carried insertion lost its original block");
|
|
310
|
+
const anchor = revisedSnapshot.anchors[id] ?? panic("A carried insertion lost its original position");
|
|
311
|
+
const prepared = prepareInsertedReferences({
|
|
312
|
+
original,
|
|
313
|
+
rebound: imported,
|
|
314
|
+
sourceStyles,
|
|
315
|
+
destinationStyles,
|
|
316
|
+
paragraphPosition: anchor.from,
|
|
317
|
+
story
|
|
318
|
+
});
|
|
319
|
+
insertedById.set(id, prepared.block);
|
|
320
|
+
referenceWarnings.push(...prepared.warnings);
|
|
321
|
+
}
|
|
322
|
+
const operations = buildRedlineOperations({
|
|
323
|
+
baseSnapshot: snapshot,
|
|
324
|
+
revisedBlocks: revisedSnapshot.blocks.map((block) => insertedById.get(block.id) ?? block),
|
|
325
|
+
nextOperationId
|
|
326
|
+
});
|
|
327
|
+
if (operations.length === 0) continue;
|
|
268
328
|
const result = baseReviewer.applyDocumentOperationsToStory({
|
|
269
329
|
story,
|
|
270
330
|
snapshot,
|
|
@@ -274,7 +334,7 @@ const generateRedlineDocx = async (base, revised, options = {}) => {
|
|
|
274
334
|
operations
|
|
275
335
|
},
|
|
276
336
|
wordDiff,
|
|
277
|
-
|
|
337
|
+
undefinedReferences: "keep"
|
|
278
338
|
});
|
|
279
339
|
applied.push(...result.applied);
|
|
280
340
|
skipped.push(...result.skipped);
|
|
@@ -291,9 +351,10 @@ const generateRedlineDocx = async (base, revised, options = {}) => {
|
|
|
291
351
|
buffer: privacyResult.buffer,
|
|
292
352
|
applied,
|
|
293
353
|
skipped,
|
|
354
|
+
referenceWarnings,
|
|
294
355
|
unprocessedStories,
|
|
295
356
|
privacyReport: privacyResult.privacyReport
|
|
296
357
|
};
|
|
297
358
|
};
|
|
298
359
|
//#endregion
|
|
299
|
-
export { InvalidGenerateRedlineDocxOptionsError, generateRedlineDocx };
|
|
360
|
+
export { GenerateRedlineDocxResourceImportError, InvalidGenerateRedlineDocxOptionsError, generateRedlineDocx };
|