@stll/folio-core 0.60.0 → 0.61.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/README.md +13 -0
- package/dist/ai-edits/apply.js +139 -32
- package/dist/ai-edits/headless.d.ts +3 -0
- package/dist/ai-edits/headless.js +57 -63
- package/dist/ai-edits/note-story-inventory.d.ts +7 -0
- package/dist/ai-edits/note-story-inventory.js +11 -0
- package/dist/ai-edits/read.js +16 -9
- package/dist/ai-edits/revisionStretches.js +52 -1
- package/dist/ai-edits/table-row-column-mutations.js +6 -1
- package/dist/compare/reproducible-package.js +2 -1
- package/dist/compare/verification.js +1 -0
- package/dist/compat/eigenpal.d.ts +3 -1
- package/dist/controller/canonicalClipboard.js +2 -1
- package/dist/controller/canonicalListRendering.d.ts +4 -6
- package/dist/controller/canonicalListRendering.js +3 -157
- package/dist/controller/headerFooterEditorManager.d.ts +1 -0
- package/dist/controller/headerFooterEditorManager.js +11 -0
- package/dist/controller/hiddenEditorManager.d.ts +1 -1
- package/dist/controller/hiddenEditorManager.js +3 -1
- package/dist/controller/layoutPipeline.d.ts +3 -1
- package/dist/controller/layoutPipeline.js +13 -4
- package/dist/controller/layoutSession.d.ts +2 -1
- package/dist/display-list/build/imagePrimitives.js +3 -6
- package/dist/docx/canonicalStoryRepack.js +3 -2
- package/dist/docx/commentTextParagraph.d.ts +6 -0
- package/dist/docx/commentTextParagraph.js +15 -0
- package/dist/docx/conformance.js +6 -1
- package/dist/docx/diagramPreview.js +2 -1
- package/dist/docx/documentParser.d.ts +13 -1
- package/dist/docx/documentParser.js +1 -1
- package/dist/docx/encryption/compoundFile.d.ts +0 -8
- package/dist/docx/encryption/compoundFile.js +2 -1
- package/dist/docx/encryption/cryptoBytes.d.ts +2 -2
- package/dist/docx/encryption/cryptoBytes.js +3 -18
- package/dist/docx/encryption/encryptionInfo.d.ts +0 -5
- package/dist/docx/encryption/encryptionInfo.js +2 -1
- package/dist/docx/ensureParaIds.js +2 -1
- package/dist/docx/groupDrawingParser.js +6 -1
- package/dist/docx/listModelNormalization.d.ts +10 -0
- package/dist/docx/listModelNormalization.js +166 -0
- package/dist/docx/metadataPrivacy.js +3 -2
- package/dist/docx/metafileRaster.js +2 -1
- package/dist/docx/packageParts.js +6 -5
- package/dist/docx/paragraphParser.js +6 -4
- package/dist/docx/parser.js +5 -4
- package/dist/docx/preservedRunContent.js +11 -2
- package/dist/docx/removeHeaderFooterParts.js +8 -7
- package/dist/docx/replyToComment.js +3 -13
- package/dist/docx/rezip.js +88 -89
- package/dist/docx/runParser.js +12 -6
- package/dist/docx/runPropertyPresence.d.ts +11 -0
- package/dist/docx/runPropertyPresence.js +14 -0
- package/dist/docx/selectiveSave.js +15 -14
- package/dist/docx/serializer/runSerializer.js +3 -2
- package/dist/docx/serializer/tableSerializer.js +2 -1
- package/dist/docx/server/applyDocxXmlPatchProposal.js +2 -2
- package/dist/docx/server/boundedArchive.js +2 -1
- package/dist/docx/server/evaluateDocxXmlPatchProposal.js +2 -1
- package/dist/docx/server/inspectDocxPackage.js +5 -1
- package/dist/docx/server/validateDocxConformance.js +2 -1
- package/dist/docx/tableParser.js +7 -4
- package/dist/docx/tableRowPropertyPresence.d.ts +9 -0
- package/dist/docx/tableRowPropertyPresence.js +15 -0
- package/dist/docx/unzip.js +2 -1
- package/dist/docx/xmlEncoding.js +6 -5
- package/dist/fonts/fontsourceFaces.js +2 -1
- package/dist/fonts/sfnt/parse.js +6 -9
- package/dist/fonts/sfnt/subset.js +2 -1
- package/dist/fonts/sfnt/tables.js +2 -3
- package/dist/fonts/sfnt/woff.js +2 -1
- package/dist/index.d.ts +3 -1
- package/dist/internal/revisionResolutionInline.d.ts +2 -1
- package/dist/internal/revisionResolutionInline.js +22 -1
- package/dist/internal/wholeStoryRevisionResolution.js +24 -7
- package/dist/layout-bridge/convert/flowConversionShared.d.ts +2 -0
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +4 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +13 -3
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +5 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +12 -15
- package/dist/layout-bridge/convert/paragraphRuns.js +2 -1
- package/dist/layout-engine/measure/crossRunWords.js +12 -2
- package/dist/managers/AutoSaveManager.js +2 -1
- package/dist/managers/EditorModeManager.d.ts +10 -1
- package/dist/managers/EditorModeManager.js +15 -1
- package/dist/managers/TableSelectionManager.d.ts +1 -1
- package/dist/managers/autoSaveCodec.js +2 -6
- package/dist/managers/reviewDisplayMode.d.ts +8 -0
- package/dist/managers/reviewDisplayMode.js +15 -0
- package/dist/paged-layout/pageText.d.ts +11 -2
- package/dist/paged-layout/pageText.js +8 -3
- package/dist/pdf/fonts.js +5 -14
- package/dist/pdf/images.js +3 -2
- package/dist/pdf/objects.d.ts +0 -11
- package/dist/pdf/objects.js +7 -9
- package/dist/pdf/writePdf.js +2 -1
- package/dist/prosemirror/commands/comments.js +51 -13
- package/dist/prosemirror/containerFinalParagraph.d.ts +8 -8
- package/dist/prosemirror/containerFinalParagraph.js +8 -8
- package/dist/prosemirror/conversion/fromProseDoc.js +9 -4
- package/dist/prosemirror/conversion/toProseDoc.js +4 -4
- package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +16 -2
- package/dist/prosemirror/findReplaceSelection.d.ts +11 -1
- package/dist/prosemirror/findReplaceSelection.js +15 -1
- package/dist/prosemirror/markupViewProjection.d.ts +10 -1
- package/dist/prosemirror/markupViewProjection.js +21 -3
- package/dist/prosemirror/plugins/transactionInvariants.js +6 -1
- package/dist/prosemirror/replacedAnnotations.d.ts +15 -1
- package/dist/prosemirror/replacedAnnotations.js +71 -12
- package/dist/prosemirror/runFormattingReconciliation.d.ts +3 -1
- package/dist/prosemirror/runFormattingReconciliation.js +10 -2
- package/dist/prosemirror/runIdentityAcrossRevisions.d.ts +5 -7
- package/dist/prosemirror/runIdentityAcrossRevisions.js +66 -38
- package/dist/prosemirror/runPropertyChangeResolution.js +13 -1
- package/dist/utils/base64.d.ts +1 -31
- package/dist/utils/base64.js +19 -33
- package/dist/utils/clipboard.js +5 -4
- package/dist/utils/colorResolver.js +11 -2
- package/dist/utils/findReplace.d.ts +5 -0
- package/dist/utils/replaceText.js +21 -4
- package/dist/utils/sliceText.d.ts +2 -0
- package/dist/utils/sliceText.js +2 -0
- package/dist/utils/textEncoding.d.ts +2 -0
- package/dist/utils/textEncoding.js +2 -0
- package/dist/utils/tiffConverter.d.ts +0 -9
- package/dist/utils/tiffConverter.js +2 -4
- package/package.json +51 -25
|
@@ -13,11 +13,13 @@ import "../extensions/nodes/SdtExtension.js";
|
|
|
13
13
|
import { canonicalFieldNode } from "../fieldRepresentation.js";
|
|
14
14
|
import { resolveStateStory } from "../markupViewProjection.js";
|
|
15
15
|
import { joinAtParagraphMark } from "../paragraphMarkJoin.js";
|
|
16
|
+
import { carryParagraphProperties, paragraphLeftAfter } from "../paragraphPropertyCarry.js";
|
|
16
17
|
import { getDocumentNumbering } from "../plugins/documentNumbering.js";
|
|
17
18
|
import { getDocumentStyleResolver } from "../plugins/documentStyleState.js";
|
|
18
19
|
import { resolvedPreservedXmlAttrs } from "../preservedXmlReview.js";
|
|
19
20
|
import { setParagraphAttrsWithRebasedRunFormatting } from "../rebaseParagraphRunFormatting.js";
|
|
20
21
|
import { rejoinRunsAt } from "../rejoinRunCarriers.js";
|
|
22
|
+
import { commentPoint, resolvedCommentPoints } from "../replacedAnnotations.js";
|
|
21
23
|
import { getFolioNodeRevisionCarriers, nodePropertyRevisionSites } from "../revisionCarriers.js";
|
|
22
24
|
import { RUN_FORMATTING_MARK_NAMES } from "../runFormattingMarkNames.js";
|
|
23
25
|
import { reconstructRejectedRunFormattingMarks, restoreHistoricalRunFormatting } from "../runPropertyChangeResolution.js";
|
|
@@ -100,6 +102,16 @@ function resolveChange(from, to, mode, revisionIds) {
|
|
|
100
102
|
const removeKeptMarksInBulk = revisionSet === null && keepType !== void 0;
|
|
101
103
|
const matchesRevision = (mark) => revisionSet === null || typeof mark.attrs["revisionId"] === "number" && revisionSet.has(mark.attrs["revisionId"]);
|
|
102
104
|
if (dispatch) {
|
|
105
|
+
const points = mode === "accept" ? resolvedCommentPoints({
|
|
106
|
+
doc: state.doc,
|
|
107
|
+
retiresStructure: (node, position) => {
|
|
108
|
+
if (node.type.name === "paragraph") return collectPPrMarkOp(node, position, from, to, mode, revisionSet)?.action === "join";
|
|
109
|
+
if (!rangeCoversNode(from, to, position, node)) return false;
|
|
110
|
+
if (node.type.name === "tableRow") return collectTableRowStructuralOp(node, position, mode, revisionSet)?.action === "remove";
|
|
111
|
+
return collectTableCellStructuralOps(node, position, mode, revisionSet).some((op) => op.type === "membership" && op.action === "remove");
|
|
112
|
+
},
|
|
113
|
+
removes: (node, position) => position >= from && position + node.nodeSize <= to && node.marks.some((mark) => mark.type === removeType && matchesRevision(mark))
|
|
114
|
+
}) : /* @__PURE__ */ new Map();
|
|
103
115
|
const tr = state.tr;
|
|
104
116
|
tr.setMeta(JOINED_RUNS_RESTYLED_META, true);
|
|
105
117
|
const deleteRanges = [];
|
|
@@ -110,6 +122,25 @@ function resolveChange(from, to, mode, revisionIds) {
|
|
|
110
122
|
const tableCellStructuralOps = [];
|
|
111
123
|
let removedSectionEndpointCount = 0;
|
|
112
124
|
const removedSectionReferences = [];
|
|
125
|
+
const carryRestoredProperties = (position) => {
|
|
126
|
+
if (mode !== "reject" || revisionSet === null) return;
|
|
127
|
+
const source = tr.doc.nodeAt(position);
|
|
128
|
+
const mark = source ? expectParagraphAttrs(source).pPrMark : null;
|
|
129
|
+
if (!source || mark?.kind !== "del" && mark?.kind !== "moveFrom" || revisionSet.has(mark.info.id)) return;
|
|
130
|
+
const survivor = paragraphLeftAfter({
|
|
131
|
+
doc: tr.doc,
|
|
132
|
+
paragraphPos: position
|
|
133
|
+
});
|
|
134
|
+
if (survivor === null) return;
|
|
135
|
+
carryParagraphProperties({
|
|
136
|
+
tr,
|
|
137
|
+
position: survivor,
|
|
138
|
+
source,
|
|
139
|
+
styleResolver,
|
|
140
|
+
numbering,
|
|
141
|
+
revision: mark.info
|
|
142
|
+
});
|
|
143
|
+
};
|
|
113
144
|
state.doc.nodesBetween(from, to, (node, pos) => {
|
|
114
145
|
if (node.type.name === "paragraph") {
|
|
115
146
|
const op = collectPPrMarkOp(node, pos, from, to, mode, revisionSet);
|
|
@@ -122,18 +153,21 @@ function resolveChange(from, to, mode, revisionIds) {
|
|
|
122
153
|
styleResolver,
|
|
123
154
|
numbering
|
|
124
155
|
});
|
|
125
|
-
if (nextAttrs)
|
|
126
|
-
nextAttrs
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
156
|
+
if (nextAttrs) {
|
|
157
|
+
if (nextAttrs["styleId"] !== node.attrs["styleId"] && styleResolver) setParagraphAttrsWithRebasedRunFormatting({
|
|
158
|
+
nextAttrs,
|
|
159
|
+
paragraphPosition: pos,
|
|
160
|
+
styleResolver,
|
|
161
|
+
tr,
|
|
162
|
+
...mode === "reject" && { shouldRebase: (inline) => {
|
|
163
|
+
const deleted = inline.marks.some(({ type }) => type.name === "deletion");
|
|
164
|
+
const direct = inline.marks.some(({ type }) => type.name === "runFormattingOverride");
|
|
165
|
+
return !deleted || !direct;
|
|
166
|
+
} }
|
|
167
|
+
});
|
|
168
|
+
else tr.setNodeMarkup(pos, void 0, nextAttrs);
|
|
169
|
+
carryRestoredProperties(pos);
|
|
170
|
+
}
|
|
137
171
|
return true;
|
|
138
172
|
}
|
|
139
173
|
if (node.type.name === "tableRow" && rangeCoversNode(from, to, pos, node)) {
|
|
@@ -388,7 +422,10 @@ function resolveChange(from, to, mode, revisionIds) {
|
|
|
388
422
|
removedSectionEndpointCount++;
|
|
389
423
|
removedSectionReferences.push(...sectionReferencesOf(paragraph));
|
|
390
424
|
}
|
|
391
|
-
} catch {
|
|
425
|
+
} catch {
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
if (op.markWasAdded) carryRestoredProperties(mappedPos);
|
|
392
429
|
}
|
|
393
430
|
if (removedSectionEndpointCount > 0) markTrackedSectionEndpointRemoval(tr, {
|
|
394
431
|
sourceDoc: state.doc,
|
|
@@ -416,6 +453,7 @@ function resolveChange(from, to, mode, revisionIds) {
|
|
|
416
453
|
if (field.type === node.type) tr.setNodeMarkup(position, void 0, node.attrs, node.marks);
|
|
417
454
|
else tr.replaceWith(position, position + field.nodeSize, node);
|
|
418
455
|
}
|
|
456
|
+
for (const [id, position] of [...points].toReversed()) tr.insert(tr.mapping.map(position, -1), commentPoint(tr.doc.type.schema, id));
|
|
419
457
|
if (tr.steps.length > 0) dispatch(tr);
|
|
420
458
|
}
|
|
421
459
|
return true;
|
|
@@ -2,15 +2,15 @@ import { Node, ResolvedPos } from "prosemirror-model";
|
|
|
2
2
|
//#region src/prosemirror/containerFinalParagraph.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* Whether the paragraph starting at `at` is the one its container ENDS with,
|
|
5
|
-
*
|
|
5
|
+
* where a paragraph break cannot join into a following paragraph.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
7
|
+
* Added boundaries normally rotate onto a preceding paragraph, so rejecting
|
|
8
|
+
* them joins back into this one. If an occupied boundary or a table prevents
|
|
9
|
+
* rotation, the final inserted paragraph must retain its own revision: the
|
|
10
|
+
* resolver removes the whole paragraph after rejecting its inserted content.
|
|
11
|
+
* A terminal deletion, by contrast, clears without removing the container's
|
|
12
|
+
* required ending. Bodies, table cells, headers, footers, notes and text boxes
|
|
13
|
+
* share these rules.
|
|
14
14
|
*
|
|
15
15
|
* A paragraph before a TABLE is not one of those: the table is a following
|
|
16
16
|
* sibling, so the paragraph does not end anything and carries its own mark
|
|
@@ -14,15 +14,15 @@ const nothingFollowsIn = (parent, fromIndex, paragraphTypeName) => {
|
|
|
14
14
|
};
|
|
15
15
|
/**
|
|
16
16
|
* Whether the paragraph starting at `at` is the one its container ENDS with,
|
|
17
|
-
*
|
|
17
|
+
* where a paragraph break cannot join into a following paragraph.
|
|
18
18
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
19
|
+
* Added boundaries normally rotate onto a preceding paragraph, so rejecting
|
|
20
|
+
* them joins back into this one. If an occupied boundary or a table prevents
|
|
21
|
+
* rotation, the final inserted paragraph must retain its own revision: the
|
|
22
|
+
* resolver removes the whole paragraph after rejecting its inserted content.
|
|
23
|
+
* A terminal deletion, by contrast, clears without removing the container's
|
|
24
|
+
* required ending. Bodies, table cells, headers, footers, notes and text boxes
|
|
25
|
+
* share these rules.
|
|
26
26
|
*
|
|
27
27
|
* A paragraph before a TABLE is not one of those: the table is a following
|
|
28
28
|
* sibling, so the paragraph does not end anything and carries its own mark
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { joinCommentRangesAcrossParagraphs } from "../../docx/commentRangeJoin.js";
|
|
2
2
|
import { completeCommentReferences } from "../../docx/commentReferenceCompletion.js";
|
|
3
|
+
import { buildSections } from "../../docx/documentParser.js";
|
|
3
4
|
import { normalizeFoldedListNumbers } from "../../docx/foldedListNumberFields.js";
|
|
4
5
|
import { getDocumentSourceStyles } from "../../docx/headerFooterVerbatim.js";
|
|
5
6
|
import { EDITED_PREVIEW_FINGERPRINT, imageRawXmlFingerprint } from "../../docx/imageRawXml.js";
|
|
@@ -397,7 +398,7 @@ function fromProseDoc(pmDoc, baseDocument, { stylesheetSource, reuse = "none" })
|
|
|
397
398
|
const documentBody = { content: blocks };
|
|
398
399
|
if (baseDocument?.package.document.background) documentBody.background = baseDocument.package.document.background;
|
|
399
400
|
if (baseDocument?.package.document.finalSectionProperties) documentBody.finalSectionProperties = baseDocument.package.document.finalSectionProperties;
|
|
400
|
-
if (baseDocument?.package.document.sections) documentBody.sections =
|
|
401
|
+
if (baseDocument?.package.document.sections) documentBody.sections = buildSections(blocks, documentBody.finalSectionProperties);
|
|
401
402
|
if (baseDocument?.package.document.comments) documentBody.comments = baseDocument.package.document.comments;
|
|
402
403
|
const numbering = completeNumberingForDoc(baseDocument?.package.numbering, pmDoc);
|
|
403
404
|
if (baseDocument) {
|
|
@@ -1582,12 +1583,16 @@ function extractParagraphContent(originalParagraph, _documentCounts, emptyHyperl
|
|
|
1582
1583
|
};
|
|
1583
1584
|
const appendDirectRun = (node, run, coalescePlainText = false) => {
|
|
1584
1585
|
if (currentHyperlink) flushCurrentInline();
|
|
1585
|
-
const marksKey = getMarksKey(node.marks)
|
|
1586
|
+
const marksKey = getMarksKey(node.marks.filter((mark) => {
|
|
1587
|
+
if (mark.type.name !== "runIdentity") return true;
|
|
1588
|
+
const { emptyFormatting, preservedAttributes, preserved } = expectRunIdentityMarkAttrs(mark);
|
|
1589
|
+
return emptyFormatting !== true || (preservedAttributes?.length ?? 0) > 0 || (preserved?.children?.length ?? 0) > 0;
|
|
1590
|
+
}));
|
|
1586
1591
|
const ownerId = runIdentityId(node);
|
|
1587
1592
|
const currentOwnerId = currentRun ? sourceRunOwners.get(currentRun) : void 0;
|
|
1588
1593
|
const currentRunIsPlainText = currentRun?.content.every((runContent) => runContent.type === "text");
|
|
1589
1594
|
const joinsOwnedSourceRun = ownerId !== void 0 && ownerId === currentOwnerId && currentRun !== null && runsShareProperties(currentRun, run);
|
|
1590
|
-
const joinsOrdinaryText = coalescePlainText &&
|
|
1595
|
+
const joinsOrdinaryText = coalescePlainText && currentRun !== null && runsShareProperties(currentRun, run) && currentRunIsPlainText === true && currentMarksKey === marksKey;
|
|
1591
1596
|
if (currentRun && (joinsOwnedSourceRun || joinsOrdinaryText)) {
|
|
1592
1597
|
if (joinsOrdinaryText) {
|
|
1593
1598
|
for (const runContent of run.content) if (runContent.type === "text") appendTextToRun(currentRun, runContent.text);
|
|
@@ -3319,7 +3324,7 @@ function tableCellAttrsToFormatting(attrs) {
|
|
|
3319
3324
|
if (attrs.margins && !sameResolvedValue(attrs.margins, attrs._resolvedMargins)) result.margins = buildCellMarginsFromAttrs(attrs.margins);
|
|
3320
3325
|
if (attrs.textDirection !== (orig.textDirection ?? void 0)) if (attrs.textDirection) result.textDirection = attrs.textDirection;
|
|
3321
3326
|
else delete result.textDirection;
|
|
3322
|
-
return result;
|
|
3327
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
3323
3328
|
}
|
|
3324
3329
|
const authoredWidth = attrs._authoredWidth;
|
|
3325
3330
|
if (!(attrs.colspan > 1 || attrs.rowspan > 1 || authoredWidth !== void 0 || attrs.verticalAlign || backgroundChanged || attrs.borders || attrs.margins || attrs.textDirection)) return;
|
|
@@ -42,7 +42,7 @@ import { directionFromBidi } from "../paragraphDirection.js";
|
|
|
42
42
|
import { paragraphIndentationFromFormatting } from "../paragraphIndentation.js";
|
|
43
43
|
import { lineSpacingProvenanceFromSpacing } from "../paragraphSpacing.js";
|
|
44
44
|
import { RUN_IDENTITY_MARK_NAME, hasRunIdentityPayload, runIdentityAttrs } from "../runIdentity.js";
|
|
45
|
-
import {
|
|
45
|
+
import { continueSourceCarrierIdentitiesAcrossRevisions } from "../runIdentityAcrossRevisions.js";
|
|
46
46
|
import { getParagraphMarkSuppressionOverrides, hasDirectRunFormatting, isParagraphMarkSuppressionEligible, resolveParagraphInheritedRunFormatting, stripParagraphMarkFormattingForBodyRuns, stripParagraphMarkOnlyFormatting, suppressParagraphMarkFormatting } from "../runStyleFormatting.js";
|
|
47
47
|
import { schema } from "../schema/index.js";
|
|
48
48
|
import { PRESERVED_XML_LEVELS } from "../schema/nodes.js";
|
|
@@ -112,7 +112,7 @@ const runIdentityMark = (run, nextRunIdentityId) => {
|
|
|
112
112
|
const payload = {
|
|
113
113
|
preservedAttributes: run.preservedAttributes,
|
|
114
114
|
preserved: run.formatting?.preserved,
|
|
115
|
-
emptyFormatting: run.formatting !== void 0 && Object.keys(run.formatting).length === 0
|
|
115
|
+
emptyFormatting: run.formatting !== void 0 && Object.keys(run.formatting).length === 0 ? true : void 0
|
|
116
116
|
};
|
|
117
117
|
if (!runHasPageBreakContent(run) && !runHasMixedContent(run) && !hasRunIdentityPayload(payload)) return null;
|
|
118
118
|
return schema.mark(RUN_IDENTITY_MARK_NAME, runIdentityAttrs(nextRunIdentityId(), payload));
|
|
@@ -676,7 +676,7 @@ function convertParagraph(paragraph, styleResolver, context, extraRunFormatting,
|
|
|
676
676
|
if (emptyHyperlinks) attrs._emptyHyperlinks = emptyHyperlinks;
|
|
677
677
|
return createProseParagraphWithPropertySource(schema.nodes["paragraph"], paragraph, {
|
|
678
678
|
attrs,
|
|
679
|
-
content:
|
|
679
|
+
content: continueSourceCarrierIdentitiesAcrossRevisions(inlineNodes)
|
|
680
680
|
});
|
|
681
681
|
}
|
|
682
682
|
/**
|
|
@@ -1256,7 +1256,7 @@ function convertTableCell({ cell, styleResolver, context, isHeader, gridWidthPer
|
|
|
1256
1256
|
attrs.margins = effectiveFormatting.margins;
|
|
1257
1257
|
attrs._resolvedMargins = effectiveFormatting.margins;
|
|
1258
1258
|
}
|
|
1259
|
-
|
|
1259
|
+
attrs._originalFormatting = formatting ?? {};
|
|
1260
1260
|
if (cell.propertyChanges && cell.propertyChanges.length > 0) attrs.tcPrChange = [...cell.propertyChanges];
|
|
1261
1261
|
if (cell.contentControls && cell.contentControls.length > 0) attrs.contentControls = cell.contentControls;
|
|
1262
1262
|
if (cell.carrierStack?.length) attrs.carrierStack = cell.carrierStack;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readCommentReferenceAttrs } from "../../commentReferenceAttrs.js";
|
|
2
2
|
import { planCommentReferenceRepairs } from "../../commentReferenceIntegrity.js";
|
|
3
3
|
import { readRangeAnchorAttrs } from "../../rangeAnchorAttrs.js";
|
|
4
|
+
import { trackedRunInlineAtomDisposition } from "../../trackedRunInlineAtoms.js";
|
|
4
5
|
import { createNodeExtension } from "../create.js";
|
|
5
6
|
import "./RangeAnchorExtension.js";
|
|
6
7
|
import { Plugin } from "prosemirror-state";
|
|
@@ -10,7 +11,16 @@ const COMMENT_REFERENCE_NODE_NAME = "commentReference";
|
|
|
10
11
|
const surveyCommentReferences = (doc) => {
|
|
11
12
|
const references = [];
|
|
12
13
|
const markEnds = /* @__PURE__ */ new Map();
|
|
14
|
+
const unanchoredMarks = [];
|
|
13
15
|
doc.descendants((node, position) => {
|
|
16
|
+
const transparent = trackedRunInlineAtomDisposition(node) === "transparent";
|
|
17
|
+
if (transparent) {
|
|
18
|
+
for (const mark of node.marks) if (mark.type.name === "comment") unanchoredMarks.push({
|
|
19
|
+
position,
|
|
20
|
+
size: node.nodeSize,
|
|
21
|
+
mark
|
|
22
|
+
});
|
|
23
|
+
}
|
|
14
24
|
if (node.type.name === "commentReference") {
|
|
15
25
|
const attrs = readCommentReferenceAttrs(node);
|
|
16
26
|
references.push(attrs.ok ? {
|
|
@@ -33,6 +43,7 @@ const surveyCommentReferences = (doc) => {
|
|
|
33
43
|
}
|
|
34
44
|
return false;
|
|
35
45
|
}
|
|
46
|
+
if (transparent) return false;
|
|
36
47
|
if (!node.isInline) return true;
|
|
37
48
|
for (const mark of node.marks) {
|
|
38
49
|
if (mark.type.name !== "comment") continue;
|
|
@@ -44,6 +55,7 @@ const surveyCommentReferences = (doc) => {
|
|
|
44
55
|
});
|
|
45
56
|
return {
|
|
46
57
|
references,
|
|
58
|
+
unanchoredMarks,
|
|
47
59
|
markExtents: [...markEnds].map(([commentId, end]) => ({
|
|
48
60
|
commentId,
|
|
49
61
|
end
|
|
@@ -84,9 +96,11 @@ const CommentReferenceExtension = createNodeExtension({
|
|
|
84
96
|
if (!transactions.some(({ docChanged }) => docChanged)) return null;
|
|
85
97
|
const referenceType = newState.schema.nodes[COMMENT_REFERENCE_NODE_NAME];
|
|
86
98
|
if (!referenceType) return null;
|
|
87
|
-
const
|
|
88
|
-
|
|
99
|
+
const survey = surveyCommentReferences(newState.doc);
|
|
100
|
+
const repairs = planCommentReferenceRepairs(survey);
|
|
101
|
+
if (repairs.length === 0 && survey.unanchoredMarks.length === 0) return null;
|
|
89
102
|
const transaction = newState.tr;
|
|
103
|
+
for (const { position, size, mark } of survey.unanchoredMarks) transaction.removeMark(position, position + size, mark);
|
|
90
104
|
for (const repair of repairs) {
|
|
91
105
|
if (repair.type === "delete") {
|
|
92
106
|
transaction.delete(repair.position, repair.position + repair.size);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { DisplayMode } from "../managers/EditorModeManager.js";
|
|
1
2
|
import { FindOptions } from "../utils/findReplace.js";
|
|
2
3
|
import { Node } from "prosemirror-model";
|
|
4
|
+
import { EditorState } from "prosemirror-state";
|
|
3
5
|
//#region src/prosemirror/findReplaceSelection.d.ts
|
|
4
6
|
/**
|
|
5
7
|
* Positional fields of a document search match that the range resolver needs.
|
|
@@ -26,5 +28,13 @@ type ProseMirrorFindMatch = FindMatchPosition & FindMatchRange & {
|
|
|
26
28
|
};
|
|
27
29
|
declare function resolveFindMatchRange(doc: Node, match: FindMatchPosition): FindMatchRange | null;
|
|
28
30
|
declare function findInProseMirrorDocument(doc: Node, searchText: string, options: FindOptions): ProseMirrorFindMatch[];
|
|
31
|
+
type FindInMarkupViewOptions = {
|
|
32
|
+
state: EditorState;
|
|
33
|
+
markupView: DisplayMode;
|
|
34
|
+
searchText: string;
|
|
35
|
+
options: FindOptions;
|
|
36
|
+
};
|
|
37
|
+
/** Search the displayed story; returned ranges address the authored editor document. */
|
|
38
|
+
declare const findInMarkupView: ({ state, markupView, searchText, options }: FindInMarkupViewOptions) => ProseMirrorFindMatch[];
|
|
29
39
|
//#endregion
|
|
30
|
-
export { FindMatchPosition, FindMatchRange, ProseMirrorFindMatch, findInProseMirrorDocument, resolveFindMatchRange };
|
|
40
|
+
export { FindMatchPosition, FindMatchRange, ProseMirrorFindMatch, findInMarkupView, findInProseMirrorDocument, resolveFindMatchRange };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { findAllMatches } from "../utils/findReplace.js";
|
|
2
2
|
import { decodeOoxmlSymbolCharacter } from "../utils/ooxmlSymbol.js";
|
|
3
3
|
import { expectSymbolAttrs } from "./attrs/index.js";
|
|
4
|
+
import { projectMarkupView } from "./markupViewProjection.js";
|
|
4
5
|
//#region src/prosemirror/findReplaceSelection.ts
|
|
5
6
|
function resolveFindMatchRange(doc, match) {
|
|
6
7
|
let resolved = null;
|
|
@@ -40,6 +41,19 @@ function findInProseMirrorDocument(doc, searchText, options) {
|
|
|
40
41
|
});
|
|
41
42
|
return matches;
|
|
42
43
|
}
|
|
44
|
+
/** Search the displayed story; returned ranges address the authored editor document. */
|
|
45
|
+
const findInMarkupView = ({ state, markupView, searchText, options }) => {
|
|
46
|
+
const projection = projectMarkupView(state, markupView);
|
|
47
|
+
if (projection.type === "authored") return findInProseMirrorDocument(state.doc, searchText, options);
|
|
48
|
+
return findInProseMirrorDocument(projection.doc, searchText, options).map((match) => ({
|
|
49
|
+
paragraphIndex: match.paragraphIndex,
|
|
50
|
+
startOffset: match.startOffset,
|
|
51
|
+
endOffset: match.endOffset,
|
|
52
|
+
text: match.text,
|
|
53
|
+
from: projection.toEditor(match.from, 1),
|
|
54
|
+
to: projection.toEditor(match.to, -1)
|
|
55
|
+
}));
|
|
56
|
+
};
|
|
43
57
|
function forEachSearchParagraph(doc, visit) {
|
|
44
58
|
let paragraphIndex = 0;
|
|
45
59
|
const walkBlocks = (container, contentStart) => {
|
|
@@ -139,4 +153,4 @@ function getSearchableParagraphText(paragraph) {
|
|
|
139
153
|
return text;
|
|
140
154
|
}
|
|
141
155
|
//#endregion
|
|
142
|
-
export { findInProseMirrorDocument, resolveFindMatchRange };
|
|
156
|
+
export { findInMarkupView, findInProseMirrorDocument, resolveFindMatchRange };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
1
2
|
import { DisplayMode } from "../managers/EditorModeManager.js";
|
|
2
3
|
import { RemovedSectionReference } from "../internal/sectionEndpointResolution.js";
|
|
3
4
|
import { indexedPositionMap } from "../internal/indexedPositionMap.js";
|
|
@@ -93,5 +94,13 @@ declare const projectMarkupView: (state: EditorState, view: DisplayMode) => Mark
|
|
|
93
94
|
* of text it cannot enter.
|
|
94
95
|
*/
|
|
95
96
|
declare const visibleCaretPosition: (projection: MarkupViewProjection, position: number) => number;
|
|
97
|
+
type ProjectStoryMarkupViewOptions = {
|
|
98
|
+
doc: Node;
|
|
99
|
+
markupView: DisplayMode;
|
|
100
|
+
styles?: document_d_exports.StyleDefinitions | null | undefined;
|
|
101
|
+
numbering?: document_d_exports.NumberingDefinitions | undefined;
|
|
102
|
+
};
|
|
103
|
+
/** Detached stories use the same state-aware projection owner as the body. */
|
|
104
|
+
declare const projectStoryMarkupView: ({ doc, markupView, styles, numbering }: ProjectStoryMarkupViewOptions) => MarkupViewProjection;
|
|
96
105
|
//#endregion
|
|
97
|
-
export { MarkupViewProjection, markupViewResolutionMode, projectMarkupView, resolveStateStory, visibleCaretPosition };
|
|
106
|
+
export { MarkupViewProjection, markupViewResolutionMode, projectMarkupView, projectStoryMarkupView, resolveStateStory, visibleCaretPosition };
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { indexedPositionMap } from "../internal/indexedPositionMap.js";
|
|
2
2
|
import { finalRevisionParagraphRanges } from "../internal/revisionResolutionTracking.js";
|
|
3
3
|
import { resolveWholeStory } from "../internal/wholeStoryRevisionResolution.js";
|
|
4
|
-
import { getDocumentNumbering } from "./plugins/documentNumbering.js";
|
|
4
|
+
import { createDocumentNumberingPlugin, getDocumentNumbering } from "./plugins/documentNumbering.js";
|
|
5
5
|
import { getDocumentStyleResolver } from "./plugins/documentStyleState.js";
|
|
6
|
-
import {
|
|
6
|
+
import { createDocumentStyleContextPlugin } from "./plugins/documentStyles.js";
|
|
7
|
+
import { EditorState, Selection } from "prosemirror-state";
|
|
7
8
|
//#region src/prosemirror/markupViewProjection.ts
|
|
8
9
|
/** Resolve every revision in the state's story with the state's own styles and numbering. */
|
|
9
10
|
const resolveStateStory = (state, mode) => resolveWholeStory({
|
|
@@ -84,5 +85,22 @@ const visibleCaretPosition = (projection, position) => {
|
|
|
84
85
|
const near = Selection.near(projection.doc.resolve(bounded), -1);
|
|
85
86
|
return projection.toEditor(near.head, -1);
|
|
86
87
|
};
|
|
88
|
+
const storyProjectionStates = /* @__PURE__ */ new WeakMap();
|
|
89
|
+
/** Detached stories use the same state-aware projection owner as the body. */
|
|
90
|
+
const projectStoryMarkupView = ({ doc, markupView, styles, numbering }) => {
|
|
91
|
+
if (markupView === "all-markup") return AUTHORED;
|
|
92
|
+
const cached = storyProjectionStates.get(doc);
|
|
93
|
+
if (cached && cached.styles === styles && cached.numbering === numbering) return projectMarkupView(cached.state, markupView);
|
|
94
|
+
const state = EditorState.create({
|
|
95
|
+
doc,
|
|
96
|
+
plugins: [createDocumentStyleContextPlugin(styles), createDocumentNumberingPlugin(numbering)]
|
|
97
|
+
});
|
|
98
|
+
storyProjectionStates.set(doc, {
|
|
99
|
+
styles,
|
|
100
|
+
numbering,
|
|
101
|
+
state
|
|
102
|
+
});
|
|
103
|
+
return projectMarkupView(state, markupView);
|
|
104
|
+
};
|
|
87
105
|
//#endregion
|
|
88
|
-
export { markupViewResolutionMode, projectMarkupView, resolveStateStory, visibleCaretPosition };
|
|
106
|
+
export { markupViewResolutionMode, projectMarkupView, projectStoryMarkupView, resolveStateStory, visibleCaretPosition };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { sliceText } from "../../utils/sliceText.js";
|
|
1
2
|
import { expectParagraphAttrs } from "../attrs/index.js";
|
|
2
3
|
import { effectiveParagraphNumberingReference, paragraphNumberingSourcesFromBoundary } from "../numberingAttr.js";
|
|
3
4
|
import { createPluginKeyOwner } from "../pluginKeyOwner.js";
|
|
@@ -30,7 +31,11 @@ const MAX_REPORTED_STEPS_LENGTH = 4e3;
|
|
|
30
31
|
const describeSteps = (transactions) => {
|
|
31
32
|
const steps = transactions.flatMap((transaction) => transaction.steps.map((step) => step.toJSON()));
|
|
32
33
|
const json = JSON.stringify(steps);
|
|
33
|
-
return json.length > MAX_REPORTED_STEPS_LENGTH ? `${
|
|
34
|
+
return json.length > MAX_REPORTED_STEPS_LENGTH ? `${sliceText({
|
|
35
|
+
text: json,
|
|
36
|
+
units: "codeUnits",
|
|
37
|
+
end: MAX_REPORTED_STEPS_LENGTH
|
|
38
|
+
})}… (${json.length} characters)` : json;
|
|
34
39
|
};
|
|
35
40
|
var TransactionInvariantError = class extends Error {
|
|
36
41
|
issues;
|
|
@@ -19,6 +19,20 @@ declare const NON_INCLUSIVE_MARK_DISPOSITION: {
|
|
|
19
19
|
};
|
|
20
20
|
/** The mark names in the schema that a replacement must not silently drop. */
|
|
21
21
|
declare const nonInclusiveMarkNames: (schema: Schema) => string[];
|
|
22
|
+
/** One typed point for a comment whose aligned coverage has no content left. */
|
|
23
|
+
declare const commentPoint: (schema: Schema, id: number) => Node;
|
|
24
|
+
type ResolvedCommentPointsOptions = {
|
|
25
|
+
doc: Node;
|
|
26
|
+
removes: (node: Node, position: number) => boolean;
|
|
27
|
+
retiresStructure: (node: Node, position: number) => boolean;
|
|
28
|
+
};
|
|
29
|
+
/** The same collector serves standalone commands and the existing bulk walk. */
|
|
30
|
+
declare const createResolvedCommentPointCollector: ({ removes, retiresStructure }: Omit<ResolvedCommentPointsOptions, "doc">) => {
|
|
31
|
+
visit: (node: Node, position: number, previous?: Node) => boolean;
|
|
32
|
+
finish: () => Map<number, number>;
|
|
33
|
+
};
|
|
34
|
+
/** Point fallback excludes comments belonging to retired blocks and table cells. */
|
|
35
|
+
declare const resolvedCommentPoints: ({ doc, removes, retiresStructure }: ResolvedCommentPointsOptions) => Map<number, number>;
|
|
22
36
|
type ReplacedAnnotations = {
|
|
23
37
|
/** Marks the replacement must carry, in document order. */
|
|
24
38
|
carried: readonly Mark[];
|
|
@@ -88,4 +102,4 @@ declare const annotatedReplacement: ({ annotations: { carried, leading, trailing
|
|
|
88
102
|
*/
|
|
89
103
|
declare const inheritedReplacementMarks: (doc: Node, from: number, to: number) => readonly Mark[];
|
|
90
104
|
//#endregion
|
|
91
|
-
export { NON_INCLUSIVE_MARK_DISPOSITION, ReplacedAnnotations, addCarriedMarks, annotatedReplacement, commentsAcrossBlockBoundary, commentsForTrackedInsertion, hasReplacedAnnotations, inheritedReplacementMarks, nonInclusiveMarkNames, placeTrackedInsertion, surveyReplacedAnnotations };
|
|
105
|
+
export { NON_INCLUSIVE_MARK_DISPOSITION, ReplacedAnnotations, addCarriedMarks, annotatedReplacement, commentPoint, commentsAcrossBlockBoundary, commentsForTrackedInsertion, createResolvedCommentPointCollector, hasReplacedAnnotations, inheritedReplacementMarks, nonInclusiveMarkNames, placeTrackedInsertion, resolvedCommentPoints, surveyReplacedAnnotations };
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { expectParagraphAttrs, expectTableCellAttrs, expectTableRowAttrs } from "./attrs/index.js";
|
|
1
2
|
import { BOOKMARK_BOUNDARY_NODE_NAME } from "./extensions/nodes/BookmarkBoundaryExtension.js";
|
|
2
3
|
import { COMMENT_REFERENCE_NODE_NAME } from "./extensions/nodes/CommentReferenceExtension.js";
|
|
3
4
|
import { MOVE_RANGE_BOUNDARY_NODE_NAME } from "./extensions/nodes/MoveRangeBoundaryExtension.js";
|
|
4
5
|
import { RANGE_ANCHOR_NODE_NAME } from "./extensions/nodes/RangeAnchorExtension.js";
|
|
5
6
|
import { TEXT_BOX_ANCHOR_NODE_NAME } from "./extensions/nodes/TextBoxAnchorExtension.js";
|
|
6
7
|
import { readMoveRangeBoundaryAttrs } from "./moveRangeBoundaryAttrs.js";
|
|
8
|
+
import { readRangeAnchorAttrs } from "./rangeAnchorAttrs.js";
|
|
7
9
|
import { isZeroWidthAnchor } from "./zeroWidthAnchors.js";
|
|
8
10
|
import { Fragment, Mark } from "prosemirror-model";
|
|
9
11
|
//#region src/prosemirror/replacedAnnotations.ts
|
|
@@ -21,15 +23,12 @@ import { Fragment, Mark } from "prosemirror-model";
|
|
|
21
23
|
* hyperlink simply stops being a link. Zero-width anchors fare worse still: a
|
|
22
24
|
* plain replace deletes them outright.
|
|
23
25
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* character it covered is gone. One rule per marker kind, and that is the
|
|
29
|
-
* whole contract:
|
|
26
|
+
* Text replacement preserves a comment's aligned coverage. Unchanged text
|
|
27
|
+
* keeps its ranges; inserted text takes the comments of the replaced aligned
|
|
28
|
+
* span. A range with no remaining content becomes a point at the replacement
|
|
29
|
+
* start. The applier decides alignment once for direct and tracked edits.
|
|
30
30
|
*
|
|
31
|
-
* - `comment` mark:
|
|
32
|
-
* a range that started inside it starts at the replacement instead.
|
|
31
|
+
* - `comment` mark: carried over its aligned replacement span.
|
|
33
32
|
* - `hyperlink` mark: the replacement carries the first link the span held, so
|
|
34
33
|
* replacing a link's display text leaves the link on the new text. A span
|
|
35
34
|
* crossing two links keeps the one it opens in, because the mark excludes
|
|
@@ -66,9 +65,8 @@ import { Fragment, Mark } from "prosemirror-model";
|
|
|
66
65
|
* - every other mark: formatting, and left to boundary inheritance, which
|
|
67
66
|
* already gives the replacement the formatting of the text it replaces.
|
|
68
67
|
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* the comment: the one case where a range is meant to disappear.
|
|
68
|
+
* Removing the owning block removes its comment. Replacing its last covered
|
|
69
|
+
* text within a surviving block retains a point rather than dropping it.
|
|
72
70
|
*/
|
|
73
71
|
/**
|
|
74
72
|
* What a replacement does with each mark the schema declares
|
|
@@ -90,6 +88,67 @@ const NON_INCLUSIVE_MARK_DISPOSITION = {
|
|
|
90
88
|
/** The mark names in the schema that a replacement must not silently drop. */
|
|
91
89
|
const nonInclusiveMarkNames = (schema) => Object.entries(schema.marks).filter(([, type]) => type.spec.inclusive === false).map(([name]) => name);
|
|
92
90
|
const isCarried = (mark) => NON_INCLUSIVE_MARK_DISPOSITION[mark.type.name] === "carry";
|
|
91
|
+
/** One typed point for a comment whose aligned coverage has no content left. */
|
|
92
|
+
const commentPoint = (schema, id) => schema.node(RANGE_ANCHOR_NODE_NAME, {
|
|
93
|
+
start: {
|
|
94
|
+
type: "commentRangeStart",
|
|
95
|
+
id
|
|
96
|
+
},
|
|
97
|
+
end: {
|
|
98
|
+
type: "commentRangeEnd",
|
|
99
|
+
id
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
/** The same collector serves standalone commands and the existing bulk walk. */
|
|
103
|
+
const createResolvedCommentPointCollector = ({ removes, retiresStructure }) => {
|
|
104
|
+
const points = /* @__PURE__ */ new Map();
|
|
105
|
+
const retained = /* @__PURE__ */ new Set();
|
|
106
|
+
const visit = (node, position, previous) => {
|
|
107
|
+
if (node.type.name === "paragraph") {
|
|
108
|
+
const mark = expectParagraphAttrs(node).pPrMark;
|
|
109
|
+
const precedingMark = previous?.type.name === "paragraph" ? expectParagraphAttrs(previous).pPrMark : null;
|
|
110
|
+
if ((mark?.kind === "del" || mark?.kind === "moveFrom") && retiresStructure(node, position) || (precedingMark?.kind === "del" || precedingMark?.kind === "moveFrom") && previous !== void 0 && retiresStructure(previous, position - previous.nodeSize)) {
|
|
111
|
+
let survivingContent = false;
|
|
112
|
+
node.descendants((inline, offset) => {
|
|
113
|
+
if (inline.isInline && !isZeroWidthAnchor(inline) && !removes(inline, position + 1 + offset)) survivingContent = true;
|
|
114
|
+
return !survivingContent;
|
|
115
|
+
});
|
|
116
|
+
if (!survivingContent) return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (node.type.name === "tableRow" && expectTableRowAttrs(node).trDel && retiresStructure(node, position)) return false;
|
|
120
|
+
if ((node.type.name === "tableCell" || node.type.name === "tableHeader") && expectTableCellAttrs(node).cellMarker?.kind === "del" && retiresStructure(node, position)) return false;
|
|
121
|
+
if (node.type.name === "rangeAnchor") {
|
|
122
|
+
const attrs = readRangeAnchorAttrs(node);
|
|
123
|
+
if (attrs.ok && attrs.value.start.type === "commentRangeStart") retained.add(attrs.value.start.id);
|
|
124
|
+
}
|
|
125
|
+
if (!node.isInline || isZeroWidthAnchor(node)) return true;
|
|
126
|
+
for (const mark of node.marks) {
|
|
127
|
+
if (mark.type.name !== "comment") continue;
|
|
128
|
+
const id = mark.attrs["commentId"];
|
|
129
|
+
if (!removes(node, position)) retained.add(id);
|
|
130
|
+
else if (!points.has(id)) points.set(id, position);
|
|
131
|
+
}
|
|
132
|
+
return true;
|
|
133
|
+
};
|
|
134
|
+
const finish = () => {
|
|
135
|
+
for (const id of retained) points.delete(id);
|
|
136
|
+
return points;
|
|
137
|
+
};
|
|
138
|
+
return {
|
|
139
|
+
visit,
|
|
140
|
+
finish
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
/** Point fallback excludes comments belonging to retired blocks and table cells. */
|
|
144
|
+
const resolvedCommentPoints = ({ doc, removes, retiresStructure }) => {
|
|
145
|
+
const collector = createResolvedCommentPointCollector({
|
|
146
|
+
removes,
|
|
147
|
+
retiresStructure
|
|
148
|
+
});
|
|
149
|
+
doc.descendants((node, position, parent, index) => collector.visit(node, position, index > 0 ? parent?.maybeChild(index - 1) ?? void 0 : void 0));
|
|
150
|
+
return collector.finish();
|
|
151
|
+
};
|
|
93
152
|
/** Anchors an edit must put back, and where relative to the replacement. */
|
|
94
153
|
const ANCHOR_PLACEMENT = {
|
|
95
154
|
[COMMENT_REFERENCE_NODE_NAME]: "after",
|
|
@@ -349,4 +408,4 @@ const inheritedReplacementMarks = (doc, from, to) => {
|
|
|
349
408
|
return (to === from ? $from.marks() : $from.marksAcross(doc.resolve(to))) ?? Mark.none;
|
|
350
409
|
};
|
|
351
410
|
//#endregion
|
|
352
|
-
export { NON_INCLUSIVE_MARK_DISPOSITION, addCarriedMarks, annotatedReplacement, commentsAcrossBlockBoundary, commentsForTrackedInsertion, hasReplacedAnnotations, inheritedReplacementMarks, nonInclusiveMarkNames, placeTrackedInsertion, surveyReplacedAnnotations };
|
|
411
|
+
export { NON_INCLUSIVE_MARK_DISPOSITION, addCarriedMarks, annotatedReplacement, commentPoint, commentsAcrossBlockBoundary, commentsForTrackedInsertion, createResolvedCommentPointCollector, hasReplacedAnnotations, inheritedReplacementMarks, nonInclusiveMarkNames, placeTrackedInsertion, resolvedCommentPoints, surveyReplacedAnnotations };
|
|
@@ -9,6 +9,8 @@ type ReadAuthoredRunFormattingOptions = {
|
|
|
9
9
|
};
|
|
10
10
|
/** Read authored run properties without confusing inherited visuals for direct formatting. */
|
|
11
11
|
declare const readAuthoredRunFormatting: ({ context, marks, styleResolver }: ReadAuthoredRunFormattingOptions) => document_d_exports.TextFormatting;
|
|
12
|
+
/** Preserve the authored distinction between an absent and empty property set in revisions. */
|
|
13
|
+
declare const readAuthoredRunPropertySnapshot: (options: ReadAuthoredRunFormattingOptions) => document_d_exports.TextFormatting | undefined;
|
|
12
14
|
type ReconcileRunFormattingMarksOptions = {
|
|
13
15
|
authoredFormatting: document_d_exports.TextFormatting;
|
|
14
16
|
context: ParagraphRunStyleContext;
|
|
@@ -22,4 +24,4 @@ type ReconcileRunFormattingMarksOptions = {
|
|
|
22
24
|
*/
|
|
23
25
|
declare const reconcileRunFormattingMarks: ({ authoredFormatting, context, node, styleResolver }: ReconcileRunFormattingMarksOptions) => readonly Mark[];
|
|
24
26
|
//#endregion
|
|
25
|
-
export { readAuthoredRunFormatting, reconcileRunFormattingMarks };
|
|
27
|
+
export { readAuthoredRunFormatting, readAuthoredRunPropertySnapshot, reconcileRunFormattingMarks };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { mergeTextFormatting } from "../utils/textFormattingMerge.js";
|
|
2
|
-
import { expectCharacterStyleMarkAttrs } from "./attrs/index.js";
|
|
2
|
+
import { expectCharacterStyleMarkAttrs, expectRunIdentityMarkAttrs } from "./attrs/index.js";
|
|
3
3
|
import { textFormattingToMarks } from "./extensions/marks/markUtils.js";
|
|
4
4
|
import { marksToTextFormatting } from "./runFormattingFromMarks.js";
|
|
5
5
|
import { RUN_FORMATTING_MARK_NAMES } from "./runFormattingMarkNames.js";
|
|
6
|
+
import { RUN_IDENTITY_MARK_NAME } from "./runIdentity.js";
|
|
6
7
|
import { getParagraphMarkSuppressionOverrides, hasDirectRunFormatting, isParagraphMarkSuppressionEligible, paragraphFormattingForRun, resolveEffectiveRunStyleFormatting } from "./runStyleFormatting.js";
|
|
7
8
|
import { Mark } from "prosemirror-model";
|
|
8
9
|
//#region src/prosemirror/runFormattingReconciliation.ts
|
|
@@ -14,6 +15,13 @@ const readAuthoredRunFormatting = ({ context, marks, styleResolver }) => marksTo
|
|
|
14
15
|
paragraphMarkPrecedesStyle: context.paragraphMarkPrecedesStyle,
|
|
15
16
|
...styleResolver !== void 0 ? { styleResolver } : {}
|
|
16
17
|
});
|
|
18
|
+
/** Preserve the authored distinction between an absent and empty property set in revisions. */
|
|
19
|
+
const readAuthoredRunPropertySnapshot = (options) => {
|
|
20
|
+
const formatting = readAuthoredRunFormatting(options);
|
|
21
|
+
if (Object.keys(formatting).length > 0) return formatting;
|
|
22
|
+
const identity = options.marks.find(({ type }) => type.name === RUN_IDENTITY_MARK_NAME);
|
|
23
|
+
return identity && expectRunIdentityMarkAttrs(identity).emptyFormatting ? formatting : void 0;
|
|
24
|
+
};
|
|
17
25
|
/**
|
|
18
26
|
* Rebuild a run's physical formatting marks from its authored properties and
|
|
19
27
|
* current style context. This is the inverse of {@link readAuthoredRunFormatting}:
|
|
@@ -54,4 +62,4 @@ const reconcileRunFormattingMarks = ({ authoredFormatting, context, node, styleR
|
|
|
54
62
|
]);
|
|
55
63
|
};
|
|
56
64
|
//#endregion
|
|
57
|
-
export { readAuthoredRunFormatting, reconcileRunFormattingMarks };
|
|
65
|
+
export { readAuthoredRunFormatting, readAuthoredRunPropertySnapshot, reconcileRunFormattingMarks };
|