@stll/folio-core 0.58.5 → 0.60.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -1
- package/dist/ai-edits/apply.d.ts +11 -12
- package/dist/ai-edits/apply.js +179 -168
- package/dist/ai-edits/headless.d.ts +15 -13
- package/dist/ai-edits/headless.js +40 -13
- package/dist/ai-edits/index.d.ts +3 -3
- package/dist/ai-edits/newListNumbering.d.ts +3 -9
- package/dist/ai-edits/newListNumbering.js +36 -41
- package/dist/ai-edits/referenceClassification.d.ts +22 -0
- package/dist/ai-edits/referenceClassification.js +21 -0
- package/dist/ai-edits/snapshot.js +39 -40
- package/dist/ai-edits/types.d.ts +24 -32
- package/dist/compare/column-alignment.d.ts +4 -4
- package/dist/compare/compare.d.ts +3 -7
- package/dist/compare/compare.js +25 -27
- package/dist/compare/content-alignment.d.ts +9 -9
- package/dist/compare/content-types.d.ts +23 -10
- package/dist/compare/content-types.js +14 -0
- package/dist/compare/content.d.ts +16 -17
- package/dist/compare/content.js +30 -7
- package/dist/compare/formatting.d.ts +3 -3
- package/dist/compare/import-style-closure.d.ts +22 -0
- package/dist/compare/import-style-closure.js +33 -0
- package/dist/compare/inserted-resource-snapshot.d.ts +15 -0
- package/dist/compare/inserted-resource-snapshot.js +63 -0
- package/dist/compare/plan.js +20 -13
- package/dist/compare/scenario.js +12 -2
- package/dist/compare/style-resources.d.ts +8 -2
- package/dist/compare/style-resources.js +63 -14
- package/dist/compare/verification.d.ts +15 -3
- package/dist/compare/verification.js +47 -8
- package/dist/compat/eigenpal.d.ts +5 -5
- package/dist/compat/eigenpal.js +2 -2
- package/dist/controller/canonicalListRendering.js +13 -22
- package/dist/controller/canonicalPublicOperations.js +1 -1
- package/dist/controller/canonicalSession.js +3 -2
- package/dist/controller/canonicalStructure.js +55 -28
- package/dist/controller/fontReadiness.js +1 -1
- package/dist/controller/layoutPipeline.js +7 -1
- package/dist/controller/layoutSession.d.ts +2 -0
- package/dist/display-list/build/fontTable.js +7 -5
- package/dist/display-list/build/furniture.d.ts +1 -0
- package/dist/display-list/build/furniture.js +1 -0
- package/dist/display-list/build/watermarkPrimitives.d.ts +2 -1
- package/dist/display-list/build/watermarkPrimitives.js +9 -3
- package/dist/display-list/editor/pageRenderer.js +1 -0
- package/dist/document-operations.d.ts +4 -9
- package/dist/document-operations.js +45 -41
- package/dist/docx/attributeRemainder.d.ts +1 -1
- package/dist/docx/bookmarkIdNormalization.d.ts +10 -0
- package/dist/docx/bookmarkIdNormalization.js +100 -0
- package/dist/docx/bookmarkParser.js +4 -2
- package/dist/docx/importedIdCollisions.d.ts +136 -0
- package/dist/docx/importedIdCollisions.js +215 -0
- package/dist/docx/index.d.ts +1 -1
- package/dist/docx/listMarkerComputation.js +9 -14
- package/dist/docx/listTemplate.d.ts +22 -0
- package/dist/docx/listTemplate.js +40 -0
- package/dist/docx/numberingParser.js +4 -4
- package/dist/docx/numberingReferenceNormalization.js +3 -3
- package/dist/docx/paragraphParser.js +3 -4
- package/dist/docx/paragraphPropertySource.js +1 -2
- package/dist/docx/parseContext.d.ts +2 -1
- package/dist/docx/parseContext.js +1 -0
- package/dist/docx/parseWarningMessage.js +1 -0
- package/dist/docx/parser.js +5 -1
- package/dist/docx/relsParser.js +1 -1
- package/dist/docx/rezip.js +4 -3
- package/dist/docx/selectedXmlIdentityScan.d.ts +10 -0
- package/dist/docx/selectedXmlIdentityScan.js +36 -0
- package/dist/docx/selectiveSave.js +5 -4
- package/dist/docx/selectiveXmlPatch.js +44 -52
- package/dist/docx/serializer/commentSerializer.d.ts +3 -1
- package/dist/docx/serializer/commentSerializer.js +11 -2
- package/dist/docx/serializer/runSerializer.js +2 -2
- package/dist/docx/serializer/trackedChangeAttributes.d.ts +1 -3
- package/dist/docx/serializer/trackedChangeAttributes.js +1 -11
- package/dist/docx/server/materializeYjsDocx.js +2 -2
- package/dist/docx/server/migrateYjsAttrSchema.js +5 -5
- package/dist/fonts/embeddedFontFingerprint.d.ts +5 -0
- package/dist/fonts/embeddedFontFingerprint.js +18 -0
- package/dist/fonts/embeddedFonts.d.ts +1 -1
- package/dist/fonts/embeddedFonts.js +1 -1
- package/dist/fonts/headlessMeasure.js +0 -0
- package/dist/generated/text_shaper.js +8 -4
- package/dist/generated/text_shaper_bg.wasm +0 -0
- package/dist/headless-layout.js +1 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.js +2 -2
- package/dist/internal/paragraphFormattingSerialization.d.ts +1 -8
- package/dist/internal/paragraphFormattingSerialization.js +6 -20
- package/dist/layout-bridge/convert/flowConversionShared.d.ts +3 -1
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -1
- package/dist/layout-bridge/convert/footnoteLayout.js +3 -0
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +2 -0
- package/dist/layout-bridge/convert/listMarkers.d.ts +1 -2
- package/dist/layout-bridge/convert/listMarkers.js +3 -11
- package/dist/layout-bridge/convert/paragraphAttrs.d.ts +1 -1
- package/dist/layout-bridge/convert/paragraphAttrs.js +8 -4
- package/dist/layout-bridge/convert/paragraphConversion.js +8 -1
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +2 -1
- package/dist/layout-bridge/convert/toFlowBlocks.js +27 -2
- package/dist/layout-engine/measure/cache.js +39 -7
- package/dist/layout-engine/measure/lineTypography.js +1 -0
- package/dist/layout-engine/measure/listMarkerWidth.d.ts +1 -0
- package/dist/layout-engine/measure/listMarkerWidth.js +1 -0
- package/dist/layout-engine/measure/measureContainer.js +3 -4
- package/dist/layout-engine/measure/measureHelpers.d.ts +6 -9
- package/dist/layout-engine/measure/measureHelpers.js +21 -18
- package/dist/layout-engine/measure/measureParagraph.js +2 -0
- package/dist/layout-engine/measure/measureTypes.d.ts +2 -0
- package/dist/layout-engine/types.d.ts +4 -1
- package/dist/layout-painter/renderPage.d.ts +1 -0
- package/dist/layout-painter/renderPage.js +11 -3
- package/dist/layout-painter/renderParagraph.js +13 -3
- package/dist/layout-painter/renderWatermark.d.ts +1 -0
- package/dist/layout-painter/renderWatermark.js +7 -3
- package/dist/managers/editorShortcuts.d.ts +2 -1
- package/dist/managers/editorShortcuts.js +2 -1
- package/dist/markdown/renderParagraph.js +29 -3
- package/dist/prosemirror/canonicalSelectionRange.d.ts +4 -1
- package/dist/prosemirror/canonicalSelectionRange.js +9 -3
- package/dist/prosemirror/commands/comments.js +5 -32
- package/dist/prosemirror/commands/paragraphBookmarkJoin.d.ts +7 -1
- package/dist/prosemirror/commands/paragraphBookmarkJoin.js +35 -1
- package/dist/prosemirror/commands/propertyChangeScope.js +6 -0
- package/dist/prosemirror/commands/resolveParagraphProperties.js +10 -5
- package/dist/prosemirror/conversion/fromProseDoc.js +23 -9
- package/dist/prosemirror/conversion/toProseDoc.js +31 -7
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +29 -14
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.d.ts +8 -2
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +39 -3
- package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.d.ts +8 -2
- package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +4 -3
- package/dist/prosemirror/extensions/features/ImageDragExtension.js +4 -3
- package/dist/prosemirror/extensions/features/JoinedRunStyleExtension.js +4 -3
- package/dist/prosemirror/extensions/features/ListExtension.js +51 -21
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +9 -3
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +6 -5
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +8 -2
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +11 -3
- package/dist/prosemirror/extensions/marks/RunIdentityExtension.js +4 -3
- package/dist/prosemirror/extensions/marks/markUtils.js +1 -1
- package/dist/prosemirror/listInstanceReferences.js +21 -15
- package/dist/prosemirror/listLabels.d.ts +4 -3
- package/dist/prosemirror/listLabels.js +18 -51
- package/dist/prosemirror/listMarker.d.ts +2 -19
- package/dist/prosemirror/listMarker.js +28 -57
- package/dist/prosemirror/listNumbering.js +16 -6
- package/dist/prosemirror/listRendering.d.ts +4 -3
- package/dist/prosemirror/listRendering.js +22 -3
- package/dist/prosemirror/listRenderingAttrs.d.ts +2 -1
- package/dist/prosemirror/listRenderingAttrs.js +6 -11
- package/dist/prosemirror/numberedRefFields.js +9 -5
- package/dist/prosemirror/numberingAttr.d.ts +19 -1
- package/dist/prosemirror/numberingAttr.js +16 -2
- package/dist/prosemirror/paragraphIndentation.js +5 -2
- package/dist/prosemirror/paragraphMarkJoin.js +17 -3
- package/dist/prosemirror/paragraphPropertyCarry.js +5 -6
- package/dist/prosemirror/pluginKeyOwner.d.ts +13 -0
- package/dist/prosemirror/pluginKeyOwner.js +35 -0
- package/dist/prosemirror/plugins/aiCitationDecorations.d.ts +11 -4
- package/dist/prosemirror/plugins/aiCitationDecorations.js +16 -3
- package/dist/prosemirror/plugins/aiSuggestionDecorations.d.ts +11 -4
- package/dist/prosemirror/plugins/aiSuggestionDecorations.js +18 -3
- package/dist/prosemirror/plugins/anonymizationDecorations.d.ts +11 -11
- package/dist/prosemirror/plugins/anonymizationDecorations.js +23 -13
- package/dist/prosemirror/plugins/autocompleteSuggestion.d.ts +8 -2
- package/dist/prosemirror/plugins/autocompleteSuggestion.js +27 -5
- package/dist/prosemirror/plugins/contentControlWidgets.d.ts +8 -2
- package/dist/prosemirror/plugins/contentControlWidgets.js +4 -3
- package/dist/prosemirror/plugins/createDocScanPlugin.d.ts +6 -5
- package/dist/prosemirror/plugins/createDocScanPlugin.js +1 -1
- package/dist/prosemirror/plugins/documentNumbering.js +5 -3
- package/dist/prosemirror/plugins/documentStyleState.d.ts +8 -2
- package/dist/prosemirror/plugins/documentStyleState.js +2 -2
- package/dist/prosemirror/plugins/documentStyles.js +1 -1
- package/dist/prosemirror/plugins/selectionTracker.d.ts +8 -2
- package/dist/prosemirror/plugins/selectionTracker.js +4 -3
- package/dist/prosemirror/plugins/suggestionMode.d.ts +8 -2
- package/dist/prosemirror/plugins/suggestionMode.js +4 -3
- package/dist/prosemirror/plugins/templateDirectives.d.ts +8 -2
- package/dist/prosemirror/plugins/templateDirectives.js +19 -4
- package/dist/prosemirror/plugins/templatePreviewValues.d.ts +8 -2
- package/dist/prosemirror/plugins/templatePreviewValues.js +27 -5
- package/dist/prosemirror/plugins/templateSlashMenu.d.ts +8 -2
- package/dist/prosemirror/plugins/templateSlashMenu.js +23 -5
- package/dist/prosemirror/plugins/transactionInvariants.js +29 -5
- package/dist/prosemirror/schema/nodes.d.ts +2 -1
- package/dist/prosemirror/selectionState.js +5 -1
- package/dist/prosemirror/storyListNumbering.js +11 -12
- package/dist/prosemirror/styles/paragraphStyleCascade.js +2 -6
- package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +11 -4
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +28 -18
- package/dist/prosemirror/yjsDocumentMetadata.d.ts +9 -3
- package/dist/prosemirror/yjsDocumentMetadata.js +42 -10
- package/dist/redline.d.ts +17 -1
- package/dist/redline.js +118 -57
- package/dist/server.d.ts +3 -3
- package/dist/server.js +2 -2
- package/dist/utils/fontLoader.d.ts +2 -2
- package/dist/utils/fontLoader.js +2 -7
- package/dist/utils/fontResolver.d.ts +7 -3
- package/dist/utils/fontResolver.js +6 -8
- package/dist/version-comparison.d.ts +1 -2
- package/dist/version-comparison.js +1 -2
- package/package.json +26 -9
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { bulletMarkerFontName, convertBulletToUnicode } from "../docx/bulletMarkers.js";
|
|
2
|
-
import {
|
|
2
|
+
import { resolveListTemplate, resolveListTemplateWithComponents } from "../docx/listTemplate.js";
|
|
3
|
+
import { paragraphNumberingLevel, paragraphNumberingReferenceId } from "../docx/numberingReference.js";
|
|
3
4
|
import { formatOoxmlCounter } from "../docx/ooxmlCounterFormatter.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
5
|
+
import { LIST_RENDERING_ATTR_KEYS, hasListRendering } from "./listRenderingAttrs.js";
|
|
6
|
+
import { effectiveParagraphNumbering, paragraphNumberingSourcesFromBoundary } from "./numberingAttr.js";
|
|
6
7
|
//#region src/prosemirror/listMarker.ts
|
|
7
8
|
const MAX_LIST_LEVEL = 8;
|
|
8
9
|
const CLEARED_LIST_RENDERING_ATTRS = Object.freeze({
|
|
@@ -65,13 +66,12 @@ function cloneListCounterState(state) {
|
|
|
65
66
|
};
|
|
66
67
|
}
|
|
67
68
|
function previousListAttrs(attrs) {
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}))?.previousFormatting;
|
|
72
|
-
if (!previous || !isListNumPr(previous.numPr)) return null;
|
|
69
|
+
const change = attrs._propertyChanges?.at(0);
|
|
70
|
+
if (!change) return null;
|
|
71
|
+
const previous = change.previousFormatting ?? {};
|
|
73
72
|
return {
|
|
74
|
-
numPr: previous.numPr,
|
|
73
|
+
...previous.numPr == null ? {} : { numPr: previous.numPr },
|
|
74
|
+
...previous.numPrFromStyle == null ? {} : { numPrFromStyle: previous.numPrFromStyle },
|
|
75
75
|
...previous.listIsBullet !== void 0 ? { listIsBullet: previous.listIsBullet } : {},
|
|
76
76
|
...previous.listIsLegal !== void 0 ? { listIsLegal: previous.listIsLegal } : {},
|
|
77
77
|
...previous.listNumFmt !== void 0 ? { listNumFmt: previous.listNumFmt } : {},
|
|
@@ -111,61 +111,20 @@ function advanceVisibleListMarker(attrs, streams) {
|
|
|
111
111
|
return advanced;
|
|
112
112
|
};
|
|
113
113
|
const previous = previousListAttrs(attrs);
|
|
114
|
-
if (!attrs.numPr) return {
|
|
115
|
-
...advance(previous ?? attrs, previous ? "original" : "final"),
|
|
116
|
-
advances
|
|
117
|
-
};
|
|
118
114
|
if (attrs.pPrMark?.kind === "del") return {
|
|
119
|
-
...advance(attrs, "original"),
|
|
115
|
+
...advance(previous ?? attrs, "original"),
|
|
120
116
|
advances
|
|
121
117
|
};
|
|
122
|
-
const
|
|
123
|
-
const
|
|
124
|
-
const visible = advance(attrs, "final");
|
|
125
|
-
if (attrs.pPrMark?.kind !== "ins" && !numberingWasAdded && !numberingChanged) advance(attrs, "original");
|
|
126
|
-
else if (numberingChanged && previous) advance(previous, "original");
|
|
118
|
+
const final = advance(attrs, "final");
|
|
119
|
+
const original = attrs.pPrMark?.kind === "ins" ? void 0 : advance(previous ?? attrs, "original");
|
|
127
120
|
return {
|
|
128
|
-
...
|
|
121
|
+
...attrs.numPr?.kind !== "none" && final.marker === null && original && original.marker !== null && previous?.numPr?.kind === "reference" ? original : final,
|
|
129
122
|
advances
|
|
130
123
|
};
|
|
131
124
|
}
|
|
132
125
|
function formatCounter(value, format) {
|
|
133
126
|
return formatOoxmlCounter(value, format);
|
|
134
127
|
}
|
|
135
|
-
function resolveListTemplate(options) {
|
|
136
|
-
return resolveListTemplateWithComponents(options).value;
|
|
137
|
-
}
|
|
138
|
-
function resolveListTemplateWithComponents({ template, counters, levelFormats, forceDecimal = false }) {
|
|
139
|
-
const components = [];
|
|
140
|
-
let value = "";
|
|
141
|
-
let sourceEnd = 0;
|
|
142
|
-
for (const match of template.matchAll(/%(?<digit>\d)(?<punct>[.):\]])?/gu)) {
|
|
143
|
-
const sourceStart = match.index;
|
|
144
|
-
const relativeStart = value.length;
|
|
145
|
-
value += template.slice(sourceEnd, sourceStart);
|
|
146
|
-
sourceEnd = sourceStart + match[0].length;
|
|
147
|
-
const index = Number.parseInt(match.groups?.["digit"] ?? "", 10) - 1;
|
|
148
|
-
if (index < 0) continue;
|
|
149
|
-
const counter = counters[index];
|
|
150
|
-
if (counter === void 0 || Number.isNaN(counter)) continue;
|
|
151
|
-
const formatted = formatCounter(counter, forceDecimal ? "decimal" : levelFormats?.[index]);
|
|
152
|
-
if (!formatted) continue;
|
|
153
|
-
const start = value.length;
|
|
154
|
-
value += formatted;
|
|
155
|
-
components.push({
|
|
156
|
-
level: index,
|
|
157
|
-
relativeStart,
|
|
158
|
-
start,
|
|
159
|
-
end: value.length
|
|
160
|
-
});
|
|
161
|
-
value += match.groups?.["punct"] ?? "";
|
|
162
|
-
}
|
|
163
|
-
value += template.slice(sourceEnd);
|
|
164
|
-
return {
|
|
165
|
-
value,
|
|
166
|
-
components
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
128
|
function getLastListCounters(state) {
|
|
170
129
|
return state.lastAdvancedNumId === void 0 ? void 0 : state.counters.get(state.lastAdvancedNumId);
|
|
171
130
|
}
|
|
@@ -179,11 +138,23 @@ function formatNumberedMarker(counters, level) {
|
|
|
179
138
|
return parts.length === 0 ? "1." : `${parts.join(".")}.`;
|
|
180
139
|
}
|
|
181
140
|
function advanceListMarker(attrs, state) {
|
|
141
|
+
if (!hasListRendering(attrs)) {
|
|
142
|
+
state.previousList = {
|
|
143
|
+
abstractNumId: null,
|
|
144
|
+
fromStyle: false,
|
|
145
|
+
numId: null
|
|
146
|
+
};
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
182
149
|
const markerTemplate = attrs.listMarkerTemplate ?? attrs.listMarker;
|
|
183
150
|
const foldedMarkerSuffix = attrs.listFoldedMarkerSuffix ?? void 0;
|
|
184
|
-
const
|
|
151
|
+
const effectiveNumbering = effectiveParagraphNumbering(paragraphNumberingSourcesFromBoundary({
|
|
152
|
+
numPr: attrs.numPr,
|
|
153
|
+
numPrFromStyle: attrs.numPrFromStyle
|
|
154
|
+
}));
|
|
155
|
+
const level = paragraphNumberingLevel(effectiveNumbering) ?? 0;
|
|
185
156
|
if (!Number.isInteger(level) || level < 0 || level > 8) return null;
|
|
186
|
-
const numId = paragraphNumberingReferenceId(
|
|
157
|
+
const numId = paragraphNumberingReferenceId(effectiveNumbering);
|
|
187
158
|
if (numId === void 0) {
|
|
188
159
|
let marker = null;
|
|
189
160
|
if (markerTemplate?.includes("%") && !attrs.listIsBullet) {
|
|
@@ -222,7 +193,7 @@ function advanceListMarker(attrs, state) {
|
|
|
222
193
|
};
|
|
223
194
|
const restartedNumIds = state.restartedNumIds ??= /* @__PURE__ */ new Set();
|
|
224
195
|
const latestAbstractCounters = abstractNumId === void 0 ? void 0 : state.abstractCounters.get(abstractNumId);
|
|
225
|
-
const styleNumbering = attrs.numPrFromStyle;
|
|
196
|
+
const styleNumbering = attrs.numPr?.kind !== "reference" && attrs.numPrFromStyle?.kind === "reference";
|
|
226
197
|
const resumesRestartedInstance = firstInstanceEncounter && attrs.listStartOverride == null && abstractNumId !== void 0 && previousList.abstractNumId === abstractNumId && previousList.numId !== null && previousList.numId !== numId && restartedNumIds.has(previousList.numId);
|
|
227
198
|
const resumesStyleInstance = firstInstanceEncounter && !styleNumbering && attrs.listStartOverride == null && abstractNumId !== void 0 && previousList.abstractNumId === abstractNumId && previousList.fromStyle;
|
|
228
199
|
if (latestAbstractCounters && (styleNumbering || resumesRestartedInstance || resumesStyleInstance)) counters = latestAbstractCounters;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { mintListInstance, restartListInstance } from "../docx/listNumberingInstances.js";
|
|
2
2
|
import { createNumberingMap, isBulletLevel } from "../docx/numberingParser.js";
|
|
3
|
-
import {
|
|
3
|
+
import { paragraphNumberingReferenceId } from "../docx/numberingReference.js";
|
|
4
4
|
import { expectParagraphAttrs } from "./attrs/index.js";
|
|
5
5
|
import { withCanonicalCommand } from "./canonicalCommands.js";
|
|
6
6
|
import { paragraphPropertiesSnapshot } from "./commands/propertyChangeScope.js";
|
|
7
7
|
import { listRenderingFor, recordsListRendering } from "./listRendering.js";
|
|
8
8
|
import { LIST_RENDERING_ATTR_KEYS } from "./listRenderingAttrs.js";
|
|
9
|
+
import { effectiveParagraphNumbering, effectiveParagraphNumberingReference, paragraphNumberingAttr, paragraphNumberingSourcesFromBoundary } from "./numberingAttr.js";
|
|
9
10
|
import { directParagraphIndentation } from "./paragraphIndentation.js";
|
|
10
11
|
import { getDocumentNumbering } from "./plugins/documentNumbering.js";
|
|
11
12
|
import { getDocumentStyleResolver } from "./plugins/documentStyleState.js";
|
|
@@ -39,14 +40,19 @@ const PARAGRAPH_NODE = "paragraph";
|
|
|
39
40
|
const listChangeSnapshot = (node, attrs) => {
|
|
40
41
|
const previousFormatting = paragraphPropertiesSnapshot(node.type.create(attrs, node.content, node.marks));
|
|
41
42
|
previousFormatting["numPr"] ??= null;
|
|
43
|
+
previousFormatting["numPrFromStyle"] = attrs["numPrFromStyle"] ?? null;
|
|
42
44
|
for (const key of LIST_RENDERING_ATTR_KEYS) previousFormatting[key] = attrs[key] ?? null;
|
|
43
45
|
return previousFormatting;
|
|
44
46
|
};
|
|
45
47
|
const originalListFormatting = ({ record, numbering, styleResolver }) => {
|
|
46
48
|
const original = { ...record };
|
|
49
|
+
const inherited = styleResolver ? styleResolver.resolveParagraphStyle(record.styleId ?? void 0).paragraphFormatting?.numPr : record.numPrFromStyle ?? void 0;
|
|
50
|
+
original["numPrFromStyle"] = inherited === void 0 ? null : paragraphNumberingAttr(inherited);
|
|
47
51
|
if (recordsListRendering(record)) return original;
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
Object.assign(original, listRenderingFor(effectiveParagraphNumbering({
|
|
53
|
+
numPr: record.numPr ?? void 0,
|
|
54
|
+
numPrFromStyle: inherited
|
|
55
|
+
}), numbering));
|
|
50
56
|
original["numPr"] = record.numPr ?? null;
|
|
51
57
|
return original;
|
|
52
58
|
};
|
|
@@ -113,9 +119,13 @@ const levelMatches = (level, request) => {
|
|
|
113
119
|
const directListMembership = (node, numbering) => {
|
|
114
120
|
if (!node || node.type.name !== PARAGRAPH_NODE) return null;
|
|
115
121
|
const attrs = expectParagraphAttrs(node);
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
122
|
+
const effective = effectiveParagraphNumberingReference(paragraphNumberingSourcesFromBoundary({
|
|
123
|
+
numPr: attrs.numPr,
|
|
124
|
+
numPrFromStyle: attrs.numPrFromStyle
|
|
125
|
+
}));
|
|
126
|
+
if (attrs.numPr?.kind !== "reference" || effective === void 0) return null;
|
|
127
|
+
const numId = effective.numId;
|
|
128
|
+
const ilvl = effective.ilvl ?? 0;
|
|
119
129
|
const level = numbering?.getLevel(numId, ilvl) ?? null;
|
|
120
130
|
return level ? {
|
|
121
131
|
numId,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ParagraphAttrs, ParagraphPropertyChangeAttrs } from "./schema/nodes.js";
|
|
2
2
|
import { NumberingMap } from "../docx/numberingParser.js";
|
|
3
|
+
import { ListRenderingAttrKey } from "./listRenderingAttrs.js";
|
|
3
4
|
import { ParagraphNumberingOverride } from "../docx/numberingReference.js";
|
|
4
5
|
//#region src/prosemirror/listRendering.d.ts
|
|
5
6
|
type PreviousFormatting = NonNullable<ParagraphPropertyChangeAttrs["previousFormatting"]>;
|
|
@@ -13,12 +14,12 @@ declare const listRenderingFor: (numPr: ParagraphNumberingOverride | null | unde
|
|
|
13
14
|
* the scope it restores wholesale, so a record that does not state them (one
|
|
14
15
|
* written by an operation, or read from a file) would leave the rendering of
|
|
15
16
|
* the numbering it undoes: a paragraph restored to no numbering still showed
|
|
16
|
-
* the marker it was given.
|
|
17
|
-
*
|
|
17
|
+
* the marker it was given. Reconcile the rendering attrs with the restored
|
|
18
|
+
* numbering even when the effective reference itself did not change.
|
|
18
19
|
*/
|
|
19
20
|
type RejectedListRenderingOptions = {
|
|
20
21
|
/** The paragraph's attrs before the reject. */
|
|
21
|
-
current: Pick<ParagraphAttrs, "numPr">;
|
|
22
|
+
current: Pick<ParagraphAttrs, "numPr" | "numPrFromStyle" | ListRenderingAttrKey>;
|
|
22
23
|
/** The previous state the rejected record restores. */
|
|
23
24
|
previousFormatting: PreviousFormatting | null | undefined;
|
|
24
25
|
numbering: NumberingMap | null;
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { paragraphNumberingLevel, paragraphNumberingReferenceId, sameStatedParagraphNumbering } from "../docx/numberingReference.js";
|
|
2
2
|
import { CLEARED_LIST_RENDERING_ATTRS } from "./listMarker.js";
|
|
3
3
|
import { LIST_RENDERING_ATTR_KEYS } from "./listRenderingAttrs.js";
|
|
4
|
+
import { effectiveParagraphNumbering, paragraphNumberingSourcesFromBoundary } from "./numberingAttr.js";
|
|
4
5
|
import { listAttrsFromNumbering } from "./styles/resolvedStyleAttrs.js";
|
|
5
6
|
//#region src/prosemirror/listRendering.ts
|
|
7
|
+
/** These attrs come from inline content, not the numbering definition. */
|
|
8
|
+
const CONTENT_DERIVED_LIST_RENDERING_ATTRS = /* @__PURE__ */ new Set(["listImplicitChildLevelAdvances", "listMarkerSecondSlotOffsetTwips"]);
|
|
6
9
|
/** Whether a `w:pPrChange` record states the list rendering it had (a list command's does). */
|
|
7
10
|
const recordsListRendering = (record) => LIST_RENDERING_ATTR_KEYS.some((key) => Object.hasOwn(record, key));
|
|
8
11
|
/** Every list-rendering attr for `numPr`: its level's, or all cleared when it numbers nothing. */
|
|
@@ -17,10 +20,26 @@ const listRenderingFor = (numPr, numbering) => {
|
|
|
17
20
|
return attrs;
|
|
18
21
|
};
|
|
19
22
|
const rejectedListRenderingPatch = ({ current, previousFormatting, numbering, restoredNumbering }) => {
|
|
20
|
-
|
|
23
|
+
const record = previousFormatting ?? {};
|
|
24
|
+
if (recordsListRendering(record)) {
|
|
25
|
+
const patch = {};
|
|
26
|
+
for (const key of LIST_RENDERING_ATTR_KEYS) patch[key] = record[key] ?? null;
|
|
27
|
+
return patch;
|
|
28
|
+
}
|
|
21
29
|
const restored = restoredNumbering ?? void 0;
|
|
22
|
-
if (sameStatedParagraphNumbering(restored,
|
|
23
|
-
|
|
30
|
+
if (!sameStatedParagraphNumbering(restored, effectiveParagraphNumbering(paragraphNumberingSourcesFromBoundary({
|
|
31
|
+
numPr: current.numPr,
|
|
32
|
+
numPrFromStyle: current.numPrFromStyle
|
|
33
|
+
})))) return listRenderingFor(restored, numbering);
|
|
34
|
+
const expected = listRenderingFor(restored, numbering);
|
|
35
|
+
const patch = {};
|
|
36
|
+
for (const key of LIST_RENDERING_ATTR_KEYS) {
|
|
37
|
+
if (CONTENT_DERIVED_LIST_RENDERING_ATTRS.has(key)) continue;
|
|
38
|
+
const currentValue = current[key] ?? null;
|
|
39
|
+
const expectedValue = expected[key] ?? null;
|
|
40
|
+
if (JSON.stringify(currentValue) !== JSON.stringify(expectedValue)) patch[key] = expectedValue;
|
|
41
|
+
}
|
|
42
|
+
return Object.keys(patch).length === 0 ? {} : patch;
|
|
24
43
|
};
|
|
25
44
|
//#endregion
|
|
26
45
|
export { listRenderingFor, recordsListRendering, rejectedListRenderingPatch };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { ParagraphNumberingBoundarySources } from "./numberingAttr.js";
|
|
2
3
|
import { ParagraphAttrs } from "./schema/nodes.js";
|
|
3
4
|
//#region src/prosemirror/listRenderingAttrs.d.ts
|
|
4
5
|
/** `ListRendering` fields that have their own editor attr. */
|
|
@@ -39,7 +40,7 @@ declare const listRenderingAttrPatch: (rendering: document_d_exports.ListRenderi
|
|
|
39
40
|
*/
|
|
40
41
|
declare const hasListRendering: (attrs: Pick<ParagraphAttrs, "listMarker" | "listIsBullet" | "listNumFmt">) => boolean;
|
|
41
42
|
/** The attrs a rendering is read back from: a paragraph's, or a recorded previous state's. */
|
|
42
|
-
type ListRenderingSourceAttrs = Pick<ParagraphAttrs, ListRenderingAttrKey
|
|
43
|
+
type ListRenderingSourceAttrs = Pick<ParagraphAttrs, ListRenderingAttrKey> & Partial<ParagraphNumberingBoundarySources>;
|
|
43
44
|
type ListRenderingFromAttrsOptions = {
|
|
44
45
|
attrs: ListRenderingSourceAttrs;
|
|
45
46
|
numId: number;
|
|
@@ -1,14 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { effectiveParagraphNumberingReference, paragraphNumberingSourcesFromBoundary } from "./numberingAttr.js";
|
|
2
2
|
//#region src/prosemirror/listRenderingAttrs.ts
|
|
3
|
-
/**
|
|
4
|
-
* The one table that ties `Paragraph.listRendering` to the editor's `list*`
|
|
5
|
-
* attrs. Both projections (model → attrs in `toProseDoc`, attrs → model in
|
|
6
|
-
* `fromProseDoc`) and the cleared-attr set derive from it, so a field added
|
|
7
|
-
* to `ListRendering` without a projection fails to compile instead of being
|
|
8
|
-
* silently dropped on the way out of the editor.
|
|
9
|
-
*
|
|
10
|
-
* `level` and `numId` are not here: they travel in `numPr`.
|
|
11
|
-
*/
|
|
12
3
|
const LIST_RENDERING_ATTR_BY_FIELD = {
|
|
13
4
|
marker: "listMarker",
|
|
14
5
|
markerTemplate: "listMarkerTemplate",
|
|
@@ -91,9 +82,13 @@ const listRenderingFromAttrs = ({ attrs, numId }) => {
|
|
|
91
82
|
implicitChildLevelAdvances: attrs.listImplicitChildLevelAdvances ?? void 0,
|
|
92
83
|
markerSecondSlotOffsetTwips: attrs.listMarkerSecondSlotOffsetTwips ?? void 0
|
|
93
84
|
};
|
|
85
|
+
const numbering = effectiveParagraphNumberingReference(paragraphNumberingSourcesFromBoundary({
|
|
86
|
+
numPr: attrs.numPr,
|
|
87
|
+
numPrFromStyle: attrs.numPrFromStyle
|
|
88
|
+
}));
|
|
94
89
|
return {
|
|
95
90
|
marker: attrs.listMarker ?? "",
|
|
96
|
-
level:
|
|
91
|
+
level: numbering?.ilvl ?? 0,
|
|
97
92
|
numId,
|
|
98
93
|
isBullet: attrs.listIsBullet ?? false,
|
|
99
94
|
...definedFields(optional)
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { resolveListTemplateWithComponents } from "../docx/listTemplate.js";
|
|
2
2
|
import { expectFieldAttrs, expectParagraphAttrs } from "./attrs/index.js";
|
|
3
3
|
import { expectBookmarkBoundaryAttrs } from "./bookmarkBoundaryAttrs.js";
|
|
4
|
-
import { advanceVisibleListMarker, createListCounterState
|
|
4
|
+
import { advanceVisibleListMarker, createListCounterState } from "./listMarker.js";
|
|
5
|
+
import { effectiveParagraphNumberingReference, paragraphNumberingSourcesFromBoundary } from "./numberingAttr.js";
|
|
5
6
|
import { Fragment } from "prosemirror-model";
|
|
6
7
|
//#region src/prosemirror/numberedRefFields.ts
|
|
7
8
|
const MAX_FIELD_INSTRUCTION_CHARS = 2048;
|
|
@@ -79,10 +80,13 @@ function numberTargetForParagraph(node, contextStreams, streams) {
|
|
|
79
80
|
return visibleTarget;
|
|
80
81
|
}
|
|
81
82
|
function numberTargetForAdvancedMarker(attrs, resolvedMarker, state, contexts) {
|
|
82
|
-
const
|
|
83
|
-
|
|
83
|
+
const numbering = effectiveParagraphNumberingReference(paragraphNumberingSourcesFromBoundary({
|
|
84
|
+
numPr: attrs.numPr,
|
|
85
|
+
numPrFromStyle: attrs.numPrFromStyle
|
|
86
|
+
}));
|
|
87
|
+
if (numbering === void 0 || attrs.listIsBullet || attrs.listMarkerHidden || attrs.listNumFmt === "none" || !resolvedMarker) return null;
|
|
88
|
+
const { numId, ilvl: level } = numbering;
|
|
84
89
|
const marker = attrs.listMarkerAllCaps ? resolvedMarker.toLocaleUpperCase() : resolvedMarker;
|
|
85
|
-
const level = paragraphNumberingLevel(attrs.numPr) ?? 0;
|
|
86
90
|
if (!Number.isInteger(level) || level < 0 || level > 8) return null;
|
|
87
91
|
const counters = state.counters.get(numId)?.slice(0, level + 1);
|
|
88
92
|
const levelFormats = attrs.listLevelNumFmts ?? (attrs.listNumFmt ? [attrs.listNumFmt] : void 0);
|
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
import { ParagraphNumberingOverride } from "@stll/docx-core/model";
|
|
2
2
|
//#region src/prosemirror/numberingAttr.d.ts
|
|
3
|
+
type ParagraphNumberingSources = {
|
|
4
|
+
numPr: ParagraphNumberingOverride | undefined;
|
|
5
|
+
numPrFromStyle: ParagraphNumberingOverride | undefined;
|
|
6
|
+
};
|
|
7
|
+
type ParagraphNumberingBoundarySources = {
|
|
8
|
+
numPr: ParagraphNumberingOverride | null | undefined;
|
|
9
|
+
numPrFromStyle: ParagraphNumberingOverride | null | undefined;
|
|
10
|
+
};
|
|
11
|
+
/** Normalize attr absence at the boundary, while requiring both source tiers. */
|
|
12
|
+
declare const paragraphNumberingSourcesFromBoundary: ({ numPr, numPrFromStyle }: ParagraphNumberingBoundarySources) => ParagraphNumberingSources;
|
|
13
|
+
/** Effective membership is derived; neither source slot becomes an authored override. */
|
|
14
|
+
declare const effectiveParagraphNumbering: ({ numPr, numPrFromStyle }: ParagraphNumberingSources) => import("@stll/docx-core/model").ResolvedParagraphNumbering;
|
|
15
|
+
/** A list reference for membership consumers; cancellation and absence are not lists.
|
|
16
|
+
* OOXML defaults an omitted ilvl to zero only within an existing numbering reference.
|
|
17
|
+
*/
|
|
18
|
+
declare const effectiveParagraphNumberingReference: (sources: ParagraphNumberingSources) => (import("@stll/docx-core/model").ParagraphNumberingReference & {
|
|
19
|
+
readonly ilvl: number;
|
|
20
|
+
}) | undefined;
|
|
3
21
|
declare const PARAGRAPH_NUMBERING_ATTR: unique symbol;
|
|
4
22
|
/**
|
|
5
23
|
* The only value a persisted `numPr` attr slot may hold.
|
|
@@ -60,4 +78,4 @@ declare const paragraphNumberingFromAttrValue: (value: unknown) => ParagraphNumb
|
|
|
60
78
|
*/
|
|
61
79
|
declare const readParagraphNumberingAttr: (value: unknown) => ParagraphNumberingAttr | null;
|
|
62
80
|
//#endregion
|
|
63
|
-
export { ParagraphNumberingAttr, paragraphNumberingAttr, paragraphNumberingFromAttrValue, readParagraphNumberingAttr, removedNumberingAttr };
|
|
81
|
+
export { ParagraphNumberingAttr, ParagraphNumberingBoundarySources, ParagraphNumberingSources, effectiveParagraphNumbering, effectiveParagraphNumberingReference, paragraphNumberingAttr, paragraphNumberingFromAttrValue, paragraphNumberingSourcesFromBoundary, readParagraphNumberingAttr, removedNumberingAttr };
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import { panic } from "better-result";
|
|
2
|
-
import { NO_PARAGRAPH_NUMBERING, paragraphNumberingFromSlots, paragraphNumberingReference } from "@stll/docx-core/model";
|
|
2
|
+
import { NO_PARAGRAPH_NUMBERING, mergeParagraphNumbering, paragraphNumberingFromSlots, paragraphNumberingReference, resolveParagraphNumbering } from "@stll/docx-core/model";
|
|
3
3
|
//#region src/prosemirror/numberingAttr.ts
|
|
4
|
+
/** Normalize attr absence at the boundary, while requiring both source tiers. */
|
|
5
|
+
const paragraphNumberingSourcesFromBoundary = ({ numPr, numPrFromStyle }) => ({
|
|
6
|
+
numPr: numPr ?? void 0,
|
|
7
|
+
numPrFromStyle: numPrFromStyle ?? void 0
|
|
8
|
+
});
|
|
9
|
+
/** Effective membership is derived; neither source slot becomes an authored override. */
|
|
10
|
+
const effectiveParagraphNumbering = ({ numPr, numPrFromStyle }) => resolveParagraphNumbering(mergeParagraphNumbering(numPrFromStyle, numPr));
|
|
11
|
+
/** A list reference for membership consumers; cancellation and absence are not lists.
|
|
12
|
+
* OOXML defaults an omitted ilvl to zero only within an existing numbering reference.
|
|
13
|
+
*/
|
|
14
|
+
const effectiveParagraphNumberingReference = (sources) => {
|
|
15
|
+
const numbering = effectiveParagraphNumbering(sources);
|
|
16
|
+
return numbering.kind === "reference" ? numbering : void 0;
|
|
17
|
+
};
|
|
4
18
|
const branded = (numbering) => numbering;
|
|
5
19
|
/** Mint the attr value for a stated override: the one model-to-attr crossing. */
|
|
6
20
|
const paragraphNumberingAttr = (numbering) => {
|
|
@@ -79,4 +93,4 @@ const readParagraphNumberingAttr = (value) => {
|
|
|
79
93
|
return numbering;
|
|
80
94
|
};
|
|
81
95
|
//#endregion
|
|
82
|
-
export { paragraphNumberingAttr, paragraphNumberingFromAttrValue, readParagraphNumberingAttr, removedNumberingAttr };
|
|
96
|
+
export { effectiveParagraphNumbering, effectiveParagraphNumberingReference, paragraphNumberingAttr, paragraphNumberingFromAttrValue, paragraphNumberingSourcesFromBoundary, readParagraphNumberingAttr, removedNumberingAttr };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { effectiveParagraphNumberingReference, paragraphNumberingSourcesFromBoundary } from "./numberingAttr.js";
|
|
2
2
|
import { panic } from "better-result";
|
|
3
3
|
//#region src/prosemirror/paragraphIndentation.ts
|
|
4
4
|
const DIRECT_PARAGRAPH_INDENTATION_KEYS = [
|
|
@@ -50,7 +50,10 @@ const PARAGRAPH_INDENTATION_VALUE_KEYS = [
|
|
|
50
50
|
const directParagraphIndentation = (attrs) => {
|
|
51
51
|
const original = attrs._originalFormatting ?? void 0;
|
|
52
52
|
const resolved = attrs._resolvedFormatting;
|
|
53
|
-
const numbered =
|
|
53
|
+
const numbered = effectiveParagraphNumberingReference(paragraphNumberingSourcesFromBoundary({
|
|
54
|
+
numPr: attrs.numPr,
|
|
55
|
+
numPrFromStyle: attrs.numPrFromStyle
|
|
56
|
+
})) !== void 0;
|
|
54
57
|
const indentation = {};
|
|
55
58
|
for (const key of PARAGRAPH_INDENTATION_VALUE_KEYS) {
|
|
56
59
|
const value = attrs[key];
|
|
@@ -1,12 +1,26 @@
|
|
|
1
|
-
import { joinProseParagraphsWithRightPropertySource } from "../docx/paragraphPropertySource.js";
|
|
1
|
+
import { getProseParagraphPropertySourceToken, joinProseParagraphsWithRightPropertySource, markParagraphPropertySourceTransfers } from "../docx/paragraphPropertySource.js";
|
|
2
|
+
import { paragraphJoinAfter } from "./commands/paragraphBookmarkJoin.js";
|
|
2
3
|
import { JOINED_RUNS_RESTYLED_META } from "./extensions/features/JoinedRunStyleExtension.js";
|
|
3
4
|
import { rebaseParagraphRuns } from "./rebaseParagraphRunFormatting.js";
|
|
4
5
|
import { paragraphRunStyleContext } from "./runStyleFormatting.js";
|
|
6
|
+
import { panic } from "better-result";
|
|
5
7
|
//#region src/prosemirror/paragraphMarkJoin.ts
|
|
6
8
|
const joinAtParagraphMark = ({ tr, paragraphPos, paragraph, next, styleResolver }) => {
|
|
7
|
-
|
|
9
|
+
const boundary = paragraphPos + paragraph.nodeSize;
|
|
10
|
+
const join = paragraphJoinAfter(tr.doc, boundary);
|
|
11
|
+
if (!join || join.next !== next) panic("A paragraph-mark join lost its next paragraph");
|
|
12
|
+
if (join.inlineBookmarks.length > 0) {
|
|
13
|
+
const leftToken = getProseParagraphPropertySourceToken(paragraph);
|
|
14
|
+
const rightToken = getProseParagraphPropertySourceToken(next);
|
|
15
|
+
tr.replaceWith(boundary - 1, join.nextPosition + 1, join.inlineBookmarks);
|
|
16
|
+
tr.setNodeMarkup(paragraphPos, void 0, next.attrs);
|
|
17
|
+
markParagraphPropertySourceTransfers(tr, [{
|
|
18
|
+
displacedToken: typeof leftToken === "string" ? leftToken : null,
|
|
19
|
+
selectedToken: typeof rightToken === "string" ? rightToken : null
|
|
20
|
+
}]);
|
|
21
|
+
} else joinProseParagraphsWithRightPropertySource({
|
|
8
22
|
attrs: next.attrs,
|
|
9
|
-
pos:
|
|
23
|
+
pos: boundary,
|
|
10
24
|
transaction: tr
|
|
11
25
|
});
|
|
12
26
|
if (!styleResolver) return;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { expectParagraphAttrs } from "./attrs/index.js";
|
|
2
|
+
import { paragraphJoinAfter } from "./commands/paragraphBookmarkJoin.js";
|
|
2
3
|
import { hasSerializableParagraphPropertyChange, paragraphPropertiesSnapshot } from "./commands/propertyChangeScope.js";
|
|
3
4
|
import { resolveParagraphChangeAttrs } from "./commands/resolveParagraphProperties.js";
|
|
4
5
|
import { rebaseParagraphRuns } from "./rebaseParagraphRunFormatting.js";
|
|
@@ -106,13 +107,11 @@ const paragraphLeftAfter = ({ doc, paragraphPos, removedBreakPositions }) => {
|
|
|
106
107
|
if (!start) return null;
|
|
107
108
|
let node = start;
|
|
108
109
|
for (;;) {
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
const join = paragraphJoinAfter(doc, position + node.nodeSize);
|
|
111
|
+
if (!join) return null;
|
|
112
|
+
const { next, nextPosition: nextPos } = join;
|
|
112
113
|
const mark = expectParagraphAttrs(next).pPrMark;
|
|
113
|
-
|
|
114
|
-
const afterNext = doc.resolve(nextPos + next.nodeSize).nodeAfter;
|
|
115
|
-
if (!nextGoes || afterNext?.type !== node.type) return nextPos;
|
|
114
|
+
if (!(removedBreakPositions?.has(nextPos) || mark != null && (mark.kind === "del" || mark.kind === "moveFrom")) || !paragraphJoinAfter(doc, nextPos + next.nodeSize)) return nextPos;
|
|
116
115
|
position = nextPos;
|
|
117
116
|
node = next;
|
|
118
117
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { EditorState, Plugin, PluginKey } from "prosemirror-state";
|
|
2
|
+
//#region src/prosemirror/pluginKeyOwner.d.ts
|
|
3
|
+
type PluginKeyOwner<State> = Readonly<{
|
|
4
|
+
key: string;
|
|
5
|
+
createKey: () => PluginKey<State>;
|
|
6
|
+
owns: (plugin: Plugin<State>) => boolean;
|
|
7
|
+
get: (state: EditorState) => Plugin<State> | undefined;
|
|
8
|
+
getState: (state: EditorState) => State | undefined;
|
|
9
|
+
}>;
|
|
10
|
+
/** An immutable plugin family descriptor; each plugin owns its actual key. */
|
|
11
|
+
declare const createPluginKeyOwner: <State = unknown>(name: string) => PluginKeyOwner<State>;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { PluginKeyOwner, createPluginKeyOwner };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { panic } from "better-result";
|
|
2
|
+
import { PluginKey } from "prosemirror-state";
|
|
3
|
+
//#region src/prosemirror/pluginKeyOwner.ts
|
|
4
|
+
const PLUGIN_KEY_PREFIX = "stll.folio.plugin.";
|
|
5
|
+
const METADATA_KEY_PREFIX = "stll.folio.meta.";
|
|
6
|
+
const PLUGIN_OWNER_BRAND = Symbol.for("stll.folio.plugin.owner");
|
|
7
|
+
/** An immutable plugin family descriptor; each plugin owns its actual key. */
|
|
8
|
+
const createPluginKeyOwner = (name) => {
|
|
9
|
+
const pluginsByState = /* @__PURE__ */ new WeakMap();
|
|
10
|
+
const owns = (plugin) => plugin.spec.key !== void 0 && PLUGIN_OWNER_BRAND in plugin.spec.key && plugin.spec.key[PLUGIN_OWNER_BRAND] === name;
|
|
11
|
+
const get = (state) => {
|
|
12
|
+
if (pluginsByState.has(state)) return pluginsByState.get(state);
|
|
13
|
+
let found;
|
|
14
|
+
for (const plugin of state.plugins) {
|
|
15
|
+
if (!owns(plugin)) continue;
|
|
16
|
+
if (found) panic(`Multiple plugins belong to ${name} in one editor state`);
|
|
17
|
+
found = plugin;
|
|
18
|
+
}
|
|
19
|
+
pluginsByState.set(state, found);
|
|
20
|
+
return found;
|
|
21
|
+
};
|
|
22
|
+
return Object.freeze({
|
|
23
|
+
key: `${METADATA_KEY_PREFIX}${name}`,
|
|
24
|
+
createKey: () => {
|
|
25
|
+
const key = new PluginKey(`${PLUGIN_KEY_PREFIX}${name}`);
|
|
26
|
+
Object.defineProperty(key, PLUGIN_OWNER_BRAND, { value: name });
|
|
27
|
+
return key;
|
|
28
|
+
},
|
|
29
|
+
owns,
|
|
30
|
+
get,
|
|
31
|
+
getState: (state) => get(state)?.getState(state)
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
//#endregion
|
|
35
|
+
export { createPluginKeyOwner };
|
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PluginKeyOwner } from "../pluginKeyOwner.js";
|
|
2
|
+
import { Plugin } from "prosemirror-state";
|
|
2
3
|
import { DecorationSet } from "prosemirror-view";
|
|
3
4
|
//#region src/prosemirror/plugins/aiCitationDecorations.d.ts
|
|
4
|
-
declare const aiCitationDecorationsKey:
|
|
5
|
+
declare const aiCitationDecorationsKey: Readonly<{
|
|
6
|
+
key: string;
|
|
7
|
+
createKey: () => import("prosemirror-state").PluginKey<AICitationDecorationState>;
|
|
8
|
+
owns: (plugin: Plugin<AICitationDecorationState>) => boolean;
|
|
9
|
+
get: (state: import("prosemirror-state").EditorState) => Plugin<AICitationDecorationState> | undefined;
|
|
10
|
+
getState: (state: import("prosemirror-state").EditorState) => AICitationDecorationState | undefined;
|
|
11
|
+
}>;
|
|
5
12
|
declare const SET_META = "set";
|
|
6
13
|
declare const ACTIVE_META = "active";
|
|
7
14
|
type AICitationRange = {
|
|
@@ -23,14 +30,14 @@ type AICitationDecorationState = {
|
|
|
23
30
|
*/
|
|
24
31
|
declare function createAICitationDecorationsPlugin(): Plugin<AICitationDecorationState>;
|
|
25
32
|
declare function setAICitationsMeta(citations: AICitationRange[]): {
|
|
26
|
-
key:
|
|
33
|
+
key: PluginKeyOwner<AICitationDecorationState>;
|
|
27
34
|
payload: {
|
|
28
35
|
type: typeof SET_META;
|
|
29
36
|
citations: AICitationRange[];
|
|
30
37
|
};
|
|
31
38
|
};
|
|
32
39
|
declare function setActiveCitationMeta(activeId: string | null): {
|
|
33
|
-
key:
|
|
40
|
+
key: PluginKeyOwner<AICitationDecorationState>;
|
|
34
41
|
payload: {
|
|
35
42
|
type: typeof ACTIVE_META;
|
|
36
43
|
activeId: string | null;
|
|
@@ -1,7 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createPluginKeyOwner } from "../pluginKeyOwner.js";
|
|
2
|
+
import { Plugin } from "prosemirror-state";
|
|
2
3
|
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
3
4
|
//#region src/prosemirror/plugins/aiCitationDecorations.ts
|
|
4
|
-
|
|
5
|
+
/**
|
|
6
|
+
* AI Citation Decorations Plugin
|
|
7
|
+
*
|
|
8
|
+
* Renders pointer-back-to-source highlights on Folio (DOCX) ranges
|
|
9
|
+
* cited by an AI answer. Distinct from the suggestion-decoration
|
|
10
|
+
* plugin: citations are read-only pointers (no edit semantics) and
|
|
11
|
+
* usually appear briefly when the user clicks a citation chip in the
|
|
12
|
+
* thread.
|
|
13
|
+
*
|
|
14
|
+
* The host pushes updates via the `setAICitationsMeta` /
|
|
15
|
+
* `setActiveCitationMeta` helpers below.
|
|
16
|
+
*/
|
|
17
|
+
const aiCitationDecorationsKey = createPluginKeyOwner("aiCitationDecorations");
|
|
5
18
|
const SET_META = "set";
|
|
6
19
|
const ACTIVE_META = "active";
|
|
7
20
|
function buildDecorationSet(doc, citations, activeId) {
|
|
@@ -31,7 +44,7 @@ function buildDecorationSet(doc, citations, activeId) {
|
|
|
31
44
|
*/
|
|
32
45
|
function createAICitationDecorationsPlugin() {
|
|
33
46
|
return new Plugin({
|
|
34
|
-
key: aiCitationDecorationsKey,
|
|
47
|
+
key: aiCitationDecorationsKey.createKey(),
|
|
35
48
|
state: {
|
|
36
49
|
init(_, state) {
|
|
37
50
|
return {
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { AISuggestion, AISuggestionSeverity } from "../../ai-suggestions/types.js";
|
|
2
|
-
import {
|
|
2
|
+
import { PluginKeyOwner } from "../pluginKeyOwner.js";
|
|
3
|
+
import { Plugin } from "prosemirror-state";
|
|
3
4
|
import { DecorationSet } from "prosemirror-view";
|
|
4
5
|
//#region src/prosemirror/plugins/aiSuggestionDecorations.d.ts
|
|
5
|
-
declare const aiSuggestionDecorationsKey:
|
|
6
|
+
declare const aiSuggestionDecorationsKey: Readonly<{
|
|
7
|
+
key: string;
|
|
8
|
+
createKey: () => import("prosemirror-state").PluginKey<AISuggestionDecorationState>;
|
|
9
|
+
owns: (plugin: Plugin<AISuggestionDecorationState>) => boolean;
|
|
10
|
+
get: (state: import("prosemirror-state").EditorState) => Plugin<AISuggestionDecorationState> | undefined;
|
|
11
|
+
getState: (state: import("prosemirror-state").EditorState) => AISuggestionDecorationState | undefined;
|
|
12
|
+
}>;
|
|
6
13
|
declare const SET_META = "set";
|
|
7
14
|
declare const FOCUS_META = "focus";
|
|
8
15
|
type AISuggestionDecorationState = {
|
|
@@ -24,14 +31,14 @@ declare const AI_SUGGESTION_SEVERITY_CLASS: Record<AISuggestionSeverity, string>
|
|
|
24
31
|
*/
|
|
25
32
|
declare function createAISuggestionDecorationsPlugin(): Plugin<AISuggestionDecorationState>;
|
|
26
33
|
declare function setAISuggestionsMeta(suggestions: AISuggestion[]): {
|
|
27
|
-
key:
|
|
34
|
+
key: PluginKeyOwner<AISuggestionDecorationState>;
|
|
28
35
|
payload: {
|
|
29
36
|
type: typeof SET_META;
|
|
30
37
|
suggestions: AISuggestion[];
|
|
31
38
|
};
|
|
32
39
|
};
|
|
33
40
|
declare function setFocusedSuggestionMeta(focusedId: string | null): {
|
|
34
|
-
key:
|
|
41
|
+
key: PluginKeyOwner<AISuggestionDecorationState>;
|
|
35
42
|
payload: {
|
|
36
43
|
type: typeof FOCUS_META;
|
|
37
44
|
focusedId: string | null;
|