@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
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { getDocumentStyleResolver } from "./plugins/documentStyleState.js";
|
|
2
|
+
import { applyMarksToRunFormattingRepresentation, selectRunFormattingCarrierRepresentations } from "./runFormattingInlineCarriers.js";
|
|
3
|
+
import { readAuthoredRunFormatting, reconcileRunFormattingMarks } from "./runFormattingReconciliation.js";
|
|
4
|
+
import { paragraphRunStyleContextAt } from "./runStyleFormatting.js";
|
|
5
|
+
//#region src/prosemirror/clearRunColor.ts
|
|
6
|
+
/** Clearing direct color reveals the run's character/paragraph style color. */
|
|
7
|
+
const clearRunColor = () => (state, dispatch) => {
|
|
8
|
+
if (!dispatch) return true;
|
|
9
|
+
const styleResolver = getDocumentStyleResolver(state);
|
|
10
|
+
const tr = state.tr;
|
|
11
|
+
const { from, to, empty } = state.selection;
|
|
12
|
+
const clearedMarks = (node, position) => {
|
|
13
|
+
const context = paragraphRunStyleContextAt({
|
|
14
|
+
doc: state.doc,
|
|
15
|
+
pos: position,
|
|
16
|
+
styleResolver
|
|
17
|
+
});
|
|
18
|
+
const { color: _color, ...authoredFormatting } = readAuthoredRunFormatting({
|
|
19
|
+
context,
|
|
20
|
+
marks: node.marks,
|
|
21
|
+
styleResolver
|
|
22
|
+
});
|
|
23
|
+
return reconcileRunFormattingMarks({
|
|
24
|
+
authoredFormatting,
|
|
25
|
+
context,
|
|
26
|
+
node,
|
|
27
|
+
styleResolver
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
if (empty) {
|
|
31
|
+
const node = state.schema.text(" ", state.storedMarks ?? state.selection.$from.marks());
|
|
32
|
+
tr.setStoredMarks(clearedMarks(node, from));
|
|
33
|
+
} else for (const representation of selectRunFormattingCarrierRepresentations({
|
|
34
|
+
doc: state.doc,
|
|
35
|
+
from,
|
|
36
|
+
to
|
|
37
|
+
})) applyMarksToRunFormattingRepresentation({
|
|
38
|
+
tr,
|
|
39
|
+
representation,
|
|
40
|
+
marks: clearedMarks(representation.node, representation.position)
|
|
41
|
+
});
|
|
42
|
+
dispatch(tr.scrollIntoView());
|
|
43
|
+
return true;
|
|
44
|
+
};
|
|
45
|
+
//#endregion
|
|
46
|
+
export { clearRunColor };
|
|
@@ -7,21 +7,23 @@ import { expectFieldAttrs, expectParagraphAttrs, expectRunPropertyChangeMarkAttr
|
|
|
7
7
|
import { addedBreakCarrierBefore, finalParagraphsOf, paragraphEndsItsContainer } from "../containerFinalParagraph.js";
|
|
8
8
|
import { enclosingRevisionIds, resolutionRemovesControl, withoutResolvedEnclosures } from "../contentControlRevisions.js";
|
|
9
9
|
import { resolveEmptyFieldResultRuns } from "../emptyFieldResultRuns.js";
|
|
10
|
+
import { JOINED_RUNS_RESTYLED_META } from "../extensions/features/JoinedRunStyleExtension.js";
|
|
10
11
|
import { markChangedParagraphRanges, markStructuralChange, markTrackedSectionEndpointRemoval } from "../extensions/features/ParagraphChangeTrackerExtension.js";
|
|
11
12
|
import "../extensions/nodes/SdtExtension.js";
|
|
12
13
|
import { resolveStateStory } from "../markupViewProjection.js";
|
|
13
14
|
import { joinAtParagraphMark } from "../paragraphMarkJoin.js";
|
|
14
15
|
import { getDocumentNumbering } from "../plugins/documentNumbering.js";
|
|
15
|
-
import { getDocumentStyleResolver } from "../plugins/
|
|
16
|
-
import { setParagraphAttrsWithRebasedRunFormatting } from "../rebaseParagraphRunFormatting.js";
|
|
16
|
+
import { getDocumentStyleResolver } from "../plugins/documentStyleState.js";
|
|
17
|
+
import { rebaseParagraphRuns, setParagraphAttrsWithRebasedRunFormatting } from "../rebaseParagraphRunFormatting.js";
|
|
17
18
|
import { rejoinRunsAt } from "../rejoinRunCarriers.js";
|
|
18
19
|
import { getFolioNodeRevisionCarriers, nodePropertyRevisionSites } from "../revisionCarriers.js";
|
|
19
20
|
import { RUN_FORMATTING_MARK_NAMES } from "../runFormattingMarkNames.js";
|
|
20
21
|
import { reconstructRejectedRunFormattingMarks } from "../runPropertyChangeResolution.js";
|
|
21
|
-
import { paragraphRunStyleContextAt } from "../runStyleFormatting.js";
|
|
22
|
+
import { paragraphRunStyleContext, paragraphRunStyleContextAt } from "../runStyleFormatting.js";
|
|
22
23
|
import { getTableCellMergeChange } from "../tableCellMergeRevision.js";
|
|
23
24
|
import { isTableCellRetainedInReviewView } from "../tableCellRevisionVisibility.js";
|
|
24
|
-
import { reconcileTableGridAfterColumnRemoval,
|
|
25
|
+
import { markRowEmptiedInBatch, reconcileTableGridAfterColumnRemoval, removeRowsWithoutCellsAfterBatch, removeTableRow } from "../tableGridMutation.js";
|
|
26
|
+
import { runInCellPending, runParagraphIntoTable } from "../tableRunIn.js";
|
|
25
27
|
import { holdsNoContent } from "../zeroWidthAnchors.js";
|
|
26
28
|
import { inlineBookmarksForParagraphJoin } from "./paragraphBookmarkJoin.js";
|
|
27
29
|
import { hasSerializableParagraphPropertyChange, paragraphPropertiesSnapshot } from "./propertyChangeScope.js";
|
|
@@ -106,6 +108,7 @@ function resolveChange(from, to, mode, revisionIds) {
|
|
|
106
108
|
const matchesRevision = (mark) => revisionSet === null || typeof mark.attrs["revisionId"] === "number" && revisionSet.has(mark.attrs["revisionId"]);
|
|
107
109
|
if (dispatch) {
|
|
108
110
|
const tr = state.tr;
|
|
111
|
+
tr.setMeta(JOINED_RUNS_RESTYLED_META, true);
|
|
109
112
|
const deleteRanges = [];
|
|
110
113
|
/** Where resolved inline content began and ended, in `state.doc`. */
|
|
111
114
|
const resolvedBoundaries = [];
|
|
@@ -278,7 +281,7 @@ function resolveChange(from, to, mode, revisionIds) {
|
|
|
278
281
|
tableCellStructuralOps.sort((left, right) => right.cellPos - left.cellPos);
|
|
279
282
|
let resolvedTableCellStructure = false;
|
|
280
283
|
let failedTableCellMergeResolution = false;
|
|
281
|
-
const emptiedTables =
|
|
284
|
+
const emptiedTables = { pending: false };
|
|
282
285
|
for (const op of tableCellStructuralOps) {
|
|
283
286
|
const mappedPos = tr.mapping.map(op.cellPos);
|
|
284
287
|
const cell = tr.doc.nodeAt(mappedPos);
|
|
@@ -301,9 +304,15 @@ function resolveChange(from, to, mode, revisionIds) {
|
|
|
301
304
|
resolvedTableCellStructure = true;
|
|
302
305
|
}
|
|
303
306
|
if (failedTableCellMergeResolution) return false;
|
|
304
|
-
|
|
307
|
+
removeRowsWithoutCellsAfterBatch(tr, emptiedTables);
|
|
305
308
|
if (resolvedTableCellStructure) markStructuralChange(tr);
|
|
306
309
|
pPrMarkOps.sort((a, b) => b.paragraphPos - a.paragraphPos);
|
|
310
|
+
const pendingTables = [];
|
|
311
|
+
state.doc.descendants((node, position) => {
|
|
312
|
+
if (node.type.spec["tableRole"] === "table" && runInCellPending(node)) pendingTables.push(position);
|
|
313
|
+
return !node.isTextblock;
|
|
314
|
+
});
|
|
315
|
+
const joinSeams = [];
|
|
307
316
|
for (const op of pPrMarkOps) {
|
|
308
317
|
const mappedPos = tr.mapping.map(op.paragraphPos);
|
|
309
318
|
const paragraph = tr.doc.nodeAt(mappedPos);
|
|
@@ -323,7 +332,18 @@ function resolveChange(from, to, mode, revisionIds) {
|
|
|
323
332
|
nextPos += boundary.nodeSize;
|
|
324
333
|
}
|
|
325
334
|
const nextNode = nextPos < tr.doc.content.size ? tr.doc.nodeAt(nextPos) : null;
|
|
326
|
-
|
|
335
|
+
const joinable = nextNode?.type.name === paragraph.type.name;
|
|
336
|
+
const ranIn = nextNode?.type.spec["tableRole"] === "table" && boundaries.length === 0 && !pendingTables.some((position) => tr.mapping.map(position) === nextPos) ? runParagraphIntoTable({
|
|
337
|
+
tr,
|
|
338
|
+
paragraphPos: mappedPos,
|
|
339
|
+
styleResolver
|
|
340
|
+
}) : null;
|
|
341
|
+
if (ranIn) {
|
|
342
|
+
tr.setMeta(JOINED_RUNS_RESTYLED_META, true);
|
|
343
|
+
markParagraphPropertySourceTransfers(tr, [ranIn.transfer]);
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
if (!joinable) {
|
|
327
347
|
const resolved = tr.doc.resolve(mappedPos);
|
|
328
348
|
const endsItsContainer = paragraphEndsItsContainer(resolved, paragraph.type.name);
|
|
329
349
|
const canGo = op.markWasAdded || !endsItsContainer;
|
|
@@ -340,12 +360,6 @@ function resolveChange(from, to, mode, revisionIds) {
|
|
|
340
360
|
}
|
|
341
361
|
try {
|
|
342
362
|
if (boundaries.length > 0) {
|
|
343
|
-
const emptyFirstParagraph = holdsNoContent(paragraph);
|
|
344
|
-
const joinedAttrs = {
|
|
345
|
-
...(emptyFirstParagraph ? nextNode : paragraph).attrs,
|
|
346
|
-
pPrMark: nextNode.attrs["pPrMark"],
|
|
347
|
-
_sectionProperties: nextNode.attrs["_sectionProperties"]
|
|
348
|
-
};
|
|
349
363
|
const leftToken = getProseParagraphPropertySourceToken(paragraph);
|
|
350
364
|
const rightToken = getProseParagraphPropertySourceToken(nextNode);
|
|
351
365
|
const inlineBookmarks = inlineBookmarksForParagraphJoin({
|
|
@@ -355,16 +369,31 @@ function resolveChange(from, to, mode, revisionIds) {
|
|
|
355
369
|
});
|
|
356
370
|
if (!inlineBookmarks) continue;
|
|
357
371
|
tr.replaceWith(joinPos - 1, nextPos + 1, inlineBookmarks);
|
|
358
|
-
tr.setNodeMarkup(mappedPos, void 0,
|
|
359
|
-
|
|
372
|
+
tr.setNodeMarkup(mappedPos, void 0, nextNode.attrs);
|
|
373
|
+
markParagraphPropertySourceTransfers(tr, [{
|
|
360
374
|
displacedToken: typeof leftToken === "string" ? leftToken : null,
|
|
361
375
|
selectedToken: typeof rightToken === "string" ? rightToken : null
|
|
362
376
|
}]);
|
|
377
|
+
if (styleResolver && paragraph.content.size > 0) rebaseParagraphRuns({
|
|
378
|
+
previousContext: paragraphRunStyleContext(paragraph, styleResolver),
|
|
379
|
+
paragraphPosition: mappedPos,
|
|
380
|
+
range: {
|
|
381
|
+
from: 0,
|
|
382
|
+
to: paragraph.content.size
|
|
383
|
+
},
|
|
384
|
+
styleResolver,
|
|
385
|
+
tr
|
|
386
|
+
});
|
|
363
387
|
} else joinAtParagraphMark({
|
|
364
388
|
tr,
|
|
365
389
|
paragraphPos: mappedPos,
|
|
366
390
|
paragraph,
|
|
367
|
-
next: nextNode
|
|
391
|
+
next: nextNode,
|
|
392
|
+
styleResolver
|
|
393
|
+
});
|
|
394
|
+
joinSeams.push({
|
|
395
|
+
position: mappedPos + 1 + paragraph.content.size,
|
|
396
|
+
step: tr.steps.length
|
|
368
397
|
});
|
|
369
398
|
if (ownsSectionEndpoint(paragraph)) {
|
|
370
399
|
removedSectionEndpointCount++;
|
|
@@ -378,9 +407,10 @@ function resolveChange(from, to, mode, revisionIds) {
|
|
|
378
407
|
removedReferences: removedSectionReferences
|
|
379
408
|
});
|
|
380
409
|
if (!terminalTableDeletionIsPending(tr)) resolveTerminalTableReviewCarrier(tr, mode);
|
|
410
|
+
const seams = new Set(joinSeams.map(({ position, step }) => tr.mapping.slice(step).map(position)));
|
|
381
411
|
rejoinRunsAt({
|
|
382
412
|
tr,
|
|
383
|
-
boundaries: resolvedBoundaries.map((position) => tr.mapping.map(position)),
|
|
413
|
+
boundaries: resolvedBoundaries.map((position) => tr.mapping.map(position)).filter((position) => !seams.has(position)),
|
|
384
414
|
styleResolver
|
|
385
415
|
});
|
|
386
416
|
if (tr.steps.length > 0) dispatch(tr);
|
|
@@ -559,6 +589,7 @@ function isTableCellRevisionAttr(value) {
|
|
|
559
589
|
const info = value.info;
|
|
560
590
|
return typeof info === "object" && info !== null && "revisionId" in info && typeof info.revisionId === "number";
|
|
561
591
|
}
|
|
592
|
+
/** Record rows for a final sweep after every cell revision has resolved. */
|
|
562
593
|
function deleteTableCellAt(tr, cellPos, emptied) {
|
|
563
594
|
const cell = tr.doc.nodeAt(cellPos);
|
|
564
595
|
if (!cell || cell.type.name !== "tableCell" && cell.type.name !== "tableHeader") return;
|
|
@@ -573,9 +604,10 @@ function deleteTableCellAt(tr, cellPos, emptied) {
|
|
|
573
604
|
const removedColumn = TableMap.get(table).findCell(cellOffset).left;
|
|
574
605
|
const spansDown = Number(cell.attrs["rowspan"]) > 1;
|
|
575
606
|
if (row.childCount > 1 || spansDown) {
|
|
576
|
-
if (row.childCount === 1)
|
|
577
|
-
|
|
578
|
-
|
|
607
|
+
if (row.childCount === 1) markRowEmptiedInBatch({
|
|
608
|
+
tr,
|
|
609
|
+
rowPosition: resolved.start() - 1,
|
|
610
|
+
emptied
|
|
579
611
|
});
|
|
580
612
|
tr.delete(cellPos, cellPos + cell.nodeSize);
|
|
581
613
|
reconcileTableGridAfterColumnRemoval({
|
|
@@ -1336,7 +1368,10 @@ const shiftAddedParagraphBreakBefore = ({ tr, paragraphPosition, mark, fallbackA
|
|
|
1336
1368
|
const paragraph = tr.doc.nodeAt(paragraphPosition);
|
|
1337
1369
|
if (!paragraph || paragraph.type.name !== "paragraph") return false;
|
|
1338
1370
|
const resolved = tr.doc.resolve(paragraphPosition);
|
|
1339
|
-
const carrier = addedBreakCarrierBefore(
|
|
1371
|
+
const carrier = addedBreakCarrierBefore({
|
|
1372
|
+
at: resolved,
|
|
1373
|
+
paragraphTypeName: paragraph.type.name
|
|
1374
|
+
});
|
|
1340
1375
|
if (!carrier) return false;
|
|
1341
1376
|
const path = [{
|
|
1342
1377
|
node: paragraph,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { mergeTextFormatting } from "../../utils/textFormattingMerge.js";
|
|
2
2
|
import { expectCharacterStyleMarkAttrs } from "../attrs/index.js";
|
|
3
|
-
import { getDocumentStyleResolver } from "../plugins/
|
|
3
|
+
import { getDocumentStyleResolver } from "../plugins/documentStyleState.js";
|
|
4
4
|
import { readAuthoredRunFormatting, reconcileRunFormattingMarks } from "../runFormattingReconciliation.js";
|
|
5
5
|
import { paragraphFormattingForRun, paragraphRunStyleContext, paragraphRunStyleContextAt, resolveEffectiveRunStyleFormatting } from "../runStyleFormatting.js";
|
|
6
6
|
//#region src/prosemirror/commands/formatPainter.ts
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { normalizeUserUrl } from "../../utils/urlSecurity.js";
|
|
2
2
|
import { expectHyperlinkMarkAttrs } from "../attrs/index.js";
|
|
3
|
+
import { removeHyperlinkInRange } from "../hyperlinkRemoval.js";
|
|
3
4
|
//#region src/prosemirror/commands/hyperlink.ts
|
|
4
5
|
const hyperlinkHref = (mark) => expectHyperlinkMarkAttrs(mark).href;
|
|
5
6
|
/**
|
|
@@ -87,7 +88,7 @@ const removeHyperlinkAtCursor = (view, { popupHref }) => {
|
|
|
87
88
|
const ranges = collectHyperlinkRanges($from.parent, $from.start(), hlType, hyperlinkHref(linkMark));
|
|
88
89
|
const targetRange = rangeAtCursor(ranges, $from.pos);
|
|
89
90
|
if (!targetRange) return false;
|
|
90
|
-
const tr = view.state.tr
|
|
91
|
+
const tr = removeHyperlinkInRange(view.state, view.state.tr, targetRange.start, targetRange.end);
|
|
91
92
|
view.dispatch(tr.scrollIntoView());
|
|
92
93
|
return true;
|
|
93
94
|
};
|
|
@@ -48,8 +48,9 @@ declare const PPR_CHANGE_SCOPED_ATTR_KEYS: readonly ["styleId", "numPr", "alignm
|
|
|
48
48
|
declare const paragraphPropertiesSnapshot: (node: Node) => ParagraphPropertySnapshot;
|
|
49
49
|
/**
|
|
50
50
|
* Build the attr patch that rejecting one pPrChange applies to a paragraph:
|
|
51
|
-
* every in-scope key set to the stored previous value, or
|
|
52
|
-
* when the stored old pPr does not carry it
|
|
51
|
+
* every in-scope key set to the stored previous value, or to what the style
|
|
52
|
+
* (`inheritedFormatting`) supplies when the stored old pPr does not carry it,
|
|
53
|
+
* `null` when neither does. Keys the record captured beyond
|
|
53
54
|
* the scoped set (editor-created list suggestions snapshot list-rendering
|
|
54
55
|
* bookkeeping attrs) merge through 1:1 so their pre-change values restore too.
|
|
55
56
|
*/
|
|
@@ -2,7 +2,9 @@ import { expectParagraphAttrs } from "../attrs/index.js";
|
|
|
2
2
|
import { readParagraphNumberingAttr } from "../numberingAttr.js";
|
|
3
3
|
import { directParagraphAlignment } from "../paragraphAlignment.js";
|
|
4
4
|
import { directionFromBidi } from "../paragraphDirection.js";
|
|
5
|
+
import { PARAGRAPH_FORMATTING_WRITE_BACK, STYLE_RESOLVED_PARAGRAPH_FIELDS } from "../paragraphFormattingProvenance.js";
|
|
5
6
|
import { directParagraphSpacing, paragraphSpacingAttrPatch, paragraphSpacingFromFormatting } from "../paragraphSpacing.js";
|
|
7
|
+
import { sameFormattingValue } from "../runFormattingFromMarks.js";
|
|
6
8
|
//#region src/prosemirror/commands/propertyChangeScope.ts
|
|
7
9
|
/** Editor-only suggestions are rebased away before save; every other entry emits `w:pPrChange`. */
|
|
8
10
|
const hasSerializableParagraphPropertyChange = (changes) => changes?.some(({ info }) => info.provenance !== "suggested") === true;
|
|
@@ -106,12 +108,27 @@ const PPR_SPACING_ATTR_KEYS = /* @__PURE__ */ new Set([
|
|
|
106
108
|
"spacingExplicit",
|
|
107
109
|
"_autospacingBase"
|
|
108
110
|
]);
|
|
111
|
+
/**
|
|
112
|
+
* Whether the attr holds only what the paragraph's style resolves to: the
|
|
113
|
+
* paragraph does not state it (its source `w:pPr` has no such field) and the
|
|
114
|
+
* value is the style's. The same test a save applies before writing it.
|
|
115
|
+
*/
|
|
116
|
+
const styleSuppliedParagraphValue = (attrs, key) => {
|
|
117
|
+
if (!STYLE_RESOLVED_ATTR_FIELDS.has(key)) return false;
|
|
118
|
+
const field = key;
|
|
119
|
+
const inherited = attrs._resolvedFormatting?.[field];
|
|
120
|
+
return attrs._originalFormatting?.[field] === void 0 && inherited !== void 0 && inherited !== null && sameFormattingValue(Reflect.get(attrs, key), inherited);
|
|
121
|
+
};
|
|
122
|
+
/** Fields whose attr carries the style-resolved value under the field's own name. */
|
|
123
|
+
const STYLE_RESOLVED_ATTR_FIELDS = new Set(STYLE_RESOLVED_PARAGRAPH_FIELDS.filter((field) => PARAGRAPH_FORMATTING_WRITE_BACK[field].attr === field));
|
|
109
124
|
/** The in-scope paragraph properties as they stand, for a `w:pPrChange` record. */
|
|
110
125
|
const paragraphPropertiesSnapshot = (node) => {
|
|
111
126
|
const attrs = expectParagraphAttrs(node);
|
|
112
127
|
const snapshot = {};
|
|
113
128
|
for (const key of PPR_CHANGE_SCOPED_ATTR_KEYS) {
|
|
114
129
|
if (key === "alignment" || PPR_SPACING_ATTR_KEYS.has(key)) continue;
|
|
130
|
+
if (styleSuppliedParagraphValue(attrs, key)) continue;
|
|
131
|
+
if (key === "hangingIndent" && styleSuppliedParagraphValue(attrs, "indentFirstLine")) continue;
|
|
115
132
|
const value = attrs[key];
|
|
116
133
|
if (key === "hangingIndent" && value === false && attrs._originalFormatting?.hangingIndent === void 0) continue;
|
|
117
134
|
if (value !== null && value !== void 0) snapshot[key] = value;
|
|
@@ -177,15 +194,19 @@ const PPR_CHANGE_SCOPED_FORMATTING_KEYS = [
|
|
|
177
194
|
];
|
|
178
195
|
/**
|
|
179
196
|
* Build the attr patch that rejecting one pPrChange applies to a paragraph:
|
|
180
|
-
* every in-scope key set to the stored previous value, or
|
|
181
|
-
* when the stored old pPr does not carry it
|
|
197
|
+
* every in-scope key set to the stored previous value, or to what the style
|
|
198
|
+
* (`inheritedFormatting`) supplies when the stored old pPr does not carry it,
|
|
199
|
+
* `null` when neither does. Keys the record captured beyond
|
|
182
200
|
* the scoped set (editor-created list suggestions snapshot list-rendering
|
|
183
201
|
* bookkeeping attrs) merge through 1:1 so their pre-change values restore too.
|
|
184
202
|
*/
|
|
185
203
|
function paragraphRejectAttrPatch(previousFormatting, inheritedFormatting) {
|
|
186
204
|
const prev = previousFormatting ?? {};
|
|
187
205
|
const patch = {};
|
|
188
|
-
for (const key of PPR_CHANGE_SCOPED_ATTR_KEYS)
|
|
206
|
+
for (const key of PPR_CHANGE_SCOPED_ATTR_KEYS) if (Object.hasOwn(prev, key)) patch[key] = prev[key] ?? null;
|
|
207
|
+
else if (STYLE_RESOLVED_ATTR_FIELDS.has(key)) patch[key] = Reflect.get(inheritedFormatting ?? {}, key) ?? null;
|
|
208
|
+
else patch[key] = null;
|
|
209
|
+
if (!Object.hasOwn(prev, "indentFirstLine") && !Object.hasOwn(prev, "hangingIndent")) patch["hangingIndent"] = inheritedFormatting?.hangingIndent ?? null;
|
|
189
210
|
if (!Object.hasOwn(prev, "alignment")) patch["alignment"] = inheritedFormatting?.alignment ?? null;
|
|
190
211
|
patch["alignmentFromStyle"] = inheritedFormatting?.alignment;
|
|
191
212
|
const directSpacing = paragraphSpacingFromFormatting(prev);
|
|
@@ -5,7 +5,7 @@ import { nodePropertyRevisionSites, propertyRevisionRecords } from "../revisionC
|
|
|
5
5
|
import { getTableCellMergeChange } from "../tableCellMergeRevision.js";
|
|
6
6
|
import { isTableCellRetainedInReviewView } from "../tableCellRevisionVisibility.js";
|
|
7
7
|
import { resolveAllNodePropertyChangeAttrs } from "./resolveNodePropertyChangeAttrs.js";
|
|
8
|
-
import { createRestoredTableCell, hasMatchingCollapsedTableCellMerge, tableCellContinuationCells, tableCellContinuationFromNode, tableCellContinuationPayload } from "./tableCellMergeResolution.js";
|
|
8
|
+
import { acceptedMergeFoldsIntoCellAbove, createRestoredTableCell, hasMatchingCollapsedTableCellMerge, tableCellContinuationCells, tableCellContinuationFromNode, tableCellContinuationPayload } from "./tableCellMergeResolution.js";
|
|
9
9
|
import { panic } from "better-result";
|
|
10
10
|
import { TableMap } from "prosemirror-tables";
|
|
11
11
|
import { StepMap } from "prosemirror-transform";
|
|
@@ -131,10 +131,12 @@ const cellRevisionMarker = (cell) => {
|
|
|
131
131
|
const marker = cell.attrs["cellMarker"];
|
|
132
132
|
if (typeof marker !== "object" || marker === null || !("kind" in marker) || marker.kind !== "ins" && marker.kind !== "del" && marker.kind !== "merge" || !("info" in marker) || typeof marker.info !== "object" || marker.info === null || !("revisionId" in marker.info) || typeof marker.info.revisionId !== "number") return null;
|
|
133
133
|
const verticalMergeOriginal = "verticalMergeOriginal" in marker && isTableCellMergeRevisionValue(marker.verticalMergeOriginal) ? marker.verticalMergeOriginal : void 0;
|
|
134
|
+
const verticalMerge = "verticalMerge" in marker && isTableCellMergeRevisionValue(marker.verticalMerge) ? marker.verticalMerge : void 0;
|
|
134
135
|
return {
|
|
135
136
|
kind: marker.kind,
|
|
136
137
|
info: { revisionId: marker.info.revisionId },
|
|
137
|
-
...verticalMergeOriginal ? { verticalMergeOriginal } : {}
|
|
138
|
+
...verticalMergeOriginal ? { verticalMergeOriginal } : {},
|
|
139
|
+
...verticalMerge ? { verticalMerge } : {}
|
|
138
140
|
};
|
|
139
141
|
};
|
|
140
142
|
/**
|
|
@@ -435,46 +437,49 @@ const resolvePureTableMerges = ({ table, mode, rowMetadata, tablePropertyTouched
|
|
|
435
437
|
count: previousWidth - currentWidth
|
|
436
438
|
});
|
|
437
439
|
}
|
|
438
|
-
} else if (marker?.kind === "merge")
|
|
439
|
-
entry.
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
440
|
+
} else if (marker?.kind === "merge") {
|
|
441
|
+
const joinsAbove = mode === "accept" ? isTableCellMergeRevisionContinuation(marker.verticalMerge) && acceptedMergeFoldsIntoCellAbove(entry.node) : isTableCellMergeRevisionContinuation(marker.verticalMergeOriginal);
|
|
442
|
+
if (mode === "accept" && !joinsAbove) {
|
|
443
|
+
entry.touched = true;
|
|
444
|
+
entry.node = entry.node.type.create({
|
|
445
|
+
...entry.node.attrs,
|
|
446
|
+
cellMarker: null
|
|
447
|
+
}, entry.node.content, entry.node.marks);
|
|
448
|
+
} else if (!joinsAbove) {
|
|
449
|
+
entry.touched = true;
|
|
450
|
+
const original = entry.node.attrs["_originalFormatting"];
|
|
451
|
+
let formatting = original;
|
|
452
|
+
if (typeof original === "object" && original !== null) {
|
|
453
|
+
const copy = { ...original };
|
|
454
|
+
delete copy["vMerge"];
|
|
455
|
+
formatting = copy;
|
|
456
|
+
}
|
|
457
|
+
entry.node = entry.node.type.create({
|
|
458
|
+
...entry.node.attrs,
|
|
459
|
+
cellMarker: null,
|
|
460
|
+
_originalFormatting: formatting
|
|
461
|
+
}, entry.node.content, entry.node.marks);
|
|
462
|
+
} else {
|
|
463
|
+
const rectangle = cellRectangle(entry.position);
|
|
464
|
+
if (rectangle.top === 0) return failedTableResolution(table);
|
|
465
|
+
const abovePosition = map.map[(rectangle.top - 1) * map.width + rectangle.left];
|
|
466
|
+
if (abovePosition === void 0) return failedTableResolution(table);
|
|
467
|
+
const aboveRectangle = cellRectangle(abovePosition);
|
|
468
|
+
const above = byPosition.get(abovePosition);
|
|
469
|
+
if (!above || !elementAt(rowCells, above.row).has(above.left) || aboveRectangle.left !== rectangle.left || aboveRectangle.right !== rectangle.right || aboveRectangle.bottom !== rectangle.top) return failedTableResolution(table);
|
|
470
|
+
const aboveRowspan = above.node.attrs["rowspan"];
|
|
471
|
+
const cellRowspan = entry.node.attrs["rowspan"];
|
|
472
|
+
if (typeof aboveRowspan !== "number" || typeof cellRowspan !== "number" || aboveRowspan < 1 || cellRowspan < 1) return failedTableResolution(table);
|
|
473
|
+
above.continuation ??= continuationSequence(tableCellContinuationCells(above.node, aboveRowspan));
|
|
474
|
+
appendContinuation(above.continuation, tableCellContinuationFromNode(entry.node));
|
|
475
|
+
const nested = entry.continuation ?? continuationSequence(tableCellContinuationPayload(entry.node)?.cells ?? []);
|
|
476
|
+
appendContinuationSequence(above.continuation, nested);
|
|
477
|
+
above.node = above.node.type.create({
|
|
478
|
+
...above.node.attrs,
|
|
479
|
+
rowspan: aboveRowspan + cellRowspan
|
|
480
|
+
}, above.node.content, above.node.marks);
|
|
481
|
+
elementAt(rowCells, entry.row).delete(entry.left);
|
|
452
482
|
}
|
|
453
|
-
entry.node = entry.node.type.create({
|
|
454
|
-
...entry.node.attrs,
|
|
455
|
-
cellMarker: null,
|
|
456
|
-
_originalFormatting: formatting
|
|
457
|
-
}, entry.node.content, entry.node.marks);
|
|
458
|
-
} else {
|
|
459
|
-
const rectangle = cellRectangle(entry.position);
|
|
460
|
-
if (rectangle.top === 0) return failedTableResolution(table);
|
|
461
|
-
const abovePosition = map.map[(rectangle.top - 1) * map.width + rectangle.left];
|
|
462
|
-
if (abovePosition === void 0) return failedTableResolution(table);
|
|
463
|
-
const aboveRectangle = cellRectangle(abovePosition);
|
|
464
|
-
const above = byPosition.get(abovePosition);
|
|
465
|
-
if (!above || !elementAt(rowCells, above.row).has(above.left) || aboveRectangle.left !== rectangle.left || aboveRectangle.right !== rectangle.right || aboveRectangle.bottom !== rectangle.top) return failedTableResolution(table);
|
|
466
|
-
const aboveRowspan = above.node.attrs["rowspan"];
|
|
467
|
-
const cellRowspan = entry.node.attrs["rowspan"];
|
|
468
|
-
if (typeof aboveRowspan !== "number" || typeof cellRowspan !== "number" || aboveRowspan < 1 || cellRowspan < 1) return failedTableResolution(table);
|
|
469
|
-
above.continuation ??= continuationSequence(tableCellContinuationCells(above.node, aboveRowspan));
|
|
470
|
-
appendContinuation(above.continuation, tableCellContinuationFromNode(entry.node));
|
|
471
|
-
const nested = entry.continuation ?? continuationSequence(tableCellContinuationPayload(entry.node)?.cells ?? []);
|
|
472
|
-
appendContinuationSequence(above.continuation, nested);
|
|
473
|
-
above.node = above.node.type.create({
|
|
474
|
-
...above.node.attrs,
|
|
475
|
-
rowspan: aboveRowspan + cellRowspan
|
|
476
|
-
}, above.node.content, above.node.marks);
|
|
477
|
-
elementAt(rowCells, entry.row).delete(entry.left);
|
|
478
483
|
}
|
|
479
484
|
if (!elementAt(rowCells, entry.row).has(entry.left)) continue;
|
|
480
485
|
if (!tableCellContinuationPayload(entry.node)?.cells.some((cell) => getTableCellMergeChange(cell) !== null)) continue;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { expectParagraphAttrs } from "../attrs/index.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { rejectedListRenderingPatch } from "../listRendering.js";
|
|
3
|
+
import { styleResolvedParagraphFormatting } from "../paragraphFormattingProvenance.js";
|
|
4
|
+
import { resolveParagraphDefaultTextFormatting } from "../styles/paragraphStyleCascade.js";
|
|
4
5
|
import { paragraphRejectAttrPatch, paragraphRejectOriginalFormatting, removeParagraphPropertyChanges, sectionRejectProperties } from "./propertyChangeScope.js";
|
|
5
6
|
//#region src/prosemirror/commands/resolveParagraphProperties.ts
|
|
6
7
|
/** Resolve paragraph and section property records before resolving their inline content. */
|
|
@@ -20,11 +21,24 @@ const resolveParagraphChangeAttrs = ({ node, boundaryCovered, mode, revisionSet,
|
|
|
20
21
|
_propertyChanges: remaining.length > 0 ? remaining : null
|
|
21
22
|
};
|
|
22
23
|
if (rejection?.type === "restore-previous") {
|
|
23
|
-
const
|
|
24
|
+
const currentAttrs = expectParagraphAttrs(node);
|
|
25
|
+
const inheritedAlignment = currentAttrs.alignmentFromStyle;
|
|
26
|
+
const restoredStyleId = rejection.previousFormatting?.styleId ?? void 0;
|
|
27
|
+
const sameStyle = restoredStyleId === (currentAttrs.styleId ?? void 0);
|
|
24
28
|
let previousFormattingFromStyle;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
let resolvedFromStyle = sameStyle ? currentAttrs._resolvedFormatting : void 0;
|
|
30
|
+
if (styleResolver) {
|
|
31
|
+
previousFormattingFromStyle = styleResolver.resolveParagraphStyle(restoredStyleId).paragraphFormatting;
|
|
32
|
+
if (!sameStyle) {
|
|
33
|
+
resolvedFromStyle = styleResolvedParagraphFormatting(previousFormattingFromStyle);
|
|
34
|
+
nextAttrs["_resolvedFormatting"] = resolvedFromStyle;
|
|
35
|
+
}
|
|
36
|
+
} else if (inheritedAlignment !== void 0) previousFormattingFromStyle = { alignment: inheritedAlignment };
|
|
37
|
+
const inheritedFormatting = previousFormattingFromStyle === void 0 && resolvedFromStyle === void 0 ? void 0 : {
|
|
38
|
+
...previousFormattingFromStyle,
|
|
39
|
+
...resolvedFromStyle
|
|
40
|
+
};
|
|
41
|
+
Object.assign(nextAttrs, paragraphRejectAttrPatch(rejection.previousFormatting, inheritedFormatting), rejectedListRenderingPatch({
|
|
28
42
|
current: expectParagraphAttrs(node),
|
|
29
43
|
previousFormatting: rejection.previousFormatting,
|
|
30
44
|
numbering
|
|
@@ -5,10 +5,17 @@ import { Transaction } from "prosemirror-state";
|
|
|
5
5
|
//#region src/prosemirror/commands/tableCellMergeResolution.d.ts
|
|
6
6
|
declare const tableCellContinuationPayload: (node: Node) => DecodedTableCellParagraphSourcePayload | null;
|
|
7
7
|
declare const hasMatchingCollapsedTableCellMerge: (node: Node, revisionSet: Set<number> | null) => boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Whether accepting a pending vertical merge folds the cell into the one above.
|
|
10
|
+
* The saved `w:vMerge` continuation is read back as its own cell when it carries
|
|
11
|
+
* content, so accepting such a merge keeps the cell standing; folding it would
|
|
12
|
+
* hide text that reappears when the document is reopened.
|
|
13
|
+
*/
|
|
14
|
+
declare const acceptedMergeFoldsIntoCellAbove: (cell: Node) => boolean;
|
|
8
15
|
declare const resolveVisibleTableCellMerge: (tr: Transaction, cellPos: number, mode: "accept" | "reject") => boolean;
|
|
9
16
|
declare const tableCellContinuationCells: (cell: Node, rowspan: number) => document_d_exports.TableCell[];
|
|
10
17
|
declare const tableCellContinuationFromNode: (cell: Node) => document_d_exports.TableCell;
|
|
11
18
|
declare const resolveCollapsedTableCellMerge: (tr: Transaction, cellPos: number, mode: "accept" | "reject", revisionSet: Set<number> | null) => boolean;
|
|
12
19
|
declare const createRestoredTableCell: (origin: Node, source: document_d_exports.TableCell) => Node | null;
|
|
13
20
|
//#endregion
|
|
14
|
-
export { createRestoredTableCell, hasMatchingCollapsedTableCellMerge, resolveCollapsedTableCellMerge, resolveVisibleTableCellMerge, tableCellContinuationCells, tableCellContinuationFromNode, tableCellContinuationPayload };
|
|
21
|
+
export { acceptedMergeFoldsIntoCellAbove, createRestoredTableCell, hasMatchingCollapsedTableCellMerge, resolveCollapsedTableCellMerge, resolveVisibleTableCellMerge, tableCellContinuationCells, tableCellContinuationFromNode, tableCellContinuationPayload };
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { decodeTableCellParagraphSourcePayload, restoreTableCellsWithParagraphPropertySources, transportTableCellsWithParagraphPropertySources } from "../../docx/paragraphPropertySource.js";
|
|
2
|
+
import { isTableCellMergeRevisionContinuation } from "../../docx/tableParser.js";
|
|
2
3
|
import { standaloneTableCellFromProseMirror } from "../conversion/fromProseDoc.js";
|
|
3
|
-
import { standaloneTableCellToProseMirror } from "../conversion/toProseDoc.js";
|
|
4
|
+
import { standaloneTableCellToProseMirror, tableCellHasMeaningfulContent } from "../conversion/toProseDoc.js";
|
|
4
5
|
import { getTableCellMergeChange } from "../tableCellMergeRevision.js";
|
|
5
|
-
import {
|
|
6
|
+
import { removeRowsWithoutCellsInRange } from "../tableGridMutation.js";
|
|
7
|
+
import { Result, panic } from "better-result";
|
|
6
8
|
import { TableMap } from "prosemirror-tables";
|
|
7
9
|
//#region src/prosemirror/commands/tableCellMergeResolution.ts
|
|
8
10
|
const tableCellContinuationPayload = (node) => {
|
|
@@ -35,15 +37,22 @@ const tableCellContext = (doc, cellPos) => {
|
|
|
35
37
|
}
|
|
36
38
|
return null;
|
|
37
39
|
};
|
|
40
|
+
/**
|
|
41
|
+
* Whether accepting a pending vertical merge folds the cell into the one above.
|
|
42
|
+
* The saved `w:vMerge` continuation is read back as its own cell when it carries
|
|
43
|
+
* content, so accepting such a merge keeps the cell standing; folding it would
|
|
44
|
+
* hide text that reappears when the document is reopened.
|
|
45
|
+
*/
|
|
46
|
+
const acceptedMergeFoldsIntoCellAbove = (cell) => !tableCellHasMeaningfulContent(standaloneTableCellFromProseMirror(cell));
|
|
38
47
|
const resolveVisibleTableCellMerge = (tr, cellPos, mode) => {
|
|
39
48
|
const cell = tr.doc.nodeAt(cellPos);
|
|
40
49
|
const marker = cell?.attrs["cellMarker"];
|
|
41
50
|
if (!cell || !isTableCellMergeRevisionAttr(marker)) return false;
|
|
51
|
+
if (mode === "accept" ? isTableCellMergeRevisionContinuation(marker.verticalMerge) && acceptedMergeFoldsIntoCellAbove(cell) : isTableCellMergeRevisionContinuation(marker.verticalMergeOriginal)) return mergeTableCellWithCellAbove(tr, cellPos);
|
|
42
52
|
if (mode === "accept") {
|
|
43
53
|
tr.setNodeAttribute(cellPos, "cellMarker", null);
|
|
44
54
|
return true;
|
|
45
55
|
}
|
|
46
|
-
if ((marker.verticalMergeOriginal ?? "rest") === "continue") return mergeTableCellWithCellAbove(tr, cellPos);
|
|
47
56
|
const originalFormatting = cell.attrs["_originalFormatting"];
|
|
48
57
|
let nextOriginalFormatting = originalFormatting;
|
|
49
58
|
if (typeof originalFormatting === "object" && originalFormatting !== null) {
|
|
@@ -73,11 +82,18 @@ const mergeTableCellWithCellAbove = (tr, cellPos) => {
|
|
|
73
82
|
const aboveRowspan = aboveCell?.attrs["rowspan"];
|
|
74
83
|
const cellRowspan = cell.attrs["rowspan"];
|
|
75
84
|
if (!aboveCell || typeof aboveRowspan !== "number" || typeof cellRowspan !== "number" || aboveRowspan < 1 || cellRowspan < 1) return false;
|
|
85
|
+
removeRowsWithoutCellsInRange({
|
|
86
|
+
tr,
|
|
87
|
+
from: cellPos + 1,
|
|
88
|
+
to: cellPos + cell.nodeSize - 1
|
|
89
|
+
});
|
|
90
|
+
const capturedCell = tr.doc.nodeAt(cellPos);
|
|
91
|
+
if (!capturedCell) panic("Nested table cleanup removed its owning cell");
|
|
76
92
|
const continuationCells = tableCellContinuationCells(aboveCell, aboveRowspan);
|
|
77
|
-
continuationCells.push(tableCellContinuationFromNode(
|
|
78
|
-
const nestedPayload = tableCellContinuationPayload(
|
|
93
|
+
continuationCells.push(tableCellContinuationFromNode(capturedCell));
|
|
94
|
+
const nestedPayload = tableCellContinuationPayload(capturedCell);
|
|
79
95
|
if (nestedPayload) continuationCells.push(...nestedPayload.cells);
|
|
80
|
-
tr.delete(cellPos, cellPos +
|
|
96
|
+
tr.delete(cellPos, cellPos + capturedCell.nodeSize);
|
|
81
97
|
tr.setNodeMarkup(abovePos, void 0, {
|
|
82
98
|
...aboveCell.attrs,
|
|
83
99
|
rowspan: aboveRowspan + cellRowspan,
|
|
@@ -185,4 +201,4 @@ const createRestoredTableCell = (origin, source) => {
|
|
|
185
201
|
return Result.try(() => origin.type.schema.nodeFromJSON(restored.toJSON())).unwrapOr(null);
|
|
186
202
|
};
|
|
187
203
|
//#endregion
|
|
188
|
-
export { createRestoredTableCell, hasMatchingCollapsedTableCellMerge, resolveCollapsedTableCellMerge, resolveVisibleTableCellMerge, tableCellContinuationCells, tableCellContinuationFromNode, tableCellContinuationPayload };
|
|
204
|
+
export { acceptedMergeFoldsIntoCellAbove, createRestoredTableCell, hasMatchingCollapsedTableCellMerge, resolveCollapsedTableCellMerge, resolveVisibleTableCellMerge, tableCellContinuationCells, tableCellContinuationFromNode, tableCellContinuationPayload };
|
|
@@ -28,18 +28,24 @@ declare const finalParagraphsOf: (doc: Node, paragraphTypeName: string) => {
|
|
|
28
28
|
position: number;
|
|
29
29
|
node: Node;
|
|
30
30
|
}[];
|
|
31
|
+
type AddedBreakCarrierBeforeOptions = {
|
|
32
|
+
at: ResolvedPos;
|
|
33
|
+
paragraphTypeName: string;
|
|
34
|
+
canCrossTable?: (table: Node) => boolean;
|
|
35
|
+
};
|
|
31
36
|
/**
|
|
32
37
|
* The paragraph an added break can rotate BACK onto from the one at `at`: the
|
|
33
38
|
* paragraph the run of inserted ones was appended after.
|
|
34
39
|
*
|
|
35
40
|
* The walk crosses the inserted paragraphs — their own marks stay where they
|
|
36
41
|
* are, and only which paragraph is left markless changes — and stops at the
|
|
37
|
-
* first one whose mark is free.
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
42
|
+
* first one whose mark is free. A table blocks the walk unless the caller
|
|
43
|
+
* authorizes a wholly inserted table: rejecting it removes that barrier too.
|
|
44
|
+
* `null` when there is no carrier: a table the caller cannot cross, a
|
|
45
|
+
* paragraph whose mark the rotation must not overwrite, or a container whose
|
|
46
|
+
* every paragraph is new.
|
|
41
47
|
*/
|
|
42
|
-
declare const addedBreakCarrierBefore: (at
|
|
48
|
+
declare const addedBreakCarrierBefore: ({ at, paragraphTypeName, canCrossTable }: AddedBreakCarrierBeforeOptions) => {
|
|
43
49
|
position: number;
|
|
44
50
|
node: Node;
|
|
45
51
|
} | null;
|
|
@@ -66,18 +66,19 @@ const marksAnAddedBreak = (node) => {
|
|
|
66
66
|
*
|
|
67
67
|
* The walk crosses the inserted paragraphs — their own marks stay where they
|
|
68
68
|
* are, and only which paragraph is left markless changes — and stops at the
|
|
69
|
-
* first one whose mark is free.
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
69
|
+
* first one whose mark is free. A table blocks the walk unless the caller
|
|
70
|
+
* authorizes a wholly inserted table: rejecting it removes that barrier too.
|
|
71
|
+
* `null` when there is no carrier: a table the caller cannot cross, a
|
|
72
|
+
* paragraph whose mark the rotation must not overwrite, or a container whose
|
|
73
|
+
* every paragraph is new.
|
|
73
74
|
*/
|
|
74
|
-
const addedBreakCarrierBefore = (at, paragraphTypeName) => {
|
|
75
|
+
const addedBreakCarrierBefore = ({ at, paragraphTypeName, canCrossTable }) => {
|
|
75
76
|
let position = at.pos;
|
|
76
77
|
for (let index = at.index() - 1; index >= 0; index--) {
|
|
77
78
|
const sibling = at.parent.child(index);
|
|
78
79
|
position -= sibling.nodeSize;
|
|
79
80
|
if (sibling.type.name !== paragraphTypeName) {
|
|
80
|
-
if (isAContainerChild(sibling, paragraphTypeName)) return null;
|
|
81
|
+
if (isAContainerChild(sibling, paragraphTypeName) && !canCrossTable?.(sibling)) return null;
|
|
81
82
|
continue;
|
|
82
83
|
}
|
|
83
84
|
if (sibling.attrs["pPrMark"] == null) return {
|