@stll/folio-core 0.37.5 → 0.38.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.js +275 -88
- package/dist/ai-edits/clean-text.js +12 -1
- package/dist/ai-edits/headless.d.ts +110 -0
- package/dist/ai-edits/headless.js +569 -40
- package/dist/ai-edits/snapshot.d.ts +24 -1
- package/dist/ai-edits/snapshot.js +206 -9
- package/dist/ai-edits/table-geometry.d.ts +7 -7
- package/dist/ai-edits/table-geometry.js +43 -27
- package/dist/ai-edits/table-template.d.ts +2 -1
- package/dist/ai-edits/table-template.js +9 -3
- package/dist/ai-edits/types.d.ts +37 -15
- package/dist/compare/__fixtures__/body-sequence.d.ts +4 -0
- package/dist/compare/__fixtures__/body-sequence.js +5 -3
- package/dist/compare/compare.d.ts +26 -2
- package/dist/compare/compare.js +444 -16
- package/dist/compare/content-alignment.js +3 -2
- package/dist/compare/content-types.d.ts +34 -2
- package/dist/compare/content.d.ts +13 -10
- package/dist/compare/content.js +69 -23
- package/dist/compare/formatting.d.ts +4 -22
- package/dist/compare/formatting.js +8 -112
- package/dist/compare/inline-atom-resources.d.ts +6 -0
- package/dist/compare/inline-atom-resources.js +26 -0
- package/dist/compare/inline-atoms.d.ts +35 -0
- package/dist/compare/inline-atoms.js +383 -0
- package/dist/compare/inline-provenance.d.ts +36 -0
- package/dist/compare/inline-provenance.js +334 -0
- package/dist/compare/plan.d.ts +4 -1
- package/dist/compare/plan.js +32 -4
- package/dist/compare/scenario.d.ts +4 -6
- package/dist/compare/section-boundary-properties.d.ts +63 -0
- package/dist/compare/section-boundary-properties.js +235 -0
- package/dist/compare/style-resources.d.ts +30 -0
- package/dist/compare/style-resources.js +404 -0
- package/dist/compare/types.d.ts +50 -11
- package/dist/compare/types.js +3 -1
- package/dist/compare/verification.d.ts +3 -5
- package/dist/compare/verification.js +8 -39
- package/dist/compat/eigenpal.d.ts +4 -4
- package/dist/compat/eigenpal.js +3 -3
- package/dist/document-operations.d.ts +5 -3
- package/dist/document-operations.js +112 -5
- package/dist/docx/blockContentParser.js +14 -2
- package/dist/docx/drawingIdNormalization.js +43 -2
- package/dist/docx/drawingRelationships.d.ts +10 -0
- package/dist/docx/drawingRelationships.js +28 -0
- package/dist/docx/fieldParser.js +1 -1
- package/dist/docx/hyperlinkParser.js +3 -5
- package/dist/docx/imageRawXml.d.ts +8 -0
- package/dist/docx/imageRawXml.js +13 -0
- package/dist/docx/newImage.d.ts +2 -2
- package/dist/docx/newImage.js +3 -3
- package/dist/docx/numberingParser.js +30 -27
- package/dist/docx/paragraphParser.js +11 -4
- package/dist/docx/removeHeaderFooterParts.d.ts +14 -0
- package/dist/docx/removeHeaderFooterParts.js +87 -0
- package/dist/docx/rezip.d.ts +3 -1
- package/dist/docx/rezip.js +143 -41
- package/dist/docx/runParser.js +16 -5
- package/dist/docx/sectionParser.js +3 -0
- package/dist/docx/sectionReferenceHistory.d.ts +17 -0
- package/dist/docx/sectionReferenceHistory.js +59 -0
- package/dist/docx/selectiveSave.js +11 -31
- package/dist/docx/selectiveXmlPatch.d.ts +8 -1
- package/dist/docx/selectiveXmlPatch.js +62 -2
- package/dist/docx/serializer/paragraphSerializer.js +2 -0
- package/dist/docx/serializer/partNamespaces.d.ts +1 -1
- package/dist/docx/serializer/partNamespaces.js +4 -0
- package/dist/docx/serializer/runSerializer.js +2 -1
- package/dist/docx/serializer/sectionPropertiesSerializer.js +5 -2
- package/dist/docx/serializer/textFormattingSerializer.d.ts +1 -1
- package/dist/docx/serializer/textFormattingSerializer.js +3 -1
- package/dist/docx/tableParser.js +21 -11
- package/dist/docx/xmlParser.d.ts +10 -1
- package/dist/docx/xmlParser.js +23 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -3
- package/dist/internal/compare/inline-presentation.d.ts +20 -0
- package/dist/internal/compare/inline-presentation.js +222 -0
- package/dist/internal/paragraphFormattingSerialization.d.ts +3 -1
- package/dist/internal/paragraphFormattingSerialization.js +8 -1
- package/dist/internal/sectionReferenceResolution.d.ts +21 -0
- package/dist/internal/sectionReferenceResolution.js +72 -0
- package/dist/layout-bridge/convert/toFlowBlocks.js +1 -0
- package/dist/markdown/renderRuns.js +1 -0
- package/dist/markdown/renderTable.js +1 -0
- package/dist/prosemirror/attrs/index.js +20 -1
- package/dist/prosemirror/commands/comments.d.ts +11 -1
- package/dist/prosemirror/commands/comments.js +68 -6
- package/dist/prosemirror/commands/propertyChangeScope.d.ts +9 -3
- package/dist/prosemirror/commands/propertyChangeScope.js +4 -10
- package/dist/prosemirror/conversion/fromProseDoc.js +16 -8
- package/dist/prosemirror/conversion/toProseDoc.js +16 -57
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +2 -0
- package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.js +3 -0
- package/dist/prosemirror/imageCommit.js +7 -9
- package/dist/prosemirror/paragraphIndentation.d.ts +21 -0
- package/dist/prosemirror/paragraphIndentation.js +72 -0
- package/dist/prosemirror/plugins/documentNumbering.d.ts +3 -1
- package/dist/prosemirror/plugins/documentNumbering.js +7 -1
- package/dist/prosemirror/plugins/documentStyles.d.ts +3 -1
- package/dist/prosemirror/plugins/documentStyles.js +7 -1
- package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +3 -1
- package/dist/prosemirror/rebaseParagraphRunFormatting.js +2 -1
- package/dist/prosemirror/runFormattingInlineCarriers.d.ts +15 -2
- package/dist/prosemirror/runFormattingInlineCarriers.js +33 -3
- package/dist/prosemirror/runStyleFormatting.d.ts +15 -2
- package/dist/prosemirror/runStyleFormatting.js +76 -2
- package/dist/prosemirror/schema/marks.d.ts +3 -1
- package/dist/prosemirror/schema/marks.js +2 -0
- package/dist/prosemirror/schema/nodes.d.ts +3 -0
- package/dist/prosemirror/tableCellRevisionVisibility.d.ts +6 -0
- package/dist/prosemirror/tableCellRevisionVisibility.js +14 -0
- package/dist/prosemirror/trackedRunInlineAtoms.d.ts +1 -1
- package/dist/prosemirror/trackedRunInlineAtoms.js +1 -1
- package/dist/redline.js +15 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.js +2 -2
- package/dist/version-comparison.d.ts +2 -0
- package/dist/version-comparison.js +7 -2
- package/package.json +2 -2
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { panic } from "better-result";
|
|
2
|
+
//#region src/internal/compare/inline-presentation.ts
|
|
3
|
+
/**
|
|
4
|
+
* Canonical interpretation of the inline presentation carried by comparison
|
|
5
|
+
* snapshots.
|
|
6
|
+
*
|
|
7
|
+
* Effective and explicitly authored values are separate facts. Every caller
|
|
8
|
+
* compares them through the descriptor grammar below, so adding a supported
|
|
9
|
+
* property cannot update redline planning while leaving verification behind.
|
|
10
|
+
*/
|
|
11
|
+
const NO_PRESENTATION_DIFFERENCE = Symbol("no-inline-presentation-difference");
|
|
12
|
+
const HEX_COLOR = /^#?(?:[0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/u;
|
|
13
|
+
const normalizeInlinePresentationColor = (color) => HEX_COLOR.test(color) ? color.replace(/^#/u, "").toUpperCase() : color;
|
|
14
|
+
/**
|
|
15
|
+
* The one grammar for every modeled run-presentation property. The
|
|
16
|
+
* `SamePropertySet` constraint also rejects a field added to `FolioContentRun`
|
|
17
|
+
* without a corresponding authored-formatting representation, or vice versa.
|
|
18
|
+
*/
|
|
19
|
+
const INLINE_PRESENTATION_GRAMMAR = {
|
|
20
|
+
boolean: [
|
|
21
|
+
"bold",
|
|
22
|
+
"italic",
|
|
23
|
+
"underline",
|
|
24
|
+
"strike"
|
|
25
|
+
],
|
|
26
|
+
string: ["fontFamily"],
|
|
27
|
+
number: ["fontSizePt"],
|
|
28
|
+
color: ["color"]
|
|
29
|
+
};
|
|
30
|
+
const INLINE_PRESENTATION_HOT_PATH_GRAMMAR = INLINE_PRESENTATION_GRAMMAR;
|
|
31
|
+
/** Derived from the descriptor grammar; tests use it to prove full coverage. */
|
|
32
|
+
const CANONICAL_INLINE_PRESENTATION_PROPERTIES = Object.freeze([
|
|
33
|
+
...INLINE_PRESENTATION_GRAMMAR.boolean,
|
|
34
|
+
...INLINE_PRESENTATION_GRAMMAR.string,
|
|
35
|
+
...INLINE_PRESENTATION_GRAMMAR.number,
|
|
36
|
+
...INLINE_PRESENTATION_GRAMMAR.color
|
|
37
|
+
]);
|
|
38
|
+
const canonicalColor = (value) => value === null || value === void 0 ? value : normalizeInlinePresentationColor(value);
|
|
39
|
+
const writeCanonicalInlinePresentationDifferences = (base, revised, patch) => {
|
|
40
|
+
let changed = false;
|
|
41
|
+
const baseDirect = base?.directFormatting ?? {};
|
|
42
|
+
const revisedDirect = revised?.directFormatting ?? {};
|
|
43
|
+
for (const property of INLINE_PRESENTATION_HOT_PATH_GRAMMAR.boolean) {
|
|
44
|
+
const baseAuthored = baseDirect[property];
|
|
45
|
+
const revisedAuthored = revisedDirect[property];
|
|
46
|
+
const baseEffective = base?.[property] === true;
|
|
47
|
+
const revisedEffective = revised?.[property] === true;
|
|
48
|
+
let value;
|
|
49
|
+
if (baseAuthored !== revisedAuthored) value = revisedAuthored ?? null;
|
|
50
|
+
else if (baseEffective === revisedEffective) value = NO_PRESENTATION_DIFFERENCE;
|
|
51
|
+
else value = revisedEffective;
|
|
52
|
+
if (value !== NO_PRESENTATION_DIFFERENCE) {
|
|
53
|
+
changed = true;
|
|
54
|
+
if (patch !== null) patch[property] = value;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const stringProperty = INLINE_PRESENTATION_HOT_PATH_GRAMMAR.string[0];
|
|
58
|
+
let stringValue;
|
|
59
|
+
if (baseDirect[stringProperty] !== revisedDirect[stringProperty]) stringValue = revisedDirect[stringProperty] ?? null;
|
|
60
|
+
else if (base?.[stringProperty] === revised?.[stringProperty]) stringValue = NO_PRESENTATION_DIFFERENCE;
|
|
61
|
+
else stringValue = revised?.[stringProperty] ?? null;
|
|
62
|
+
if (stringValue !== NO_PRESENTATION_DIFFERENCE) {
|
|
63
|
+
changed = true;
|
|
64
|
+
if (patch !== null) patch[stringProperty] = stringValue;
|
|
65
|
+
}
|
|
66
|
+
const numberProperty = INLINE_PRESENTATION_HOT_PATH_GRAMMAR.number[0];
|
|
67
|
+
let numberValue;
|
|
68
|
+
if (baseDirect[numberProperty] !== revisedDirect[numberProperty]) numberValue = revisedDirect[numberProperty] ?? null;
|
|
69
|
+
else if (base?.[numberProperty] === revised?.[numberProperty]) numberValue = NO_PRESENTATION_DIFFERENCE;
|
|
70
|
+
else numberValue = revised?.[numberProperty] ?? null;
|
|
71
|
+
if (numberValue !== NO_PRESENTATION_DIFFERENCE) {
|
|
72
|
+
changed = true;
|
|
73
|
+
if (patch !== null) patch[numberProperty] = numberValue;
|
|
74
|
+
}
|
|
75
|
+
const colorProperty = INLINE_PRESENTATION_HOT_PATH_GRAMMAR.color[0];
|
|
76
|
+
const baseAuthoredColor = canonicalColor(baseDirect[colorProperty]);
|
|
77
|
+
const revisedAuthoredColor = canonicalColor(revisedDirect[colorProperty]);
|
|
78
|
+
const baseEffectiveColor = canonicalColor(base?.[colorProperty]);
|
|
79
|
+
const revisedEffectiveColor = canonicalColor(revised?.[colorProperty]);
|
|
80
|
+
let color;
|
|
81
|
+
if (baseAuthoredColor !== revisedAuthoredColor) color = revisedAuthoredColor ?? null;
|
|
82
|
+
else if (baseEffectiveColor === revisedEffectiveColor) color = NO_PRESENTATION_DIFFERENCE;
|
|
83
|
+
else color = revisedEffectiveColor ?? null;
|
|
84
|
+
if (color !== NO_PRESENTATION_DIFFERENCE) {
|
|
85
|
+
changed = true;
|
|
86
|
+
if (patch !== null) patch[colorProperty] = color;
|
|
87
|
+
}
|
|
88
|
+
return changed;
|
|
89
|
+
};
|
|
90
|
+
const canonicalInlinePresentationsEqual = (base, revised) => !writeCanonicalInlinePresentationDifferences(base, revised, null);
|
|
91
|
+
const changedCanonicalInlinePresentation = (base, revised) => {
|
|
92
|
+
const patch = {};
|
|
93
|
+
return writeCanonicalInlinePresentationDifferences(base, revised, patch) ? patch : null;
|
|
94
|
+
};
|
|
95
|
+
const sameCanonicalInlinePresentationPatch = (left, right) => {
|
|
96
|
+
for (const property of INLINE_PRESENTATION_GRAMMAR.boolean) if (left[property] !== right[property]) return false;
|
|
97
|
+
for (const property of INLINE_PRESENTATION_GRAMMAR.string) if (left[property] !== right[property]) return false;
|
|
98
|
+
for (const property of INLINE_PRESENTATION_GRAMMAR.number) if (left[property] !== right[property]) return false;
|
|
99
|
+
for (const property of INLINE_PRESENTATION_GRAMMAR.color) if (left[property] !== right[property]) return false;
|
|
100
|
+
return true;
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Walk the shared UTF-16 coordinate space once. Run boundaries may differ;
|
|
104
|
+
* malformed run streams never yield a trusted projection.
|
|
105
|
+
*/
|
|
106
|
+
const visitAlignedRunRanges = (options) => {
|
|
107
|
+
const { baseBlock, revisedBlock } = options;
|
|
108
|
+
if (baseBlock.text !== revisedBlock.text) return "unalignable";
|
|
109
|
+
const baseRuns = baseBlock.previewRuns ?? [{ text: baseBlock.text }];
|
|
110
|
+
const revisedRuns = revisedBlock.previewRuns ?? [{ text: revisedBlock.text }];
|
|
111
|
+
let baseRunIndex = 0;
|
|
112
|
+
let revisedRunIndex = 0;
|
|
113
|
+
let baseRunOffset = 0;
|
|
114
|
+
let revisedRunOffset = 0;
|
|
115
|
+
let baseBlockOffset = 0;
|
|
116
|
+
let revisedBlockOffset = 0;
|
|
117
|
+
let exceededBudget = false;
|
|
118
|
+
while (true) {
|
|
119
|
+
let baseRunText = baseRuns[baseRunIndex]?.text;
|
|
120
|
+
while (baseRunText !== void 0 && baseRunOffset === baseRunText.length) {
|
|
121
|
+
baseRunIndex++;
|
|
122
|
+
baseRunOffset = 0;
|
|
123
|
+
baseRunText = baseRuns[baseRunIndex]?.text;
|
|
124
|
+
}
|
|
125
|
+
let revisedRunText = revisedRuns[revisedRunIndex]?.text;
|
|
126
|
+
while (revisedRunText !== void 0 && revisedRunOffset === revisedRunText.length) {
|
|
127
|
+
revisedRunIndex++;
|
|
128
|
+
revisedRunOffset = 0;
|
|
129
|
+
revisedRunText = revisedRuns[revisedRunIndex]?.text;
|
|
130
|
+
}
|
|
131
|
+
if (baseRunIndex === baseRuns.length || revisedRunIndex === revisedRuns.length) {
|
|
132
|
+
if (!(baseRunIndex === baseRuns.length && revisedRunIndex === revisedRuns.length && baseBlockOffset === baseBlock.text.length && revisedBlockOffset === revisedBlock.text.length)) return "unalignable";
|
|
133
|
+
if (exceededBudget) return "budget-exceeded";
|
|
134
|
+
return "complete";
|
|
135
|
+
}
|
|
136
|
+
if (baseRunText === void 0 || revisedRunText === void 0) return "unalignable";
|
|
137
|
+
if (baseRunOffset === 0 && !baseBlock.text.startsWith(baseRunText, baseBlockOffset) || revisedRunOffset === 0 && !revisedBlock.text.startsWith(revisedRunText, revisedBlockOffset)) return "unalignable";
|
|
138
|
+
const length = Math.min(baseRunText.length - baseRunOffset, revisedRunText.length - revisedRunOffset);
|
|
139
|
+
const baseRun = baseRuns[baseRunIndex];
|
|
140
|
+
const revisedRun = revisedRuns[revisedRunIndex];
|
|
141
|
+
if (options.type === "equivalence") {
|
|
142
|
+
if (!canonicalInlinePresentationsEqual(baseRun, revisedRun)) return "stopped";
|
|
143
|
+
} else if (!exceededBudget) {
|
|
144
|
+
const formatting = changedCanonicalInlinePresentation(baseRun, revisedRun);
|
|
145
|
+
if (formatting !== null) {
|
|
146
|
+
const previous = options.segments.at(-1);
|
|
147
|
+
if (previous && previous.endOffset === baseBlockOffset && sameCanonicalInlinePresentationPatch(previous.formatting, formatting)) previous.endOffset += length;
|
|
148
|
+
else if (options.segments.length >= options.maxSegments) exceededBudget = true;
|
|
149
|
+
else options.segments.push({
|
|
150
|
+
startOffset: baseBlockOffset,
|
|
151
|
+
endOffset: baseBlockOffset + length,
|
|
152
|
+
formatting
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
baseRunOffset += length;
|
|
157
|
+
revisedRunOffset += length;
|
|
158
|
+
baseBlockOffset += length;
|
|
159
|
+
revisedBlockOffset += length;
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
const hasAlignedRunStream = (block) => {
|
|
163
|
+
if (block.previewRuns === void 0) return true;
|
|
164
|
+
let offset = 0;
|
|
165
|
+
for (const run of block.previewRuns) {
|
|
166
|
+
if (!block.text.startsWith(run.text, offset)) return false;
|
|
167
|
+
offset += run.text.length;
|
|
168
|
+
}
|
|
169
|
+
return offset === block.text.length;
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* Collect coalesced canonical presentation differences in character order.
|
|
173
|
+
* Invalid run streams take precedence over the segment budget, so malformed
|
|
174
|
+
* content cannot change meaning as the caller's remaining budget changes.
|
|
175
|
+
*/
|
|
176
|
+
const canonicalInlinePresentationSegments = ({ baseBlock, revisedBlock, maxSegments }) => {
|
|
177
|
+
const segments = [];
|
|
178
|
+
const result = visitAlignedRunRanges({
|
|
179
|
+
type: "segments",
|
|
180
|
+
baseBlock,
|
|
181
|
+
revisedBlock,
|
|
182
|
+
maxSegments,
|
|
183
|
+
segments
|
|
184
|
+
});
|
|
185
|
+
switch (result) {
|
|
186
|
+
case "complete": return {
|
|
187
|
+
status: "compared",
|
|
188
|
+
segments
|
|
189
|
+
};
|
|
190
|
+
case "budget-exceeded": return {
|
|
191
|
+
status: "budget-exceeded",
|
|
192
|
+
maximum: maxSegments
|
|
193
|
+
};
|
|
194
|
+
case "unalignable": {
|
|
195
|
+
const baseAligned = hasAlignedRunStream(baseBlock);
|
|
196
|
+
if (baseAligned === hasAlignedRunStream(revisedBlock)) return {
|
|
197
|
+
status: "unalignable",
|
|
198
|
+
side: "both"
|
|
199
|
+
};
|
|
200
|
+
if (baseAligned) return {
|
|
201
|
+
status: "unalignable",
|
|
202
|
+
side: "revised"
|
|
203
|
+
};
|
|
204
|
+
return {
|
|
205
|
+
status: "unalignable",
|
|
206
|
+
side: "base"
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
case "stopped": return panic("A segment traversal cannot stop at a presentation difference");
|
|
210
|
+
default: return result;
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
/** Effective and authored presentation equality, independent of run splits. */
|
|
214
|
+
const sameCanonicalInlinePresentation = (baseBlock, revisedBlock) => {
|
|
215
|
+
return visitAlignedRunRanges({
|
|
216
|
+
type: "equivalence",
|
|
217
|
+
baseBlock,
|
|
218
|
+
revisedBlock
|
|
219
|
+
}) === "complete";
|
|
220
|
+
};
|
|
221
|
+
//#endregion
|
|
222
|
+
export { CANONICAL_INLINE_PRESENTATION_PROPERTIES, canonicalInlinePresentationSegments, sameCanonicalInlinePresentation };
|
|
@@ -6,6 +6,8 @@ type ClassifiedParagraphFormattingField = "alignment" | "bidi" | "kinsoku" | "ov
|
|
|
6
6
|
type ExhaustiveParagraphFormatting = ExhaustiveFields<document_d_exports.ParagraphFormatting, ClassifiedParagraphFormattingField>;
|
|
7
7
|
/** Compare numbering references by their emitted id and effective level. */
|
|
8
8
|
declare const paragraphNumberingReferencesEqual: (left: ParagraphNumberingReference, right: ParagraphNumberingReference) => boolean;
|
|
9
|
+
/** Compare the authored `w:numPr` attributes, including an absent `w:ilvl`. */
|
|
10
|
+
declare const sameAuthoredParagraphNumberingReference: (left: ParagraphNumberingReference, right: ParagraphNumberingReference) => boolean;
|
|
9
11
|
/** Whether resolved numbering still belongs to the paragraph's style tier. */
|
|
10
12
|
declare const isStyleSourcedParagraphNumbering: (numPr: ParagraphNumberingReference, numPrFromStyle: ParagraphNumberingReference) => boolean;
|
|
11
13
|
/** Exact fallback-emission instructions for the modeled part of `w:pPr`. */
|
|
@@ -20,4 +22,4 @@ type ModeledParagraphFormattingEmission = Readonly<{
|
|
|
20
22
|
*/
|
|
21
23
|
declare const modelParagraphFormattingEmission: (input: ExhaustiveParagraphFormatting | undefined) => ModeledParagraphFormattingEmission;
|
|
22
24
|
//#endregion
|
|
23
|
-
export { ModeledParagraphFormattingEmission, isStyleSourcedParagraphNumbering, modelParagraphFormattingEmission, paragraphNumberingReferencesEqual };
|
|
25
|
+
export { ModeledParagraphFormattingEmission, isStyleSourcedParagraphNumbering, modelParagraphFormattingEmission, paragraphNumberingReferencesEqual, sameAuthoredParagraphNumberingReference };
|
|
@@ -17,6 +17,13 @@ const paragraphNumberingReferencesEqual = (left, right) => {
|
|
|
17
17
|
if (modeledLeft === null || modeledRight === null) return modeledLeft === null && modeledRight === null;
|
|
18
18
|
return modeledLeft.numId === modeledRight.numId && (modeledLeft.ilvl ?? 0) === (modeledRight.ilvl ?? 0);
|
|
19
19
|
};
|
|
20
|
+
/** Compare the authored `w:numPr` attributes, including an absent `w:ilvl`. */
|
|
21
|
+
const sameAuthoredParagraphNumberingReference = (left, right) => {
|
|
22
|
+
const modeledLeft = modelParagraphNumberingReference(left);
|
|
23
|
+
const modeledRight = modelParagraphNumberingReference(right);
|
|
24
|
+
if (modeledLeft === null || modeledRight === null) return modeledLeft === null && modeledRight === null;
|
|
25
|
+
return modeledLeft.numId === modeledRight.numId && modeledLeft.ilvl === modeledRight.ilvl;
|
|
26
|
+
};
|
|
20
27
|
/** Whether resolved numbering still belongs to the paragraph's style tier. */
|
|
21
28
|
const isStyleSourcedParagraphNumbering = (numPr, numPrFromStyle) => numPr != null && numPrFromStyle != null && paragraphNumberingReferencesEqual(numPr, numPrFromStyle);
|
|
22
29
|
const serializeToggle = (name, value) => {
|
|
@@ -154,4 +161,4 @@ const modelParagraphFormattingEmission = (input) => {
|
|
|
154
161
|
return emission;
|
|
155
162
|
};
|
|
156
163
|
//#endregion
|
|
157
|
-
export { isStyleSourcedParagraphNumbering, modelParagraphFormattingEmission, paragraphNumberingReferencesEqual };
|
|
164
|
+
export { isStyleSourcedParagraphNumbering, modelParagraphFormattingEmission, paragraphNumberingReferencesEqual, sameAuthoredParagraphNumberingReference };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { RemovedSectionReference } from "./sectionEndpointResolution.js";
|
|
3
|
+
import { Node } from "prosemirror-model";
|
|
4
|
+
//#region src/internal/sectionReferenceResolution.d.ts
|
|
5
|
+
type SectionReferenceInventory = {
|
|
6
|
+
references: readonly RemovedSectionReference[];
|
|
7
|
+
revisionRelationships: ReadonlySet<string>;
|
|
8
|
+
};
|
|
9
|
+
declare const captureSectionReferenceInventory: (document: Node, finalProperties: document_d_exports.SectionProperties | undefined) => SectionReferenceInventory;
|
|
10
|
+
declare const resolvedSectionReferenceLosses: ({ before, after }: {
|
|
11
|
+
before: SectionReferenceInventory;
|
|
12
|
+
after: SectionReferenceInventory;
|
|
13
|
+
}) => RemovedSectionReference[];
|
|
14
|
+
declare const withSectionReferenceResolution: <T>({ document, removedReferences, repack }: {
|
|
15
|
+
document: document_d_exports.Document;
|
|
16
|
+
removedReferences: readonly RemovedSectionReference[];
|
|
17
|
+
repack: () => Promise<T>;
|
|
18
|
+
}) => Promise<T>;
|
|
19
|
+
declare const consumeSectionReferenceResolution: (document: document_d_exports.Document) => readonly RemovedSectionReference[];
|
|
20
|
+
//#endregion
|
|
21
|
+
export { SectionReferenceInventory, captureSectionReferenceInventory, consumeSectionReferenceResolution, resolvedSectionReferenceLosses, withSectionReferenceResolution };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { expectParagraphAttrs } from "../prosemirror/attrs/index.js";
|
|
2
|
+
import { panic } from "better-result";
|
|
3
|
+
//#region src/internal/sectionReferenceResolution.ts
|
|
4
|
+
const relationshipKey = ({ part, relationshipId }) => `${part}:${relationshipId}`;
|
|
5
|
+
const referenceKey = (reference) => `${relationshipKey(reference)}:${reference.type}`;
|
|
6
|
+
const captureSectionReferenceInventory = (document, finalProperties) => {
|
|
7
|
+
const references = [];
|
|
8
|
+
const revisionRelationships = /* @__PURE__ */ new Set();
|
|
9
|
+
const collect = (properties) => {
|
|
10
|
+
if (!properties) return;
|
|
11
|
+
const start = references.length;
|
|
12
|
+
const append = (selection) => {
|
|
13
|
+
for (const { type, rId } of selection.headerReferences ?? []) references.push({
|
|
14
|
+
part: "header",
|
|
15
|
+
type,
|
|
16
|
+
relationshipId: rId
|
|
17
|
+
});
|
|
18
|
+
for (const { type, rId } of selection.footerReferences ?? []) references.push({
|
|
19
|
+
part: "footer",
|
|
20
|
+
type,
|
|
21
|
+
relationshipId: rId
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
append(properties);
|
|
25
|
+
const history = properties.propertyChanges?.filter(({ previousReferences }) => previousReferences !== void 0) ?? [];
|
|
26
|
+
for (const change of history) if (change.previousReferences) append(change.previousReferences);
|
|
27
|
+
if (history.length > 0) for (const reference of references.slice(start)) revisionRelationships.add(relationshipKey(reference));
|
|
28
|
+
};
|
|
29
|
+
document.descendants((node) => {
|
|
30
|
+
if (node.type.name === "paragraph") collect(expectParagraphAttrs(node)._sectionProperties);
|
|
31
|
+
});
|
|
32
|
+
collect(finalProperties);
|
|
33
|
+
return {
|
|
34
|
+
references,
|
|
35
|
+
revisionRelationships
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
const resolvedSectionReferenceLosses = ({ before, after }) => {
|
|
39
|
+
const remaining = /* @__PURE__ */ new Map();
|
|
40
|
+
for (const reference of after.references) {
|
|
41
|
+
const key = referenceKey(reference);
|
|
42
|
+
remaining.set(key, (remaining.get(key) ?? 0) + 1);
|
|
43
|
+
}
|
|
44
|
+
const removed = [];
|
|
45
|
+
for (const reference of before.references) {
|
|
46
|
+
if (!before.revisionRelationships.has(relationshipKey(reference))) continue;
|
|
47
|
+
const key = referenceKey(reference);
|
|
48
|
+
const count = remaining.get(key) ?? 0;
|
|
49
|
+
if (count > 0) remaining.set(key, count - 1);
|
|
50
|
+
else removed.push(reference);
|
|
51
|
+
}
|
|
52
|
+
return removed;
|
|
53
|
+
};
|
|
54
|
+
const activeResolutions = /* @__PURE__ */ new WeakMap();
|
|
55
|
+
const withSectionReferenceResolution = async ({ document, removedReferences, repack }) => {
|
|
56
|
+
if (activeResolutions.has(document)) panic("A section reference repack is already active");
|
|
57
|
+
activeResolutions.set(document, removedReferences.map((reference) => ({ ...reference })));
|
|
58
|
+
try {
|
|
59
|
+
const result = await repack();
|
|
60
|
+
if (activeResolutions.has(document)) panic("The section reference repack did not consume its resolution");
|
|
61
|
+
return result;
|
|
62
|
+
} finally {
|
|
63
|
+
activeResolutions.delete(document);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
const consumeSectionReferenceResolution = (document) => {
|
|
67
|
+
const references = activeResolutions.get(document) ?? [];
|
|
68
|
+
activeResolutions.delete(document);
|
|
69
|
+
return references;
|
|
70
|
+
};
|
|
71
|
+
//#endregion
|
|
72
|
+
export { captureSectionReferenceInventory, consumeSectionReferenceResolution, resolvedSectionReferenceLosses, withSectionReferenceResolution };
|
|
@@ -393,6 +393,7 @@ const RUN_FORMATTING_OVERRIDE_HANDLER_ENTRIES = Object.entries({
|
|
|
393
393
|
fontSizeCs(formatting, value) {
|
|
394
394
|
if (typeof value === "number") formatting.complexScriptFontSize = value / 2;
|
|
395
395
|
},
|
|
396
|
+
noProof() {},
|
|
396
397
|
hidden(formatting, value) {
|
|
397
398
|
if (typeof value === "boolean") formatting.hidden = value;
|
|
398
399
|
},
|
|
@@ -148,6 +148,7 @@ function renderTrackedWrapper(ctx, pkg, wrapper, paraId) {
|
|
|
148
148
|
const renderChild = (child) => {
|
|
149
149
|
if (child.type === "run") return renderRun(ctx, pkg, child, paraId);
|
|
150
150
|
if (child.type === "hyperlink") return renderHyperlink(ctx, pkg, child, paraId);
|
|
151
|
+
if (child.type === "mathEquation") return child.plainText ? escapeInline(child.plainText) : "";
|
|
151
152
|
return "";
|
|
152
153
|
};
|
|
153
154
|
if (ctx.opts.trackedChanges === "clean") {
|
|
@@ -160,6 +160,7 @@ function renderHtmlChildren(ctx, pkg, children, paraId) {
|
|
|
160
160
|
return children.map((child) => {
|
|
161
161
|
if (child.type === "run") return renderHtmlRun(ctx, pkg, child, paraId);
|
|
162
162
|
if (child.type === "hyperlink") return renderHtmlHyperlink(ctx, pkg, child, paraId);
|
|
163
|
+
if (child.type === "mathEquation") return child.plainText ? escapeHtml(child.plainText) : "";
|
|
163
164
|
return "";
|
|
164
165
|
}).join("");
|
|
165
166
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LINE_SPACING_RULE_VALUES, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES } from "../../types/documentEnumValues.js";
|
|
2
|
+
import { canonicalJson } from "../../utils/canonicalJson.js";
|
|
2
3
|
import { normalizeHorizontalScalePercent } from "../../utils/horizontalScale.js";
|
|
3
4
|
import { isParagraphDirection } from "../paragraphDirection.js";
|
|
4
5
|
import { COMPLEX_SCRIPT_RUN_PROPERTY_KEYS, RUN_FORMATTING_BOOLEAN_PROPERTIES, RUN_FORMATTING_VALUE_PROPERTIES, TRACKED_CHANGE_PROVENANCE_VALUES } from "../schema/marks.js";
|
|
@@ -241,6 +242,7 @@ const readParagraphAttrs = (node) => {
|
|
|
241
242
|
optionalRecord(attrs, "spacingFromDocDefaults", "paragraph.attrs.spacingFromDocDefaults", issues);
|
|
242
243
|
optionalRecord(attrs, "spacingFromImplicitDefaultStyle", "paragraph.attrs.spacingFromImplicitDefaultStyle", issues);
|
|
243
244
|
optionalTextFormatting(attrs, "defaultTextFormatting", "paragraph.attrs.defaultTextFormatting", issues);
|
|
245
|
+
optionalTextFormatting(attrs, "_tableRunFormatting", "paragraph.attrs._tableRunFormatting", issues);
|
|
244
246
|
optionalRecord(attrs, "numPr", "paragraph.attrs.numPr", issues);
|
|
245
247
|
validateNumPr(attrs["numPr"], issues);
|
|
246
248
|
optionalBookmarkArray(attrs["bookmarks"], issues);
|
|
@@ -814,7 +816,24 @@ const mergeNodeAttrs = (node, readAttrs, label, patch) => {
|
|
|
814
816
|
for (const [key, value] of Object.entries(mergedAttrs)) if (value !== void 0) nextAttrs[key] = value;
|
|
815
817
|
return nextAttrs;
|
|
816
818
|
};
|
|
817
|
-
const
|
|
819
|
+
const IMAGE_RESOURCE_ATTRS = /* @__PURE__ */ new Set([
|
|
820
|
+
"rId",
|
|
821
|
+
"_docxRawXml",
|
|
822
|
+
"_docxRawXmlMode",
|
|
823
|
+
"_docxObjectPreview"
|
|
824
|
+
]);
|
|
825
|
+
const imageAttrValuesEqual = (left, right) => {
|
|
826
|
+
if (left === right) return true;
|
|
827
|
+
if ((left === void 0 || left === null) && (right === void 0 || right === null)) return true;
|
|
828
|
+
return canonicalJson(left) === canonicalJson(right);
|
|
829
|
+
};
|
|
830
|
+
const mergeImageAttrs = (node, patch) => {
|
|
831
|
+
const current = expectImageAttrs(node);
|
|
832
|
+
const merged = mergeNodeAttrs(node, readImageAttrs, "image attrs", patch);
|
|
833
|
+
if (!Object.entries(patch).some(([key, value]) => !IMAGE_RESOURCE_ATTRS.has(key) && !imageAttrValuesEqual(Reflect.get(current, key), value)) || current._docxRawXml === void 0 || current._docxRawXmlMode === DRAWING_RAW_XML_MODES.PRESERVE_ONLY) return merged;
|
|
834
|
+
const { _docxRawXml: _discardedRawXml, ...editableAttrs } = merged;
|
|
835
|
+
return editableAttrs;
|
|
836
|
+
};
|
|
818
837
|
const mergeParagraphAttrs = (node, patch) => mergeNodeAttrs(node, readParagraphAttrs, "paragraph attrs", patch);
|
|
819
838
|
const mergeTableAttrs = (node, patch) => mergeNodeAttrs(node, readTableAttrs, "table attrs", patch);
|
|
820
839
|
const mergeTableRowAttrs = (node, patch) => mergeNodeAttrs(node, readTableRowAttrs, "table row attrs", patch);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Command, EditorState } from "prosemirror-state";
|
|
2
|
+
import { Mapping } from "prosemirror-transform";
|
|
2
3
|
//#region src/prosemirror/commands/comments.d.ts
|
|
3
4
|
/**
|
|
4
5
|
* Add a comment mark to the current selection.
|
|
@@ -46,6 +47,15 @@ declare function rejectAllChanges(): Command;
|
|
|
46
47
|
* mapped through concurrent edits.
|
|
47
48
|
*/
|
|
48
49
|
declare function resolveAllChangesInHeadlessState(state: EditorState, mode: ResolveMode): EditorState;
|
|
50
|
+
/**
|
|
51
|
+
* Resolve through the editor command path when a caller must map a position in
|
|
52
|
+
* the reviewed document back to the tracked source. The bulk resolver is
|
|
53
|
+
* faster, but deliberately replaces inline content without retaining mapping.
|
|
54
|
+
*/
|
|
55
|
+
declare const resolveAllChangesInHeadlessStateWithMapping: (state: EditorState, mode: ResolveMode) => {
|
|
56
|
+
state: EditorState;
|
|
57
|
+
mapping: Mapping;
|
|
58
|
+
};
|
|
49
59
|
/**
|
|
50
60
|
* Find the document range covered by all revision carriers with any of the
|
|
51
61
|
* given ids. Returns null when none are present (already accepted/rejected, or
|
|
@@ -174,4 +184,4 @@ declare function findNextChange(state: EditorState, startPos: number): ChangeRan
|
|
|
174
184
|
*/
|
|
175
185
|
declare function findPreviousChange(state: EditorState, startPos: number): ChangeRange | null;
|
|
176
186
|
//#endregion
|
|
177
|
-
export { AcceptSuggestionOptions, FolioSuggestion, ParagraphBoundaryChange, SuggestionAppliedAs, SuggestionKind, acceptAIEditRevision, acceptAllChanges, acceptAllSuggestions, acceptChange, acceptSuggestion, addCommentMark, findAIEditRevisionRange, findChangeAtPosition, findNextChange, findParagraphBoundaryChangeAtPosition, findPreviousChange, findSuggestionRange, getSuggestions, rejectAIEditRevision, rejectAllChanges, rejectAllSuggestions, rejectChange, rejectSuggestion, removeCommentMark, resolveAllChangesInHeadlessState };
|
|
187
|
+
export { AcceptSuggestionOptions, FolioSuggestion, ParagraphBoundaryChange, SuggestionAppliedAs, SuggestionKind, acceptAIEditRevision, acceptAllChanges, acceptAllSuggestions, acceptChange, acceptSuggestion, addCommentMark, findAIEditRevisionRange, findChangeAtPosition, findNextChange, findParagraphBoundaryChangeAtPosition, findPreviousChange, findSuggestionRange, getSuggestions, rejectAIEditRevision, rejectAllChanges, rejectAllSuggestions, rejectChange, rejectSuggestion, removeCommentMark, resolveAllChangesInHeadlessState, resolveAllChangesInHeadlessStateWithMapping };
|
|
@@ -12,12 +12,14 @@ import { RUN_FORMATTING_MARK_NAMES } from "../runFormattingMarkNames.js";
|
|
|
12
12
|
import { reconstructRejectedRunFormattingMarks } from "../runPropertyChangeResolution.js";
|
|
13
13
|
import { paragraphRunStyleContextAt } from "../runStyleFormatting.js";
|
|
14
14
|
import { getTableCellMergeChange } from "../tableCellMergeRevision.js";
|
|
15
|
+
import { isTableCellRetainedInReviewView } from "../tableCellRevisionVisibility.js";
|
|
15
16
|
import { reconcileTableGridAfterColumnRemoval } from "../tableGridMutation.js";
|
|
16
17
|
import { holdsNoContent } from "../zeroWidthAnchors.js";
|
|
17
18
|
import { hasSerializableParagraphPropertyChange, paragraphPropertiesSnapshot, paragraphRejectAttrPatch, paragraphRejectOriginalFormatting, removeParagraphPropertyChanges, sectionRejectProperties, tableCellRejectAttrPatch, tableRejectAttrPatch, tableRowRejectAttrPatch } from "./propertyChangeScope.js";
|
|
18
19
|
import { hasMatchingCollapsedTableCellMerge, resolveCollapsedTableCellMerge, resolveVisibleTableCellMerge } from "./tableCellMergeResolution.js";
|
|
19
20
|
import { TableMap, removeRow } from "prosemirror-tables";
|
|
20
|
-
import {
|
|
21
|
+
import { Mapping } from "prosemirror-transform";
|
|
22
|
+
import { PARAGRAPH_MARK_CHANGE_KINDS, REVIEW_CARRIERS } from "@stll/docx-core/model";
|
|
21
23
|
//#region src/prosemirror/commands/comments.ts
|
|
22
24
|
/**
|
|
23
25
|
* Add a comment mark to the current selection.
|
|
@@ -120,7 +122,11 @@ function resolveChange(from, to, mode, revisionIds, execution = "legacy") {
|
|
|
120
122
|
if (matches.length > 0) {
|
|
121
123
|
const remaining = sectionChanges.filter((c) => revisionSet !== null && (!c.info || !revisionSet.has(c.info.id)));
|
|
122
124
|
let restored = { ...sectionProperties };
|
|
123
|
-
if (mode === "reject") for (const change of matches.toReversed()) restored = sectionRejectProperties(
|
|
125
|
+
if (mode === "reject") for (const change of matches.toReversed()) restored = sectionRejectProperties({
|
|
126
|
+
live: restored,
|
|
127
|
+
previousProperties: change.previousProperties,
|
|
128
|
+
previousReferences: change.previousReferences
|
|
129
|
+
});
|
|
124
130
|
delete restored.propertyChanges;
|
|
125
131
|
if (remaining.length > 0) restored.propertyChanges = remaining;
|
|
126
132
|
nextAttrs = nextAttrs ?? { ...node.attrs };
|
|
@@ -132,7 +138,12 @@ function resolveChange(from, to, mode, revisionIds, execution = "legacy") {
|
|
|
132
138
|
nextAttrs,
|
|
133
139
|
paragraphPosition: pos,
|
|
134
140
|
styleResolver,
|
|
135
|
-
tr
|
|
141
|
+
tr,
|
|
142
|
+
...mode === "reject" && { shouldRebase: (inline) => {
|
|
143
|
+
const deleted = inline.marks.some(({ type }) => type.name === "deletion");
|
|
144
|
+
const direct = inline.marks.some(({ type }) => type.name === "runFormattingOverride");
|
|
145
|
+
return !deleted || !direct;
|
|
146
|
+
} }
|
|
136
147
|
});
|
|
137
148
|
else tr.setNodeMarkup(pos, void 0, nextAttrs);
|
|
138
149
|
return true;
|
|
@@ -309,11 +320,45 @@ function resolveChange(from, to, mode, revisionIds, execution = "legacy") {
|
|
|
309
320
|
removedEndpointCount: removedSectionEndpointCount,
|
|
310
321
|
removedReferences: removedSectionReferences
|
|
311
322
|
});
|
|
323
|
+
if (!terminalTableDeletionIsPending(tr)) resolveTerminalTableReviewCarrier(tr, mode);
|
|
312
324
|
if (tr.steps.length > 0) dispatch(tr);
|
|
313
325
|
}
|
|
314
326
|
return true;
|
|
315
327
|
};
|
|
316
328
|
}
|
|
329
|
+
/**
|
|
330
|
+
* The receiver belongs to the deleted terminal table, not every revision in
|
|
331
|
+
* the document. Keep it through independently resolved changes, then resolve
|
|
332
|
+
* it as soon as that table's deletion has been decided.
|
|
333
|
+
*/
|
|
334
|
+
const terminalTableDeletionIsPending = (tr) => {
|
|
335
|
+
let terminalTable = null;
|
|
336
|
+
for (let index = tr.doc.childCount - 1; index >= 0; index--) {
|
|
337
|
+
const node = tr.doc.child(index);
|
|
338
|
+
if (node.type.name === "table") {
|
|
339
|
+
terminalTable = node;
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
if (terminalTable === null) return false;
|
|
344
|
+
let pending = false;
|
|
345
|
+
terminalTable.descendants((node) => {
|
|
346
|
+
pending ||= node.type.name === "tableRow" && isTableRowRevisionAttr(node.attrs["trDel"]) || node.type.name !== "tableRow" && node.marks.some((mark) => mark.type.name === "deletion");
|
|
347
|
+
return !pending;
|
|
348
|
+
});
|
|
349
|
+
return pending;
|
|
350
|
+
};
|
|
351
|
+
/** Resolve the Folio-only receiver Word needs after a terminal deleted table. */
|
|
352
|
+
const resolveTerminalTableReviewCarrier = (tr, mode) => {
|
|
353
|
+
const carrier = tr.doc.lastChild;
|
|
354
|
+
if (carrier?.type.name !== "paragraph" || carrier.attrs["reviewCarrier"] !== REVIEW_CARRIERS.TERMINAL_TABLE) return;
|
|
355
|
+
const position = tr.doc.content.size - carrier.nodeSize;
|
|
356
|
+
if (mode === "accept") {
|
|
357
|
+
tr.setNodeAttribute(position, "reviewCarrier", void 0);
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
tr.delete(position, position + carrier.nodeSize);
|
|
361
|
+
};
|
|
317
362
|
const resolveRunPropertyChange = ({ tr, node, from, to, mark, mode, revisionSet, styleResolver }) => {
|
|
318
363
|
const { changes } = expectRunPropertyChangeMarkAttrs(mark);
|
|
319
364
|
const matches = changes.filter((change) => revisionSet === null || revisionSet.has(change.info.id));
|
|
@@ -401,11 +446,11 @@ function collectTableCellStructuralOps(node, cellPos, mode, revisionSet) {
|
|
|
401
446
|
revisionSet
|
|
402
447
|
});
|
|
403
448
|
else {
|
|
404
|
-
const
|
|
449
|
+
const view = mode === "accept" ? "final" : "original";
|
|
405
450
|
operations.push({
|
|
406
451
|
type: "membership",
|
|
407
452
|
cellPos,
|
|
408
|
-
action:
|
|
453
|
+
action: isTableCellRetainedInReviewView(marker.kind, view) ? "clear" : "remove"
|
|
409
454
|
});
|
|
410
455
|
}
|
|
411
456
|
if (hasMatchingCollapsedTableCellMerge(node, revisionSet)) operations.push({
|
|
@@ -671,6 +716,23 @@ function resolveAllChangesInHeadlessState(state, mode) {
|
|
|
671
716
|
return resolvedState;
|
|
672
717
|
}
|
|
673
718
|
/**
|
|
719
|
+
* Resolve through the editor command path when a caller must map a position in
|
|
720
|
+
* the reviewed document back to the tracked source. The bulk resolver is
|
|
721
|
+
* faster, but deliberately replaces inline content without retaining mapping.
|
|
722
|
+
*/
|
|
723
|
+
const resolveAllChangesInHeadlessStateWithMapping = (state, mode) => {
|
|
724
|
+
let resolvedState = state;
|
|
725
|
+
let mapping = new Mapping();
|
|
726
|
+
resolveChange(0, state.doc.content.size, mode)(state, (transaction) => {
|
|
727
|
+
resolvedState = state.apply(transaction);
|
|
728
|
+
mapping = transaction.mapping;
|
|
729
|
+
});
|
|
730
|
+
return {
|
|
731
|
+
state: resolvedState,
|
|
732
|
+
mapping
|
|
733
|
+
};
|
|
734
|
+
};
|
|
735
|
+
/**
|
|
674
736
|
* Find the document range covered by all revision carriers with any of the
|
|
675
737
|
* given ids. Returns null when none are present (already accepted/rejected, or
|
|
676
738
|
* never existed). A replace operation typically passes two ids; standalone
|
|
@@ -1664,4 +1726,4 @@ function findPreviousChange(state, startPos) {
|
|
|
1664
1726
|
return result.value;
|
|
1665
1727
|
}
|
|
1666
1728
|
//#endregion
|
|
1667
|
-
export { acceptAIEditRevision, acceptAllChanges, acceptAllSuggestions, acceptChange, acceptSuggestion, addCommentMark, findAIEditRevisionRange, findChangeAtPosition, findNextChange, findParagraphBoundaryChangeAtPosition, findPreviousChange, findSuggestionRange, getSuggestions, rejectAIEditRevision, rejectAllChanges, rejectAllSuggestions, rejectChange, rejectSuggestion, removeCommentMark, resolveAllChangesInHeadlessState };
|
|
1729
|
+
export { acceptAIEditRevision, acceptAllChanges, acceptAllSuggestions, acceptChange, acceptSuggestion, addCommentMark, findAIEditRevisionRange, findChangeAtPosition, findNextChange, findParagraphBoundaryChangeAtPosition, findPreviousChange, findSuggestionRange, getSuggestions, rejectAIEditRevision, rejectAllChanges, rejectAllSuggestions, rejectChange, rejectSuggestion, removeCommentMark, resolveAllChangesInHeadlessState, resolveAllChangesInHeadlessStateWithMapping };
|
|
@@ -66,10 +66,16 @@ declare function paragraphRejectOriginalFormatting(previousFormatting: Paragraph
|
|
|
66
66
|
* Rejected section properties: the stored old sectPr wholesale, preserving
|
|
67
67
|
* the live header/footer references — `EG_HdrFtrReferences` is not part of
|
|
68
68
|
* the `CT_SectPrBase` payload a `w:sectPrChange` stores (ECMA-376
|
|
69
|
-
* §17.13.5.32), so those children survive a reject.
|
|
70
|
-
*
|
|
69
|
+
* §17.13.5.32), so those children survive a native reject. An explicit Folio reference
|
|
70
|
+
* history replaces that selection, including restoring its absence. The
|
|
71
|
+
* caller re-attaches whatever `propertyChanges` remain unresolved.
|
|
71
72
|
*/
|
|
72
|
-
|
|
73
|
+
type SectionRejectPropertiesOptions = {
|
|
74
|
+
live: document_d_exports.SectionProperties;
|
|
75
|
+
previousProperties: document_d_exports.SectionProperties | undefined;
|
|
76
|
+
previousReferences?: document_d_exports.SectionPropertyChange["previousReferences"];
|
|
77
|
+
};
|
|
78
|
+
declare function sectionRejectProperties({ live, previousProperties, previousReferences }: SectionRejectPropertiesOptions): document_d_exports.SectionProperties;
|
|
73
79
|
/**
|
|
74
80
|
* Attr patch for rejecting a `w:tblPrChange`: the stored old tblPr wholesale
|
|
75
81
|
* (`w:tblPrChange` stores the complete previous tblPr, so every tblPr-derived
|
|
@@ -220,19 +220,13 @@ function paragraphRejectOriginalFormatting(previousFormatting, liveOriginal) {
|
|
|
220
220
|
if (Object.keys(result).length === 0) return null;
|
|
221
221
|
return result;
|
|
222
222
|
}
|
|
223
|
-
|
|
224
|
-
* Rejected section properties: the stored old sectPr wholesale, preserving
|
|
225
|
-
* the live header/footer references — `EG_HdrFtrReferences` is not part of
|
|
226
|
-
* the `CT_SectPrBase` payload a `w:sectPrChange` stores (ECMA-376
|
|
227
|
-
* §17.13.5.32), so those children survive a reject. The caller re-attaches
|
|
228
|
-
* whatever `propertyChanges` remain unresolved.
|
|
229
|
-
*/
|
|
230
|
-
function sectionRejectProperties(live, previousProperties) {
|
|
223
|
+
function sectionRejectProperties({ live, previousProperties, previousReferences }) {
|
|
231
224
|
const restored = { ...previousProperties };
|
|
232
225
|
delete restored.propertyChanges;
|
|
233
|
-
|
|
226
|
+
const references = previousReferences ?? live;
|
|
227
|
+
if (references.headerReferences) restored.headerReferences = references.headerReferences;
|
|
234
228
|
else delete restored.headerReferences;
|
|
235
|
-
if (
|
|
229
|
+
if (references.footerReferences) restored.footerReferences = references.footerReferences;
|
|
236
230
|
else delete restored.footerReferences;
|
|
237
231
|
return restored;
|
|
238
232
|
}
|