@stll/folio-core 0.54.1 → 0.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-edits/apply.d.ts +1 -1
- package/dist/ai-edits/apply.js +40 -32
- package/dist/ai-edits/headless.d.ts +1 -2
- package/dist/ai-edits/headless.js +13 -27
- package/dist/ai-edits/read.d.ts +1 -0
- package/dist/ai-edits/read.js +7 -2
- package/dist/ai-edits/table-mutation-plan.d.ts +2 -1
- package/dist/ai-edits/table-mutation-plan.js +39 -1
- package/dist/ai-suggestions/apply.d.ts +1 -1
- package/dist/ai-suggestions/apply.js +3 -2
- package/dist/compare/compare.js +2 -1
- package/dist/compare/content-types.d.ts +3 -15
- package/dist/controller/canonicalComposition.d.ts +36 -0
- package/dist/controller/canonicalComposition.js +168 -0
- package/dist/controller/canonicalInput.d.ts +45 -0
- package/dist/controller/canonicalInput.js +338 -0
- package/dist/controller/canonicalOperations.d.ts +22 -0
- package/dist/controller/canonicalOperations.js +85 -0
- package/dist/controller/canonicalReview.d.ts +12 -0
- package/dist/controller/canonicalReview.js +19 -0
- package/dist/controller/canonicalSession.d.ts +149 -0
- package/dist/controller/canonicalSession.js +1038 -0
- package/dist/controller/canonicalStoryEditor.d.ts +34 -0
- package/dist/controller/canonicalStoryEditor.js +82 -0
- package/dist/controller/canonicalStructure.d.ts +16 -0
- package/dist/controller/canonicalStructure.js +269 -0
- package/dist/controller/folioEditor.d.ts +1 -1
- package/dist/controller/folioEditor.js +9 -0
- package/dist/controller/headerFooterEditorManager.d.ts +4 -0
- package/dist/controller/headerFooterEditorManager.js +71 -3
- package/dist/controller/hiddenEditorApi.d.ts +35 -0
- package/dist/controller/hiddenEditorApi.js +25 -8
- package/dist/controller/hiddenEditorManager.d.ts +11 -2
- package/dist/controller/hiddenEditorManager.js +456 -30
- package/dist/controller/layoutPipeline.d.ts +1 -1
- package/dist/controller/layoutPipeline.js +2 -0
- package/dist/controller/noteEditorManager.d.ts +4 -0
- package/dist/controller/noteEditorManager.js +113 -15
- package/dist/docx/attributeRemainder.js +1 -0
- package/dist/docx/bookmarkIds.d.ts +11 -0
- package/dist/docx/bookmarkIds.js +33 -0
- package/dist/docx/canonicalSessionInput.d.ts +11 -0
- package/dist/docx/canonicalSessionInput.js +27 -0
- package/dist/docx/canonicalStoryRepack.d.ts +10 -0
- package/dist/docx/canonicalStoryRepack.js +41 -0
- package/dist/docx/contentTypeRegistry.d.ts +8 -0
- package/dist/docx/contentTypeRegistry.js +64 -0
- package/dist/docx/documentParser.d.ts +14 -1
- package/dist/docx/documentParser.js +17 -4
- package/dist/docx/drawingIdNormalization.js +23 -8
- package/dist/docx/ensureParaIds.d.ts +12 -1
- package/dist/docx/ensureParaIds.js +173 -213
- package/dist/docx/foldedListNumberFields.d.ts +85 -0
- package/dist/docx/foldedListNumberFields.js +267 -0
- package/dist/docx/headerFooterVerbatim.d.ts +14 -1
- package/dist/docx/headerFooterVerbatim.js +95 -2
- package/dist/docx/listNumberingInstances.js +11 -9
- package/dist/docx/noteIds.d.ts +9 -0
- package/dist/docx/noteIds.js +17 -0
- package/dist/docx/noteReferenceMark.d.ts +3 -1
- package/dist/docx/noteReferenceMark.js +15 -14
- package/dist/docx/numberingIds.d.ts +14 -0
- package/dist/docx/numberingIds.js +16 -0
- package/dist/docx/numberingParser.d.ts +3 -1
- package/dist/docx/numberingParser.js +17 -3
- package/dist/docx/numericIdAllocator.d.ts +12 -0
- package/dist/docx/numericIdAllocator.js +33 -0
- package/dist/docx/numericIdNormalization.d.ts +16 -0
- package/dist/docx/numericIdNormalization.js +174 -0
- package/dist/docx/packageParts.d.ts +3 -1
- package/dist/docx/packageParts.js +65 -16
- package/dist/docx/paragraphMarkPropertyPresence.d.ts +9 -0
- package/dist/docx/paragraphMarkPropertyPresence.js +21 -0
- package/dist/docx/paragraphParser.js +101 -53
- package/dist/docx/paragraphPropertySource.d.ts +15 -1
- package/dist/docx/paragraphPropertySource.js +76 -22
- package/dist/docx/paragraphTextBoxEnrichment.js +2 -1
- package/dist/docx/parser.js +19 -6
- package/dist/docx/rasterMime.d.ts +64 -0
- package/dist/docx/rasterMime.js +116 -0
- package/dist/docx/replyToComment.js +13 -6
- package/dist/docx/reviewHistoryNamespace.d.ts +4 -0
- package/dist/docx/reviewHistoryNamespace.js +4 -0
- package/dist/docx/reviewResolutionProvenance.d.ts +25 -0
- package/dist/docx/reviewResolutionProvenance.js +153 -0
- package/dist/docx/rezip.d.ts +7 -3
- package/dist/docx/rezip.js +121 -52
- package/dist/docx/runConsolidator.d.ts +2 -58
- package/dist/docx/runConsolidator.js +3 -175
- package/dist/docx/runParser.d.ts +2 -1
- package/dist/docx/runParser.js +156 -116
- package/dist/docx/saveDiagnostics.d.ts +11 -0
- package/dist/docx/saveDiagnostics.js +0 -0
- package/dist/docx/selectiveSave.d.ts +2 -1
- package/dist/docx/selectiveSave.js +14 -1
- package/dist/docx/selectiveXmlPatch.d.ts +16 -8
- package/dist/docx/selectiveXmlPatch.js +74 -2
- package/dist/docx/serializer/headerFooterSerializer.d.ts +5 -1
- package/dist/docx/serializer/headerFooterSerializer.js +19 -11
- package/dist/docx/serializer/noteSerializer.d.ts +2 -2
- package/dist/docx/serializer/noteSerializer.js +24 -8
- package/dist/docx/serializer/paragraphSerializer.js +41 -4
- package/dist/docx/serializer/partNamespaces.js +6 -3
- package/dist/docx/serializer/runSerializer.js +8 -5
- package/dist/docx/serializer/trackedChangeAttributes.js +7 -1
- package/dist/docx/server/build.js +14 -3
- package/dist/docx/server/createBilingualDocument.js +10 -9
- package/dist/docx/settingsHeaderFooterUpdate.d.ts +5 -0
- package/dist/docx/settingsHeaderFooterUpdate.js +90 -0
- package/dist/docx/settingsParser.d.ts +1 -2
- package/dist/docx/settingsParser.js +5 -6
- package/dist/docx/storyBlockReplay.d.ts +11 -0
- package/dist/docx/storyBlockReplay.js +367 -0
- package/dist/docx/streamingXmlParser.d.ts +31 -1
- package/dist/docx/streamingXmlParser.js +136 -21
- package/dist/docx/structuralXmlPatch.js +8 -1
- package/dist/docx/unzip.d.ts +3 -1
- package/dist/docx/unzip.js +36 -16
- package/dist/docx/verbatimCapture.d.ts +3 -1
- package/dist/docx/verbatimCapture.js +49 -6
- package/dist/i18n/messages/ar.gen.d.ts +5 -0
- package/dist/i18n/messages/ar.gen.js +656 -0
- package/dist/i18n/messages/cs.gen.d.ts +5 -0
- package/dist/i18n/messages/cs.gen.js +656 -0
- package/dist/i18n/messages/de.gen.d.ts +5 -0
- package/dist/i18n/messages/de.gen.js +656 -0
- package/dist/i18n/messages/en.gen.d.ts +5 -0
- package/dist/i18n/messages/en.gen.js +656 -0
- package/dist/i18n/messages/es.gen.d.ts +5 -0
- package/dist/i18n/messages/es.gen.js +656 -0
- package/dist/i18n/messages/et.gen.d.ts +5 -0
- package/dist/i18n/messages/et.gen.js +656 -0
- package/dist/i18n/messages/fr.gen.d.ts +5 -0
- package/dist/i18n/messages/fr.gen.js +656 -0
- package/dist/i18n/messages/he.gen.d.ts +5 -0
- package/dist/i18n/messages/he.gen.js +656 -0
- package/dist/i18n/messages/hi.gen.d.ts +5 -0
- package/dist/i18n/messages/hi.gen.js +656 -0
- package/dist/i18n/messages/hu.gen.d.ts +5 -0
- package/dist/i18n/messages/hu.gen.js +656 -0
- package/dist/i18n/messages/locales.d.ts +5 -0
- package/dist/i18n/messages/locales.js +22 -0
- package/dist/i18n/messages/lt.gen.d.ts +5 -0
- package/dist/i18n/messages/lt.gen.js +656 -0
- package/dist/i18n/messages/lv.gen.d.ts +5 -0
- package/dist/i18n/messages/lv.gen.js +656 -0
- package/dist/i18n/messages/pl.gen.d.ts +5 -0
- package/dist/i18n/messages/pl.gen.js +656 -0
- package/dist/i18n/messages/pt-BR.gen.d.ts +5 -0
- package/dist/i18n/messages/pt-BR.gen.js +656 -0
- package/dist/i18n/messages/sk.gen.d.ts +5 -0
- package/dist/i18n/messages/sk.gen.js +656 -0
- package/dist/i18n/messages/tr.gen.d.ts +5 -0
- package/dist/i18n/messages/tr.gen.js +656 -0
- package/dist/i18n/messages/zh-CN.gen.d.ts +5 -0
- package/dist/i18n/messages/zh-CN.gen.js +656 -0
- package/dist/i18n/messages.d.ts +2 -3
- package/dist/i18n/messages.js +1 -19
- package/dist/internal/noteMarkerAttrs.d.ts +8 -0
- package/dist/internal/noteMarkerAttrs.js +16 -0
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +1 -0
- package/dist/internal/prosemirrorAttrBoundary.d.ts +21 -0
- package/dist/internal/prosemirrorAttrBoundary.js +50 -0
- package/dist/layout-bridge/convert/fixedTableColumnWidths.d.ts +6 -0
- package/dist/layout-bridge/convert/fixedTableColumnWidths.js +23 -0
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +3 -3
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +1 -0
- package/dist/layout-bridge/convert/noteReferences.d.ts +1 -3
- package/dist/layout-bridge/convert/noteReferences.js +1 -6
- package/dist/layout-bridge/convert/paragraphRuns.js +2 -4
- package/dist/layout-bridge/convert/tableConversion.js +4 -1
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +2 -2
- package/dist/layout-bridge/convert/toFlowBlocks.js +2 -2
- package/dist/layout-painter/index.js +2 -5
- package/dist/managers/DocumentLoaderManager.d.ts +1 -0
- package/dist/managers/DocumentLoaderManager.js +8 -1
- package/dist/markdown/renderBlock.js +15 -1
- package/dist/markdown/renderParagraph.js +9 -13
- package/dist/markdown/renderRuns.js +3 -2
- package/dist/markdown/renderTable.js +2 -0
- package/dist/markdown/types.d.ts +3 -9
- package/dist/paged-layout/editorScrollRoot.d.ts +15 -0
- package/dist/paged-layout/editorScrollRoot.js +72 -0
- package/dist/paged-layout/scrollToPmPosition.js +8 -22
- package/dist/prosemirror/attrs/index.d.ts +2 -12
- package/dist/prosemirror/attrs/index.js +22 -48
- package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +2 -1
- package/dist/prosemirror/canonicalCommands.d.ts +97 -0
- package/dist/prosemirror/canonicalCommands.js +28 -0
- package/dist/prosemirror/commands/clearParagraphIndent.d.ts +6 -0
- package/dist/prosemirror/commands/clearParagraphIndent.js +25 -0
- package/dist/prosemirror/commands/pageBreak.js +15 -1
- package/dist/prosemirror/commentIdAllocator.d.ts +15 -22
- package/dist/prosemirror/commentIdAllocator.js +50 -25
- package/dist/prosemirror/commentReferenceAttrs.d.ts +2 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +91 -19
- package/dist/prosemirror/conversion/listRenderingDefinition.d.ts +6 -0
- package/dist/prosemirror/conversion/listRenderingDefinition.js +97 -0
- package/dist/prosemirror/conversion/toProseDoc.d.ts +4 -3
- package/dist/prosemirror/conversion/toProseDoc.js +51 -11
- package/dist/prosemirror/executeEditorCommand.d.ts +11 -0
- package/dist/prosemirror/executeEditorCommand.js +26 -0
- package/dist/prosemirror/extensions/StarterKit.js +2 -0
- package/dist/prosemirror/extensions/core/HistoryExtension.js +97 -5
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +53 -20
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +22 -28
- package/dist/prosemirror/extensions/features/ListExtension.js +18 -5
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +5 -2
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +13 -1
- package/dist/prosemirror/extensions/marks/TextColorExtension.js +3 -2
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +2 -0
- package/dist/prosemirror/extensions/marks/markUtils.js +70 -8
- package/dist/prosemirror/extensions/nodes/NoteMarkerExtension.d.ts +6 -0
- package/dist/prosemirror/extensions/nodes/NoteMarkerExtension.js +36 -0
- package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.js +4 -2
- package/dist/prosemirror/extensions/nodes/ShapeExtension.js +8 -6
- package/dist/prosemirror/listMarker.d.ts +1 -0
- package/dist/prosemirror/listMarker.js +16 -7
- package/dist/prosemirror/listNumbering.js +26 -5
- package/dist/prosemirror/listRenderingAttrs.d.ts +1 -0
- package/dist/prosemirror/listRenderingAttrs.js +3 -0
- package/dist/prosemirror/markupViewNotes.js +3 -2
- package/dist/prosemirror/moveRangeBoundaryAttrs.d.ts +2 -1
- package/dist/prosemirror/noteReferenceReview.js +5 -3
- package/dist/prosemirror/plugins/revisionIds.d.ts +23 -19
- package/dist/prosemirror/plugins/revisionIds.js +110 -29
- package/dist/prosemirror/plugins/suggestionMode.d.ts +2 -2
- package/dist/prosemirror/plugins/suggestionMode.js +246 -42
- package/dist/prosemirror/rangeAnchorAttrs.d.ts +2 -1
- package/dist/prosemirror/runFormattingFromMarks.d.ts +4 -1
- package/dist/prosemirror/runFormattingFromMarks.js +15 -1
- package/dist/prosemirror/runFormattingInlineCarriers.d.ts +2 -1
- package/dist/prosemirror/runFormattingInlineCarriers.js +4 -1
- package/dist/prosemirror/schema/marks.d.ts +2 -0
- package/dist/prosemirror/schema/nodes.d.ts +10 -2
- package/dist/prosemirror/storyListNumbering.js +11 -9
- package/dist/prosemirror/textBoxAnchorAttrs.d.ts +2 -1
- package/dist/prosemirror/textInput.d.ts +6 -1
- package/dist/prosemirror/textInput.js +14 -3
- package/dist/prosemirror/trackedRevisionPath.js +2 -1
- package/dist/prosemirror/trackedRunInlineAtoms.d.ts +1 -0
- package/dist/prosemirror/trackedRunInlineAtoms.js +1 -0
- package/dist/prosemirror/utils/visualLineNavigation.js +6 -8
- package/dist/prosemirror/validation.js +4 -0
- package/dist/types/content.d.ts +2 -2
- package/dist/utils/createDocument.js +2 -2
- package/dist/utils/mergeDocumentContent.d.ts +2 -2
- package/dist/utils/mergeDocumentContent.js +11 -8
- package/package.json +14 -2
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { expectParagraphAttrs, expectTrackedChangeMarkAttrs } from "../attrs/index.js";
|
|
2
|
+
import { clearIndentOnBackspace } from "../commands/clearParagraphIndent.js";
|
|
2
3
|
import { paragraphPropertiesSnapshot } from "../commands/propertyChangeScope.js";
|
|
3
4
|
import { paragraphEndsItsContainer } from "../containerFinalParagraph.js";
|
|
4
5
|
import { encloseWholeControls } from "../contentControlRevisions.js";
|
|
@@ -10,14 +11,16 @@ import { rebaseParagraphRuns } from "../rebaseParagraphRunFormatting.js";
|
|
|
10
11
|
import { RUN_FORMATTING_MARK_NAMES } from "../runFormattingMarkNames.js";
|
|
11
12
|
import { paragraphRunStyleContext } from "../runStyleFormatting.js";
|
|
12
13
|
import { cellPasteRange, pasteTableCells } from "../tableCellPaste.js";
|
|
13
|
-
import { handleEditorBeforeInput } from "../textInput.js";
|
|
14
|
+
import { afterNativeCompositionFlush, handleEditorBeforeInput } from "../textInput.js";
|
|
14
15
|
import { canCarryTrackedRunMark } from "../trackedRunInlineAtoms.js";
|
|
15
16
|
import { getDocumentNumbering } from "./documentNumbering.js";
|
|
16
|
-
import { getDocumentStyleResolver } from "./documentStyleState.js";
|
|
17
|
+
import { documentStylesKey, getDocumentStyleResolver } from "./documentStyleState.js";
|
|
17
18
|
import { mintRevisionId, seedRevisionIdsFromDoc } from "./revisionIds.js";
|
|
18
19
|
import { Slice } from "prosemirror-model";
|
|
20
|
+
import { CellSelection } from "prosemirror-tables";
|
|
19
21
|
import { Mapping, ReplaceStep } from "prosemirror-transform";
|
|
20
|
-
import { AllSelection, Plugin, PluginKey, Selection, TextSelection } from "prosemirror-state";
|
|
22
|
+
import { AllSelection, EditorState, Plugin, PluginKey, Selection, TextSelection } from "prosemirror-state";
|
|
23
|
+
import { joinBackward, joinForward, selectNodeBackward, selectNodeForward } from "prosemirror-commands";
|
|
21
24
|
import { isHistoryTransaction } from "prosemirror-history";
|
|
22
25
|
import { undoInputRule } from "prosemirror-inputrules";
|
|
23
26
|
//#region src/prosemirror/plugins/suggestionMode.ts
|
|
@@ -241,10 +244,44 @@ function markRangeAsInserted(tr, doc, from, to, insertionType, deletionType, att
|
|
|
241
244
|
function handleSuggestionPaste(view, slice, pluginState) {
|
|
242
245
|
const { selection } = view.state;
|
|
243
246
|
const selectsAll = selection instanceof AllSelection;
|
|
244
|
-
if (!(selection instanceof TextSelection || selectsAll)
|
|
247
|
+
if (!(selection instanceof TextSelection || selectsAll)) return false;
|
|
245
248
|
const insertionType = view.state.schema.marks["insertion"];
|
|
246
249
|
const deletionType = view.state.schema.marks["deletion"];
|
|
247
250
|
if (!insertionType || !deletionType) return false;
|
|
251
|
+
if (selection.empty) {
|
|
252
|
+
const { $from } = selection;
|
|
253
|
+
const closedTable = slice.openStart === 0 && slice.openEnd === 0 && slice.content.firstChild?.type.name === "table" && slice.content.lastChild?.type.name === "table";
|
|
254
|
+
const prefix = $from.parent.content.cut(0, $from.parentOffset);
|
|
255
|
+
let deletedPrefix = prefix.size > 0;
|
|
256
|
+
prefix.forEach((node) => {
|
|
257
|
+
if (!node.marks.some((mark) => mark.type === deletionType)) deletedPrefix = false;
|
|
258
|
+
});
|
|
259
|
+
if (!closedTable || $from.parent.type.name !== "paragraph" || !deletedPrefix) return false;
|
|
260
|
+
const suffix = $from.parent.content.cut($from.parentOffset);
|
|
261
|
+
let deletedSuffix = true;
|
|
262
|
+
suffix.forEach((node) => {
|
|
263
|
+
if (!node.marks.some((mark) => mark.type === deletionType)) deletedSuffix = false;
|
|
264
|
+
});
|
|
265
|
+
const tr = view.state.tr.setMeta(SUGGESTION_META, true).setMeta("paste", true);
|
|
266
|
+
const at = $from.before();
|
|
267
|
+
tr.replaceRange(at, at, slice);
|
|
268
|
+
const revision = makeMarkAttrs(pluginState);
|
|
269
|
+
const end = tr.mapping.map(at, 1);
|
|
270
|
+
enclosePastedRunRevisions({
|
|
271
|
+
tr,
|
|
272
|
+
from: at,
|
|
273
|
+
to: end,
|
|
274
|
+
revision
|
|
275
|
+
});
|
|
276
|
+
markRangeAsInserted(tr, tr.doc, at, end, insertionType, deletionType, revision);
|
|
277
|
+
if (deletedSuffix && $from.parent.attrs["pPrMark"] == null && !paragraphEndsItsContainer($from.doc.resolve($from.before()), "paragraph")) tr.setNodeAttribute(tr.mapping.map($from.before()), "pPrMark", {
|
|
278
|
+
kind: "del",
|
|
279
|
+
info: makeParagraphMarkInfo(pluginState)
|
|
280
|
+
});
|
|
281
|
+
tr.setSelection(TextSelection.create(tr.doc, tr.mapping.map(selection.from)));
|
|
282
|
+
view.dispatch(tr.scrollIntoView());
|
|
283
|
+
return true;
|
|
284
|
+
}
|
|
248
285
|
if (selectsAll && (slice.openStart > 0 || slice.openEnd > 0)) slice = new Slice(view.state.tr.replaceSelection(slice).doc.content, 0, 0);
|
|
249
286
|
const { from, to } = selectsAll ? {
|
|
250
287
|
from: Selection.atStart(view.state.doc).from,
|
|
@@ -372,16 +409,54 @@ function handleSuggestionTableCellPaste(view, slice, pluginState) {
|
|
|
372
409
|
const insertFrom = tr.mapping.slice(mapFrom).map(to);
|
|
373
410
|
const sizeBefore = tr.doc.content.size;
|
|
374
411
|
tr.replaceRange(insertFrom, insertFrom, content);
|
|
375
|
-
|
|
412
|
+
let insertTo = insertFrom + (tr.doc.content.size - sizeBefore);
|
|
413
|
+
let pastedFrom = insertFrom;
|
|
414
|
+
const finalParagraph = cell.lastChild;
|
|
415
|
+
const $pasteFrom = tr.doc.resolve(pastedFrom);
|
|
416
|
+
const $pasteTo = tr.doc.resolve(insertTo);
|
|
417
|
+
if (content.openStart > 0 && content.openEnd > 0 && finalParagraph?.type.name === "paragraph" && $pasteFrom.parent.type.name === "paragraph" && $pasteTo.parent.type.name === "paragraph" && $pasteFrom.before() !== $pasteTo.before()) {
|
|
418
|
+
tr.setNodeAttribute($pasteFrom.before(), "pPrMark", {
|
|
419
|
+
kind: "ins",
|
|
420
|
+
info: {
|
|
421
|
+
id: revision.revisionId,
|
|
422
|
+
author: revision.author,
|
|
423
|
+
date: revision.date
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
tr.setNodeAttribute($pasteTo.before(), "pPrMark", finalParagraph.attrs["pPrMark"]);
|
|
427
|
+
recordReplacedParagraphProperties({
|
|
428
|
+
tr,
|
|
429
|
+
position: $pasteTo.before(),
|
|
430
|
+
replaced: finalParagraph,
|
|
431
|
+
revision: {
|
|
432
|
+
id: revision.revisionId,
|
|
433
|
+
author: revision.author,
|
|
434
|
+
date: revision.date
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
const emptyInsertions = [];
|
|
439
|
+
tr.doc.nodeAt(cellPos)?.forEach((node, offset) => {
|
|
440
|
+
const pos = cellPos + 1 + offset;
|
|
441
|
+
if (pos < pastedFrom && node.type.name === "paragraph" && node.content.size === 0 && isCurrentAuthorParagraphInsertion(node.attrs["pPrMark"], pluginState.author)) emptyInsertions.push({
|
|
442
|
+
from: pos,
|
|
443
|
+
to: pos + node.nodeSize
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
const retraction = tr.mapping.maps.length;
|
|
447
|
+
for (const range of emptyInsertions.toReversed()) tr.delete(range.from, range.to);
|
|
448
|
+
const retracted = tr.mapping.slice(retraction);
|
|
449
|
+
pastedFrom = retracted.map(pastedFrom);
|
|
450
|
+
insertTo = retracted.map(insertTo);
|
|
376
451
|
enclosePastedRunRevisions({
|
|
377
452
|
tr,
|
|
378
|
-
from:
|
|
453
|
+
from: pastedFrom,
|
|
379
454
|
to: insertTo,
|
|
380
455
|
revision
|
|
381
456
|
});
|
|
382
|
-
markRangeAsInserted(tr, tr.doc,
|
|
383
|
-
tr.doc.nodesBetween(
|
|
384
|
-
if (node.type.name === "paragraph" && pos >=
|
|
457
|
+
markRangeAsInserted(tr, tr.doc, pastedFrom, insertTo, insertionType, deletionType, revision);
|
|
458
|
+
tr.doc.nodesBetween(pastedFrom, insertTo, (node, pos) => {
|
|
459
|
+
if (node.type.name === "paragraph" && pos >= pastedFrom && pos + node.nodeSize <= insertTo && node.attrs["pPrMark"] == null) tr.setNodeAttribute(pos, "pPrMark", {
|
|
385
460
|
kind: "ins",
|
|
386
461
|
info: {
|
|
387
462
|
id: revision.revisionId,
|
|
@@ -452,7 +527,9 @@ function applySuggestionInsert(view, from, to, text, pluginState) {
|
|
|
452
527
|
const tr = view.state.tr;
|
|
453
528
|
tr.setMeta(SUGGESTION_META, true);
|
|
454
529
|
tr.setMeta(SUGGESTED_TEXT_INPUT_META, text);
|
|
455
|
-
const
|
|
530
|
+
const { selection } = view.state;
|
|
531
|
+
const typesOverSelection = !selection.empty && selection.from === from && selection.to === to;
|
|
532
|
+
const selectsAll = selection instanceof AllSelection;
|
|
456
533
|
if (selectsAll) {
|
|
457
534
|
from = Math.max(from, Selection.atStart(view.state.doc).from);
|
|
458
535
|
to = Math.min(to, Selection.atEnd(view.state.doc).to);
|
|
@@ -473,7 +550,7 @@ function applySuggestionInsert(view, from, to, text, pluginState) {
|
|
|
473
550
|
for (const mark of replacedFormatting) tr.addMark(insertAt, insertAt + text.length, mark);
|
|
474
551
|
}
|
|
475
552
|
separateSplitStretch(tr, insertAt, insertAt + text.length, insertAttrs.revisionId);
|
|
476
|
-
if (
|
|
553
|
+
if (typesOverSelection) tr.setSelection(TextSelection.create(tr.doc, insertAt + text.length));
|
|
477
554
|
view.dispatch(tr.scrollIntoView());
|
|
478
555
|
return true;
|
|
479
556
|
}
|
|
@@ -533,15 +610,38 @@ function suggestRangeDeletion(state, tr, from, to) {
|
|
|
533
610
|
* prior author's revision must not be silently overwritten.
|
|
534
611
|
*/
|
|
535
612
|
function handleSuggestionEnter(view, pluginState) {
|
|
536
|
-
const
|
|
537
|
-
if (
|
|
613
|
+
const state = view.state;
|
|
614
|
+
if (state.selection.$from.parent.type.name !== "paragraph") return false;
|
|
615
|
+
const replacement = { tr: null };
|
|
616
|
+
let splitState = state;
|
|
617
|
+
if (state.selection instanceof TextSelection && !state.selection.empty) {
|
|
618
|
+
if (!handleSuggestionDelete(state, (tr) => {
|
|
619
|
+
replacement.tr = tr;
|
|
620
|
+
const styles = documentStylesKey.get(state);
|
|
621
|
+
const plugins = [];
|
|
622
|
+
if (styles) {
|
|
623
|
+
const spec = { ...styles.spec };
|
|
624
|
+
delete spec.appendTransaction;
|
|
625
|
+
delete spec.filterTransaction;
|
|
626
|
+
plugins.push(new Plugin(spec));
|
|
627
|
+
}
|
|
628
|
+
splitState = state.reconfigure({ plugins }).apply(tr);
|
|
629
|
+
}, "forward")) return false;
|
|
630
|
+
}
|
|
631
|
+
const { $from } = splitState.selection;
|
|
538
632
|
const sourcePos = $from.before();
|
|
539
633
|
const sourceAttrs = $from.parent.attrs;
|
|
540
634
|
const captured = { tr: null };
|
|
541
|
-
if (!splitBlockClearBorders(
|
|
635
|
+
if (!splitBlockClearBorders(splitState, (tr) => {
|
|
542
636
|
captured.tr = tr;
|
|
543
637
|
}, view) || !captured.tr) return false;
|
|
544
|
-
const tr = captured.tr;
|
|
638
|
+
const tr = replacement.tr ?? captured.tr;
|
|
639
|
+
if (replacement.tr) {
|
|
640
|
+
for (const step of captured.tr.steps) tr.step(step);
|
|
641
|
+
tr.setSelection(captured.tr.selection.getBookmark().resolve(tr.doc));
|
|
642
|
+
tr.setStoredMarks(captured.tr.storedMarks);
|
|
643
|
+
}
|
|
644
|
+
tr.setMeta(SUGGESTION_META, true);
|
|
545
645
|
if (sourceAttrs["pPrMark"] == null) {
|
|
546
646
|
if (tr.doc.nodeAt(sourcePos)?.type.name === "paragraph") {
|
|
547
647
|
const markInfo = {
|
|
@@ -561,6 +661,24 @@ function handleSuggestionEnter(view, pluginState) {
|
|
|
561
661
|
view.dispatch(tr.scrollIntoView());
|
|
562
662
|
return true;
|
|
563
663
|
}
|
|
664
|
+
/** Find the adjacent visible unit without consuming a bookmark range marker. */
|
|
665
|
+
function caretDeleteTarget(state, direction) {
|
|
666
|
+
const { $from } = state.selection;
|
|
667
|
+
const backward = direction === "backward";
|
|
668
|
+
let from = backward ? $from.pos - 1 : $from.pos;
|
|
669
|
+
let to = backward ? $from.pos : $from.pos + 1;
|
|
670
|
+
while (from >= $from.start() && to <= $from.end()) {
|
|
671
|
+
const adjacent = state.doc.resolve(from).nodeAfter;
|
|
672
|
+
if (adjacent?.type.name !== "bookmarkBoundary") return {
|
|
673
|
+
type: "inlineUnit",
|
|
674
|
+
from,
|
|
675
|
+
to
|
|
676
|
+
};
|
|
677
|
+
from += backward ? -adjacent.nodeSize : adjacent.nodeSize;
|
|
678
|
+
to += backward ? -adjacent.nodeSize : adjacent.nodeSize;
|
|
679
|
+
}
|
|
680
|
+
return { type: "paragraphEdge" };
|
|
681
|
+
}
|
|
564
682
|
/**
|
|
565
683
|
* Detect a caret-at-paragraph-boundary scenario where Backspace/Delete should
|
|
566
684
|
* record a tracked paragraph-mark deletion instead of joining paragraphs.
|
|
@@ -572,8 +690,8 @@ function handleSuggestionEnter(view, pluginState) {
|
|
|
572
690
|
* - Delete-at-paragraph-end → current paragraph.
|
|
573
691
|
*
|
|
574
692
|
* Returns `null` when there is no adjacent sibling paragraph (the join would
|
|
575
|
-
* not produce paragraph-mark merging
|
|
576
|
-
*
|
|
693
|
+
* not produce paragraph-mark merging, e.g. doc start, doc end, or a table).
|
|
694
|
+
* Bookmark markers at an edge do not hide the adjacent paragraph break.
|
|
577
695
|
*/
|
|
578
696
|
function paragraphBoundaryTarget(state, direction) {
|
|
579
697
|
const { $from, empty } = state.selection;
|
|
@@ -581,14 +699,13 @@ function paragraphBoundaryTarget(state, direction) {
|
|
|
581
699
|
if ($from.parent.type.name !== "paragraph") return null;
|
|
582
700
|
const paragraphStart = $from.before();
|
|
583
701
|
const paragraphEnd = $from.after();
|
|
702
|
+
if (caretDeleteTarget(state, direction).type !== "paragraphEdge") return null;
|
|
584
703
|
if (direction === "backward") {
|
|
585
|
-
if ($from.parentOffset !== 0) return null;
|
|
586
704
|
if (paragraphStart === 0) return null;
|
|
587
705
|
const prev = state.doc.resolve(paragraphStart).nodeBefore;
|
|
588
706
|
if (!prev || prev.type.name !== "paragraph") return null;
|
|
589
707
|
return paragraphStart - prev.nodeSize;
|
|
590
708
|
}
|
|
591
|
-
if ($from.parentOffset !== $from.parent.content.size) return null;
|
|
592
709
|
if (paragraphEnd >= state.doc.content.size) return null;
|
|
593
710
|
const next = state.doc.resolve(paragraphEnd).nodeAfter;
|
|
594
711
|
if (!next || next.type.name !== "paragraph") return null;
|
|
@@ -612,7 +729,13 @@ function applyPPrDel(view, targetParagraphPos, pluginState) {
|
|
|
612
729
|
const joined = view.state.doc.nodeAt(joinPos);
|
|
613
730
|
try {
|
|
614
731
|
tr.join(joinPos);
|
|
615
|
-
tr.setNodeAttribute(targetParagraphPos, "pPrMark", null);
|
|
732
|
+
tr.setNodeAttribute(targetParagraphPos, "pPrMark", joined?.type === targetNode.type ? expectParagraphAttrs(joined).pPrMark : null);
|
|
733
|
+
if (joined?.type === targetNode.type) recordReplacedParagraphProperties({
|
|
734
|
+
tr,
|
|
735
|
+
position: targetParagraphPos,
|
|
736
|
+
replaced: joined,
|
|
737
|
+
revision: existingMark.info
|
|
738
|
+
});
|
|
616
739
|
const styleResolver = getDocumentStyleResolver(view.state);
|
|
617
740
|
if (styleResolver && joined?.type === targetNode.type && joined.content.size > 0) rebaseParagraphRuns({
|
|
618
741
|
previousContext: paragraphRunStyleContext(joined, styleResolver),
|
|
@@ -671,15 +794,28 @@ function handleSuggestionDelete(state, dispatch, direction) {
|
|
|
671
794
|
to: rangeTo.pos
|
|
672
795
|
}).sort((a, b) => b.from - a.from);
|
|
673
796
|
for (const { from, to } of ranges) markRangeAsDeleted(tr, state.doc, from, to, insertionType, deletionType, pluginState, state);
|
|
674
|
-
|
|
675
|
-
|
|
797
|
+
if (state.selection instanceof CellSelection) tr.setSelection(state.selection.map(tr.doc, tr.mapping));
|
|
798
|
+
else {
|
|
799
|
+
const cursorPos = tr.mapping.map($to.pos);
|
|
800
|
+
tr.setSelection(TextSelection.near(tr.doc.resolve(cursorPos)));
|
|
801
|
+
}
|
|
676
802
|
dispatch(tr.scrollIntoView());
|
|
677
803
|
return true;
|
|
678
804
|
}
|
|
679
805
|
const isBackward = direction === "backward";
|
|
680
|
-
const
|
|
681
|
-
|
|
682
|
-
|
|
806
|
+
const target = caretDeleteTarget(state, direction);
|
|
807
|
+
if (target.type === "paragraphEdge") {
|
|
808
|
+
const edge = isBackward ? $from.start() : $from.end();
|
|
809
|
+
if ($from.pos === edge) return false;
|
|
810
|
+
const virtual = EditorState.create({
|
|
811
|
+
doc: state.doc,
|
|
812
|
+
selection: TextSelection.create(state.doc, edge)
|
|
813
|
+
});
|
|
814
|
+
if ((isBackward ? joinBackward : joinForward)(virtual, dispatch)) return true;
|
|
815
|
+
return (isBackward ? selectNodeBackward : selectNodeForward)(virtual, dispatch);
|
|
816
|
+
}
|
|
817
|
+
const deletePos = target.from;
|
|
818
|
+
const deleteEnd = target.to;
|
|
683
819
|
const noteRange = expandNoteReferenceDeletionRange(state.doc, deletePos, deleteEnd);
|
|
684
820
|
const rangeFrom = noteRange?.from ?? deletePos;
|
|
685
821
|
const rangeTo = noteRange?.to ?? deleteEnd;
|
|
@@ -701,19 +837,7 @@ function handleSuggestionDelete(state, dispatch, direction) {
|
|
|
701
837
|
}
|
|
702
838
|
/** Apply the editor's selected-content deletion path for a host cut action. */
|
|
703
839
|
const deleteSelectionAsSuggestion = (state, dispatch) => state.selection.empty ? false : handleSuggestionDelete(state, dispatch, "forward");
|
|
704
|
-
|
|
705
|
-
* Mark the text committed by an IME composition as a tracked insertion.
|
|
706
|
-
*
|
|
707
|
-
* Invoked from `compositionend` (deferred to a microtask) rather than from the
|
|
708
|
-
* `appendTransaction` catch-all. ProseMirror commits composed text as part of
|
|
709
|
-
* its own composition-end flush; adding the insertion mark *synchronously*
|
|
710
|
-
* during that flush re-wraps the very text node the IME just finalized, which
|
|
711
|
-
* corrupts CJK (Japanese / Chinese / Korean) input — characters duplicate or
|
|
712
|
-
* garble. Running one tick later, after the composition has settled, wraps the
|
|
713
|
-
* committed range safely. `markRangeAsInserted` skips nodes that already carry a
|
|
714
|
-
* tracked-change mark, so this is idempotent. eigenpal/docx-editor#938.
|
|
715
|
-
*/
|
|
716
|
-
function markComposedAsInsertion(view, from, pluginState, replaced) {
|
|
840
|
+
function markComposedAsInsertion({ view, from, pluginState, replaced, compositionId }) {
|
|
717
841
|
const insertionType = view.state.schema.marks["insertion"];
|
|
718
842
|
const deletionType = view.state.schema.marks["deletion"];
|
|
719
843
|
if (!insertionType || !deletionType) return;
|
|
@@ -721,9 +845,16 @@ function markComposedAsInsertion(view, from, pluginState, replaced) {
|
|
|
721
845
|
if (to <= from && !replaced) return;
|
|
722
846
|
const tr = view.state.tr;
|
|
723
847
|
tr.setMeta(SUGGESTION_META, true);
|
|
848
|
+
if (compositionId !== null) tr.setMeta("composition", compositionId);
|
|
724
849
|
if (replaced) {
|
|
725
|
-
tr.
|
|
726
|
-
markRangeAsDeleted(tr, tr.doc, from,
|
|
850
|
+
tr.replaceRange(from, from, replaced);
|
|
851
|
+
markRangeAsDeleted(tr, tr.doc, from, tr.mapping.map(from, 1), insertionType, deletionType, pluginState);
|
|
852
|
+
const restoredEnd = tr.doc.resolve(tr.mapping.map(from, 1));
|
|
853
|
+
const restoredStart = tr.doc.resolve(from);
|
|
854
|
+
if (restoredStart.parent.type.name === "paragraph" && restoredEnd.parent.type.name === "paragraph" && restoredStart.parent !== restoredEnd.parent) {
|
|
855
|
+
const mark = expectParagraphAttrs(restoredStart.parent).pPrMark;
|
|
856
|
+
if (mark?.kind === "del") carryIntoParagraphLeft(view.state, tr, view.state.doc.resolve(from).parent, restoredEnd.before(), mark.info);
|
|
857
|
+
}
|
|
727
858
|
}
|
|
728
859
|
const insertionFrom = tr.mapping.map(from, 1);
|
|
729
860
|
const insertionTo = tr.mapping.map(to, 1);
|
|
@@ -766,6 +897,38 @@ function recordSplitParagraph(tr, before, step, insertedFrom, insertedTo, attrs)
|
|
|
766
897
|
});
|
|
767
898
|
}
|
|
768
899
|
/**
|
|
900
|
+
* The inline content a step removed from within one textblock, and where it
|
|
901
|
+
* started: the node a node selection held (an image, a field, a note
|
|
902
|
+
* reference) or a range of runs. Null for a step that removed nothing, or removed paragraph or table
|
|
903
|
+
* structure the catch-all cannot put back.
|
|
904
|
+
*/
|
|
905
|
+
function replacedInline(before, step) {
|
|
906
|
+
if (!(step instanceof ReplaceStep) || !before || step.from === step.to) return null;
|
|
907
|
+
const $from = before.resolve(step.from);
|
|
908
|
+
if (!$from.parent.inlineContent || !$from.sameParent(before.resolve(step.to))) return null;
|
|
909
|
+
return {
|
|
910
|
+
from: step.from,
|
|
911
|
+
content: $from.parent.content.cut($from.parentOffset, step.to - $from.start())
|
|
912
|
+
};
|
|
913
|
+
}
|
|
914
|
+
/**
|
|
915
|
+
* A transaction the plugin did not build (a command, a default paste, a
|
|
916
|
+
* keymap) replaced inline content directly. Put it back in front of what
|
|
917
|
+
* replaced it as a tracked deletion, as typing over a selection does, so
|
|
918
|
+
* rejecting restores it and accepting removes it. The author's own
|
|
919
|
+
* insertions are retracted instead.
|
|
920
|
+
*/
|
|
921
|
+
function restoreReplacedInline({ tr, replaced, insertionType, deletionType, pluginState }) {
|
|
922
|
+
for (const { at, content } of replaced) {
|
|
923
|
+
const pos = tr.mapping.map(at, -1);
|
|
924
|
+
const $pos = tr.doc.resolve(pos);
|
|
925
|
+
const index = $pos.index();
|
|
926
|
+
if (!$pos.parent.canReplace(index, index, content)) continue;
|
|
927
|
+
tr.insert(pos, content);
|
|
928
|
+
markRangeAsDeleted(tr, tr.doc, pos, pos + content.size, insertionType, deletionType, pluginState);
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
/**
|
|
769
932
|
* Create the suggestion mode plugin.
|
|
770
933
|
* When active, text edits become tracked changes.
|
|
771
934
|
*/
|
|
@@ -773,6 +936,7 @@ function createSuggestionModePlugin(initialActive = false, author = "User") {
|
|
|
773
936
|
let composing = false;
|
|
774
937
|
let compositionFrom = null;
|
|
775
938
|
let compositionReplaced = null;
|
|
939
|
+
let compositionId = null;
|
|
776
940
|
return new Plugin({
|
|
777
941
|
key: suggestionModeKey,
|
|
778
942
|
state: {
|
|
@@ -784,6 +948,8 @@ function createSuggestionModePlugin(initialActive = false, author = "User") {
|
|
|
784
948
|
};
|
|
785
949
|
},
|
|
786
950
|
apply(tr, state) {
|
|
951
|
+
const nativeCompositionId = tr.getMeta("composition");
|
|
952
|
+
if (composing && tr.docChanged && typeof nativeCompositionId === "number") compositionId = nativeCompositionId;
|
|
787
953
|
const meta = tr.getMeta(suggestionModeKey);
|
|
788
954
|
if (meta) return {
|
|
789
955
|
...state,
|
|
@@ -809,6 +975,7 @@ function createSuggestionModePlugin(initialActive = false, author = "User") {
|
|
|
809
975
|
if (!suggestionModeKey.getState(view.state)?.active) return false;
|
|
810
976
|
if (composing) return false;
|
|
811
977
|
composing = true;
|
|
978
|
+
compositionId = null;
|
|
812
979
|
const { from, to } = view.state.selection;
|
|
813
980
|
compositionFrom = from;
|
|
814
981
|
compositionReplaced = from === to ? null : view.state.doc.slice(from, to);
|
|
@@ -822,14 +989,23 @@ function createSuggestionModePlugin(initialActive = false, author = "User") {
|
|
|
822
989
|
compositionReplaced = null;
|
|
823
990
|
if (!pluginState?.active || from == null) {
|
|
824
991
|
composing = false;
|
|
992
|
+
compositionId = null;
|
|
825
993
|
return false;
|
|
826
994
|
}
|
|
827
|
-
|
|
995
|
+
afterNativeCompositionFlush(() => {
|
|
828
996
|
try {
|
|
829
997
|
const current = suggestionModeKey.getState(view.state);
|
|
830
|
-
|
|
998
|
+
const nativeCompositionId = compositionId;
|
|
999
|
+
if (current?.active) markComposedAsInsertion({
|
|
1000
|
+
view,
|
|
1001
|
+
from,
|
|
1002
|
+
pluginState: current,
|
|
1003
|
+
replaced,
|
|
1004
|
+
compositionId: nativeCompositionId
|
|
1005
|
+
});
|
|
831
1006
|
} finally {
|
|
832
1007
|
composing = false;
|
|
1008
|
+
compositionId = null;
|
|
833
1009
|
}
|
|
834
1010
|
});
|
|
835
1011
|
return false;
|
|
@@ -851,6 +1027,20 @@ function createSuggestionModePlugin(initialActive = false, author = "User") {
|
|
|
851
1027
|
if (event.key === "Backspace" || event.key === "Delete") {
|
|
852
1028
|
const { $from, empty } = view.state.selection;
|
|
853
1029
|
if (event.key === "Backspace" && empty && $from.parentOffset === 0 && $from.parent.type.name === "paragraph" && expectParagraphAttrs($from.parent).numPr?.kind === "reference") return false;
|
|
1030
|
+
if (event.key === "Backspace" && clearIndentOnBackspace(view.state, (tr) => {
|
|
1031
|
+
const revision = makeMarkAttrs(pluginState);
|
|
1032
|
+
recordReplacedParagraphProperties({
|
|
1033
|
+
tr,
|
|
1034
|
+
position: $from.before(),
|
|
1035
|
+
replaced: $from.parent,
|
|
1036
|
+
revision: {
|
|
1037
|
+
id: revision.revisionId,
|
|
1038
|
+
author: revision.author,
|
|
1039
|
+
date: revision.date
|
|
1040
|
+
}
|
|
1041
|
+
});
|
|
1042
|
+
view.dispatch(tr.setMeta("suggestionModeApplied", true));
|
|
1043
|
+
})) return true;
|
|
854
1044
|
const boundaryTarget = paragraphBoundaryTarget(view.state, event.key === "Backspace" ? "backward" : "forward");
|
|
855
1045
|
if (boundaryTarget !== null) return applyPPrDel(view, boundaryTarget, pluginState);
|
|
856
1046
|
const direction = event.key === "Backspace" ? "backward" : "forward";
|
|
@@ -883,9 +1073,16 @@ function createSuggestionModePlugin(initialActive = false, author = "User") {
|
|
|
883
1073
|
tr.setMeta(SUGGESTION_META, true);
|
|
884
1074
|
const deletionType = newState.schema.marks["deletion"];
|
|
885
1075
|
const laterMaps = transactions.slice(transactions.indexOf(userTr) + 1).flatMap((transaction) => transaction.mapping.maps);
|
|
1076
|
+
const restoresReplaced = userTr.getMeta("appendedTransaction") === void 0;
|
|
1077
|
+
const replaced = [];
|
|
886
1078
|
for (const [stepIndex, step] of userTr.steps.entries()) {
|
|
887
1079
|
const stepMap = step.getMap();
|
|
888
1080
|
const following = new Mapping([...userTr.mapping.maps.slice(stepIndex + 1), ...laterMaps]);
|
|
1081
|
+
const removed = restoresReplaced ? replacedInline(userTr.docs[stepIndex], step) : null;
|
|
1082
|
+
if (removed) replaced.push({
|
|
1083
|
+
at: following.map(removed.from, -1),
|
|
1084
|
+
content: removed.content
|
|
1085
|
+
});
|
|
889
1086
|
stepMap.forEach((_oldFrom, _oldTo, stepFrom, stepTo) => {
|
|
890
1087
|
const newFrom = following.map(stepFrom, -1);
|
|
891
1088
|
const newTo = following.map(stepTo, 1);
|
|
@@ -901,6 +1098,13 @@ function createSuggestionModePlugin(initialActive = false, author = "User") {
|
|
|
901
1098
|
}
|
|
902
1099
|
});
|
|
903
1100
|
}
|
|
1101
|
+
if (deletionType) restoreReplacedInline({
|
|
1102
|
+
tr,
|
|
1103
|
+
replaced,
|
|
1104
|
+
insertionType,
|
|
1105
|
+
deletionType,
|
|
1106
|
+
pluginState
|
|
1107
|
+
});
|
|
904
1108
|
return tr.steps.length > 0 ? tr : null;
|
|
905
1109
|
}
|
|
906
1110
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { ReadProseMirrorAttrsResult } from "
|
|
1
|
+
import { ReadProseMirrorAttrsResult } from "../internal/prosemirrorAttrBoundary.js";
|
|
2
|
+
import "./attrs/index.js";
|
|
2
3
|
import { RangeAnchorAttrs } from "./emptyRangeAnchor.js";
|
|
3
4
|
import { Node } from "prosemirror-model";
|
|
4
5
|
//#region src/prosemirror/rangeAnchorAttrs.d.ts
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
2
|
import { RunStyleResolver } from "./runStyleFormatting.js";
|
|
3
3
|
import { Mark } from "prosemirror-model";
|
|
4
|
+
import { RunPropsPatch } from "@stll/docx-core/ops";
|
|
4
5
|
//#region src/prosemirror/runFormattingFromMarks.d.ts
|
|
5
6
|
/**
|
|
6
7
|
* Convert ProseMirror marks to TextFormatting
|
|
@@ -12,7 +13,9 @@ type MarksToTextFormattingOptions = {
|
|
|
12
13
|
paragraphMarkPrecedesStyle?: boolean | undefined;
|
|
13
14
|
styleResolver?: RunStyleResolver | null | undefined;
|
|
14
15
|
};
|
|
16
|
+
/** Overlay only changed visual marks; private authored properties stay with the run. */
|
|
17
|
+
declare const runFormattingPatchFromMarks: (beforeMarks: readonly Mark[], afterMarks: readonly Mark[]) => RunPropsPatch;
|
|
15
18
|
declare const sameFormattingValue: (left: unknown, right: unknown) => boolean;
|
|
16
19
|
declare function marksToTextFormatting(marks: readonly Mark[], options?: MarksToTextFormattingOptions): document_d_exports.TextFormatting;
|
|
17
20
|
//#endregion
|
|
18
|
-
export { MarksToTextFormattingOptions, marksToTextFormatting, sameFormattingValue };
|
|
21
|
+
export { MarksToTextFormattingOptions, marksToTextFormatting, runFormattingPatchFromMarks, sameFormattingValue };
|
|
@@ -203,6 +203,20 @@ const changedVisualFormattingGroups = (observedFormatting, expectedFormatting) =
|
|
|
203
203
|
}
|
|
204
204
|
return changed;
|
|
205
205
|
};
|
|
206
|
+
/** Overlay only changed visual marks; private authored properties stay with the run. */
|
|
207
|
+
const runFormattingPatchFromMarks = (beforeMarks, afterMarks) => {
|
|
208
|
+
const observedMarks = (marks) => marks.filter(({ type }) => type.name !== "runFormattingOverride");
|
|
209
|
+
const before = marksToTextFormatting(observedMarks(beforeMarks));
|
|
210
|
+
const after = marksToTextFormatting(observedMarks(afterMarks));
|
|
211
|
+
const changed = changedVisualFormattingGroups(after, before);
|
|
212
|
+
const patch = before.styleId === after.styleId ? {} : { styleId: after.styleId ?? null };
|
|
213
|
+
const isFormattingKey = (key) => Object.hasOwn(RUN_FORMATTING_VISUAL_GROUPS, key);
|
|
214
|
+
for (const [key, group] of Object.entries(RUN_FORMATTING_VISUAL_GROUPS)) {
|
|
215
|
+
if (!isFormattingKey(key) || group === null || !changed.has(group)) continue;
|
|
216
|
+
Reflect.set(patch, key, after[key] ?? null);
|
|
217
|
+
}
|
|
218
|
+
return patch;
|
|
219
|
+
};
|
|
206
220
|
const VISUAL_BOOLEAN_FORMATTING_PROPERTIES = /* @__PURE__ */ new Set([
|
|
207
221
|
"allCaps",
|
|
208
222
|
"bold",
|
|
@@ -564,4 +578,4 @@ function marksToTextFormatting(marks, options) {
|
|
|
564
578
|
};
|
|
565
579
|
}
|
|
566
580
|
//#endregion
|
|
567
|
-
export { marksToTextFormatting, sameFormattingValue };
|
|
581
|
+
export { marksToTextFormatting, runFormattingPatchFromMarks, sameFormattingValue };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Mark, Node } from "prosemirror-model";
|
|
2
2
|
import { Transaction } from "prosemirror-state";
|
|
3
3
|
//#region src/prosemirror/runFormattingInlineCarriers.d.ts
|
|
4
|
-
type RunFormattingInlineAtomDisposition = "break-run" | "field-run" | "not-a-run" | "page-break-carrier" | "preserved-xml-run" | "structured-field" | "symbol-run" | "tab-run" | "text-run";
|
|
4
|
+
type RunFormattingInlineAtomDisposition = "break-run" | "field-run" | "not-a-run" | "note-marker-run" | "page-break-carrier" | "preserved-xml-run" | "structured-field" | "symbol-run" | "tab-run" | "text-run";
|
|
5
5
|
/**
|
|
6
6
|
* How every inline atom maps to a serialized run-formatting carrier.
|
|
7
7
|
*
|
|
@@ -18,6 +18,7 @@ declare const RUN_FORMATTING_INLINE_ATOM_DISPOSITIONS: Readonly<{
|
|
|
18
18
|
readonly image: "not-a-run";
|
|
19
19
|
readonly math: "not-a-run";
|
|
20
20
|
readonly moveRangeBoundary: "not-a-run";
|
|
21
|
+
readonly noteMarker: "note-marker-run";
|
|
21
22
|
readonly pageBreakRun: "page-break-carrier";
|
|
22
23
|
readonly preservedXml: "preserved-xml-run";
|
|
23
24
|
readonly rangeAnchor: "not-a-run";
|
|
@@ -20,6 +20,7 @@ const RUN_FORMATTING_INLINE_ATOM_DISPOSITIONS = Object.freeze({
|
|
|
20
20
|
image: "not-a-run",
|
|
21
21
|
math: "not-a-run",
|
|
22
22
|
moveRangeBoundary: "not-a-run",
|
|
23
|
+
noteMarker: "note-marker-run",
|
|
23
24
|
pageBreakRun: "page-break-carrier",
|
|
24
25
|
preservedXml: "preserved-xml-run",
|
|
25
26
|
rangeAnchor: "not-a-run",
|
|
@@ -52,6 +53,7 @@ const CONTROL_CHARACTER_BY_DISPOSITION = Object.freeze({
|
|
|
52
53
|
"break-run": "\n",
|
|
53
54
|
"field-run": null,
|
|
54
55
|
"not-a-run": null,
|
|
56
|
+
"note-marker-run": null,
|
|
55
57
|
"page-break-carrier": null,
|
|
56
58
|
"preserved-xml-run": null,
|
|
57
59
|
"structured-field": null,
|
|
@@ -179,7 +181,8 @@ const runFormattingCarrierReviewText = (carrier) => {
|
|
|
179
181
|
case "tab-run":
|
|
180
182
|
case "break-run": return CONTROL_CHARACTER_BY_DISPOSITION[carrier.disposition];
|
|
181
183
|
case "text-run": return carrier.node.text ?? "";
|
|
182
|
-
case "page-break-carrier":
|
|
184
|
+
case "page-break-carrier":
|
|
185
|
+
case "note-marker-run": return "";
|
|
183
186
|
case "symbol-run": {
|
|
184
187
|
const { char } = expectSymbolAttrs(carrier.node);
|
|
185
188
|
return decodeOoxmlSymbolCharacter(char) ?? "�";
|
|
@@ -107,6 +107,7 @@ type TrackedRevisionAncestor = {
|
|
|
107
107
|
utcDate?: string;
|
|
108
108
|
initials?: string;
|
|
109
109
|
outerWrapperCount: number;
|
|
110
|
+
resolutionJoins?: document_d_exports.Insertion["resolutionJoins"];
|
|
110
111
|
};
|
|
111
112
|
type TrackedChangeMarkAttrs = {
|
|
112
113
|
revisionId: number;
|
|
@@ -119,6 +120,7 @@ type TrackedChangeMarkAttrs = {
|
|
|
119
120
|
moveKind?: "moveTo" | "moveFrom";
|
|
120
121
|
/** Number of inline-wrapper layers authored outside this revision. */
|
|
121
122
|
_docxOuterWrapperCount?: number;
|
|
123
|
+
_docxResolutionJoins?: document_d_exports.Insertion["resolutionJoins"];
|
|
122
124
|
/** Outer revisions, in authored order, that ProseMirror cannot hold as nested marks. */
|
|
123
125
|
_docxRevisionAncestors?: readonly TrackedRevisionAncestor[];
|
|
124
126
|
/** Defaults to `"user"`; `"suggested"` for AI-proposed, non-serialized edits. */
|
|
@@ -44,6 +44,10 @@ declare const PRESERVED_XML_LEVELS: {
|
|
|
44
44
|
readonly inline: "inline";
|
|
45
45
|
};
|
|
46
46
|
type PreservedXmlLevel = (typeof PRESERVED_XML_LEVELS)[keyof typeof PRESERVED_XML_LEVELS];
|
|
47
|
+
/** The automatic number mark authored inside a note story, with no reader text. */
|
|
48
|
+
type NoteMarkerAttrs = {
|
|
49
|
+
kind: "footnote" | "endnote";
|
|
50
|
+
};
|
|
47
51
|
/** A run or inline child folio does not model, carried through the editor untouched. */
|
|
48
52
|
type PreservedXmlAttrs = {
|
|
49
53
|
/** Replayable markup, as `captureVerbatimXml` wrote it. */
|
|
@@ -51,6 +55,8 @@ type PreservedXmlAttrs = {
|
|
|
51
55
|
/** The visible text the markup puts on the line, empty when it shows none. */
|
|
52
56
|
text: string;
|
|
53
57
|
level: PreservedXmlLevel;
|
|
58
|
+
/** `PreservedInline.foldedListNumber`, for a capture the list marker stands in for. */
|
|
59
|
+
foldedListNumber?: document_d_exports.FoldedListNumber;
|
|
54
60
|
};
|
|
55
61
|
/** A block child folio does not model, carried through the editor untouched. */
|
|
56
62
|
type PreservedBlockAttrs = {
|
|
@@ -166,6 +172,8 @@ type ParagraphAttrs = {
|
|
|
166
172
|
* next marker letter.
|
|
167
173
|
*/
|
|
168
174
|
listImplicitChildLevelAdvances?: number;
|
|
175
|
+
/** Cached inline LISTNUM display text appended after the resolved list template. */
|
|
176
|
+
listFoldedMarkerSuffix?: string;
|
|
169
177
|
/**
|
|
170
178
|
* When the marker text contains a TAB separator, this column offset (in
|
|
171
179
|
* twips) is where the slot after the tab should land — used to align an
|
|
@@ -338,7 +346,7 @@ type ParagraphPropertyChangeAttrs = Omit<document_d_exports.ParagraphPropertyCha
|
|
|
338
346
|
};
|
|
339
347
|
previousFormatting?: Omit<document_d_exports.ParagraphFormatting, "numPr"> & {
|
|
340
348
|
numPr?: ParagraphAttrs["numPr"] | null;
|
|
341
|
-
} & Partial<Pick<ParagraphAttrs, "listIsBullet" | "listIsLegal" | "listNumFmt" | "listMarker" | "listMarkerTemplate" | "listMarkerHidden" | "listMarkerFormatting" | "listMarkerAlignment" | "listMarkerSuffix" | "listMarkerAllCaps" | "listImplicitChildLevelAdvances" | "listMarkerSecondSlotOffsetTwips" | "listLevelNumFmts" | "listLevelStarts" | "listLevelTabs" | "listAbstractNumId" | "listStartOverride" | "lineSpacingExplicit" | "direction" | "_autospacingBase">>;
|
|
349
|
+
} & Partial<Pick<ParagraphAttrs, "listIsBullet" | "listIsLegal" | "listNumFmt" | "listMarker" | "listMarkerTemplate" | "listMarkerHidden" | "listMarkerFormatting" | "listMarkerAlignment" | "listMarkerSuffix" | "listMarkerAllCaps" | "listImplicitChildLevelAdvances" | "listFoldedMarkerSuffix" | "listMarkerSecondSlotOffsetTwips" | "listLevelNumFmts" | "listLevelStarts" | "listLevelTabs" | "listAbstractNumId" | "listStartOverride" | "lineSpacingExplicit" | "direction" | "_autospacingBase">>;
|
|
342
350
|
currentFormatting?: document_d_exports.ParagraphFormatting;
|
|
343
351
|
};
|
|
344
352
|
/**
|
|
@@ -1258,4 +1266,4 @@ type TableCellAttrs = {
|
|
|
1258
1266
|
_docxVMergeContinuationCells?: unknown;
|
|
1259
1267
|
};
|
|
1260
1268
|
//#endregion
|
|
1261
|
-
export { AlternateContentAttrs, AuthoredEmuAttrs, BlockCustomXmlAttrs, BlockSdtAttrs, BookmarkBoundaryAttrs, CommentReferenceAttrs, FieldAttrs, HardBreakAttrs, ImageAttrs, ImagePositionAttrs, MathAttrs, PRESERVED_XML_LEVELS, PageBreakRunAttrs, ParagraphAttrs, ParagraphAttrsPatch, ParagraphPropertyChangeAttrs, PreservedBlockAttrs, PreservedXmlAttrs, PreservedXmlLevel, SdtAttrs, ShapeAttrs, SuggestedStructuralMarker, SymbolAttrs, TEXT_BOX_TEXT_BODY_CONTENT_STATE_TYPES, TabAttrs, TableAttrs, TableCellAttrs, TableRowAttrs, TextBoxAnchorAttrs, TextBoxAttrs, TextBoxTextBodyContentState };
|
|
1269
|
+
export { AlternateContentAttrs, AuthoredEmuAttrs, BlockCustomXmlAttrs, BlockSdtAttrs, BookmarkBoundaryAttrs, CommentReferenceAttrs, FieldAttrs, HardBreakAttrs, ImageAttrs, ImagePositionAttrs, MathAttrs, NoteMarkerAttrs, PRESERVED_XML_LEVELS, PageBreakRunAttrs, ParagraphAttrs, ParagraphAttrsPatch, ParagraphPropertyChangeAttrs, PreservedBlockAttrs, PreservedXmlAttrs, PreservedXmlLevel, SdtAttrs, ShapeAttrs, SuggestedStructuralMarker, SymbolAttrs, TEXT_BOX_TEXT_BODY_CONTENT_STATE_TYPES, TabAttrs, TableAttrs, TableCellAttrs, TableRowAttrs, TextBoxAnchorAttrs, TextBoxAttrs, TextBoxTextBodyContentState };
|