@stll/folio-core 0.56.0 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-edits/apply.js +45 -14
- package/dist/ai-edits/batch-claims.d.ts +3 -1
- package/dist/ai-edits/batch-claims.js +25 -1
- package/dist/ai-edits/table-row-column-mutations.js +17 -3
- package/dist/ai-suggestions/apply.js +20 -1
- package/dist/compare/inline-atoms.js +40 -16
- package/dist/compare/inline-provenance.js +12 -5
- package/dist/compat/eigenpal.d.ts +2 -1
- package/dist/compat/eigenpal.js +2 -1
- package/dist/controller/canonicalClipboard.js +7 -1
- package/dist/controller/canonicalComments.d.ts +41 -0
- package/dist/controller/canonicalComments.js +152 -0
- package/dist/controller/canonicalComposition.d.ts +4 -0
- package/dist/controller/canonicalComposition.js +43 -11
- package/dist/controller/canonicalInlineProjection.d.ts +6 -1
- package/dist/controller/canonicalInlineProjection.js +86 -3
- package/dist/controller/canonicalInput.js +10 -1
- package/dist/controller/canonicalInputTimer.d.ts +10 -1
- package/dist/controller/canonicalInputTimer.js +24 -1
- package/dist/controller/canonicalPublicOperations.d.ts +2 -2
- package/dist/controller/canonicalPublicOperations.js +107 -15
- package/dist/controller/canonicalSelection.d.ts +18 -0
- package/dist/controller/canonicalSelection.js +32 -0
- package/dist/controller/canonicalSession.d.ts +3 -0
- package/dist/controller/canonicalSession.js +58 -24
- package/dist/controller/canonicalStoryEditor.d.ts +2 -0
- package/dist/controller/canonicalStoryEditor.js +20 -0
- package/dist/controller/folioEditor.js +13 -0
- package/dist/controller/headerFooterEditorManager.d.ts +1 -1
- package/dist/controller/headerFooterEditorManager.js +25 -11
- package/dist/controller/hiddenEditorApi.d.ts +13 -2
- package/dist/controller/hiddenEditorApi.js +4 -0
- package/dist/controller/hiddenEditorManager.d.ts +3 -1
- package/dist/controller/hiddenEditorManager.js +166 -13
- package/dist/controller/noteEditorManager.d.ts +1 -1
- package/dist/controller/noteEditorManager.js +28 -13
- package/dist/docx/builtInStyles.js +13 -6
- package/dist/docx/containerChildren.gen.d.ts +3 -1
- package/dist/docx/containerChildren.gen.js +33 -1
- package/dist/docx/fieldParser.js +14 -2
- package/dist/docx/hyperlinkParser.d.ts +1 -1
- package/dist/docx/hyperlinkParser.js +20 -1
- package/dist/docx/inlineWrapperContent.d.ts +4 -4
- package/dist/docx/inlineWrapperContent.js +4 -4
- package/dist/docx/linkedSdtPreservation.d.ts +10 -0
- package/dist/docx/linkedSdtPreservation.js +37 -0
- package/dist/docx/paragraphParser.js +88 -67
- package/dist/docx/paragraphPropertySource.d.ts +22 -1
- package/dist/docx/paragraphPropertySource.js +107 -1
- package/dist/docx/preservedRunContent.js +2 -1
- package/dist/docx/relsParser.js +26 -2
- package/dist/docx/rezip.js +9 -6
- package/dist/docx/selectiveSave.js +10 -8
- package/dist/docx/serializer/commentSerializer.d.ts +4 -1
- package/dist/docx/serializer/commentSerializer.js +7 -3
- package/dist/docx/serializer/paragraphSerializer.js +207 -94
- package/dist/docx/server/materializeYjsDocx.js +14 -6
- package/dist/docx/server/migrateYjsAttrSchema.js +17 -5
- package/dist/i18n/messages/ar.gen.js +4 -0
- package/dist/i18n/messages/catalogs.gen.d.ts +68 -0
- package/dist/i18n/messages/catalogs.gen.js +68 -0
- package/dist/i18n/messages/cs.gen.js +4 -0
- package/dist/i18n/messages/de.gen.js +4 -0
- package/dist/i18n/messages/en.gen.js +4 -0
- package/dist/i18n/messages/es.gen.js +4 -0
- package/dist/i18n/messages/et.gen.js +4 -0
- package/dist/i18n/messages/fr.gen.js +4 -0
- package/dist/i18n/messages/he.gen.js +4 -0
- package/dist/i18n/messages/hi.gen.js +4 -0
- package/dist/i18n/messages/hu.gen.js +4 -0
- package/dist/i18n/messages/lt.gen.js +4 -0
- package/dist/i18n/messages/lv.gen.js +4 -0
- package/dist/i18n/messages/messages.gen.d.ts +4 -0
- package/dist/i18n/messages/pl.gen.js +4 -0
- package/dist/i18n/messages/pt-BR.gen.js +4 -0
- package/dist/i18n/messages/sk.gen.js +4 -0
- package/dist/i18n/messages/tr.gen.js +4 -0
- package/dist/i18n/messages/zh-CN.gen.js +4 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/internal/revisionResolutionInline.js +25 -3
- package/dist/markdown/renderRuns.js +1 -11
- package/dist/panel-layout.d.ts +11 -9
- package/dist/panel-layout.js +13 -9
- package/dist/prosemirror/addTrackedDeletionMark.d.ts +18 -0
- package/dist/prosemirror/addTrackedDeletionMark.js +87 -0
- package/dist/prosemirror/attrs/index.js +5 -0
- package/dist/prosemirror/commands/comments.js +60 -35
- package/dist/prosemirror/commands/propertyChangeScope.js +3 -6
- package/dist/prosemirror/commands/resolveParagraphProperties.js +22 -13
- package/dist/prosemirror/commentOps.js +15 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +22 -3
- package/dist/prosemirror/conversion/toProseDoc.js +119 -18
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +22 -5
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +74 -25
- package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +11 -0
- package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +22 -14
- package/dist/prosemirror/extensions/marks/markUtils.js +8 -7
- package/dist/prosemirror/extensions/marks/noteReferenceDeletion.js +5 -2
- package/dist/prosemirror/fieldRepresentation.d.ts +8 -0
- package/dist/prosemirror/fieldRepresentation.js +18 -0
- package/dist/prosemirror/hyperlinkRemoval.d.ts +13 -1
- package/dist/prosemirror/hyperlinkRemoval.js +28 -9
- package/dist/prosemirror/listNumbering.js +11 -5
- package/dist/prosemirror/noteReferenceOccurrenceId.d.ts +5 -0
- package/dist/prosemirror/noteReferenceOccurrenceId.js +5 -0
- package/dist/prosemirror/noteReferenceOccurrences.d.ts +21 -0
- package/dist/prosemirror/noteReferenceOccurrences.js +185 -0
- package/dist/prosemirror/noteReferenceReview.js +14 -1
- package/dist/prosemirror/plugins/documentStyles.d.ts +4 -1
- package/dist/prosemirror/plugins/documentStyles.js +17 -10
- package/dist/prosemirror/plugins/suggestionMode.js +47 -49
- package/dist/prosemirror/preservedXmlReview.d.ts +6 -0
- package/dist/prosemirror/preservedXmlReview.js +35 -0
- package/dist/prosemirror/runFormattingFromMarks.js +2 -2
- package/dist/prosemirror/runFormattingReconciliation.js +5 -4
- package/dist/prosemirror/runPropertyChangeResolution.d.ts +8 -1
- package/dist/prosemirror/runPropertyChangeResolution.js +24 -2
- package/dist/prosemirror/runStyleFormatting.d.ts +3 -1
- package/dist/prosemirror/runStyleFormatting.js +3 -1
- package/dist/prosemirror/schema/marks.d.ts +1 -0
- package/dist/prosemirror/schema/nodes.d.ts +2 -0
- package/dist/prosemirror/styles/paragraphStyleCascade.js +4 -1
- package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +15 -15
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +69 -28
- package/dist/prosemirror/textInput.d.ts +5 -1
- package/dist/prosemirror/textInput.js +3 -3
- package/dist/prosemirror/trackedRevisionPath.d.ts +5 -1
- package/dist/prosemirror/trackedRevisionPath.js +39 -1
- package/dist/prosemirror/validation.js +3 -5
- package/dist/prosemirror/yjsDocumentMetadata.d.ts +9 -3
- package/dist/prosemirror/yjsDocumentMetadata.js +37 -8
- package/dist/types/canonicalCapabilities.d.ts +6 -20
- package/dist/types/canonicalCapabilities.js +6 -20
- package/dist/types/canonicalComments.d.ts +51 -0
- package/dist/types/canonicalComments.js +0 -0
- package/dist/types/canonicalSections.d.ts +12 -0
- package/dist/types/canonicalSections.js +0 -0
- package/dist/utils/headingCollector.js +45 -4
- package/dist/utils/outlineDepth.d.ts +9 -0
- package/dist/utils/outlineDepth.js +9 -0
- package/package.json +2 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { addTrackedDeletionMark } from "../addTrackedDeletionMark.js";
|
|
1
2
|
import { expectParagraphAttrs, expectTrackedChangeMarkAttrs } from "../attrs/index.js";
|
|
2
3
|
import { clearIndentOnBackspace } from "../commands/clearParagraphIndent.js";
|
|
3
4
|
import { paragraphPropertiesSnapshot } from "../commands/propertyChangeScope.js";
|
|
@@ -117,20 +118,13 @@ function findAdjacentRevisionForRange(doc, from, to, markTypeName, author) {
|
|
|
117
118
|
* Retract the current author's own inserted text.
|
|
118
119
|
* Processes in reverse order to maintain position validity.
|
|
119
120
|
*/
|
|
120
|
-
function markRangeAsDeleted(tr, doc, from, to,
|
|
121
|
-
|
|
121
|
+
function markRangeAsDeleted(tr, doc, from, to, deletionType, pluginState, joinState) {
|
|
122
|
+
let hasMarkableContent = false;
|
|
122
123
|
doc.nodesBetween(from, to, (node, pos) => {
|
|
123
124
|
if (!canCarryTrackedRunMark(node)) return;
|
|
124
|
-
|
|
125
|
-
const end = Math.min(pos + node.nodeSize, to);
|
|
126
|
-
if (start >= end) return;
|
|
127
|
-
const isOwnInsert = node.marks.some((m) => m.type === insertionType && m.attrs["author"] === pluginState.author);
|
|
125
|
+
if (Math.max(pos, from) >= Math.min(pos + node.nodeSize, to)) return;
|
|
128
126
|
if (node.marks.some((m) => m.type === deletionType)) return;
|
|
129
|
-
|
|
130
|
-
from: start,
|
|
131
|
-
to: end,
|
|
132
|
-
isOwnInsert
|
|
133
|
-
});
|
|
127
|
+
hasMarkableContent = true;
|
|
134
128
|
});
|
|
135
129
|
const delAttrs = findAdjacentRevisionForRange(doc, from, to, "deletion", pluginState.author) || makeMarkAttrs(pluginState);
|
|
136
130
|
let removedMark = false;
|
|
@@ -165,18 +159,20 @@ function markRangeAsDeleted(tr, doc, from, to, insertionType, deletionType, plug
|
|
|
165
159
|
date: delAttrs.date
|
|
166
160
|
});
|
|
167
161
|
}
|
|
168
|
-
if (
|
|
162
|
+
if (!hasMarkableContent) return;
|
|
169
163
|
encloseWholeControls({
|
|
170
164
|
tr,
|
|
171
165
|
from,
|
|
172
166
|
to,
|
|
173
167
|
revisionId: delAttrs.revisionId
|
|
174
168
|
});
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
169
|
+
addTrackedDeletionMark({
|
|
170
|
+
tr,
|
|
171
|
+
from,
|
|
172
|
+
to,
|
|
173
|
+
mark: deletionType.create(delAttrs),
|
|
174
|
+
insertionPolicy: "retract-own"
|
|
175
|
+
});
|
|
180
176
|
}
|
|
181
177
|
/** Preserve clipboard revisions inside the revision that inserted their content. */
|
|
182
178
|
function enclosePastedRunRevisions({ tr, from, to, revision: insertion }) {
|
|
@@ -298,7 +294,7 @@ function handleSuggestionPaste(view, slice, pluginState) {
|
|
|
298
294
|
const endsContainer = wholeBlocks && paragraphEndsItsContainer(doc.resolve($to.before()), $to.parent.type.name);
|
|
299
295
|
const rotates = endsContainer && slice.content.firstChild?.type === $to.parent.type && slice.content.lastChild?.type === $to.parent.type;
|
|
300
296
|
const tableFirst = endsContainer && !rotates;
|
|
301
|
-
if (!tableFirst) markRangeAsDeleted(tr, doc, from, wholeBlocks && !endsContainer ? $to.after() : to,
|
|
297
|
+
if (!tableFirst) markRangeAsDeleted(tr, doc, from, wholeBlocks && !endsContainer ? $to.after() : to, deletionType, pluginState);
|
|
302
298
|
const carryAcross = () => {
|
|
303
299
|
if (selectsAll || $from.parent.type.name !== "paragraph" || $from.parent === $to.parent || from <= $from.start()) return;
|
|
304
300
|
const firstPos = tr.mapping.map($from.before());
|
|
@@ -332,7 +328,7 @@ function handleSuggestionPaste(view, slice, pluginState) {
|
|
|
332
328
|
let insertTo = placed.length === 0 ? at : Math.max(...placed.map((range) => range.to));
|
|
333
329
|
if (tableFirst) {
|
|
334
330
|
const struck = tr.steps.length;
|
|
335
|
-
markRangeAsDeleted(tr, tr.doc, tr.mapping.map(from), tr.mapping.map(to),
|
|
331
|
+
markRangeAsDeleted(tr, tr.doc, tr.mapping.map(from), tr.mapping.map(to), deletionType, pluginState);
|
|
336
332
|
const since = tr.mapping.slice(struck);
|
|
337
333
|
insertFrom = since.map(insertFrom, -1);
|
|
338
334
|
insertTo = since.map(insertTo, -1);
|
|
@@ -405,7 +401,7 @@ function handleSuggestionTableCellPaste(view, slice, pluginState) {
|
|
|
405
401
|
if (!cell) return;
|
|
406
402
|
const { from, to } = cellPasteRange(cell, cellPos, content);
|
|
407
403
|
const mapFrom = tr.mapping.maps.length;
|
|
408
|
-
markRangeAsDeleted(tr, tr.doc, from, to,
|
|
404
|
+
markRangeAsDeleted(tr, tr.doc, from, to, deletionType, pluginState);
|
|
409
405
|
const insertFrom = tr.mapping.slice(mapFrom).map(to);
|
|
410
406
|
const sizeBefore = tr.doc.content.size;
|
|
411
407
|
tr.replaceRange(insertFrom, insertFrom, content);
|
|
@@ -538,7 +534,7 @@ function applySuggestionInsert(view, from, to, text, pluginState) {
|
|
|
538
534
|
const insertAttrs = findAdjacentRevision(view.state.doc, from, "insertion", pluginState.author) || makeMarkAttrs(pluginState);
|
|
539
535
|
if (from !== to) {
|
|
540
536
|
const deletionType = view.state.schema.marks["deletion"];
|
|
541
|
-
if (deletionType) markRangeAsDeleted(tr, view.state.doc, from, to,
|
|
537
|
+
if (deletionType) markRangeAsDeleted(tr, view.state.doc, from, to, deletionType, pluginState, view.state);
|
|
542
538
|
}
|
|
543
539
|
const insertAt = tr.mapping.map(to);
|
|
544
540
|
tr.insertText(text, insertAt, insertAt);
|
|
@@ -597,7 +593,7 @@ function suggestRangeDeletion(state, tr, from, to) {
|
|
|
597
593
|
const insertionType = state.schema.marks["insertion"];
|
|
598
594
|
const deletionType = state.schema.marks["deletion"];
|
|
599
595
|
if (!pluginState?.active || !insertionType || !deletionType) return false;
|
|
600
|
-
markRangeAsDeleted(tr, tr.doc, from, to,
|
|
596
|
+
markRangeAsDeleted(tr, tr.doc, from, to, deletionType, pluginState);
|
|
601
597
|
return true;
|
|
602
598
|
}
|
|
603
599
|
/**
|
|
@@ -665,19 +661,19 @@ function handleSuggestionEnter(view, pluginState) {
|
|
|
665
661
|
function caretDeleteTarget(state, direction) {
|
|
666
662
|
const { $from } = state.selection;
|
|
667
663
|
const backward = direction === "backward";
|
|
668
|
-
let
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
664
|
+
let cursor = $from.pos;
|
|
665
|
+
while (cursor >= $from.start() && cursor <= $from.end()) {
|
|
666
|
+
const adjacent = backward ? state.doc.resolve(cursor).nodeBefore : state.doc.resolve(cursor).nodeAfter;
|
|
667
|
+
if (!adjacent) return { type: "paragraphEdge" };
|
|
668
|
+
if (adjacent.type.name !== "bookmarkBoundary" && !adjacent.marks.some((mark) => mark.type === state.schema.marks["deletion"])) {
|
|
669
|
+
const size = adjacent.isAtom && !adjacent.isText ? adjacent.nodeSize : 1;
|
|
670
|
+
return {
|
|
671
|
+
type: "inlineUnit",
|
|
672
|
+
from: backward ? cursor - size : cursor,
|
|
673
|
+
to: backward ? cursor : cursor + size
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
cursor += backward ? -adjacent.nodeSize : adjacent.nodeSize;
|
|
681
677
|
}
|
|
682
678
|
return { type: "paragraphEdge" };
|
|
683
679
|
}
|
|
@@ -795,7 +791,7 @@ function handleSuggestionDelete(state, dispatch, direction) {
|
|
|
795
791
|
from: rangeFrom.pos,
|
|
796
792
|
to: rangeTo.pos
|
|
797
793
|
}).sort((a, b) => b.from - a.from);
|
|
798
|
-
for (const { from, to } of ranges) markRangeAsDeleted(tr, state.doc, from, to,
|
|
794
|
+
for (const { from, to } of ranges) markRangeAsDeleted(tr, state.doc, from, to, deletionType, pluginState, state);
|
|
799
795
|
if (state.selection instanceof CellSelection) tr.setSelection(state.selection.map(tr.doc, tr.mapping));
|
|
800
796
|
else {
|
|
801
797
|
const cursorPos = tr.mapping.map($to.pos);
|
|
@@ -823,17 +819,20 @@ function handleSuggestionDelete(state, dispatch, direction) {
|
|
|
823
819
|
const rangeTo = noteRange?.to ?? deleteEnd;
|
|
824
820
|
const nodeAfter = state.doc.resolve(rangeFrom).nodeAfter;
|
|
825
821
|
if (!nodeAfter || !canCarryTrackedRunMark(nodeAfter)) return false;
|
|
826
|
-
const
|
|
827
|
-
if (
|
|
828
|
-
|
|
829
|
-
tr.setSelection(TextSelection.near(tr.doc.resolve(newPos)));
|
|
830
|
-
} else if (hasOwnInsertion) tr.delete(rangeFrom, rangeTo);
|
|
831
|
-
else {
|
|
822
|
+
const mapFrom = tr.mapping.maps.length;
|
|
823
|
+
if (noteRange) markRangeAsDeleted(tr, state.doc, noteRange.from, noteRange.to, deletionType, pluginState);
|
|
824
|
+
else if (!nodeAfter.marks.some((m) => m.type === deletionType)) {
|
|
832
825
|
const delAttrs = findAdjacentRevisionForRange(state.doc, rangeFrom, rangeTo, "deletion", pluginState.author) || makeMarkAttrs(pluginState);
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
826
|
+
addTrackedDeletionMark({
|
|
827
|
+
insertionPolicy: "retract-own",
|
|
828
|
+
tr,
|
|
829
|
+
from: rangeFrom,
|
|
830
|
+
to: rangeTo,
|
|
831
|
+
mark: deletionType.create(delAttrs)
|
|
832
|
+
});
|
|
836
833
|
}
|
|
834
|
+
const newPos = tr.mapping.slice(mapFrom).map(isBackward ? rangeFrom : rangeTo);
|
|
835
|
+
tr.setSelection(TextSelection.near(tr.doc.resolve(newPos)));
|
|
837
836
|
dispatch(tr.scrollIntoView());
|
|
838
837
|
return true;
|
|
839
838
|
}
|
|
@@ -850,7 +849,7 @@ function markComposedAsInsertion({ view, from, pluginState, replaced, compositio
|
|
|
850
849
|
if (compositionId !== null) tr.setMeta("composition", compositionId);
|
|
851
850
|
if (replaced) {
|
|
852
851
|
tr.replaceRange(from, from, replaced);
|
|
853
|
-
markRangeAsDeleted(tr, tr.doc, from, tr.mapping.map(from, 1),
|
|
852
|
+
markRangeAsDeleted(tr, tr.doc, from, tr.mapping.map(from, 1), deletionType, pluginState);
|
|
854
853
|
const restoredEnd = tr.doc.resolve(tr.mapping.map(from, 1));
|
|
855
854
|
const restoredStart = tr.doc.resolve(from);
|
|
856
855
|
if (restoredStart.parent.type.name === "paragraph" && restoredEnd.parent.type.name === "paragraph" && restoredStart.parent !== restoredEnd.parent) {
|
|
@@ -920,14 +919,14 @@ function replacedInline(before, step) {
|
|
|
920
919
|
* rejecting restores it and accepting removes it. The author's own
|
|
921
920
|
* insertions are retracted instead.
|
|
922
921
|
*/
|
|
923
|
-
function restoreReplacedInline({ tr, replaced,
|
|
922
|
+
function restoreReplacedInline({ tr, replaced, deletionType, pluginState }) {
|
|
924
923
|
for (const { at, content } of replaced) {
|
|
925
924
|
const pos = tr.mapping.map(at, -1);
|
|
926
925
|
const $pos = tr.doc.resolve(pos);
|
|
927
926
|
const index = $pos.index();
|
|
928
927
|
if (!$pos.parent.canReplace(index, index, content)) continue;
|
|
929
928
|
tr.insert(pos, content);
|
|
930
|
-
markRangeAsDeleted(tr, tr.doc, pos, pos + content.size,
|
|
929
|
+
markRangeAsDeleted(tr, tr.doc, pos, pos + content.size, deletionType, pluginState);
|
|
931
930
|
}
|
|
932
931
|
}
|
|
933
932
|
/**
|
|
@@ -1103,7 +1102,6 @@ function createSuggestionModePlugin(initialActive = false, author = "User") {
|
|
|
1103
1102
|
if (deletionType) restoreReplacedInline({
|
|
1104
1103
|
tr,
|
|
1105
1104
|
replaced,
|
|
1106
|
-
insertionType,
|
|
1107
1105
|
deletionType,
|
|
1108
1106
|
pluginState
|
|
1109
1107
|
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Mark, Node } from "prosemirror-model";
|
|
2
|
+
//#region src/prosemirror/preservedXmlReview.d.ts
|
|
3
|
+
/** A retained opaque deleted result becomes ordinary text when its last deletion resolves. */
|
|
4
|
+
declare const resolvedPreservedXmlAttrs: (node: Node, marks: readonly Mark[]) => import("prosemirror-model").Attrs;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { resolvedPreservedXmlAttrs };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { captureVerbatimXml } from "../docx/verbatimCapture.js";
|
|
2
|
+
import { OOXML_NAMESPACE_SCOPE, WORDPROCESSINGML_NAMESPACE_URIS, cloneElement, getChildElements, getLocalName, parseXml } from "../docx/xmlParser.js";
|
|
3
|
+
import { expectPreservedXmlAttrs, expectTrackedChangeMarkAttrs } from "./attrs/index.js";
|
|
4
|
+
//#region src/prosemirror/preservedXmlReview.ts
|
|
5
|
+
const restoreDeletedText = (node) => {
|
|
6
|
+
if (node.type !== "element") return node;
|
|
7
|
+
const name = getLocalName(node.name);
|
|
8
|
+
let target;
|
|
9
|
+
if (name === "delText") target = "t";
|
|
10
|
+
if (name === "delInstrText") target = "instrText";
|
|
11
|
+
const renamed = target !== void 0 && WORDPROCESSINGML_NAMESPACE_URIS.has(node.namespaceUri ?? "") ? node.name?.replace(/[^:]+$/u, target) : node.name;
|
|
12
|
+
const elements = node.elements?.map(restoreDeletedText);
|
|
13
|
+
if (renamed === node.name && elements?.every((child, index) => child === node.elements?.[index]) !== false) return node;
|
|
14
|
+
return cloneElement(node, {
|
|
15
|
+
...renamed !== void 0 && renamed !== node.name ? { name: renamed } : {},
|
|
16
|
+
...elements ? { elements } : {}
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
const hasPendingDeletion = (marks) => marks.some((mark) => {
|
|
20
|
+
if (mark.type.name === "deletion") return true;
|
|
21
|
+
if (mark.type.name !== "insertion") return false;
|
|
22
|
+
return expectTrackedChangeMarkAttrs(mark)._docxRevisionAncestors?.some((ancestor) => ancestor.type === "deletion" || ancestor.type === "moveFrom") ?? false;
|
|
23
|
+
});
|
|
24
|
+
/** A retained opaque deleted result becomes ordinary text when its last deletion resolves. */
|
|
25
|
+
const resolvedPreservedXmlAttrs = (node, marks) => {
|
|
26
|
+
if (node.type.name !== "preservedXml" || !hasPendingDeletion(node.marks) || hasPendingDeletion(marks)) return node.attrs;
|
|
27
|
+
const attrs = expectPreservedXmlAttrs(node);
|
|
28
|
+
const xml = getChildElements(parseXml(attrs.xml, OOXML_NAMESPACE_SCOPE)).map((element) => captureVerbatimXml(restoreDeletedText(element))).join("");
|
|
29
|
+
return xml === attrs.xml ? node.attrs : {
|
|
30
|
+
...node.attrs,
|
|
31
|
+
xml
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
//#endregion
|
|
35
|
+
export { resolvedPreservedXmlAttrs };
|
|
@@ -4,7 +4,7 @@ import { expectCharacterSpacingMarkAttrs, expectCharacterStyleMarkAttrs, expectE
|
|
|
4
4
|
import { runShadingAttrsToShading, shadingToRunShadingAttrs } from "./conversion/runShadingMark.js";
|
|
5
5
|
import { applyRunFormattingOverrideAttrs, buildRunFormattingOverrideAttrs } from "./extensions/marks/RunFormattingOverrideExtension.js";
|
|
6
6
|
import { authoredRunFormattingFromAttrs, hasAuthoredRunFormattingProvenance } from "./runFormattingProvenance.js";
|
|
7
|
-
import { paragraphFormattingForRun, resolveEffectiveRunStyleFormatting, suppressParagraphMarkFormatting } from "./runStyleFormatting.js";
|
|
7
|
+
import { isParagraphMarkSuppressionEligible, paragraphFormattingForRun, resolveEffectiveRunStyleFormatting, suppressParagraphMarkFormatting } from "./runStyleFormatting.js";
|
|
8
8
|
//#region src/prosemirror/runFormattingFromMarks.ts
|
|
9
9
|
const RUN_FORMATTING_VISUAL_GROUPS = {
|
|
10
10
|
bold: "bold",
|
|
@@ -570,7 +570,7 @@ function marksToTextFormatting(marks, options) {
|
|
|
570
570
|
inheritedFormatting: suppressedInheritedFormatting,
|
|
571
571
|
observedFormatting: formatting
|
|
572
572
|
});
|
|
573
|
-
if (formattingAuthorshipCost(suppressed) < formattingAuthorshipCost(reconciled)) reconciled = suppressed;
|
|
573
|
+
if (isParagraphMarkSuppressionEligible(suppressed) && formattingAuthorshipCost(suppressed) < formattingAuthorshipCost(reconciled)) reconciled = suppressed;
|
|
574
574
|
}
|
|
575
575
|
return {
|
|
576
576
|
...reconciled,
|
|
@@ -3,7 +3,7 @@ import { expectCharacterStyleMarkAttrs } 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 { getParagraphMarkSuppressionOverrides, hasDirectRunFormatting, paragraphFormattingForRun, resolveEffectiveRunStyleFormatting } from "./runStyleFormatting.js";
|
|
6
|
+
import { getParagraphMarkSuppressionOverrides, hasDirectRunFormatting, isParagraphMarkSuppressionEligible, paragraphFormattingForRun, resolveEffectiveRunStyleFormatting } from "./runStyleFormatting.js";
|
|
7
7
|
import { Mark } from "prosemirror-model";
|
|
8
8
|
//#region src/prosemirror/runFormattingReconciliation.ts
|
|
9
9
|
/** Read authored run properties without confusing inherited visuals for direct formatting. */
|
|
@@ -37,14 +37,15 @@ const reconcileRunFormattingMarks = ({ authoredFormatting, context, node, styleR
|
|
|
37
37
|
paragraphFormatting,
|
|
38
38
|
...styleResolver !== void 0 ? { styleResolver } : {}
|
|
39
39
|
}), authoredFormatting);
|
|
40
|
-
const overrideFormatting = mergeTextFormatting(getParagraphMarkSuppressionOverrides({
|
|
40
|
+
const overrideFormatting = mergeTextFormatting(isParagraphMarkSuppressionEligible(authoredFormatting) ? getParagraphMarkSuppressionOverrides({
|
|
41
41
|
directFormatting: authoredFormatting,
|
|
42
42
|
paragraphMarkFormatting: context.paragraphMarkFormatting,
|
|
43
43
|
suppressedFormatting: paragraphFormatting
|
|
44
|
-
}), authoredFormatting);
|
|
44
|
+
}) : void 0, authoredFormatting);
|
|
45
45
|
const formattingMarks = textFormattingToMarks(effectiveFormatting, node.type.schema, {
|
|
46
46
|
overrideFormatting,
|
|
47
|
-
directFormatting: authoredFormatting
|
|
47
|
+
directFormatting: authoredFormatting,
|
|
48
|
+
authoredCarrier: "preserve"
|
|
48
49
|
});
|
|
49
50
|
return Mark.setFrom([
|
|
50
51
|
...marks.filter(({ type }) => !RUN_FORMATTING_MARK_NAMES.has(type.name)),
|
|
@@ -14,5 +14,12 @@ type ReconstructRejectedRunFormattingMarksOptions = {
|
|
|
14
14
|
* owner so their reject semantics cannot diverge at the bulk threshold.
|
|
15
15
|
*/
|
|
16
16
|
declare const reconstructRejectedRunFormattingMarks: ({ node, paragraphContext, previousFormatting, styleResolver }: ReconstructRejectedRunFormattingMarksOptions) => readonly Mark[];
|
|
17
|
+
type RestoreHistoricalRunFormattingOptions = {
|
|
18
|
+
node: Node;
|
|
19
|
+
paragraphContext: ParagraphRunStyleContext;
|
|
20
|
+
styleResolver?: RunStyleResolver | null;
|
|
21
|
+
};
|
|
22
|
+
/** Restored deletions inherit the live paragraph cascade without authoring their historical visuals. */
|
|
23
|
+
declare const restoreHistoricalRunFormatting: ({ node, paragraphContext, styleResolver }: RestoreHistoricalRunFormattingOptions) => readonly Mark[];
|
|
17
24
|
//#endregion
|
|
18
|
-
export { reconstructRejectedRunFormattingMarks };
|
|
25
|
+
export { reconstructRejectedRunFormattingMarks, restoreHistoricalRunFormatting };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { runFormattingInlineAtomDisposition } from "./runFormattingInlineCarriers.js";
|
|
1
2
|
import { RUN_FORMATTING_MARK_NAMES } from "./runFormattingMarkNames.js";
|
|
2
|
-
import { reconcileRunFormattingMarks } from "./runFormattingReconciliation.js";
|
|
3
|
+
import { readAuthoredRunFormatting, reconcileRunFormattingMarks } from "./runFormattingReconciliation.js";
|
|
3
4
|
//#region src/prosemirror/runPropertyChangeResolution.ts
|
|
4
5
|
/**
|
|
5
6
|
* Rebuild the pre-change run marks against the paragraph's live style cascade.
|
|
@@ -14,5 +15,26 @@ const reconstructRejectedRunFormattingMarks = ({ node, paragraphContext, previou
|
|
|
14
15
|
...styleResolver !== void 0 ? { styleResolver } : {}
|
|
15
16
|
}).filter(({ type }) => RUN_FORMATTING_MARK_NAMES.has(type.name));
|
|
16
17
|
};
|
|
18
|
+
/** Restored deletions inherit the live paragraph cascade without authoring their historical visuals. */
|
|
19
|
+
const restoreHistoricalRunFormatting = ({ node, paragraphContext, styleResolver }) => {
|
|
20
|
+
const disposition = runFormattingInlineAtomDisposition(node);
|
|
21
|
+
if (disposition === null || disposition === "not-a-run") return node.marks;
|
|
22
|
+
if (paragraphContext.paragraphMarkFormatting === void 0) return node.marks;
|
|
23
|
+
return reconcileRunFormattingMarks({
|
|
24
|
+
authoredFormatting: readAuthoredRunFormatting({
|
|
25
|
+
context: {
|
|
26
|
+
baseParagraphFormatting: paragraphContext.baseParagraphFormatting,
|
|
27
|
+
paragraphFormatting: paragraphContext.baseParagraphFormatting,
|
|
28
|
+
paragraphMarkFormatting: void 0,
|
|
29
|
+
paragraphMarkPrecedesStyle: false
|
|
30
|
+
},
|
|
31
|
+
marks: node.marks,
|
|
32
|
+
...styleResolver !== void 0 ? { styleResolver } : {}
|
|
33
|
+
}),
|
|
34
|
+
context: paragraphContext,
|
|
35
|
+
node,
|
|
36
|
+
...styleResolver !== void 0 ? { styleResolver } : {}
|
|
37
|
+
});
|
|
38
|
+
};
|
|
17
39
|
//#endregion
|
|
18
|
-
export { reconstructRejectedRunFormattingMarks };
|
|
40
|
+
export { reconstructRejectedRunFormattingMarks, restoreHistoricalRunFormatting };
|
|
@@ -5,6 +5,8 @@ import { cascadeStyleTextFormatting } from "./styles/styleToggleCascade.js";
|
|
|
5
5
|
import { Mark, Node } from "prosemirror-model";
|
|
6
6
|
//#region src/prosemirror/runStyleFormatting.d.ts
|
|
7
7
|
declare const hasDirectRunFormatting: (formatting: document_d_exports.TextFormatting | undefined) => boolean;
|
|
8
|
+
/** A stated run property or character style establishes paragraph-mark suppression. */
|
|
9
|
+
declare const isParagraphMarkSuppressionEligible: (formatting: document_d_exports.TextFormatting | undefined) => boolean;
|
|
8
10
|
declare const stripParagraphMarkOnlyFormatting: (formatting: document_d_exports.TextFormatting) => document_d_exports.TextFormatting | undefined;
|
|
9
11
|
declare const stripParagraphMarkFormattingForBodyRuns: (formatting: document_d_exports.TextFormatting) => document_d_exports.TextFormatting | undefined;
|
|
10
12
|
type SuppressParagraphMarkFormattingOptions = {
|
|
@@ -66,4 +68,4 @@ type ResolveEffectiveRunStyleFormattingOptions = {
|
|
|
66
68
|
/** Resolve the non-direct run cascade from shared document styles and the current paragraph. */
|
|
67
69
|
declare const resolveEffectiveRunStyleFormatting: ({ marks, paragraphFormatting, styleResolver }: ResolveEffectiveRunStyleFormattingOptions) => document_d_exports.TextFormatting | undefined;
|
|
68
70
|
//#endregion
|
|
69
|
-
export { ParagraphRunStyleContext, RunStyleResolver, getParagraphMarkSuppressionOverrides, hasDirectRunFormatting, nearestParagraphRunStyleContext, paragraphFormattingForRun, paragraphRunStyleContext, paragraphRunStyleContextAt, resolveEffectiveRunStyleFormatting, resolveParagraphBodyRunFormatting, stripParagraphMarkFormattingForBodyRuns, stripParagraphMarkOnlyFormatting, suppressParagraphMarkFormatting };
|
|
71
|
+
export { ParagraphRunStyleContext, RunStyleResolver, getParagraphMarkSuppressionOverrides, hasDirectRunFormatting, isParagraphMarkSuppressionEligible, nearestParagraphRunStyleContext, paragraphFormattingForRun, paragraphRunStyleContext, paragraphRunStyleContextAt, resolveEffectiveRunStyleFormatting, resolveParagraphBodyRunFormatting, stripParagraphMarkFormattingForBodyRuns, stripParagraphMarkOnlyFormatting, suppressParagraphMarkFormatting };
|
|
@@ -20,6 +20,8 @@ const hasDirectRunFormatting = (formatting) => {
|
|
|
20
20
|
if (!formatting) return false;
|
|
21
21
|
return Object.entries(formatting).some(([property, value]) => property !== "styleId" && value !== void 0);
|
|
22
22
|
};
|
|
23
|
+
/** A stated run property or character style establishes paragraph-mark suppression. */
|
|
24
|
+
const isParagraphMarkSuppressionEligible = (formatting) => hasDirectRunFormatting(formatting) || formatting?.styleId !== void 0;
|
|
23
25
|
const stripParagraphMarkOnlyFormatting = (formatting) => {
|
|
24
26
|
const { allCaps: _allCaps, highlight: _highlight, shading: _shading, smallCaps: _smallCaps, vertAlign: _vertAlign, preserved: _preserved, ...formattingForBody } = formatting;
|
|
25
27
|
return Object.keys(formattingForBody).length > 0 ? formattingForBody : void 0;
|
|
@@ -182,4 +184,4 @@ const resolveEffectiveRunStyleFormatting = ({ marks, paragraphFormatting, styleR
|
|
|
182
184
|
});
|
|
183
185
|
};
|
|
184
186
|
//#endregion
|
|
185
|
-
export { getParagraphMarkSuppressionOverrides, hasDirectRunFormatting, nearestParagraphRunStyleContext, paragraphFormattingForRun, paragraphRunStyleContext, paragraphRunStyleContextAt, resolveEffectiveRunStyleFormatting, resolveParagraphBodyRunFormatting, stripParagraphMarkFormattingForBodyRuns, stripParagraphMarkOnlyFormatting, suppressParagraphMarkFormatting };
|
|
187
|
+
export { getParagraphMarkSuppressionOverrides, hasDirectRunFormatting, isParagraphMarkSuppressionEligible, nearestParagraphRunStyleContext, paragraphFormattingForRun, paragraphRunStyleContext, paragraphRunStyleContextAt, resolveEffectiveRunStyleFormatting, resolveParagraphBodyRunFormatting, stripParagraphMarkFormattingForBodyRuns, stripParagraphMarkOnlyFormatting, suppressParagraphMarkFormatting };
|
|
@@ -272,6 +272,8 @@ type ParagraphAttrs = {
|
|
|
272
272
|
* paragraph. `TableCellAttrs._resolvedBorders` is the same device.
|
|
273
273
|
*/
|
|
274
274
|
_resolvedFormatting?: document_d_exports.ParagraphFormatting;
|
|
275
|
+
/** Style-only inheritance baseline, before numbering-level indentation. PM-only. */
|
|
276
|
+
_styleResolvedFormatting?: document_d_exports.ParagraphFormatting;
|
|
275
277
|
/** Import-effective spacing baseline for HTML auto-spacing detection.
|
|
276
278
|
* PM-only; never serialized back into DOCX formatting. */
|
|
277
279
|
_autospacingBase?: {
|
|
@@ -59,7 +59,10 @@ function paragraphStyleCascadeAttrs({ styleId, formatting, styleResolver, tableP
|
|
|
59
59
|
};
|
|
60
60
|
const stylePpr = styleResolver.resolveParagraphStyleInTable(styleId, tableParagraphOverlay).paragraphFormatting;
|
|
61
61
|
const resolvedFormatting = styleResolvedParagraphFormatting(stylePpr);
|
|
62
|
-
if (resolvedFormatting)
|
|
62
|
+
if (resolvedFormatting) {
|
|
63
|
+
attrs._resolvedFormatting = resolvedFormatting;
|
|
64
|
+
attrs._styleResolvedFormatting = resolvedFormatting;
|
|
65
|
+
}
|
|
63
66
|
set("alignment", formatting?.alignment ?? stylePpr?.alignment);
|
|
64
67
|
set("alignmentFromStyle", stylePpr?.alignment);
|
|
65
68
|
set("spaceBefore", formatting?.spaceBefore ?? stylePpr?.spaceBefore);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { document_d_exports } from "../../types/document.js";
|
|
1
2
|
import { ParagraphAttrs, ParagraphAttrsPatch } from "../schema/nodes.js";
|
|
2
3
|
import { ResolvedParagraphStyle } from "./styleResolver.js";
|
|
3
4
|
import { NumberingMap } from "../../docx/numberingParser.js";
|
|
@@ -38,17 +39,18 @@ declare function listAttrsFromNumbering(numPr: {
|
|
|
38
39
|
numId: number;
|
|
39
40
|
ilvl: number;
|
|
40
41
|
}, numbering: NumberingMap | null | undefined): ParagraphAttrsPatch;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
42
|
+
type ListIndentationProvenanceOptions = {
|
|
43
|
+
direct: DirectParagraphIndentation | undefined;
|
|
44
|
+
styleFormatting: document_d_exports.ParagraphFormatting | undefined;
|
|
45
|
+
numberingSource: "style" | "paragraph";
|
|
46
|
+
numPr: {
|
|
47
|
+
numId: number;
|
|
48
|
+
ilvl: number;
|
|
49
|
+
} | undefined;
|
|
50
|
+
numbering: NumberingMap | null | undefined;
|
|
51
|
+
};
|
|
52
|
+
/** Project effective indentation and both inheritance layers together. */
|
|
53
|
+
declare function listIndentationProvenancePatch({ direct, styleFormatting, numberingSource, numPr, numbering }: ListIndentationProvenanceOptions): ParagraphAttrsPatch;
|
|
52
54
|
/**
|
|
53
55
|
* The indentation a paragraph leaving its list keeps: the level's indentation
|
|
54
56
|
* it only read from its numbering goes with the numbering, back to what its
|
|
@@ -57,11 +59,9 @@ declare function listLevelIndentAttrPatch(stated: DirectParagraphIndentation | u
|
|
|
57
59
|
*/
|
|
58
60
|
declare function listLevelIndentRemovalPatch(attrs: Readonly<ParagraphAttrs>, numbering: NumberingMap | null | undefined): ParagraphAttrsPatch;
|
|
59
61
|
/** Recompute every level-dependent attr when a paragraph changes list level. */
|
|
60
|
-
declare function listLevelAttrPatch(attrs: {
|
|
61
|
-
listImplicitChildLevelAdvances?: number | null;
|
|
62
|
-
}, numPr: {
|
|
62
|
+
declare function listLevelAttrPatch(attrs: Pick<ParagraphAttrs, "listImplicitChildLevelAdvances" | "_originalFormatting" | "_resolvedFormatting" | "_styleResolvedFormatting" | "numPr" | "numPrFromStyle" | "indentLeft" | "indentRight" | "indentFirstLine" | "hangingIndent">, numPr: {
|
|
63
63
|
numId: number;
|
|
64
64
|
ilvl: number;
|
|
65
65
|
}, numbering: NumberingMap | null | undefined): ParagraphAttrsPatch;
|
|
66
66
|
//#endregion
|
|
67
|
-
export { listAttrsFromNumbering, listAttrsFromResolvedStyle,
|
|
67
|
+
export { listAttrsFromNumbering, listAttrsFromResolvedStyle, listIndentationProvenancePatch, listLevelAttrPatch, listLevelIndentRemovalPatch, paragraphAttrsFromResolvedStyle };
|
|
@@ -6,6 +6,7 @@ import { CLEARED_LIST_RENDERING_ATTRS } from "../listMarker.js";
|
|
|
6
6
|
import { listRenderingAttrPatch } from "../listRenderingAttrs.js";
|
|
7
7
|
import { paragraphNumberingAttr } from "../numberingAttr.js";
|
|
8
8
|
import { styleResolvedParagraphFormatting } from "../paragraphFormattingProvenance.js";
|
|
9
|
+
import { directParagraphIndentation, paragraphIndentationAttrPatch, paragraphIndentationFromFormatting, withDirectParagraphIndentation } from "../paragraphIndentation.js";
|
|
9
10
|
//#region src/prosemirror/styles/resolvedStyleAttrs.ts
|
|
10
11
|
/**
|
|
11
12
|
* Shared helper for projecting a resolved paragraph style onto ProseMirror
|
|
@@ -48,6 +49,7 @@ function paragraphAttrsFromResolvedStyle(resolved, identity) {
|
|
|
48
49
|
borders: ppr?.borders ?? null,
|
|
49
50
|
defaultTextFormatting: hasRunFormatting ? runFormatting : null,
|
|
50
51
|
_resolvedFormatting: styleResolvedParagraphFormatting(ppr),
|
|
52
|
+
_styleResolvedFormatting: styleResolvedParagraphFormatting(ppr),
|
|
51
53
|
_autospacingBase: autospacingBaseFromResolvedParagraphFormatting(ppr),
|
|
52
54
|
_tableOfContentsLevel: tableOfContentsStyleLevel(identity) ?? null
|
|
53
55
|
};
|
|
@@ -84,19 +86,26 @@ function listAttrsFromResolvedStyle(resolved, numbering) {
|
|
|
84
86
|
numId,
|
|
85
87
|
ilvl
|
|
86
88
|
}, numbering);
|
|
87
|
-
const level = numbering?.getLevel(numId, ilvl);
|
|
88
89
|
attrs.numPrFromStyle = paragraphNumberingAttr(paragraphNumberingReference({
|
|
89
90
|
numId,
|
|
90
91
|
ilvl
|
|
91
92
|
}));
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
93
|
+
Object.assign(attrs, listIndentationProvenancePatch({
|
|
94
|
+
direct: void 0,
|
|
95
|
+
styleFormatting: resolved.paragraphFormatting,
|
|
96
|
+
numberingSource: "style",
|
|
97
|
+
numPr: {
|
|
98
|
+
numId,
|
|
99
|
+
ilvl
|
|
100
|
+
},
|
|
101
|
+
numbering
|
|
102
|
+
}));
|
|
103
|
+
for (const key of [
|
|
104
|
+
"indentLeft",
|
|
105
|
+
"indentRight",
|
|
106
|
+
"indentFirstLine"
|
|
107
|
+
]) if (attrs[key] == null) Reflect.deleteProperty(attrs, key);
|
|
108
|
+
if (attrs.indentFirstLine === void 0 && resolved.paragraphFormatting?.hangingIndent === void 0) Reflect.deleteProperty(attrs, "hangingIndent");
|
|
100
109
|
return attrs;
|
|
101
110
|
}
|
|
102
111
|
/** Project one resolved numbering level into the complete editor attr group. */
|
|
@@ -115,9 +124,9 @@ function listAttrsFromNumbering(numPr, numbering) {
|
|
|
115
124
|
/**
|
|
116
125
|
* The numbering level's indentation a directly numbered paragraph reads as its
|
|
117
126
|
* own where it states none: the load path folds the level's `w:ind` into the
|
|
118
|
-
* paragraph (a direct `w:ind` wins per group, left vs first line/hanging)
|
|
119
|
-
*
|
|
120
|
-
*
|
|
127
|
+
* paragraph (a direct `w:ind` wins per group, left vs first line/hanging).
|
|
128
|
+
* Keep this projection private: callers use the paired provenance helper so
|
|
129
|
+
* effective level values cannot be mistaken for authored indentation.
|
|
121
130
|
*/
|
|
122
131
|
function listLevelIndentAttrPatch(stated, numPr, numbering) {
|
|
123
132
|
const level = numbering?.getLevel(numPr.numId, numPr.ilvl);
|
|
@@ -130,6 +139,33 @@ function listLevelIndentAttrPatch(stated, numPr, numbering) {
|
|
|
130
139
|
}
|
|
131
140
|
return patch;
|
|
132
141
|
}
|
|
142
|
+
/** Project effective indentation and both inheritance layers together. */
|
|
143
|
+
function listIndentationProvenancePatch({ direct, styleFormatting, numberingSource, numPr, numbering }) {
|
|
144
|
+
const style = {
|
|
145
|
+
...styleResolvedParagraphFormatting(styleFormatting),
|
|
146
|
+
...styleFormatting?.hangingIndent === void 0 ? {} : { hangingIndent: styleFormatting.hangingIndent }
|
|
147
|
+
};
|
|
148
|
+
const level = numPr === void 0 ? {} : listLevelIndentAttrPatch(numberingSource === "style" ? paragraphIndentationFromFormatting(style) : void 0, numPr, numbering);
|
|
149
|
+
if (level.indentLeft === 0 && style.indentLeft === void 0) Reflect.deleteProperty(level, "indentLeft");
|
|
150
|
+
if (level.indentFirstLine === 0 && style.indentFirstLine === void 0 && style.hangingIndent === void 0) {
|
|
151
|
+
Reflect.deleteProperty(level, "indentFirstLine");
|
|
152
|
+
Reflect.deleteProperty(level, "hangingIndent");
|
|
153
|
+
}
|
|
154
|
+
const resolved = {
|
|
155
|
+
...style,
|
|
156
|
+
...typeof level.indentLeft === "number" ? { indentLeft: level.indentLeft } : {},
|
|
157
|
+
...typeof level.indentFirstLine === "number" ? { indentFirstLine: level.indentFirstLine } : {},
|
|
158
|
+
...typeof level.hangingIndent === "boolean" ? { hangingIndent: level.hangingIndent } : {}
|
|
159
|
+
};
|
|
160
|
+
return {
|
|
161
|
+
...paragraphIndentationAttrPatch({
|
|
162
|
+
direct,
|
|
163
|
+
inherited: paragraphIndentationFromFormatting(resolved)
|
|
164
|
+
}),
|
|
165
|
+
_resolvedFormatting: Object.keys(resolved).length === 0 ? null : resolved,
|
|
166
|
+
_styleResolvedFormatting: Object.keys(style).length === 0 ? null : style
|
|
167
|
+
};
|
|
168
|
+
}
|
|
133
169
|
/**
|
|
134
170
|
* The indentation a paragraph leaving its list keeps: the level's indentation
|
|
135
171
|
* it only read from its numbering goes with the numbering, back to what its
|
|
@@ -138,28 +174,33 @@ function listLevelIndentAttrPatch(stated, numPr, numbering) {
|
|
|
138
174
|
*/
|
|
139
175
|
function listLevelIndentRemovalPatch(attrs, numbering) {
|
|
140
176
|
if (attrs.numPr?.kind !== "reference") return {};
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
177
|
+
const direct = directParagraphIndentation(attrs);
|
|
178
|
+
return {
|
|
179
|
+
...listIndentationProvenancePatch({
|
|
180
|
+
direct,
|
|
181
|
+
styleFormatting: attrs._styleResolvedFormatting,
|
|
182
|
+
numberingSource: "paragraph",
|
|
183
|
+
numPr: void 0,
|
|
184
|
+
numbering
|
|
185
|
+
}),
|
|
186
|
+
_originalFormatting: withDirectParagraphIndentation(attrs._originalFormatting, direct) ?? null
|
|
187
|
+
};
|
|
151
188
|
}
|
|
152
189
|
/** Recompute every level-dependent attr when a paragraph changes list level. */
|
|
153
190
|
function listLevelAttrPatch(attrs, numPr, numbering) {
|
|
154
|
-
const
|
|
155
|
-
const hasMarkerSlot = level ? numberingLevelHasMarkerSlot(level) : false;
|
|
191
|
+
const direct = directParagraphIndentation(attrs);
|
|
156
192
|
return {
|
|
157
193
|
...listAttrsFromNumbering(numPr, numbering),
|
|
158
194
|
listImplicitChildLevelAdvances: attrs.listImplicitChildLevelAdvances ?? null,
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
195
|
+
...listIndentationProvenancePatch({
|
|
196
|
+
direct,
|
|
197
|
+
styleFormatting: attrs._styleResolvedFormatting,
|
|
198
|
+
numberingSource: attrs.numPrFromStyle == null ? "paragraph" : "style",
|
|
199
|
+
numPr,
|
|
200
|
+
numbering
|
|
201
|
+
}),
|
|
202
|
+
_originalFormatting: withDirectParagraphIndentation(attrs._originalFormatting, direct) ?? null
|
|
162
203
|
};
|
|
163
204
|
}
|
|
164
205
|
//#endregion
|
|
165
|
-
export { listAttrsFromNumbering, listAttrsFromResolvedStyle,
|
|
206
|
+
export { listAttrsFromNumbering, listAttrsFromResolvedStyle, listIndentationProvenancePatch, listLevelAttrPatch, listLevelIndentRemovalPatch, paragraphAttrsFromResolvedStyle };
|
|
@@ -13,6 +13,10 @@ type TextInput = {
|
|
|
13
13
|
to: number;
|
|
14
14
|
};
|
|
15
15
|
declare const dispatchEditorTextInput: <TView extends TextInputDispatchTarget<TView>>(view: TView, input: string | TextInput) => void;
|
|
16
|
+
declare const getEditorInputTargetRange: (view: EditorView, event: InputEvent) => {
|
|
17
|
+
from: number;
|
|
18
|
+
to: number;
|
|
19
|
+
} | null;
|
|
16
20
|
/** Shared DOM boundary for editor runtimes and standalone suggestion views. */
|
|
17
21
|
declare const handleEditorBeforeInput: (view: EditorView, event: InputEvent) => boolean;
|
|
18
22
|
/**
|
|
@@ -23,4 +27,4 @@ declare const afterNativeCompositionFlush: (callback: () => void) => void;
|
|
|
23
27
|
/** Route committed text through the model before the browser mutates mark spans. */
|
|
24
28
|
declare const createTextInputPlugin: () => Plugin<any>;
|
|
25
29
|
//#endregion
|
|
26
|
-
export { afterNativeCompositionFlush, createTextInputPlugin, dispatchEditorTextInput, handleEditorBeforeInput };
|
|
30
|
+
export { afterNativeCompositionFlush, createTextInputPlugin, dispatchEditorTextInput, getEditorInputTargetRange, handleEditorBeforeInput };
|