@stll/folio-core 0.53.0 → 0.54.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 +390 -166
- package/dist/ai-edits/batch-claims.d.ts +21 -6
- package/dist/ai-edits/batch-claims.js +47 -16
- package/dist/ai-edits/headless.d.ts +20 -0
- package/dist/ai-edits/headless.js +140 -11
- package/dist/ai-edits/pending-suggestions.js +1 -1
- package/dist/ai-edits/read.d.ts +5 -3
- package/dist/ai-edits/read.js +97 -47
- package/dist/ai-edits/revisionStretches.d.ts +17 -0
- package/dist/ai-edits/revisionStretches.js +80 -0
- package/dist/ai-edits/snapshot.js +3 -2
- package/dist/ai-edits/table-cell-mutations.d.ts +3 -1
- package/dist/ai-edits/table-cell-mutations.js +2 -1
- package/dist/ai-edits/table-row-column-mutations.d.ts +6 -1
- package/dist/ai-edits/table-row-column-mutations.js +27 -10
- package/dist/compare/content-alignment.d.ts +5 -1
- package/dist/compare/content-alignment.js +39 -32
- package/dist/compare/inline-provenance.js +1 -1
- package/dist/controller/layoutPipeline.js +3 -2
- package/dist/docx/archiveInflation.d.ts +127 -0
- package/dist/docx/archiveInflation.js +181 -0
- package/dist/docx/metadataPrivacy.js +24 -1
- package/dist/docx/noteReferenceMark.d.ts +15 -0
- package/dist/docx/noteReferenceMark.js +48 -0
- package/dist/docx/paragraphParser.js +5 -3
- package/dist/docx/paragraphPropertySource.d.ts +1 -1
- package/dist/docx/paragraphPropertySource.js +3 -1
- package/dist/docx/parser.js +2 -2
- package/dist/docx/rezip.js +4 -2
- package/dist/docx/selectiveXmlPatch.d.ts +3 -1
- package/dist/docx/selectiveXmlPatch.js +81 -3
- package/dist/docx/server/boundedArchive.d.ts +8 -13
- package/dist/docx/server/boundedArchive.js +70 -59
- package/dist/docx/server/extractDocxText.d.ts +8 -2
- package/dist/docx/server/extractDocxText.js +2 -2
- package/dist/docx/server/validateDocxConformance.d.ts +1 -1
- package/dist/docx/server/validateDocxConformance.js +1 -0
- package/dist/docx/unzip.d.ts +19 -2
- package/dist/docx/unzip.js +135 -24
- package/dist/fonts/embeddedFonts.js +1 -1
- package/dist/i18n/messages/catalogs.gen.d.ts +34 -34
- package/dist/i18n/messages/catalogs.gen.js +34 -34
- package/dist/i18n/messages/messages.gen.d.ts +2 -2
- package/dist/internal/wholeStoryRevisionResolution.js +95 -25
- package/dist/layout-engine/measure/measureParagraph.js +2 -2
- package/dist/layout-engine/measure/paragraphMeasureShared.d.ts +12 -1
- package/dist/layout-engine/measure/paragraphMeasureShared.js +14 -1
- package/dist/markdown/escape.d.ts +2 -2
- package/dist/markdown/escape.js +4 -5
- package/dist/markdown/renderBlock.js +91 -25
- package/dist/markdown/renderRuns.d.ts +10 -1
- package/dist/markdown/renderRuns.js +320 -59
- package/dist/prosemirror/clearRunColor.d.ts +6 -0
- package/dist/prosemirror/clearRunColor.js +46 -0
- package/dist/prosemirror/commands/comments.js +56 -21
- package/dist/prosemirror/commands/formatPainter.js +1 -1
- package/dist/prosemirror/commands/hyperlink.js +2 -1
- package/dist/prosemirror/commands/propertyChangeScope.d.ts +3 -2
- package/dist/prosemirror/commands/propertyChangeScope.js +24 -3
- package/dist/prosemirror/commands/resolveAllTableChanges.js +46 -41
- package/dist/prosemirror/commands/resolveParagraphProperties.js +20 -6
- package/dist/prosemirror/commands/tableCellMergeResolution.d.ts +8 -1
- package/dist/prosemirror/commands/tableCellMergeResolution.js +23 -7
- package/dist/prosemirror/containerFinalParagraph.d.ts +11 -5
- package/dist/prosemirror/containerFinalParagraph.js +7 -6
- package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -13
- package/dist/prosemirror/conversion/fromProseDoc.js +12 -590
- package/dist/prosemirror/conversion/toProseDoc.d.ts +4 -11
- package/dist/prosemirror/conversion/toProseDoc.js +31 -150
- package/dist/prosemirror/documentSchema.d.ts +8 -0
- package/dist/prosemirror/documentSchema.js +18 -0
- package/dist/prosemirror/extensions/StarterKit.js +2 -0
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +104 -63
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +1 -1
- package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +24 -3
- package/dist/prosemirror/extensions/features/JoinedRunStyleExtension.d.ts +20 -0
- package/dist/prosemirror/extensions/features/JoinedRunStyleExtension.js +43 -0
- package/dist/prosemirror/extensions/features/ListExtension.js +10 -9
- package/dist/prosemirror/extensions/features/pastedHeadingStyles.js +1 -1
- package/dist/prosemirror/extensions/features/pastedHtmlLists.js +2 -4
- package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +14 -8
- package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +8 -4
- package/dist/prosemirror/extensions/marks/StrikeExtension.js +2 -2
- package/dist/prosemirror/extensions/marks/SubscriptExtension.js +2 -2
- package/dist/prosemirror/extensions/marks/SuperscriptExtension.js +2 -2
- package/dist/prosemirror/extensions/marks/TextColorExtension.js +4 -3
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +8 -6
- package/dist/prosemirror/extensions/marks/markUtils.js +17 -8
- package/dist/prosemirror/extensions/marks/noteReferenceDeletion.d.ts +3 -1
- package/dist/prosemirror/extensions/marks/noteReferenceDeletion.js +12 -1
- package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +2 -2
- package/dist/prosemirror/extensions/nodes/HardBreakExtension.js +5 -3
- package/dist/prosemirror/extensions/nodes/TableExtension.js +104 -210
- package/dist/prosemirror/extensions/types.d.ts +7 -0
- package/dist/prosemirror/hyperlinkRemoval.d.ts +9 -0
- package/dist/prosemirror/hyperlinkRemoval.js +129 -0
- package/dist/prosemirror/index.d.ts +2 -1
- package/dist/prosemirror/index.js +2 -1
- package/dist/prosemirror/listNumbering.d.ts +3 -21
- package/dist/prosemirror/listNumbering.js +10 -25
- package/dist/prosemirror/listRendering.d.ts +27 -0
- package/dist/prosemirror/listRendering.js +27 -0
- package/dist/prosemirror/markupViewNotes.d.ts +8 -0
- package/dist/prosemirror/markupViewNotes.js +49 -0
- package/dist/prosemirror/markupViewProjection.d.ts +3 -1
- package/dist/prosemirror/markupViewProjection.js +7 -2
- package/dist/prosemirror/noteReferenceReview.d.ts +77 -0
- package/dist/prosemirror/noteReferenceReview.js +332 -0
- package/dist/prosemirror/paragraphIndentation.js +5 -2
- package/dist/prosemirror/paragraphMarkJoin.d.ts +6 -4
- package/dist/prosemirror/paragraphMarkJoin.js +21 -19
- package/dist/prosemirror/paragraphPropertyCarry.d.ts +64 -0
- package/dist/prosemirror/paragraphPropertyCarry.js +158 -0
- package/dist/prosemirror/plugins/documentStyleState.d.ts +26 -0
- package/dist/prosemirror/plugins/documentStyleState.js +32 -0
- package/dist/prosemirror/plugins/documentStyles.d.ts +2 -21
- package/dist/prosemirror/plugins/documentStyles.js +66 -29
- package/dist/prosemirror/plugins/index.d.ts +2 -1
- package/dist/prosemirror/plugins/index.js +2 -1
- package/dist/prosemirror/plugins/paragraphStyleResolution.d.ts +15 -0
- package/dist/prosemirror/plugins/paragraphStyleResolution.js +230 -0
- package/dist/prosemirror/plugins/suggestionMode.d.ts +12 -2
- package/dist/prosemirror/plugins/suggestionMode.js +391 -28
- package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +22 -2
- package/dist/prosemirror/rebaseParagraphRunFormatting.js +39 -13
- package/dist/prosemirror/rebaseParagraphRuns.d.ts +36 -0
- package/dist/prosemirror/rebaseParagraphRuns.js +99 -0
- package/dist/prosemirror/runFormattingFromMarks.d.ts +18 -0
- package/dist/prosemirror/runFormattingFromMarks.js +567 -0
- package/dist/prosemirror/runFormattingReconciliation.js +10 -9
- package/dist/prosemirror/schema/nodes.d.ts +2 -0
- package/dist/prosemirror/styles/paragraphStyleCascade.d.ts +59 -0
- package/dist/prosemirror/styles/paragraphStyleCascade.js +145 -0
- package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +21 -2
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +38 -1
- package/dist/prosemirror/styles/tableStyleRegions.d.ts +31 -0
- package/dist/prosemirror/styles/tableStyleRegions.js +55 -0
- package/dist/prosemirror/tableCellPaste.d.ts +74 -0
- package/dist/prosemirror/tableCellPaste.js +525 -0
- package/dist/prosemirror/tableGridMutation.d.ts +53 -14
- package/dist/prosemirror/tableGridMutation.js +166 -18
- package/dist/prosemirror/tableRunIn.d.ts +51 -0
- package/dist/prosemirror/tableRunIn.js +165 -0
- package/dist/prosemirror/textInput.js +11 -2
- package/dist/prosemirror/trackedRevisionPath.d.ts +17 -0
- package/dist/prosemirror/trackedRevisionPath.js +32 -0
- package/dist/server.d.ts +2 -2
- package/package.json +5 -5
package/dist/ai-edits/apply.js
CHANGED
|
@@ -2,10 +2,12 @@ import { paragraphNumberingReference, paragraphNumberingReferenceId } from "../d
|
|
|
2
2
|
import { formattingEquals } from "../docx/runConsolidator.js";
|
|
3
3
|
import { isStyleSourcedParagraphNumbering } from "../internal/paragraphFormattingSerialization.js";
|
|
4
4
|
import { deleteTextBoxesAnchoredAt, droppedTextBoxAnchorIds, endOfParagraphWithItsTextBoxes, gatherTextBoxesAfterParagraph, textBoxAnchorIdOf, textBoxAnchorIdsBetween } from "../prosemirror/anchoredTextBoxes.js";
|
|
5
|
-
import { expectParagraphAttrs, expectRunPropertyChangeMarkAttrs } from "../prosemirror/attrs/index.js";
|
|
5
|
+
import { expectParagraphAttrs, expectRunPropertyChangeMarkAttrs, expectTableRowAttrs } from "../prosemirror/attrs/index.js";
|
|
6
6
|
import { hasSerializableParagraphPropertyChange, paragraphPropertiesSnapshot } from "../prosemirror/commands/propertyChangeScope.js";
|
|
7
|
+
import { resolveParagraphChangeAttrs } from "../prosemirror/commands/resolveParagraphProperties.js";
|
|
7
8
|
import { addedBreakCarrierBefore, finalParagraphsOf, paragraphEndsItsContainer } from "../prosemirror/containerFinalParagraph.js";
|
|
8
9
|
import { encloseWholeControls } from "../prosemirror/contentControlRevisions.js";
|
|
10
|
+
import { JOINED_RUNS_RESTYLED_META } from "../prosemirror/extensions/features/JoinedRunStyleExtension.js";
|
|
9
11
|
import { requestDeterministicParaIds } from "../prosemirror/extensions/features/ParaIdAllocatorExtension.js";
|
|
10
12
|
import { markStructuralChange } from "../prosemirror/extensions/features/ParagraphChangeTrackerExtension.js";
|
|
11
13
|
import "../prosemirror/extensions/nodes/TextBoxAnchorExtension.js";
|
|
@@ -15,9 +17,11 @@ import { directParagraphAlignment } from "../prosemirror/paragraphAlignment.js";
|
|
|
15
17
|
import { styleResolvedParagraphFormatting } from "../prosemirror/paragraphFormattingProvenance.js";
|
|
16
18
|
import { directParagraphIndentation, paragraphIndentationAttrPatch, paragraphIndentationEqual, paragraphIndentationFromFormatting, withDirectParagraphIndentation } from "../prosemirror/paragraphIndentation.js";
|
|
17
19
|
import { joinAtParagraphMark } from "../prosemirror/paragraphMarkJoin.js";
|
|
20
|
+
import { carryParagraphProperties, paragraphLeftAfter, propertiesSetInBatch, recordReplacedParagraphProperties } from "../prosemirror/paragraphPropertyCarry.js";
|
|
18
21
|
import { directParagraphSpacing, paragraphSpacingAttrPatch, paragraphSpacingEqual, paragraphSpacingFromFormatting, withDirectParagraphSpacing } from "../prosemirror/paragraphSpacing.js";
|
|
19
22
|
import { getDocumentNumbering, getDocumentNumberingInstanceIds } from "../prosemirror/plugins/documentNumbering.js";
|
|
20
|
-
import { getDocumentStyleDefinitions, getDocumentStyleResolver } from "../prosemirror/plugins/
|
|
23
|
+
import { getDocumentStyleDefinitions, getDocumentStyleResolver } from "../prosemirror/plugins/documentStyleState.js";
|
|
24
|
+
import { rebaseParagraphRuns } from "../prosemirror/rebaseParagraphRuns.js";
|
|
21
25
|
import { NON_INCLUSIVE_MARK_DISPOSITION, addCarriedMarks, annotatedReplacement, commentsAcrossBlockBoundary, commentsForTrackedInsertion, hasReplacedAnnotations, inheritedReplacementMarks, placeTrackedInsertion, surveyReplacedAnnotations } from "../prosemirror/replacedAnnotations.js";
|
|
22
26
|
import { applyMarksToRunFormattingRepresentation, runFormattingInlineControlNodeName, selectRunFormattingCarrierRepresentations } from "../prosemirror/runFormattingInlineCarriers.js";
|
|
23
27
|
import { RUN_FORMATTING_MARK_NAMES } from "../prosemirror/runFormattingMarkNames.js";
|
|
@@ -25,6 +29,7 @@ import { readAuthoredRunFormatting, reconcileRunFormattingMarks } from "../prose
|
|
|
25
29
|
import { paragraphRunStyleContext, paragraphRunStyleContextAt, resolveParagraphBodyRunFormatting } from "../prosemirror/runStyleFormatting.js";
|
|
26
30
|
import { sectionPropertiesOf } from "../prosemirror/sectionCarrier.js";
|
|
27
31
|
import { listAttrsFromNumbering, listLevelAttrPatch } from "../prosemirror/styles/resolvedStyleAttrs.js";
|
|
32
|
+
import { removeRowsWithoutCellsAfterBatch } from "../prosemirror/tableGridMutation.js";
|
|
28
33
|
import { isZeroWidthAnchor } from "../prosemirror/zeroWidthAnchors.js";
|
|
29
34
|
import { getFolioParaIdFromBlockId } from "../types/block-id.js";
|
|
30
35
|
import { BatchClaims } from "./batch-claims.js";
|
|
@@ -35,8 +40,9 @@ import { hasInlineEmphasis, parseInlineEmphasisRuns, stripInlineEmphasisMarkers
|
|
|
35
40
|
import { applyTextChanges, changesFromSegments, keepAtomicSpans, planTextChanges, widenChangesToAtomicSpans } from "./minimal-replacement.js";
|
|
36
41
|
import { concreteListReference, resolveNewListOperations } from "./newListNumbering.js";
|
|
37
42
|
import { cutsIntoNoteReference, noteReferenceEditsAllowed, noteReferenceOf, noteReferenceSpansWithin, planChangesAroundNoteReferences, segmentsAroundNoteReferences } from "./note-references.js";
|
|
43
|
+
import { separateRevisionStretches } from "./revisionStretches.js";
|
|
38
44
|
import { collectNoteReferenceLabels, hashFolioAIBlockStructuralBoundaries, hashFolioAIBlockText, isHiddenTableRow, normalizeFolioAIBlockText } from "./snapshot.js";
|
|
39
|
-
import { mergeTableRectangle, mergeTrackedVerticalTableCells, splitTableRectangle, splitTrackedVerticalTableCell } from "./table-cell-mutations.js";
|
|
45
|
+
import { isEmptyTableCell, mergeTableRectangle, mergeTrackedVerticalTableCells, splitTableRectangle, splitTrackedVerticalTableCell } from "./table-cell-mutations.js";
|
|
40
46
|
import { planTableMutations } from "./table-mutation-plan.js";
|
|
41
47
|
import { applyTableColumnDeletion, applyTableColumnInsertion, applyTableRowDeletion, applyTableRowInsertion, describeUnplacedCellTexts, findTableColumnInsertion, findTableRowInsertion, getTableColumnCoordinateKey, markTableRowContent, splitCellParagraphTexts } from "./table-row-column-mutations.js";
|
|
42
48
|
import { findEnclosingTableCell, findEnclosingTableRow, findOutermostTableBoundary, tableRectangleCutsMergedCell } from "./table-targets.js";
|
|
@@ -346,13 +352,23 @@ const undeletedContentAtomRanges = (tr, blockFrom) => {
|
|
|
346
352
|
});
|
|
347
353
|
return ranges;
|
|
348
354
|
};
|
|
349
|
-
/**
|
|
350
|
-
|
|
355
|
+
/**
|
|
356
|
+
* The carrier pPr before any pending change to it, for final-mark rotation.
|
|
357
|
+
*
|
|
358
|
+
* A paragraph added after the carrier copies its pending property change, as
|
|
359
|
+
* a break typed at a paragraph's end does: rejecting the addition leaves the
|
|
360
|
+
* added paragraph (its mark is the one that stays), so that change is what
|
|
361
|
+
* gives the carrier's words back the properties they had.
|
|
362
|
+
*/
|
|
363
|
+
const paragraphPropertiesBeforePendingChanges = (node) => {
|
|
351
364
|
const propertyChanges = expectParagraphAttrs(node)._propertyChanges;
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
365
|
+
const earliest = Array.isArray(propertyChanges) ? propertyChanges[0] : void 0;
|
|
366
|
+
return earliest === void 0 ? paragraphPropertiesSnapshot(node) : earliest.previousFormatting ?? {};
|
|
367
|
+
};
|
|
368
|
+
/** The pPr rejecting every pending change of a paragraph's properties leaves. */
|
|
369
|
+
const paragraphPropertiesOnReject = (node) => {
|
|
370
|
+
const [earliest] = expectParagraphAttrs(node)._propertyChanges ?? [];
|
|
371
|
+
return earliest ? earliest.previousFormatting ?? {} : paragraphPropertiesSnapshot(node);
|
|
356
372
|
};
|
|
357
373
|
const resolveFormattingFromStyle = ({ attrs, styleId, styleResolver }) => {
|
|
358
374
|
const resolved = styleResolver?.resolveParagraphStyle(styleId).paragraphFormatting;
|
|
@@ -425,6 +441,7 @@ const preserveRunFormattingAcrossTrackedStyleChange = ({ allocateRevisionInfo, n
|
|
|
425
441
|
* the change left alone from one it explicitly cleared when rejecting it.
|
|
426
442
|
*/
|
|
427
443
|
const applyBlockParagraphProperties = ({ tr, position, node, properties, styleResolver, numbering = null, revisionInfo }) => {
|
|
444
|
+
const storedMarks = tr.storedMarks ?? tr.selection.$from.marks();
|
|
428
445
|
const attrs = expectParagraphAttrs(node);
|
|
429
446
|
const resolvedFormattingFromStyle = properties.styleId === void 0 ? resolveFormattingFromStyle({
|
|
430
447
|
attrs,
|
|
@@ -476,45 +493,25 @@ const applyBlockParagraphProperties = ({ tr, position, node, properties, styleRe
|
|
|
476
493
|
tr,
|
|
477
494
|
revisionIds: []
|
|
478
495
|
};
|
|
479
|
-
const styled = bridgeResult.tr.setNodeMarkup(position, void 0, nextAttrs);
|
|
480
496
|
return {
|
|
481
|
-
tr:
|
|
482
|
-
tr:
|
|
497
|
+
tr: rebaseParagraphRuns({
|
|
498
|
+
tr: bridgeResult.tr.setNodeMarkup(position, void 0, nextAttrs),
|
|
483
499
|
position,
|
|
484
500
|
previous: node,
|
|
485
|
-
styleResolver
|
|
501
|
+
styleResolver,
|
|
502
|
+
storedMarks
|
|
486
503
|
}),
|
|
487
504
|
changed: true,
|
|
488
505
|
revisionId: change?.info.id ?? null,
|
|
489
506
|
revisionIds: change ? [change.info.id, ...bridgeResult.revisionIds] : []
|
|
490
507
|
};
|
|
491
508
|
};
|
|
492
|
-
/**
|
|
493
|
-
const
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
const representations = selectRunFormattingCarrierRepresentations({
|
|
499
|
-
doc: tr.doc,
|
|
500
|
-
from: position + 1,
|
|
501
|
-
to: position + paragraph.nodeSize - 1
|
|
502
|
-
});
|
|
503
|
-
for (const representation of representations) applyMarksToRunFormattingRepresentation({
|
|
504
|
-
tr,
|
|
505
|
-
representation,
|
|
506
|
-
marks: reconcileRunFormattingMarks({
|
|
507
|
-
authoredFormatting: readAuthoredRunFormatting({
|
|
508
|
-
context: sourceContext,
|
|
509
|
-
marks: representation.node.marks,
|
|
510
|
-
styleResolver
|
|
511
|
-
}),
|
|
512
|
-
context: targetContext,
|
|
513
|
-
node: representation.node,
|
|
514
|
-
styleResolver
|
|
515
|
-
})
|
|
516
|
-
});
|
|
517
|
-
return tr;
|
|
509
|
+
/** No inherited formatting: every run-formatting mark reads as authored. */
|
|
510
|
+
const OPERATION_TEXT_CONTEXT = {
|
|
511
|
+
baseParagraphFormatting: void 0,
|
|
512
|
+
paragraphFormatting: void 0,
|
|
513
|
+
paragraphMarkFormatting: void 0,
|
|
514
|
+
paragraphMarkPrecedesStyle: false
|
|
518
515
|
};
|
|
519
516
|
const applyReplaceBlockStyleId = ({ item, tr, styleResolver, revisionInfo }) => {
|
|
520
517
|
if (item.operation.type !== "replaceBlock" || item.operation.styleId === void 0) return {
|
|
@@ -529,6 +526,7 @@ const applyReplaceBlockStyleId = ({ item, tr, styleResolver, revisionInfo }) =>
|
|
|
529
526
|
revisionId: null,
|
|
530
527
|
revisionIds: []
|
|
531
528
|
};
|
|
529
|
+
const storedMarks = tr.storedMarks ?? tr.selection.$from.marks();
|
|
532
530
|
const attrs = expectParagraphAttrs(block);
|
|
533
531
|
const resolvedFormattingFromStyle = resolveFormattingFromStyle({
|
|
534
532
|
attrs,
|
|
@@ -573,13 +571,13 @@ const applyReplaceBlockStyleId = ({ item, tr, styleResolver, revisionInfo }) =>
|
|
|
573
571
|
tr,
|
|
574
572
|
revisionIds: []
|
|
575
573
|
};
|
|
576
|
-
const styled = bridgeResult.tr.setNodeMarkup(blockPosition, void 0, nextAttrs);
|
|
577
574
|
return {
|
|
578
|
-
tr:
|
|
579
|
-
tr:
|
|
575
|
+
tr: rebaseParagraphRuns({
|
|
576
|
+
tr: bridgeResult.tr.setNodeMarkup(blockPosition, void 0, nextAttrs),
|
|
580
577
|
position: blockPosition,
|
|
581
578
|
previous: block,
|
|
582
|
-
styleResolver
|
|
579
|
+
styleResolver,
|
|
580
|
+
storedMarks
|
|
583
581
|
}),
|
|
584
582
|
revisionId: change?.info.id ?? null,
|
|
585
583
|
revisionIds: change ? [change.info.id, ...bridgeResult.revisionIds] : []
|
|
@@ -978,6 +976,27 @@ const deletedRowAffectedRanges = ({ doc, deletion, row }) => {
|
|
|
978
976
|
}
|
|
979
977
|
return ranges;
|
|
980
978
|
};
|
|
979
|
+
/**
|
|
980
|
+
* The blank cells a merge folds into the first cell of its rectangle. Only a
|
|
981
|
+
* blank cell can fold away tracked, so an edit that fills one decides whether
|
|
982
|
+
* the merge applies in one mode and not the other; see `batch-claims.ts`. A
|
|
983
|
+
* cell with content folds directly and is refused tracked whatever the batch
|
|
984
|
+
* does inside it.
|
|
985
|
+
*/
|
|
986
|
+
const foldedBlankCellRanges = (doc, { tablePosition, rectangle }) => {
|
|
987
|
+
const table = doc.nodeAt(tablePosition);
|
|
988
|
+
if (table?.type.spec["tableRole"] !== "table") return panic("A resolved cell merge lost its table", { position: tablePosition });
|
|
989
|
+
const map = TableMap.get(table);
|
|
990
|
+
const tableStart = tablePosition + 1;
|
|
991
|
+
const kept = map.map[rectangle.top * map.width + rectangle.left];
|
|
992
|
+
return map.cellsInRect(rectangle).flatMap((relative) => {
|
|
993
|
+
const cell = relative === kept ? null : table.nodeAt(relative);
|
|
994
|
+
return cell && isEmptyTableCell(cell) ? [{
|
|
995
|
+
from: tableStart + relative,
|
|
996
|
+
to: tableStart + relative + cell.nodeSize
|
|
997
|
+
}] : [];
|
|
998
|
+
});
|
|
999
|
+
};
|
|
981
1000
|
/** What `item` claims of the document its batch resolved against; see `batch-claims.ts`. */
|
|
982
1001
|
const batchClaimOf = ({ item, doc, producesTrackedChanges }) => {
|
|
983
1002
|
const block = item.blockFrom;
|
|
@@ -1028,9 +1047,7 @@ const batchClaimOf = ({ item, doc, producesTrackedChanges }) => {
|
|
|
1028
1047
|
type: "deleteBlock",
|
|
1029
1048
|
block,
|
|
1030
1049
|
end: item.blockTo,
|
|
1031
|
-
keepsParagraph
|
|
1032
|
-
removesNode: !producesTrackedChanges && !keepsParagraph,
|
|
1033
|
-
direct: !producesTrackedChanges
|
|
1050
|
+
keepsParagraph
|
|
1034
1051
|
};
|
|
1035
1052
|
}
|
|
1036
1053
|
case "insertAfterBlock":
|
|
@@ -1090,10 +1107,12 @@ const batchClaimOf = ({ item, doc, producesTrackedChanges }) => {
|
|
|
1090
1107
|
let axis = "cell";
|
|
1091
1108
|
if (item.operation.type === "insertTableRow") axis = "row";
|
|
1092
1109
|
if (item.operation.type === "insertTableColumn") axis = "column";
|
|
1093
|
-
|
|
1110
|
+
if (target.type === "none") return { type: "unclaimed" };
|
|
1111
|
+
return {
|
|
1094
1112
|
type: "tableStructure",
|
|
1095
1113
|
table: target.tablePosition,
|
|
1096
|
-
axis
|
|
1114
|
+
axis,
|
|
1115
|
+
folded: target.type === "mergeCells" ? foldedBlankCellRanges(doc, target) : []
|
|
1097
1116
|
};
|
|
1098
1117
|
}
|
|
1099
1118
|
}
|
|
@@ -1251,6 +1270,21 @@ const isBatchableParagraphInsertion = (item, mode) => {
|
|
|
1251
1270
|
const isEmptyInsert = insertTexts.length === 1 && insertTexts[0]?.length === 0;
|
|
1252
1271
|
return !(mode === "tracked-changes" && item.operation.pageBreakBefore === true && isEmptyInsert);
|
|
1253
1272
|
};
|
|
1273
|
+
/** The comments running across both edges of the table at `tablePosition`: over all of it. */
|
|
1274
|
+
const commentsAcrossTable = (doc, tablePosition) => {
|
|
1275
|
+
const table = doc.nodeAt(tablePosition);
|
|
1276
|
+
if (!table) return [];
|
|
1277
|
+
const atEnd = commentsAcrossBlockBoundary(doc, tablePosition + table.nodeSize);
|
|
1278
|
+
return commentsAcrossBlockBoundary(doc, tablePosition).filter((comment) => comment.isInSet(atEnd));
|
|
1279
|
+
};
|
|
1280
|
+
/** `comments` over the inline content of the node at `position`, which an insertion just placed. */
|
|
1281
|
+
const addCommentsOver = (tr, position, comments) => {
|
|
1282
|
+
const node = tr.doc.nodeAt(position);
|
|
1283
|
+
if (!node || !comments) return tr;
|
|
1284
|
+
let next = tr;
|
|
1285
|
+
for (const comment of comments) next = next.addMark(position + 1, position + node.nodeSize - 1, comment);
|
|
1286
|
+
return next;
|
|
1287
|
+
};
|
|
1254
1288
|
const insertBlocksInsideComments = ({ tr, at, blocks, carriedComments }) => {
|
|
1255
1289
|
const spanning = carriedComments ?? commentsAcrossBlockBoundary(tr.doc, at);
|
|
1256
1290
|
const fragment = Fragment.from(blocks);
|
|
@@ -1350,6 +1384,20 @@ const holdsOnlyDeletedContent = (paragraph) => {
|
|
|
1350
1384
|
});
|
|
1351
1385
|
return whollyDeleted;
|
|
1352
1386
|
};
|
|
1387
|
+
/**
|
|
1388
|
+
* Whether everything after `position` in its container is paragraphs pending
|
|
1389
|
+
* deletion: a join there, once accepted, has no words after it.
|
|
1390
|
+
*/
|
|
1391
|
+
const followedOnlyByDeletedParagraphs = (doc, position) => {
|
|
1392
|
+
const at = doc.resolve(position);
|
|
1393
|
+
let deletes = false;
|
|
1394
|
+
for (let index = at.index(); index < at.parent.childCount; index++) {
|
|
1395
|
+
const node = at.parent.child(index);
|
|
1396
|
+
if (node.type.name !== "paragraph" || !holdsOnlyDeletedContent(node)) return false;
|
|
1397
|
+
deletes ||= node.content.size > 0 || isPlainDeletedPPrMark(node.attrs["pPrMark"]);
|
|
1398
|
+
}
|
|
1399
|
+
return deletes;
|
|
1400
|
+
};
|
|
1353
1401
|
/** A paragraph mark that is a plain pending deletion (not a relocation's source). */
|
|
1354
1402
|
const isPlainDeletedPPrMark = (value) => typeof value === "object" && value !== null && "kind" in value && value.kind === "del";
|
|
1355
1403
|
/** An emptied paragraph still carries deleted content, rather than being an original blank. */
|
|
@@ -1380,11 +1428,30 @@ const deletedFinalParagraphAfter = (at, paragraphTypeName) => {
|
|
|
1380
1428
|
* Where the added break of the final paragraph at `at` rotates to: the free
|
|
1381
1429
|
* mark `addedBreakCarrierBefore` finds, or else a paragraph the batch deletes
|
|
1382
1430
|
* whole, whose deleted break the added one cancels (`cancelsDeletedBreak`).
|
|
1431
|
+
* A table whose rows all share one insertion revision from this batch is not
|
|
1432
|
+
* a barrier: rejecting that table removes it before the paragraphs join.
|
|
1433
|
+
* Existing and partially inserted tables remain barriers.
|
|
1383
1434
|
* The cancelling paragraph must be followed directly by the paragraph its
|
|
1384
1435
|
* words run into.
|
|
1385
1436
|
*/
|
|
1386
1437
|
const finalBreakCarrierBefore = (at, paragraphTypeName, batchRevisionIds) => {
|
|
1387
|
-
const free = addedBreakCarrierBefore(
|
|
1438
|
+
const free = addedBreakCarrierBefore({
|
|
1439
|
+
at,
|
|
1440
|
+
paragraphTypeName,
|
|
1441
|
+
canCrossTable: (table) => {
|
|
1442
|
+
if (table.childCount === 0) return false;
|
|
1443
|
+
let revisionId;
|
|
1444
|
+
for (let index = 0; index < table.childCount; index++) {
|
|
1445
|
+
const row = table.child(index);
|
|
1446
|
+
if (row.type.spec["tableRole"] !== "row") return false;
|
|
1447
|
+
const { trIns, trDel } = expectTableRowAttrs(row);
|
|
1448
|
+
if (!trIns || trDel || !batchRevisionIds.has(trIns.revisionId)) return false;
|
|
1449
|
+
revisionId ??= trIns.revisionId;
|
|
1450
|
+
if (trIns.revisionId !== revisionId) return false;
|
|
1451
|
+
}
|
|
1452
|
+
return true;
|
|
1453
|
+
}
|
|
1454
|
+
});
|
|
1388
1455
|
if (free) return {
|
|
1389
1456
|
...free,
|
|
1390
1457
|
cancelsDeletedBreak: false
|
|
@@ -1409,6 +1476,36 @@ const finalBreakCarrierBefore = (at, paragraphTypeName, batchRevisionIds) => {
|
|
|
1409
1476
|
}
|
|
1410
1477
|
return null;
|
|
1411
1478
|
};
|
|
1479
|
+
/** The preceding paragraph whose break a final deletion can retire. */
|
|
1480
|
+
const finalParagraphPredecessor = (doc, at) => {
|
|
1481
|
+
const emptied = doc.nodeAt(at);
|
|
1482
|
+
if (emptied?.type.name !== "paragraph") return null;
|
|
1483
|
+
const $emptied = doc.resolve(at);
|
|
1484
|
+
if (!paragraphEndsItsContainer($emptied, emptied.type.name)) return null;
|
|
1485
|
+
let position = at;
|
|
1486
|
+
for (let index = $emptied.index() - 1; index >= 0; index--) {
|
|
1487
|
+
const node = $emptied.parent.child(index);
|
|
1488
|
+
position -= node.nodeSize;
|
|
1489
|
+
if (node.type !== emptied.type) return null;
|
|
1490
|
+
if (isPlainDeletedPPrMark(node.attrs["pPrMark"]) && holdsOnlyDeletedContent(node)) continue;
|
|
1491
|
+
return {
|
|
1492
|
+
node,
|
|
1493
|
+
position
|
|
1494
|
+
};
|
|
1495
|
+
}
|
|
1496
|
+
return null;
|
|
1497
|
+
};
|
|
1498
|
+
/** Pending retirements, read after the merge has mapped any inserted separator. */
|
|
1499
|
+
const pendingRemovedFinalBreakPositions = (tr, deletions) => {
|
|
1500
|
+
const positions = /* @__PURE__ */ new Set();
|
|
1501
|
+
for (const deletion of deletions) {
|
|
1502
|
+
const at = tr.mapping.slice(deletion.mappedFrom).map(deletion.position);
|
|
1503
|
+
const predecessor = finalParagraphPredecessor(tr.doc, at);
|
|
1504
|
+
if (!predecessor || predecessor.node.attrs["pPrMark"] != null) continue;
|
|
1505
|
+
positions.add(predecessor.position);
|
|
1506
|
+
}
|
|
1507
|
+
return positions;
|
|
1508
|
+
};
|
|
1412
1509
|
/**
|
|
1413
1510
|
* Finish the tracked deletion of every paragraph a container ends with.
|
|
1414
1511
|
*
|
|
@@ -1432,7 +1529,7 @@ const finalBreakCarrierBefore = (at, paragraphTypeName, batchRevisionIds) => {
|
|
|
1432
1529
|
* emptied one is settled only then, since the batch runs backwards and an
|
|
1433
1530
|
* insertion or deletion before it lands after it.
|
|
1434
1531
|
*/
|
|
1435
|
-
const withRetiredFinalParagraphs = ({ tr, deletions, appliedIds, batchRevisionIds, revisionSeed, author, date }) => {
|
|
1532
|
+
const withRetiredFinalParagraphs = ({ tr, deletions, mergedPropertyTargets, appliedIds, batchRevisionIds, revisionSeed, author, date, styleResolver, numbering }) => {
|
|
1436
1533
|
let nextRevisionId = revisionSeed;
|
|
1437
1534
|
const addedRevisions = [];
|
|
1438
1535
|
const retractedRevisionIds = [];
|
|
@@ -1444,76 +1541,92 @@ const withRetiredFinalParagraphs = ({ tr, deletions, appliedIds, batchRevisionId
|
|
|
1444
1541
|
for (const { deletion: { operationId, revisionExtras }, at } of located) {
|
|
1445
1542
|
const emptied = tr.doc.nodeAt(at);
|
|
1446
1543
|
if (emptied?.type.name !== "paragraph") continue;
|
|
1447
|
-
const
|
|
1448
|
-
if (!
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1544
|
+
const predecessor = finalParagraphPredecessor(tr.doc, at);
|
|
1545
|
+
if (!predecessor) continue;
|
|
1546
|
+
const { node: previous, position } = predecessor;
|
|
1547
|
+
const mark = previous.attrs["pPrMark"];
|
|
1548
|
+
if (mark == null) {
|
|
1549
|
+
const revisionId = nextRevisionId++;
|
|
1550
|
+
tr.setNodeAttribute(position, "pPrMark", {
|
|
1551
|
+
kind: "del",
|
|
1552
|
+
info: {
|
|
1553
|
+
id: revisionId,
|
|
1554
|
+
author,
|
|
1555
|
+
date,
|
|
1556
|
+
...revisionExtras
|
|
1557
|
+
}
|
|
1558
|
+
});
|
|
1559
|
+
const beforeBatch = resolveParagraphChangeAttrs({
|
|
1560
|
+
node: previous,
|
|
1561
|
+
mode: "reject",
|
|
1562
|
+
boundaryCovered: true,
|
|
1563
|
+
revisionSet: batchRevisionIds,
|
|
1564
|
+
styleResolver,
|
|
1565
|
+
numbering
|
|
1566
|
+
});
|
|
1567
|
+
if (!mergedPropertyTargets.some(({ position: target, mappedFrom }) => {
|
|
1568
|
+
const mapped = tr.mapping.slice(mappedFrom).mapResult(target);
|
|
1569
|
+
return !mapped.deleted && mapped.pos === at;
|
|
1570
|
+
})) carryParagraphProperties({
|
|
1571
|
+
tr,
|
|
1572
|
+
position: at,
|
|
1573
|
+
source: beforeBatch ? previous.type.create(beforeBatch, previous.content, previous.marks) : previous,
|
|
1574
|
+
styleResolver,
|
|
1575
|
+
numbering,
|
|
1576
|
+
revision: {
|
|
1577
|
+
id: revisionId,
|
|
1578
|
+
author,
|
|
1579
|
+
date,
|
|
1580
|
+
...revisionExtras
|
|
1581
|
+
},
|
|
1582
|
+
keep: propertiesSetInBatch(emptied, batchRevisionIds)
|
|
1583
|
+
});
|
|
1584
|
+
resolvedOperationIds.add(operationId);
|
|
1585
|
+
addedRevisions.push({
|
|
1586
|
+
operationId,
|
|
1587
|
+
revisionId
|
|
1588
|
+
});
|
|
1589
|
+
continue;
|
|
1590
|
+
}
|
|
1591
|
+
if (isInsertedPPrMark(mark)) {
|
|
1592
|
+
const following = tr.doc.nodeAt(position + previous.nodeSize);
|
|
1593
|
+
if (following?.type.name !== emptied.type.name) continue;
|
|
1594
|
+
const previousFormatting = paragraphPropertiesBeforePendingChanges(following);
|
|
1595
|
+
const formattingChanges = JSON.stringify(previousFormatting) !== JSON.stringify(paragraphPropertiesSnapshot(previous));
|
|
1596
|
+
const existing = expectParagraphAttrs(previous)._propertyChanges;
|
|
1597
|
+
if (formattingChanges && hasSerializableParagraphPropertyChange(existing)) continue;
|
|
1598
|
+
joinAtParagraphMark({
|
|
1599
|
+
tr,
|
|
1600
|
+
paragraphPos: position,
|
|
1601
|
+
paragraph: previous,
|
|
1602
|
+
next: following,
|
|
1603
|
+
styleResolver
|
|
1604
|
+
});
|
|
1605
|
+
resolvedOperationIds.add(operationId);
|
|
1606
|
+
const retracted = addedBreakRevisionId(mark);
|
|
1607
|
+
if (retracted !== null) retractedRevisionIds.push(retracted);
|
|
1608
|
+
const revisionId = nextRevisionId;
|
|
1609
|
+
if (carryParagraphProperties({
|
|
1610
|
+
tr,
|
|
1611
|
+
position,
|
|
1612
|
+
source: previous,
|
|
1613
|
+
styleResolver,
|
|
1614
|
+
numbering,
|
|
1615
|
+
revision: {
|
|
1616
|
+
id: revisionId,
|
|
1617
|
+
author,
|
|
1618
|
+
date,
|
|
1619
|
+
...revisionExtras
|
|
1620
|
+
},
|
|
1621
|
+
keep: propertiesSetInBatch(following, batchRevisionIds)
|
|
1622
|
+
}).tracked) {
|
|
1623
|
+
nextRevisionId++;
|
|
1467
1624
|
addedRevisions.push({
|
|
1468
1625
|
operationId,
|
|
1469
1626
|
revisionId
|
|
1470
1627
|
});
|
|
1471
|
-
break;
|
|
1472
|
-
}
|
|
1473
|
-
if (isPlainDeletedPPrMark(mark)) {
|
|
1474
|
-
if (holdsOnlyDeletedContent(previous)) continue;
|
|
1475
|
-
break;
|
|
1476
1628
|
}
|
|
1477
|
-
|
|
1478
|
-
const following = tr.doc.nodeAt(position + previous.nodeSize);
|
|
1479
|
-
if (following?.type.name !== emptied.type.name) break;
|
|
1480
|
-
const previousFormatting = paragraphPropertiesBeforeBatch(following, batchRevisionIds);
|
|
1481
|
-
const formattingChanges = JSON.stringify(previousFormatting) !== JSON.stringify(paragraphPropertiesSnapshot(previous));
|
|
1482
|
-
const existing = expectParagraphAttrs(previous)._propertyChanges;
|
|
1483
|
-
if (formattingChanges && hasSerializableParagraphPropertyChange(existing)) break;
|
|
1484
|
-
joinAtParagraphMark({
|
|
1485
|
-
tr,
|
|
1486
|
-
paragraphPos: position,
|
|
1487
|
-
paragraph: previous,
|
|
1488
|
-
next: following
|
|
1489
|
-
});
|
|
1490
|
-
resolvedOperationIds.add(operationId);
|
|
1491
|
-
const retracted = addedBreakRevisionId(mark);
|
|
1492
|
-
if (retracted !== null) retractedRevisionIds.push(retracted);
|
|
1493
|
-
const joined = tr.doc.nodeAt(position);
|
|
1494
|
-
if (formattingChanges && joined) {
|
|
1495
|
-
const revisionId = nextRevisionId++;
|
|
1496
|
-
tr.setNodeMarkup(position, void 0, {
|
|
1497
|
-
...joined.attrs,
|
|
1498
|
-
_propertyChanges: [...Array.isArray(existing) ? existing : [], {
|
|
1499
|
-
type: "paragraphPropertyChange",
|
|
1500
|
-
info: {
|
|
1501
|
-
id: revisionId,
|
|
1502
|
-
author,
|
|
1503
|
-
date,
|
|
1504
|
-
...revisionExtras
|
|
1505
|
-
},
|
|
1506
|
-
previousFormatting
|
|
1507
|
-
}]
|
|
1508
|
-
});
|
|
1509
|
-
addedRevisions.push({
|
|
1510
|
-
operationId,
|
|
1511
|
-
revisionId
|
|
1512
|
-
});
|
|
1513
|
-
}
|
|
1514
|
-
break;
|
|
1515
|
-
}
|
|
1516
|
-
break;
|
|
1629
|
+
continue;
|
|
1517
1630
|
}
|
|
1518
1631
|
}
|
|
1519
1632
|
return {
|
|
@@ -1545,6 +1658,8 @@ const withRetiredFinalParagraphs = ({ tr, deletions, appliedIds, batchRevisionId
|
|
|
1545
1658
|
* which paragraph ends a container is only settled when the batch is, and an
|
|
1546
1659
|
* insertion that looked final was undone by the next operation writing a table
|
|
1547
1660
|
* after it.
|
|
1661
|
+
* A wholly inserted table from this batch can be crossed to reach the carrier;
|
|
1662
|
+
* its removal on reject exposes that same paragraph boundary again.
|
|
1548
1663
|
*
|
|
1549
1664
|
* The paragraph the run was appended after may be one the same batch deletes:
|
|
1550
1665
|
* the insertion landed first, so the deletion took that paragraph's mark as
|
|
@@ -1553,7 +1668,7 @@ const withRetiredFinalParagraphs = ({ tr, deletions, appliedIds, batchRevisionId
|
|
|
1553
1668
|
* paragraph's words run into the one after it, which ends with the free mark,
|
|
1554
1669
|
* and neither break is left to resolve.
|
|
1555
1670
|
*/
|
|
1556
|
-
const withRotatedAddedFinalBreaks = ({ tr, batchRevisionIds, revisionSeed, author, date, initials }) => {
|
|
1671
|
+
const withRotatedAddedFinalBreaks = ({ tr, batchRevisionIds, revisionSeed, author, date, initials, styleResolver }) => {
|
|
1557
1672
|
const supersededDeletedBreaks = [];
|
|
1558
1673
|
const collectSupersededDeletedBreaks = (parent, contentStart) => {
|
|
1559
1674
|
let previous = null;
|
|
@@ -1634,7 +1749,7 @@ const withRotatedAddedFinalBreaks = ({ tr, batchRevisionIds, revisionSeed, autho
|
|
|
1634
1749
|
const revisionId = addedBreakRevisionId(node.attrs["pPrMark"]);
|
|
1635
1750
|
return revisionId === null || !batchRevisionIds.has(revisionId);
|
|
1636
1751
|
})) continue;
|
|
1637
|
-
const previousFormatting =
|
|
1752
|
+
const previousFormatting = paragraphPropertiesBeforePendingChanges(carrier.node);
|
|
1638
1753
|
next = next.setNodeAttribute(finalPosition, "pPrMark", null);
|
|
1639
1754
|
let carriedMark = finalMark;
|
|
1640
1755
|
for (let index = 1; index < path.length; index++) {
|
|
@@ -1680,7 +1795,7 @@ const withRotatedAddedFinalBreaks = ({ tr, batchRevisionIds, revisionSeed, autho
|
|
|
1680
1795
|
paragraphPos: previous.position,
|
|
1681
1796
|
paragraph: deleted,
|
|
1682
1797
|
next: following,
|
|
1683
|
-
|
|
1798
|
+
styleResolver
|
|
1684
1799
|
});
|
|
1685
1800
|
retractedRevisionIds.push(ownerRevisionId);
|
|
1686
1801
|
const deletedBreakId = addedOrDeletedBreakRevisionId(displacedMark);
|
|
@@ -1875,7 +1990,7 @@ const buildInsertedParagraphs = ({ item, schema, formattingFromStyle, mode, auth
|
|
|
1875
1990
|
...initials ? { initials } : {}
|
|
1876
1991
|
};
|
|
1877
1992
|
const paragraph = item.blockNode.type.create(attrs, content);
|
|
1878
|
-
const sourceContext =
|
|
1993
|
+
const sourceContext = OPERATION_TEXT_CONTEXT;
|
|
1879
1994
|
const targetContext = paragraphRunStyleContext(paragraph, styleResolver);
|
|
1880
1995
|
const reconciled = [];
|
|
1881
1996
|
paragraph.forEach((child) => {
|
|
@@ -2125,6 +2240,7 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations: reques
|
|
|
2125
2240
|
const deletedTextBoxAnchorIds = /* @__PURE__ */ new Set();
|
|
2126
2241
|
/** Container-ending paragraphs a tracked `deleteBlock` emptied: see `withRetiredFinalParagraphs`. */
|
|
2127
2242
|
const deletedFinalParagraphs = [];
|
|
2243
|
+
const mergedPropertyTargets = [];
|
|
2128
2244
|
const deferredNoopFinalDeletions = /* @__PURE__ */ new Set();
|
|
2129
2245
|
const ownsSharedRevisionIdCursor = revisionIdSeed === void 0 && revisionStamp === void 0;
|
|
2130
2246
|
let revisionSeed = revisionIdSeed ?? revisionStamp?.idSeed ?? revisionIdCursor;
|
|
@@ -2141,6 +2257,7 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations: reques
|
|
|
2141
2257
|
};
|
|
2142
2258
|
const date = revisionStamp?.date ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
2143
2259
|
const insertedColumnCounts = /* @__PURE__ */ new Map();
|
|
2260
|
+
const emptiedRows = { pending: false };
|
|
2144
2261
|
const tableAfterDeletedSplit = /* @__PURE__ */ new Map();
|
|
2145
2262
|
if (mode === "tracked-changes") {
|
|
2146
2263
|
const afterTables = /* @__PURE__ */ new Map();
|
|
@@ -2671,9 +2788,10 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations: reques
|
|
|
2671
2788
|
}
|
|
2672
2789
|
const revision = structuralRevision;
|
|
2673
2790
|
const template = tableTemplates?.get(item.operation.id);
|
|
2791
|
+
const mappedInsertion = mapTableRowInsertion(tr, insertion);
|
|
2674
2792
|
const result = applyTableRowInsertion({
|
|
2675
2793
|
tr,
|
|
2676
|
-
insertion:
|
|
2794
|
+
insertion: mappedInsertion,
|
|
2677
2795
|
cellTexts: item.operation.cellTexts,
|
|
2678
2796
|
revision,
|
|
2679
2797
|
...template !== void 0 && { template }
|
|
@@ -2685,7 +2803,7 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations: reques
|
|
|
2685
2803
|
});
|
|
2686
2804
|
continue;
|
|
2687
2805
|
}
|
|
2688
|
-
tr = result.transaction;
|
|
2806
|
+
tr = addCommentsOver(result.transaction, mappedInsertion.rowPosition, item.tableRowComments);
|
|
2689
2807
|
if (result.revisionId !== null) {
|
|
2690
2808
|
operationRevisionSeed++;
|
|
2691
2809
|
appliedRevisionIds = [result.revisionId];
|
|
@@ -2723,11 +2841,9 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations: reques
|
|
|
2723
2841
|
});
|
|
2724
2842
|
continue;
|
|
2725
2843
|
}
|
|
2726
|
-
tr = result.transaction;
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
appliedRevisionIds = [result.revisionId];
|
|
2730
|
-
}
|
|
2844
|
+
tr = addCommentsOver(result.transaction, tr.mapping.map(insertion.tablePosition, 1), item.tableColumnComments);
|
|
2845
|
+
operationRevisionSeed += result.revisionIds.length;
|
|
2846
|
+
appliedRevisionIds = [...result.revisionIds];
|
|
2731
2847
|
const columnKey = getTableColumnCoordinateKey(insertion);
|
|
2732
2848
|
insertedColumnCounts.set(columnKey, (insertedColumnCounts.get(columnKey) ?? 0) + 1);
|
|
2733
2849
|
break;
|
|
@@ -2747,7 +2863,8 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations: reques
|
|
|
2747
2863
|
tr,
|
|
2748
2864
|
deletion,
|
|
2749
2865
|
insertedColumnCount: insertedColumnCounts.get(columnKey) ?? 0,
|
|
2750
|
-
revision
|
|
2866
|
+
revision,
|
|
2867
|
+
emptiedRows
|
|
2751
2868
|
});
|
|
2752
2869
|
if (result.type === "unsupported") {
|
|
2753
2870
|
skipped.push({
|
|
@@ -2757,10 +2874,8 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations: reques
|
|
|
2757
2874
|
continue;
|
|
2758
2875
|
}
|
|
2759
2876
|
tr = result.transaction;
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
appliedRevisionIds = [result.revisionId];
|
|
2763
|
-
}
|
|
2877
|
+
operationRevisionSeed += result.revisionIds.length;
|
|
2878
|
+
appliedRevisionIds = [...result.revisionIds];
|
|
2764
2879
|
break;
|
|
2765
2880
|
}
|
|
2766
2881
|
case "mergeTableCells": {
|
|
@@ -2893,8 +3008,26 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations: reques
|
|
|
2893
3008
|
});
|
|
2894
3009
|
continue;
|
|
2895
3010
|
}
|
|
3011
|
+
const retracted = tr.doc.nodeAt(item.blockFrom);
|
|
2896
3012
|
tr = tr.delete(item.blockFrom, item.blockTo);
|
|
2897
|
-
if (retraction.clearBreakAt !== null)
|
|
3013
|
+
if (retraction.clearBreakAt !== null) {
|
|
3014
|
+
tr = tr.setNodeAttribute(retraction.clearBreakAt, "pPrMark", null);
|
|
3015
|
+
const revisionIdProperties = operationRevisionSeed;
|
|
3016
|
+
if (retracted && recordReplacedParagraphProperties({
|
|
3017
|
+
tr,
|
|
3018
|
+
position: retraction.clearBreakAt,
|
|
3019
|
+
replaced: retracted,
|
|
3020
|
+
revision: {
|
|
3021
|
+
id: revisionIdProperties,
|
|
3022
|
+
author,
|
|
3023
|
+
date,
|
|
3024
|
+
...trackedRevisionExtras
|
|
3025
|
+
}
|
|
3026
|
+
})) {
|
|
3027
|
+
operationRevisionSeed++;
|
|
3028
|
+
appliedRevisionIds = [revisionIdProperties];
|
|
3029
|
+
}
|
|
3030
|
+
}
|
|
2898
3031
|
break;
|
|
2899
3032
|
}
|
|
2900
3033
|
if (deletionType) {
|
|
@@ -2922,14 +3055,36 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations: reques
|
|
|
2922
3055
|
const endsItsContainer = paragraphEndsItsContainer(tr.doc.resolve(markPosition), item.blockNode.type.name);
|
|
2923
3056
|
const deleted = tr.doc.nodeAt(markPosition);
|
|
2924
3057
|
const following = deleted && tr.doc.nodeAt(markPosition + deleted.nodeSize);
|
|
2925
|
-
if (deleted && following?.type === deleted.type && !isPairedMove(item.operation.moveId) && isInsertedPPrMark(deleted.attrs["pPrMark"]))
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
3058
|
+
if (deleted && following?.type === deleted.type && !isPairedMove(item.operation.moveId) && isInsertedPPrMark(deleted.attrs["pPrMark"])) {
|
|
3059
|
+
const restored = paragraphPropertiesOnReject(deleted);
|
|
3060
|
+
const followingChanges = expectParagraphAttrs(following)._propertyChanges;
|
|
3061
|
+
const recordsRestored = isInsertedPPrMark(following.attrs["pPrMark"]) && !hasSerializableParagraphPropertyChange(followingChanges) && JSON.stringify(restored) !== JSON.stringify(paragraphPropertiesSnapshot(following));
|
|
3062
|
+
joinAtParagraphMark({
|
|
3063
|
+
tr,
|
|
3064
|
+
paragraphPos: markPosition,
|
|
3065
|
+
paragraph: deleted,
|
|
3066
|
+
next: following,
|
|
3067
|
+
styleResolver: styleResolver ?? null
|
|
3068
|
+
});
|
|
3069
|
+
const joined = tr.doc.nodeAt(markPosition);
|
|
3070
|
+
if (recordsRestored && joined) {
|
|
3071
|
+
const propertyRevisionId = operationRevisionSeed++;
|
|
3072
|
+
tr = tr.setNodeMarkup(markPosition, void 0, {
|
|
3073
|
+
...joined.attrs,
|
|
3074
|
+
_propertyChanges: [...Array.isArray(followingChanges) ? followingChanges : [], {
|
|
3075
|
+
type: "paragraphPropertyChange",
|
|
3076
|
+
info: {
|
|
3077
|
+
id: propertyRevisionId,
|
|
3078
|
+
author,
|
|
3079
|
+
date,
|
|
3080
|
+
...trackedRevisionExtras
|
|
3081
|
+
},
|
|
3082
|
+
previousFormatting: restored
|
|
3083
|
+
}]
|
|
3084
|
+
});
|
|
3085
|
+
appliedRevisionIds = [...appliedRevisionIds, propertyRevisionId];
|
|
3086
|
+
}
|
|
3087
|
+
} else if (!endsItsContainer && deleted?.attrs["pPrMark"] == null) {
|
|
2933
3088
|
const markRevisionId = operationRevisionSeed++;
|
|
2934
3089
|
tr = tr.setNodeAttribute(markPosition, "pPrMark", {
|
|
2935
3090
|
kind: isPairedMove(item.operation.moveId) ? "moveFrom" : "del",
|
|
@@ -3218,8 +3373,17 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations: reques
|
|
|
3218
3373
|
break;
|
|
3219
3374
|
}
|
|
3220
3375
|
case "mergeBlockWithNext": {
|
|
3221
|
-
|
|
3376
|
+
if (mode === "direct" && !canJoin(tr.doc, item.blockTo)) {
|
|
3377
|
+
skipped.push({
|
|
3378
|
+
id: item.operation.id,
|
|
3379
|
+
reason: "unsupportedBlock"
|
|
3380
|
+
});
|
|
3381
|
+
continue;
|
|
3382
|
+
}
|
|
3383
|
+
const separator = followedOnlyByDeletedParagraphs(tr.doc, item.blockTo) ? "" : item.operation.separator ?? "";
|
|
3222
3384
|
const insertAt = item.blockTo - 1;
|
|
3385
|
+
let mergedPropertiesAt = item.blockFrom;
|
|
3386
|
+
let mergedPropertiesRecorded = false;
|
|
3223
3387
|
const second = tr.doc.nodeAt(item.blockTo);
|
|
3224
3388
|
const spanningComments = commentsAcrossBlockBoundary(tr.doc, item.blockTo);
|
|
3225
3389
|
const withSeparator = (transaction) => {
|
|
@@ -3253,6 +3417,7 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations: reques
|
|
|
3253
3417
|
target: paragraph,
|
|
3254
3418
|
styleResolver
|
|
3255
3419
|
});
|
|
3420
|
+
tr.setMeta(JOINED_RUNS_RESTYLED_META, true);
|
|
3256
3421
|
tr = tr.join(item.blockTo + separator.length);
|
|
3257
3422
|
const secondSection = second ? sectionPropertiesOf(second) : null;
|
|
3258
3423
|
const joined = tr.doc.nodeAt(item.blockFrom);
|
|
@@ -3280,42 +3445,77 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations: reques
|
|
|
3280
3445
|
tr,
|
|
3281
3446
|
paragraphPos: item.blockFrom,
|
|
3282
3447
|
paragraph,
|
|
3283
|
-
next
|
|
3448
|
+
next,
|
|
3449
|
+
styleResolver
|
|
3284
3450
|
});
|
|
3285
|
-
const
|
|
3286
|
-
const
|
|
3287
|
-
|
|
3288
|
-
|
|
3451
|
+
const joinedMark = tr.doc.nodeAt(item.blockFrom)?.attrs["pPrMark"];
|
|
3452
|
+
const removedBreakPositions = pendingRemovedFinalBreakPositions(tr, deletedFinalParagraphs);
|
|
3453
|
+
const carryPos = isDeletedPPrMark(joinedMark) || removedBreakPositions.has(item.blockFrom) ? paragraphLeftAfter({
|
|
3454
|
+
doc: tr.doc,
|
|
3455
|
+
paragraphPos: item.blockFrom,
|
|
3456
|
+
removedBreakPositions
|
|
3457
|
+
}) ?? item.blockFrom : item.blockFrom;
|
|
3458
|
+
const carried = carryParagraphProperties({
|
|
3459
|
+
tr,
|
|
3460
|
+
position: carryPos,
|
|
3461
|
+
source: paragraph,
|
|
3462
|
+
styleResolver,
|
|
3463
|
+
numbering,
|
|
3464
|
+
revision: {
|
|
3465
|
+
id: revisionIdMark,
|
|
3466
|
+
author,
|
|
3467
|
+
date,
|
|
3468
|
+
...trackedRevisionExtras
|
|
3469
|
+
}
|
|
3470
|
+
});
|
|
3471
|
+
mergedPropertiesAt = carryPos;
|
|
3472
|
+
tr = carried.tr;
|
|
3473
|
+
mergedPropertiesRecorded = carried.tracked;
|
|
3474
|
+
if (!carried.tracked) appliedRevisionIds = appliedRevisionIds.filter((id) => id !== revisionIdMark);
|
|
3475
|
+
} else {
|
|
3476
|
+
tr = tr.setNodeAttribute(item.blockFrom, "pPrMark", {
|
|
3477
|
+
kind: "del",
|
|
3289
3478
|
info: {
|
|
3290
3479
|
id: revisionIdMark,
|
|
3291
3480
|
author,
|
|
3292
3481
|
date,
|
|
3293
3482
|
...trackedRevisionExtras
|
|
3294
|
-
}
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3483
|
+
}
|
|
3484
|
+
});
|
|
3485
|
+
const survivorPos = paragraphLeftAfter({
|
|
3486
|
+
doc: tr.doc,
|
|
3487
|
+
paragraphPos: item.blockFrom,
|
|
3488
|
+
removedBreakPositions: pendingRemovedFinalBreakPositions(tr, deletedFinalParagraphs)
|
|
3489
|
+
}) ?? joinPos;
|
|
3490
|
+
const carried = carryParagraphProperties({
|
|
3491
|
+
tr,
|
|
3492
|
+
position: survivorPos,
|
|
3493
|
+
source: paragraph,
|
|
3494
|
+
styleResolver,
|
|
3495
|
+
numbering,
|
|
3496
|
+
revision: {
|
|
3497
|
+
id: revisionIdMark,
|
|
3498
|
+
author,
|
|
3499
|
+
date,
|
|
3500
|
+
...trackedRevisionExtras
|
|
3501
|
+
}
|
|
3502
|
+
});
|
|
3503
|
+
tr = carried.tr;
|
|
3504
|
+
mergedPropertiesRecorded = carried.tracked;
|
|
3505
|
+
mergedPropertiesAt = survivorPos;
|
|
3506
|
+
}
|
|
3307
3507
|
}
|
|
3308
3508
|
if (item.operation.mergedParagraphProperties) {
|
|
3309
|
-
const mergedParagraph = tr.doc.nodeAt(
|
|
3509
|
+
const mergedParagraph = tr.doc.nodeAt(mergedPropertiesAt);
|
|
3310
3510
|
if (!mergedParagraph) panic("A resolved merge did not produce a paragraph");
|
|
3311
3511
|
const appliedProperties = applyBlockParagraphProperties({
|
|
3312
3512
|
tr,
|
|
3313
|
-
position:
|
|
3513
|
+
position: mergedPropertiesAt,
|
|
3314
3514
|
node: mergedParagraph,
|
|
3315
3515
|
properties: item.operation.mergedParagraphProperties,
|
|
3316
3516
|
styleResolver,
|
|
3317
3517
|
numbering,
|
|
3318
|
-
...mode === "direct" ? {} : { revisionInfo: () => ({
|
|
3518
|
+
...mode === "direct" || mergedPropertiesRecorded ? {} : { revisionInfo: () => ({
|
|
3319
3519
|
id: operationRevisionSeed++,
|
|
3320
3520
|
author,
|
|
3321
3521
|
date,
|
|
@@ -3325,6 +3525,10 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations: reques
|
|
|
3325
3525
|
tr = appliedProperties.tr;
|
|
3326
3526
|
if (appliedProperties.revisionIds.length > 0) appliedRevisionIds.push(...appliedProperties.revisionIds);
|
|
3327
3527
|
}
|
|
3528
|
+
if (mode !== "direct") mergedPropertyTargets.push({
|
|
3529
|
+
position: mergedPropertiesAt,
|
|
3530
|
+
mappedFrom: tr.mapping.maps.length
|
|
3531
|
+
});
|
|
3328
3532
|
break;
|
|
3329
3533
|
}
|
|
3330
3534
|
case "commentOnBlock":
|
|
@@ -3373,6 +3577,7 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations: reques
|
|
|
3373
3577
|
...suggestionId !== null && { suggestionId }
|
|
3374
3578
|
});
|
|
3375
3579
|
}
|
|
3580
|
+
removeRowsWithoutCellsAfterBatch(tr, emptiedRows);
|
|
3376
3581
|
if (tr.docChanged || deferredNoopFinalDeletions.size > 0) {
|
|
3377
3582
|
const batchRevisionIds = new Set(applied.flatMap(({ revisionIds }) => revisionIds ?? []));
|
|
3378
3583
|
tr = withoutRevisionsOnZeroWidthAnchors(tr, batchRevisionIds, deletedTextBoxAnchorIds);
|
|
@@ -3384,18 +3589,22 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations: reques
|
|
|
3384
3589
|
revisionSeed,
|
|
3385
3590
|
author,
|
|
3386
3591
|
date,
|
|
3387
|
-
initials
|
|
3592
|
+
initials,
|
|
3593
|
+
styleResolver: styleResolver ?? null
|
|
3388
3594
|
});
|
|
3389
3595
|
tr = rotated.transaction;
|
|
3390
3596
|
revisionSeed = rotated.nextRevisionId;
|
|
3391
3597
|
const retired = withRetiredFinalParagraphs({
|
|
3392
3598
|
tr,
|
|
3393
3599
|
deletions: deletedFinalParagraphs,
|
|
3600
|
+
mergedPropertyTargets,
|
|
3394
3601
|
appliedIds: new Set(applied.map(({ id }) => id)),
|
|
3395
3602
|
batchRevisionIds,
|
|
3396
3603
|
revisionSeed,
|
|
3397
3604
|
author,
|
|
3398
|
-
date
|
|
3605
|
+
date,
|
|
3606
|
+
styleResolver,
|
|
3607
|
+
numbering
|
|
3399
3608
|
});
|
|
3400
3609
|
revisionSeed = retired.nextRevisionId;
|
|
3401
3610
|
for (const operationId of deferredNoopFinalDeletions) {
|
|
@@ -3447,6 +3656,19 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations: reques
|
|
|
3447
3656
|
revisionIds
|
|
3448
3657
|
};
|
|
3449
3658
|
}
|
|
3659
|
+
const separated = separateRevisionStretches({
|
|
3660
|
+
tr,
|
|
3661
|
+
revisionSeed
|
|
3662
|
+
});
|
|
3663
|
+
revisionSeed = separated.nextRevisionId;
|
|
3664
|
+
for (const { revisionId, from } of separated.minted) {
|
|
3665
|
+
const receiptIndex = applied.findIndex(({ revisionIds }) => revisionIds?.includes(from));
|
|
3666
|
+
const receipt = applied.at(receiptIndex);
|
|
3667
|
+
if (receiptIndex >= 0 && receipt?.revisionIds) applied[receiptIndex] = {
|
|
3668
|
+
...receipt,
|
|
3669
|
+
revisionIds: [...receipt.revisionIds, revisionId]
|
|
3670
|
+
};
|
|
3671
|
+
}
|
|
3450
3672
|
claimSharedRevisionIds(revisionSeed);
|
|
3451
3673
|
if (revisionStamp) requestDeterministicParaIds(tr, `${revisionStamp.date}:${String(revisionStamp.idSeed)}`);
|
|
3452
3674
|
if (tr.docChanged) view.dispatch(tr);
|
|
@@ -4409,7 +4631,8 @@ const resolveOperationTarget = ({ snapshot, operation, liveBlocks, liveBlocksByP
|
|
|
4409
4631
|
blockFrom,
|
|
4410
4632
|
blockTo,
|
|
4411
4633
|
blockNode,
|
|
4412
|
-
tableRowInsertion: insertion
|
|
4634
|
+
tableRowInsertion: insertion,
|
|
4635
|
+
tableRowComments: commentsAcrossBlockBoundary(doc, insertion.rowPosition)
|
|
4413
4636
|
}
|
|
4414
4637
|
};
|
|
4415
4638
|
}
|
|
@@ -4457,7 +4680,8 @@ const resolveOperationTarget = ({ snapshot, operation, liveBlocks, liveBlocksByP
|
|
|
4457
4680
|
blockFrom,
|
|
4458
4681
|
blockTo,
|
|
4459
4682
|
blockNode,
|
|
4460
|
-
tableColumnInsertion
|
|
4683
|
+
tableColumnInsertion,
|
|
4684
|
+
tableColumnComments: commentsAcrossTable(doc, tableColumnInsertion.tablePosition)
|
|
4461
4685
|
}
|
|
4462
4686
|
};
|
|
4463
4687
|
}
|