@stll/folio-core 0.54.1 → 0.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-edits/apply.d.ts +1 -1
- package/dist/ai-edits/apply.js +40 -32
- package/dist/ai-edits/headless.d.ts +1 -2
- package/dist/ai-edits/headless.js +13 -27
- package/dist/ai-edits/read.d.ts +1 -0
- package/dist/ai-edits/read.js +7 -2
- package/dist/ai-edits/table-mutation-plan.d.ts +2 -1
- package/dist/ai-edits/table-mutation-plan.js +39 -1
- package/dist/ai-suggestions/apply.d.ts +1 -1
- package/dist/ai-suggestions/apply.js +3 -2
- package/dist/compare/compare.js +2 -1
- package/dist/compare/content-types.d.ts +3 -15
- package/dist/controller/canonicalComposition.d.ts +36 -0
- package/dist/controller/canonicalComposition.js +168 -0
- package/dist/controller/canonicalInput.d.ts +45 -0
- package/dist/controller/canonicalInput.js +338 -0
- package/dist/controller/canonicalOperations.d.ts +22 -0
- package/dist/controller/canonicalOperations.js +85 -0
- package/dist/controller/canonicalReview.d.ts +12 -0
- package/dist/controller/canonicalReview.js +19 -0
- package/dist/controller/canonicalSession.d.ts +149 -0
- package/dist/controller/canonicalSession.js +1038 -0
- package/dist/controller/canonicalStoryEditor.d.ts +34 -0
- package/dist/controller/canonicalStoryEditor.js +82 -0
- package/dist/controller/canonicalStructure.d.ts +16 -0
- package/dist/controller/canonicalStructure.js +269 -0
- package/dist/controller/folioEditor.d.ts +1 -1
- package/dist/controller/folioEditor.js +9 -0
- package/dist/controller/headerFooterEditorManager.d.ts +4 -0
- package/dist/controller/headerFooterEditorManager.js +71 -3
- package/dist/controller/hiddenEditorApi.d.ts +35 -0
- package/dist/controller/hiddenEditorApi.js +25 -8
- package/dist/controller/hiddenEditorManager.d.ts +11 -2
- package/dist/controller/hiddenEditorManager.js +456 -30
- package/dist/controller/layoutPipeline.d.ts +1 -1
- package/dist/controller/layoutPipeline.js +2 -0
- package/dist/controller/noteEditorManager.d.ts +4 -0
- package/dist/controller/noteEditorManager.js +113 -15
- package/dist/docx/attributeRemainder.js +1 -0
- package/dist/docx/bookmarkIds.d.ts +11 -0
- package/dist/docx/bookmarkIds.js +33 -0
- package/dist/docx/canonicalSessionInput.d.ts +11 -0
- package/dist/docx/canonicalSessionInput.js +27 -0
- package/dist/docx/canonicalStoryRepack.d.ts +10 -0
- package/dist/docx/canonicalStoryRepack.js +41 -0
- package/dist/docx/contentTypeRegistry.d.ts +8 -0
- package/dist/docx/contentTypeRegistry.js +64 -0
- package/dist/docx/documentParser.d.ts +14 -1
- package/dist/docx/documentParser.js +17 -4
- package/dist/docx/drawingIdNormalization.js +23 -8
- package/dist/docx/ensureParaIds.d.ts +12 -1
- package/dist/docx/ensureParaIds.js +173 -213
- package/dist/docx/foldedListNumberFields.d.ts +85 -0
- package/dist/docx/foldedListNumberFields.js +267 -0
- package/dist/docx/headerFooterVerbatim.d.ts +14 -1
- package/dist/docx/headerFooterVerbatim.js +95 -2
- package/dist/docx/listNumberingInstances.js +11 -9
- package/dist/docx/noteIds.d.ts +9 -0
- package/dist/docx/noteIds.js +17 -0
- package/dist/docx/noteReferenceMark.d.ts +3 -1
- package/dist/docx/noteReferenceMark.js +15 -14
- package/dist/docx/numberingIds.d.ts +14 -0
- package/dist/docx/numberingIds.js +16 -0
- package/dist/docx/numberingParser.d.ts +3 -1
- package/dist/docx/numberingParser.js +17 -3
- package/dist/docx/numericIdAllocator.d.ts +12 -0
- package/dist/docx/numericIdAllocator.js +33 -0
- package/dist/docx/numericIdNormalization.d.ts +16 -0
- package/dist/docx/numericIdNormalization.js +174 -0
- package/dist/docx/packageParts.d.ts +3 -1
- package/dist/docx/packageParts.js +65 -16
- package/dist/docx/paragraphMarkPropertyPresence.d.ts +9 -0
- package/dist/docx/paragraphMarkPropertyPresence.js +21 -0
- package/dist/docx/paragraphParser.js +101 -53
- package/dist/docx/paragraphPropertySource.d.ts +15 -1
- package/dist/docx/paragraphPropertySource.js +76 -22
- package/dist/docx/paragraphTextBoxEnrichment.js +2 -1
- package/dist/docx/parser.js +19 -6
- package/dist/docx/rasterMime.d.ts +64 -0
- package/dist/docx/rasterMime.js +116 -0
- package/dist/docx/replyToComment.js +13 -6
- package/dist/docx/reviewHistoryNamespace.d.ts +4 -0
- package/dist/docx/reviewHistoryNamespace.js +4 -0
- package/dist/docx/reviewResolutionProvenance.d.ts +25 -0
- package/dist/docx/reviewResolutionProvenance.js +153 -0
- package/dist/docx/rezip.d.ts +7 -3
- package/dist/docx/rezip.js +121 -52
- package/dist/docx/runConsolidator.d.ts +2 -58
- package/dist/docx/runConsolidator.js +3 -175
- package/dist/docx/runParser.d.ts +2 -1
- package/dist/docx/runParser.js +156 -116
- package/dist/docx/saveDiagnostics.d.ts +11 -0
- package/dist/docx/saveDiagnostics.js +0 -0
- package/dist/docx/selectiveSave.d.ts +2 -1
- package/dist/docx/selectiveSave.js +14 -1
- package/dist/docx/selectiveXmlPatch.d.ts +16 -8
- package/dist/docx/selectiveXmlPatch.js +74 -2
- package/dist/docx/serializer/headerFooterSerializer.d.ts +5 -1
- package/dist/docx/serializer/headerFooterSerializer.js +19 -11
- package/dist/docx/serializer/noteSerializer.d.ts +2 -2
- package/dist/docx/serializer/noteSerializer.js +24 -8
- package/dist/docx/serializer/paragraphSerializer.js +41 -4
- package/dist/docx/serializer/partNamespaces.js +6 -3
- package/dist/docx/serializer/runSerializer.js +8 -5
- package/dist/docx/serializer/trackedChangeAttributes.js +7 -1
- package/dist/docx/server/build.js +14 -3
- package/dist/docx/server/createBilingualDocument.js +10 -9
- package/dist/docx/settingsHeaderFooterUpdate.d.ts +5 -0
- package/dist/docx/settingsHeaderFooterUpdate.js +90 -0
- package/dist/docx/settingsParser.d.ts +1 -2
- package/dist/docx/settingsParser.js +5 -6
- package/dist/docx/storyBlockReplay.d.ts +11 -0
- package/dist/docx/storyBlockReplay.js +367 -0
- package/dist/docx/streamingXmlParser.d.ts +31 -1
- package/dist/docx/streamingXmlParser.js +136 -21
- package/dist/docx/structuralXmlPatch.js +8 -1
- package/dist/docx/unzip.d.ts +3 -1
- package/dist/docx/unzip.js +36 -16
- package/dist/docx/verbatimCapture.d.ts +3 -1
- package/dist/docx/verbatimCapture.js +49 -6
- package/dist/i18n/messages/ar.gen.d.ts +5 -0
- package/dist/i18n/messages/ar.gen.js +656 -0
- package/dist/i18n/messages/cs.gen.d.ts +5 -0
- package/dist/i18n/messages/cs.gen.js +656 -0
- package/dist/i18n/messages/de.gen.d.ts +5 -0
- package/dist/i18n/messages/de.gen.js +656 -0
- package/dist/i18n/messages/en.gen.d.ts +5 -0
- package/dist/i18n/messages/en.gen.js +656 -0
- package/dist/i18n/messages/es.gen.d.ts +5 -0
- package/dist/i18n/messages/es.gen.js +656 -0
- package/dist/i18n/messages/et.gen.d.ts +5 -0
- package/dist/i18n/messages/et.gen.js +656 -0
- package/dist/i18n/messages/fr.gen.d.ts +5 -0
- package/dist/i18n/messages/fr.gen.js +656 -0
- package/dist/i18n/messages/he.gen.d.ts +5 -0
- package/dist/i18n/messages/he.gen.js +656 -0
- package/dist/i18n/messages/hi.gen.d.ts +5 -0
- package/dist/i18n/messages/hi.gen.js +656 -0
- package/dist/i18n/messages/hu.gen.d.ts +5 -0
- package/dist/i18n/messages/hu.gen.js +656 -0
- package/dist/i18n/messages/locales.d.ts +5 -0
- package/dist/i18n/messages/locales.js +22 -0
- package/dist/i18n/messages/lt.gen.d.ts +5 -0
- package/dist/i18n/messages/lt.gen.js +656 -0
- package/dist/i18n/messages/lv.gen.d.ts +5 -0
- package/dist/i18n/messages/lv.gen.js +656 -0
- package/dist/i18n/messages/pl.gen.d.ts +5 -0
- package/dist/i18n/messages/pl.gen.js +656 -0
- package/dist/i18n/messages/pt-BR.gen.d.ts +5 -0
- package/dist/i18n/messages/pt-BR.gen.js +656 -0
- package/dist/i18n/messages/sk.gen.d.ts +5 -0
- package/dist/i18n/messages/sk.gen.js +656 -0
- package/dist/i18n/messages/tr.gen.d.ts +5 -0
- package/dist/i18n/messages/tr.gen.js +656 -0
- package/dist/i18n/messages/zh-CN.gen.d.ts +5 -0
- package/dist/i18n/messages/zh-CN.gen.js +656 -0
- package/dist/i18n/messages.d.ts +2 -3
- package/dist/i18n/messages.js +1 -19
- package/dist/internal/noteMarkerAttrs.d.ts +8 -0
- package/dist/internal/noteMarkerAttrs.js +16 -0
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +1 -0
- package/dist/internal/prosemirrorAttrBoundary.d.ts +21 -0
- package/dist/internal/prosemirrorAttrBoundary.js +50 -0
- package/dist/layout-bridge/convert/fixedTableColumnWidths.d.ts +6 -0
- package/dist/layout-bridge/convert/fixedTableColumnWidths.js +23 -0
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +3 -3
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +1 -0
- package/dist/layout-bridge/convert/noteReferences.d.ts +1 -3
- package/dist/layout-bridge/convert/noteReferences.js +1 -6
- package/dist/layout-bridge/convert/paragraphRuns.js +2 -4
- package/dist/layout-bridge/convert/tableConversion.js +4 -1
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +2 -2
- package/dist/layout-bridge/convert/toFlowBlocks.js +2 -2
- package/dist/layout-painter/index.js +2 -5
- package/dist/managers/DocumentLoaderManager.d.ts +1 -0
- package/dist/managers/DocumentLoaderManager.js +8 -1
- package/dist/markdown/renderBlock.js +15 -1
- package/dist/markdown/renderParagraph.js +9 -13
- package/dist/markdown/renderRuns.js +3 -2
- package/dist/markdown/renderTable.js +2 -0
- package/dist/markdown/types.d.ts +3 -9
- package/dist/paged-layout/editorScrollRoot.d.ts +15 -0
- package/dist/paged-layout/editorScrollRoot.js +72 -0
- package/dist/paged-layout/scrollToPmPosition.js +8 -22
- package/dist/prosemirror/attrs/index.d.ts +2 -12
- package/dist/prosemirror/attrs/index.js +22 -48
- package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +2 -1
- package/dist/prosemirror/canonicalCommands.d.ts +97 -0
- package/dist/prosemirror/canonicalCommands.js +28 -0
- package/dist/prosemirror/commands/clearParagraphIndent.d.ts +6 -0
- package/dist/prosemirror/commands/clearParagraphIndent.js +25 -0
- package/dist/prosemirror/commands/pageBreak.js +15 -1
- package/dist/prosemirror/commentIdAllocator.d.ts +15 -22
- package/dist/prosemirror/commentIdAllocator.js +50 -25
- package/dist/prosemirror/commentReferenceAttrs.d.ts +2 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +91 -19
- package/dist/prosemirror/conversion/listRenderingDefinition.d.ts +6 -0
- package/dist/prosemirror/conversion/listRenderingDefinition.js +97 -0
- package/dist/prosemirror/conversion/toProseDoc.d.ts +4 -3
- package/dist/prosemirror/conversion/toProseDoc.js +51 -11
- package/dist/prosemirror/executeEditorCommand.d.ts +11 -0
- package/dist/prosemirror/executeEditorCommand.js +26 -0
- package/dist/prosemirror/extensions/StarterKit.js +2 -0
- package/dist/prosemirror/extensions/core/HistoryExtension.js +97 -5
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +53 -20
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +22 -28
- package/dist/prosemirror/extensions/features/ListExtension.js +18 -5
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +5 -2
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +13 -1
- package/dist/prosemirror/extensions/marks/TextColorExtension.js +3 -2
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +2 -0
- package/dist/prosemirror/extensions/marks/markUtils.js +70 -8
- package/dist/prosemirror/extensions/nodes/NoteMarkerExtension.d.ts +6 -0
- package/dist/prosemirror/extensions/nodes/NoteMarkerExtension.js +36 -0
- package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.js +4 -2
- package/dist/prosemirror/extensions/nodes/ShapeExtension.js +8 -6
- package/dist/prosemirror/listMarker.d.ts +1 -0
- package/dist/prosemirror/listMarker.js +16 -7
- package/dist/prosemirror/listNumbering.js +26 -5
- package/dist/prosemirror/listRenderingAttrs.d.ts +1 -0
- package/dist/prosemirror/listRenderingAttrs.js +3 -0
- package/dist/prosemirror/markupViewNotes.js +3 -2
- package/dist/prosemirror/moveRangeBoundaryAttrs.d.ts +2 -1
- package/dist/prosemirror/noteReferenceReview.js +5 -3
- package/dist/prosemirror/plugins/revisionIds.d.ts +23 -19
- package/dist/prosemirror/plugins/revisionIds.js +110 -29
- package/dist/prosemirror/plugins/suggestionMode.d.ts +2 -2
- package/dist/prosemirror/plugins/suggestionMode.js +246 -42
- package/dist/prosemirror/rangeAnchorAttrs.d.ts +2 -1
- package/dist/prosemirror/runFormattingFromMarks.d.ts +4 -1
- package/dist/prosemirror/runFormattingFromMarks.js +15 -1
- package/dist/prosemirror/runFormattingInlineCarriers.d.ts +2 -1
- package/dist/prosemirror/runFormattingInlineCarriers.js +4 -1
- package/dist/prosemirror/schema/marks.d.ts +2 -0
- package/dist/prosemirror/schema/nodes.d.ts +10 -2
- package/dist/prosemirror/storyListNumbering.js +11 -9
- package/dist/prosemirror/textBoxAnchorAttrs.d.ts +2 -1
- package/dist/prosemirror/textInput.d.ts +6 -1
- package/dist/prosemirror/textInput.js +14 -3
- package/dist/prosemirror/trackedRevisionPath.js +2 -1
- package/dist/prosemirror/trackedRunInlineAtoms.d.ts +1 -0
- package/dist/prosemirror/trackedRunInlineAtoms.js +1 -0
- package/dist/prosemirror/utils/visualLineNavigation.js +6 -8
- package/dist/prosemirror/validation.js +4 -0
- package/dist/types/content.d.ts +2 -2
- package/dist/utils/createDocument.js +2 -2
- package/dist/utils/mergeDocumentContent.d.ts +2 -2
- package/dist/utils/mergeDocumentContent.js +11 -8
- package/package.json +14 -2
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { expectNoteMarkerAttrs } from "../../../internal/noteMarkerAttrs.js";
|
|
2
|
+
import { createNodeExtension } from "../create.js";
|
|
3
|
+
//#region src/prosemirror/extensions/nodes/NoteMarkerExtension.ts
|
|
4
|
+
/** An authored automatic note mark: invisible, but retained through PM JSON and edits. */
|
|
5
|
+
const NOTE_MARKER_NODE_NAME = "noteMarker";
|
|
6
|
+
const NoteMarkerExtension = createNodeExtension({
|
|
7
|
+
name: NOTE_MARKER_NODE_NAME,
|
|
8
|
+
schemaNodeName: NOTE_MARKER_NODE_NAME,
|
|
9
|
+
nodeSpec: {
|
|
10
|
+
inline: true,
|
|
11
|
+
group: "inline",
|
|
12
|
+
atom: true,
|
|
13
|
+
marks: "_",
|
|
14
|
+
selectable: false,
|
|
15
|
+
attrs: { kind: {} },
|
|
16
|
+
parseDOM: [{
|
|
17
|
+
tag: "span[data-docx-note-marker]",
|
|
18
|
+
getAttrs(node) {
|
|
19
|
+
if (!(node instanceof HTMLElement)) return false;
|
|
20
|
+
const kind = node.dataset["docxNoteMarker"];
|
|
21
|
+
return kind === "footnote" || kind === "endnote" ? { kind } : false;
|
|
22
|
+
}
|
|
23
|
+
}],
|
|
24
|
+
toDOM(node) {
|
|
25
|
+
const { kind } = expectNoteMarkerAttrs(node);
|
|
26
|
+
return ["span", {
|
|
27
|
+
"data-docx-note-marker": kind,
|
|
28
|
+
"aria-hidden": "true",
|
|
29
|
+
contenteditable: "false",
|
|
30
|
+
style: "display: none;"
|
|
31
|
+
}];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
//#endregion
|
|
36
|
+
export { NOTE_MARKER_NODE_NAME, NoteMarkerExtension };
|
|
@@ -25,7 +25,8 @@ const PreservedXmlExtension = createNodeExtension({
|
|
|
25
25
|
attrs: {
|
|
26
26
|
xml: {},
|
|
27
27
|
text: { default: "" },
|
|
28
|
-
level: { default: PRESERVED_XML_LEVELS.run }
|
|
28
|
+
level: { default: PRESERVED_XML_LEVELS.run },
|
|
29
|
+
foldedListNumber: { default: void 0 }
|
|
29
30
|
},
|
|
30
31
|
parseDOM: [{
|
|
31
32
|
tag: "span[data-docx-preserved-xml]",
|
|
@@ -42,7 +43,8 @@ const PreservedXmlExtension = createNodeExtension({
|
|
|
42
43
|
}
|
|
43
44
|
}],
|
|
44
45
|
toDOM(node) {
|
|
45
|
-
const { xml, text, level } = expectPreservedXmlAttrs(node);
|
|
46
|
+
const { xml, text, level, foldedListNumber } = expectPreservedXmlAttrs(node);
|
|
47
|
+
if (foldedListNumber) return ["span", { contenteditable: "false" }];
|
|
46
48
|
return [
|
|
47
49
|
"span",
|
|
48
50
|
{
|
|
@@ -268,9 +268,9 @@ function createShapeElement(type, w, h, adjustments) {
|
|
|
268
268
|
case "straightConnector1": {
|
|
269
269
|
const el = document.createElementNS(SVG_NS, "line");
|
|
270
270
|
setNum(el, "x1", 0);
|
|
271
|
-
setNum(el, "y1",
|
|
271
|
+
setNum(el, "y1", 0);
|
|
272
272
|
setNum(el, "x2", w);
|
|
273
|
-
setNum(el, "y2", h
|
|
273
|
+
setNum(el, "y2", h);
|
|
274
274
|
return el;
|
|
275
275
|
}
|
|
276
276
|
case "rightBrace": {
|
|
@@ -537,9 +537,11 @@ const ShapeExtension = createNodeExtension({
|
|
|
537
537
|
const strokeWidth = finiteNumber(attrs.outlineWidth) ?? 1;
|
|
538
538
|
const svg = document.createElementNS(SVG_NS, "svg");
|
|
539
539
|
svg.setAttribute("xmlns", SVG_NS);
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
svg
|
|
540
|
+
const viewportWidth = w === 0 ? 1 : w;
|
|
541
|
+
const viewportHeight = h === 0 ? 1 : h;
|
|
542
|
+
setNum(svg, "width", viewportWidth);
|
|
543
|
+
setNum(svg, "height", viewportHeight);
|
|
544
|
+
svg.setAttribute("viewBox", `0 0 ${viewportWidth} ${viewportHeight}`);
|
|
543
545
|
let gradient = null;
|
|
544
546
|
let fillAttr;
|
|
545
547
|
if (attrs.fillType === "gradient" && attrs.gradientStops) {
|
|
@@ -548,7 +550,7 @@ const ShapeExtension = createNodeExtension({
|
|
|
548
550
|
fillAttr = gradient ? `url(#${gradId})` : safeFillColor;
|
|
549
551
|
} else fillAttr = attrs.fillType === "none" ? "none" : safeFillColor;
|
|
550
552
|
const strokeAttr = attrs.outlineStyle === "none" ? "none" : safeStrokeColor;
|
|
551
|
-
svg.setAttribute("style", `fill:${fillAttr};stroke:${strokeAttr};stroke-width:${strokeWidth}`);
|
|
553
|
+
svg.setAttribute("style", `fill:${fillAttr};stroke:${strokeAttr};stroke-width:${strokeWidth};overflow:visible`);
|
|
552
554
|
if (gradient) {
|
|
553
555
|
const defs = document.createElementNS(SVG_NS, "defs");
|
|
554
556
|
defs.append(gradient);
|
|
@@ -55,6 +55,7 @@ declare const CLEARED_LIST_RENDERING_ATTRS: Readonly<{
|
|
|
55
55
|
listMarkerSuffix: null;
|
|
56
56
|
listMarkerAllCaps: null;
|
|
57
57
|
listImplicitChildLevelAdvances: null;
|
|
58
|
+
listFoldedMarkerSuffix: null;
|
|
58
59
|
listMarkerSecondSlotOffsetTwips: null;
|
|
59
60
|
listLevelNumFmts: null;
|
|
60
61
|
listLevelStarts: null;
|
|
@@ -17,6 +17,7 @@ const CLEARED_LIST_RENDERING_ATTRS = Object.freeze({
|
|
|
17
17
|
listMarkerSuffix: null,
|
|
18
18
|
listMarkerAllCaps: null,
|
|
19
19
|
listImplicitChildLevelAdvances: null,
|
|
20
|
+
listFoldedMarkerSuffix: null,
|
|
20
21
|
listMarkerSecondSlotOffsetTwips: null,
|
|
21
22
|
listLevelNumFmts: null,
|
|
22
23
|
listLevelStarts: null,
|
|
@@ -76,6 +77,7 @@ function previousListAttrs(attrs) {
|
|
|
76
77
|
...previous.listNumFmt !== void 0 ? { listNumFmt: previous.listNumFmt } : {},
|
|
77
78
|
...previous.listMarker !== void 0 ? { listMarker: previous.listMarker } : {},
|
|
78
79
|
...previous.listMarkerTemplate !== void 0 ? { listMarkerTemplate: previous.listMarkerTemplate } : {},
|
|
80
|
+
...previous.listFoldedMarkerSuffix !== void 0 ? { listFoldedMarkerSuffix: previous.listFoldedMarkerSuffix } : {},
|
|
79
81
|
...previous.listMarkerHidden !== void 0 ? { listMarkerHidden: previous.listMarkerHidden } : {},
|
|
80
82
|
...previous.listMarkerFormatting !== void 0 ? { listMarkerFormatting: previous.listMarkerFormatting } : {},
|
|
81
83
|
...previous.listMarkerAlignment !== void 0 ? { listMarkerAlignment: previous.listMarkerAlignment } : {},
|
|
@@ -178,6 +180,7 @@ function formatNumberedMarker(counters, level) {
|
|
|
178
180
|
}
|
|
179
181
|
function advanceListMarker(attrs, state) {
|
|
180
182
|
const markerTemplate = attrs.listMarkerTemplate ?? attrs.listMarker;
|
|
183
|
+
const foldedMarkerSuffix = attrs.listFoldedMarkerSuffix ?? void 0;
|
|
181
184
|
const level = paragraphNumberingLevel(attrs.numPr) ?? 0;
|
|
182
185
|
if (!Number.isInteger(level) || level < 0 || level > 8) return null;
|
|
183
186
|
const numId = paragraphNumberingReferenceId(attrs.numPr);
|
|
@@ -205,7 +208,9 @@ function advanceListMarker(attrs, state) {
|
|
|
205
208
|
fromStyle: false,
|
|
206
209
|
numId: null
|
|
207
210
|
};
|
|
208
|
-
|
|
211
|
+
if (foldedMarkerSuffix !== void 0 && attrs.listMarkerTemplate == null) return attrs.listMarker ?? null;
|
|
212
|
+
const marker = convertBulletToUnicode(attrs.listMarkerTemplate ?? attrs.listMarker ?? "", bulletMarkerFontName(attrs.listMarkerFormatting));
|
|
213
|
+
return foldedMarkerSuffix === void 0 ? marker : `${marker}\t${foldedMarkerSuffix}`;
|
|
209
214
|
}
|
|
210
215
|
const firstInstanceEncounter = !state.counters.has(numId);
|
|
211
216
|
let counters = state.counters.get(numId) ?? Array.from({ length: 9 }, () => NaN);
|
|
@@ -250,12 +255,16 @@ function advanceListMarker(attrs, state) {
|
|
|
250
255
|
numId
|
|
251
256
|
};
|
|
252
257
|
const levelFormats = attrs.listLevelNumFmts ?? (attrs.listNumFmt ? [attrs.listNumFmt] : void 0);
|
|
253
|
-
if (markerTemplate?.includes("%")
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
258
|
+
if (markerTemplate?.includes("%") && (foldedMarkerSuffix === void 0 || attrs.listMarkerTemplate != null)) {
|
|
259
|
+
const marker = resolveListTemplate({
|
|
260
|
+
template: markerTemplate,
|
|
261
|
+
counters,
|
|
262
|
+
levelFormats,
|
|
263
|
+
forceDecimal: attrs.listIsLegal
|
|
264
|
+
});
|
|
265
|
+
return foldedMarkerSuffix === void 0 ? marker : `${marker}\t${foldedMarkerSuffix}`;
|
|
266
|
+
}
|
|
267
|
+
if (foldedMarkerSuffix !== void 0 && attrs.listMarkerTemplate != null) return `${attrs.listMarkerTemplate}\t${foldedMarkerSuffix}`;
|
|
259
268
|
if (attrs.listMarker) return attrs.listMarker;
|
|
260
269
|
if ((levelFormats?.[level] ?? attrs.listNumFmt) === "none" || attrs.listMarker === "") return null;
|
|
261
270
|
return formatNumberedMarker(counters, level);
|
|
@@ -2,6 +2,7 @@ import { mintListInstance, restartListInstance } from "../docx/listNumberingInst
|
|
|
2
2
|
import { createNumberingMap, isBulletLevel } from "../docx/numberingParser.js";
|
|
3
3
|
import { paragraphNumberingLevel, paragraphNumberingReferenceId } from "../docx/numberingReference.js";
|
|
4
4
|
import { expectParagraphAttrs } from "./attrs/index.js";
|
|
5
|
+
import { withCanonicalCommand } from "./canonicalCommands.js";
|
|
5
6
|
import { paragraphPropertiesSnapshot } from "./commands/propertyChangeScope.js";
|
|
6
7
|
import { listRenderingFor, recordsListRendering } from "./listRendering.js";
|
|
7
8
|
import { LIST_RENDERING_ATTR_KEYS } from "./listRenderingAttrs.js";
|
|
@@ -11,6 +12,22 @@ import { getDocumentStyleResolver } from "./plugins/documentStyleState.js";
|
|
|
11
12
|
import { SUGGESTION_META, makeRevisionInfo } from "./plugins/suggestionMode.js";
|
|
12
13
|
import { listAttrsFromNumbering, listLevelIndentAttrPatch } from "./styles/resolvedStyleAttrs.js";
|
|
13
14
|
//#region src/prosemirror/listNumbering.ts
|
|
15
|
+
/**
|
|
16
|
+
* Which numbering instance a list command puts a paragraph in, and the
|
|
17
|
+
* *Restart Numbering*, *Continue Numbering* and *Set Numbering Value* commands.
|
|
18
|
+
*
|
|
19
|
+
* A paragraph made into a list item continues the list directly above or below
|
|
20
|
+
* it when that list is of the requested kind (and, for a typed marker, has the
|
|
21
|
+
* typed format). Otherwise it starts a new list: a new `w:num`, defined on the
|
|
22
|
+
* paragraphs it numbers (see `docx/listNumberingInstances.ts`). A list that a
|
|
23
|
+
* paragraph style supplies (a heading's numbering from `styles.xml`) is never
|
|
24
|
+
* joined implicitly; it belongs to the style, not to the body text around it.
|
|
25
|
+
*
|
|
26
|
+
* Every change made while suggesting is recorded as one `w:pPrChange` per
|
|
27
|
+
* paragraph. A paragraph that already carries one keeps a single record whose
|
|
28
|
+
* previous state is the paragraph's original, so rejecting it restores what the
|
|
29
|
+
* paragraph was before any of the tracked changes.
|
|
30
|
+
*/
|
|
14
31
|
const PARAGRAPH_NODE = "paragraph";
|
|
15
32
|
/**
|
|
16
33
|
* The paragraph's properties as a `w:pPrChange` records them before a list
|
|
@@ -187,6 +204,7 @@ const listItemAttrs = (attrs, { numId, ilvl }, numbering) => ({
|
|
|
187
204
|
ilvl
|
|
188
205
|
}, numbering),
|
|
189
206
|
listImplicitChildLevelAdvances: attrs["listImplicitChildLevelAdvances"] ?? null,
|
|
207
|
+
listFoldedMarkerSuffix: attrs["listFoldedMarkerSuffix"] ?? void 0,
|
|
190
208
|
listMarkerSecondSlotOffsetTwips: attrs["listMarkerSecondSlotOffsetTwips"] ?? null
|
|
191
209
|
});
|
|
192
210
|
/**
|
|
@@ -260,7 +278,7 @@ const moveItems = ({ state, items, numId, numbering }) => {
|
|
|
260
278
|
* its list move to a new instance of the same definition, whose
|
|
261
279
|
* `w:startOverride` at the item's level is `value`.
|
|
262
280
|
*/
|
|
263
|
-
const setNumberingValue = (value) => (state, dispatch) => {
|
|
281
|
+
const setNumberingValue = (value) => withCanonicalCommand((state, dispatch) => {
|
|
264
282
|
if (!Number.isSafeInteger(value) || value < 0) return false;
|
|
265
283
|
const selected = selectedListParagraph(state);
|
|
266
284
|
const numbering = getDocumentNumbering(state);
|
|
@@ -279,9 +297,12 @@ const setNumberingValue = (value) => (state, dispatch) => {
|
|
|
279
297
|
numbering: createNumberingMap(restarted.definitions)
|
|
280
298
|
}));
|
|
281
299
|
return true;
|
|
282
|
-
}
|
|
300
|
+
}, () => [{
|
|
301
|
+
type: "restartNumbering",
|
|
302
|
+
start: value
|
|
303
|
+
}]);
|
|
283
304
|
/** *Restart at 1*: the selected item starts its list over at one. */
|
|
284
|
-
const restartNumbering = (state, dispatch) => setNumberingValue(1)(state, dispatch);
|
|
305
|
+
const restartNumbering = withCanonicalCommand((state, dispatch) => setNumberingValue(1)(state, dispatch), () => [{ type: "restartNumbering" }]);
|
|
285
306
|
/** The nearest list before `beforePos` of the kind `membership` has, other than its own. */
|
|
286
307
|
const previousListOfKind = (state, beforePos, membership) => {
|
|
287
308
|
const numbering = getDocumentNumbering(state);
|
|
@@ -301,7 +322,7 @@ const previousListOfKind = (state, beforePos, membership) => {
|
|
|
301
322
|
* join the nearest earlier list of the same kind, so their numbers carry on
|
|
302
323
|
* from it. Not applicable when no such list precedes the item.
|
|
303
324
|
*/
|
|
304
|
-
const continueNumbering = (state, dispatch) => {
|
|
325
|
+
const continueNumbering = withCanonicalCommand((state, dispatch) => {
|
|
305
326
|
const selected = selectedListParagraph(state);
|
|
306
327
|
const numbering = getDocumentNumbering(state);
|
|
307
328
|
if (!selected || !numbering) return false;
|
|
@@ -315,7 +336,7 @@ const continueNumbering = (state, dispatch) => {
|
|
|
315
336
|
numbering
|
|
316
337
|
}));
|
|
317
338
|
return true;
|
|
318
|
-
};
|
|
339
|
+
}, () => [{ type: "continueNumbering" }]);
|
|
319
340
|
const NO_LIST_NUMBERING_MENU = { type: "none" };
|
|
320
341
|
/**
|
|
321
342
|
* Whether the selection is in a list item whose numbering can be restarted
|
|
@@ -6,6 +6,7 @@ type ListRenderingAttrField = Exclude<keyof document_d_exports.ListRendering, "l
|
|
|
6
6
|
declare const LIST_RENDERING_ATTR_BY_FIELD: {
|
|
7
7
|
readonly marker: "listMarker";
|
|
8
8
|
readonly markerTemplate: "listMarkerTemplate";
|
|
9
|
+
readonly foldedMarkerSuffix: "listFoldedMarkerSuffix";
|
|
9
10
|
readonly isBullet: "listIsBullet";
|
|
10
11
|
readonly isLegal: "listIsLegal";
|
|
11
12
|
readonly numFmt: "listNumFmt";
|
|
@@ -12,6 +12,7 @@ import { paragraphNumberingLevel } from "@stll/docx-core/model";
|
|
|
12
12
|
const LIST_RENDERING_ATTR_BY_FIELD = {
|
|
13
13
|
marker: "listMarker",
|
|
14
14
|
markerTemplate: "listMarkerTemplate",
|
|
15
|
+
foldedMarkerSuffix: "listFoldedMarkerSuffix",
|
|
15
16
|
isBullet: "listIsBullet",
|
|
16
17
|
isLegal: "listIsLegal",
|
|
17
18
|
numFmt: "listNumFmt",
|
|
@@ -41,6 +42,7 @@ const listRenderingAttrPatch = (rendering) => {
|
|
|
41
42
|
const patch = {
|
|
42
43
|
listMarker: rendering.marker || void 0,
|
|
43
44
|
listMarkerTemplate: rendering.markerTemplate || void 0,
|
|
45
|
+
listFoldedMarkerSuffix: rendering.foldedMarkerSuffix,
|
|
44
46
|
listIsBullet: rendering.isBullet || void 0,
|
|
45
47
|
listIsLegal: rendering.isLegal || void 0,
|
|
46
48
|
listNumFmt: rendering.numFmt || void 0,
|
|
@@ -73,6 +75,7 @@ const hasListRendering = (attrs) => attrs.listMarker != null || attrs.listIsBull
|
|
|
73
75
|
const listRenderingFromAttrs = ({ attrs, numId }) => {
|
|
74
76
|
const optional = {
|
|
75
77
|
markerTemplate: attrs.listMarkerTemplate ?? void 0,
|
|
78
|
+
foldedMarkerSuffix: attrs.listFoldedMarkerSuffix ?? void 0,
|
|
76
79
|
isLegal: attrs.listIsLegal ?? void 0,
|
|
77
80
|
numFmt: attrs.listNumFmt ?? void 0,
|
|
78
81
|
markerHidden: attrs.listMarkerHidden ?? void 0,
|
|
@@ -10,10 +10,11 @@ const resolvedNote = (note, mode, state, document) => {
|
|
|
10
10
|
const styleResolver = getDocumentStyleResolver(state);
|
|
11
11
|
const cached = resolvedNotes.get(note)?.get(mode);
|
|
12
12
|
if (cached?.styleResolver === styleResolver) return cached.note;
|
|
13
|
-
const { styles, theme } = document.package;
|
|
13
|
+
const { styles, theme, numbering } = document.package;
|
|
14
14
|
const doc = footnoteToProseDoc(note.content, {
|
|
15
15
|
...styles !== void 0 && { styles },
|
|
16
|
-
...theme !== void 0 && { theme }
|
|
16
|
+
...theme !== void 0 && { theme },
|
|
17
|
+
...numbering !== void 0 && { numbering }
|
|
17
18
|
});
|
|
18
19
|
const result = resolveWholeStory({
|
|
19
20
|
doc,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
|
-
import { ReadProseMirrorAttrsResult } from "
|
|
2
|
+
import { ReadProseMirrorAttrsResult } from "../internal/prosemirrorAttrBoundary.js";
|
|
3
|
+
import "./attrs/index.js";
|
|
3
4
|
import { Node } from "prosemirror-model";
|
|
4
5
|
//#region src/prosemirror/moveRangeBoundaryAttrs.d.ts
|
|
5
6
|
type MoveRangeMarker = Extract<document_d_exports.ParagraphContent, {
|
|
@@ -64,7 +64,8 @@ const restoredNote = (note, document, reference) => {
|
|
|
64
64
|
const { styles, theme, numbering } = document.package;
|
|
65
65
|
const doc = footnoteToProseDoc(note.content, {
|
|
66
66
|
...styles !== void 0 && { styles },
|
|
67
|
-
...theme !== void 0 && { theme }
|
|
67
|
+
...theme !== void 0 && { theme },
|
|
68
|
+
...numbering !== void 0 && { numbering }
|
|
68
69
|
});
|
|
69
70
|
const revisions = noteDeletionRevisions(doc, reference);
|
|
70
71
|
if (revisions.length === 0) return note;
|
|
@@ -164,10 +165,11 @@ const deleteNoteWithReference = (transform, reference) => {
|
|
|
164
165
|
* deleted too, by the reference's author at the reference's date.
|
|
165
166
|
*/
|
|
166
167
|
const deletedNote = (note, document, reference) => {
|
|
167
|
-
const { styles, theme } = document.package;
|
|
168
|
+
const { styles, theme, numbering } = document.package;
|
|
168
169
|
const doc = footnoteToProseDoc(note.content, {
|
|
169
170
|
...styles !== void 0 && { styles },
|
|
170
|
-
...theme !== void 0 && { theme }
|
|
171
|
+
...theme !== void 0 && { theme },
|
|
172
|
+
...numbering !== void 0 && { numbering }
|
|
171
173
|
});
|
|
172
174
|
const transform = deleteNoteWithReference(new Transform(doc), reference);
|
|
173
175
|
if (!transform.docChanged) return note;
|
|
@@ -1,31 +1,35 @@
|
|
|
1
1
|
import { Node } from "prosemirror-model";
|
|
2
2
|
//#region src/prosemirror/plugins/revisionIds.d.ts
|
|
3
|
+
declare const RevisionIdAllocationError_base: import("better-result").TaggedErrorClass<"RevisionIdAllocationError">;
|
|
4
|
+
declare class RevisionIdAllocationError extends RevisionIdAllocationError_base<{
|
|
5
|
+
message: string;
|
|
6
|
+
first: number;
|
|
7
|
+
next: number;
|
|
8
|
+
}> {}
|
|
9
|
+
/** Deterministic package-local batches prefer ids above loaded revisions, then a free interval. */
|
|
10
|
+
declare const revisionIdSeedAbove: (existingIds: Iterable<number>) => number;
|
|
11
|
+
/** The next free id, including after the signed 32-bit boundary wraps. */
|
|
12
|
+
declare const nextRevisionId: () => number;
|
|
3
13
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
14
|
+
* A shared batch increments its seed locally, so a single free id is not
|
|
15
|
+
* enough: start in the largest free interval. Every contiguous batch that
|
|
16
|
+
* can fit anywhere fits here, including after loaded ids shorten the tail.
|
|
17
|
+
* Continue within this interval until another producer changes the cursor.
|
|
6
18
|
*/
|
|
19
|
+
declare const nextRevisionIdRange: () => number;
|
|
20
|
+
/** Reserve a deterministic batch without changing its caller-supplied ids. */
|
|
21
|
+
declare const reserveRevisionIds: (first: number, next: number) => void;
|
|
22
|
+
/** Shared producers must never cross a loaded or already issued id on wrap. */
|
|
23
|
+
declare const claimRevisionIds: (first: number, next: number) => void;
|
|
24
|
+
/** Mint a bounded id without reusing loaded or previously issued ids. */
|
|
7
25
|
declare function mintRevisionId(): number;
|
|
8
|
-
/**
|
|
9
|
-
* Raise the counter above `maxId` so freshly minted ids cannot collide with
|
|
10
|
-
* ids already present in a loaded document. Only ever raises.
|
|
11
|
-
*
|
|
12
|
-
* `maxId` is derived from file content, so it is untrusted: a malformed or
|
|
13
|
-
* out-of-range value is ignored outright rather than folded into range.
|
|
14
|
-
*/
|
|
26
|
+
/** Reserve a valid loaded id and prefer the range above it. */
|
|
15
27
|
declare function seedRevisionIdsAbove(maxId: number): void;
|
|
16
|
-
|
|
17
|
-
* The highest id in `doc` from any part of the annotation space.
|
|
18
|
-
*
|
|
19
|
-
* A revision, a comment and a bookmark draw their `w:id` from one space, so a
|
|
20
|
-
* counter seeded above its own kind alone still mints over another kind's id.
|
|
21
|
-
* Both allocators seed from this, and the save-time normalization avoids the
|
|
22
|
-
* same space, so the three agree on what is taken.
|
|
23
|
-
*/
|
|
24
|
-
declare function maxAnnotationIdInDoc(doc: Node): number;
|
|
28
|
+
declare const maxAnnotationIdInDoc: (doc: Node) => number;
|
|
25
29
|
/**
|
|
26
30
|
* Raise the counter above every annotation id already present in `doc`.
|
|
27
31
|
* Called from the suggestion-mode plugin's `state.init`.
|
|
28
32
|
*/
|
|
29
33
|
declare function seedRevisionIdsFromDoc(doc: Node): void;
|
|
30
34
|
//#endregion
|
|
31
|
-
export { maxAnnotationIdInDoc, mintRevisionId, seedRevisionIdsAbove, seedRevisionIdsFromDoc };
|
|
35
|
+
export { RevisionIdAllocationError, claimRevisionIds, maxAnnotationIdInDoc, mintRevisionId, nextRevisionId, nextRevisionIdRange, reserveRevisionIds, revisionIdSeedAbove, seedRevisionIdsAbove, seedRevisionIdsFromDoc };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TaggedError } from "better-result";
|
|
1
2
|
import { MAX_REVISION_ID } from "@stll/docx-core/model";
|
|
2
3
|
//#region src/prosemirror/plugins/revisionIds.ts
|
|
3
4
|
/**
|
|
@@ -9,23 +10,98 @@ import { MAX_REVISION_ID } from "@stll/docx-core/model";
|
|
|
9
10
|
* int consumers read `w:id` into.
|
|
10
11
|
*/
|
|
11
12
|
let counter = 1;
|
|
13
|
+
const occupiedIds = /* @__PURE__ */ new Set();
|
|
14
|
+
var RevisionIdAllocationError = class extends TaggedError("RevisionIdAllocationError") {};
|
|
15
|
+
/** Batches use contiguous ids; on rollover prefer the largest unused interval. */
|
|
16
|
+
const largestFreeIntervalStart = (reservedIds) => {
|
|
17
|
+
let first = 1;
|
|
18
|
+
let bestFirst = 1;
|
|
19
|
+
let bestSize = 0;
|
|
20
|
+
const boundaries = [...reservedIds].filter((id) => id > 0).toSorted((a, b) => a - b);
|
|
21
|
+
boundaries.push(MAX_REVISION_ID + 1);
|
|
22
|
+
for (const boundary of boundaries) {
|
|
23
|
+
const size = boundary - first;
|
|
24
|
+
if (size > bestSize) {
|
|
25
|
+
bestFirst = first;
|
|
26
|
+
bestSize = size;
|
|
27
|
+
}
|
|
28
|
+
first = boundary + 1;
|
|
29
|
+
}
|
|
30
|
+
if (bestSize === 0) throw new RevisionIdAllocationError({
|
|
31
|
+
message: "Revision id space exhausted",
|
|
32
|
+
first: 1,
|
|
33
|
+
next: 1
|
|
34
|
+
});
|
|
35
|
+
return bestFirst;
|
|
36
|
+
};
|
|
37
|
+
/** Deterministic package-local batches prefer ids above loaded revisions, then a free interval. */
|
|
38
|
+
const revisionIdSeedAbove = (existingIds) => {
|
|
39
|
+
const reservedIds = /* @__PURE__ */ new Set();
|
|
40
|
+
let maxId = 0;
|
|
41
|
+
for (const id of existingIds) {
|
|
42
|
+
if (!Number.isInteger(id) || id < 0 || id > MAX_REVISION_ID) continue;
|
|
43
|
+
reservedIds.add(id);
|
|
44
|
+
maxId = Math.max(maxId, id);
|
|
45
|
+
}
|
|
46
|
+
return maxId < MAX_REVISION_ID ? maxId + 1 : largestFreeIntervalStart(reservedIds);
|
|
47
|
+
};
|
|
48
|
+
/** The next free id, including after the signed 32-bit boundary wraps. */
|
|
49
|
+
const nextRevisionId = () => {
|
|
50
|
+
if (counter > MAX_REVISION_ID) counter = largestFreeIntervalStart(occupiedIds);
|
|
51
|
+
while (occupiedIds.has(counter)) {
|
|
52
|
+
counter += 1;
|
|
53
|
+
if (counter > MAX_REVISION_ID) counter = largestFreeIntervalStart(occupiedIds);
|
|
54
|
+
if (occupiedIds.size >= MAX_REVISION_ID) throw new RevisionIdAllocationError({
|
|
55
|
+
message: "Revision id space exhausted",
|
|
56
|
+
first: counter,
|
|
57
|
+
next: counter
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return counter;
|
|
61
|
+
};
|
|
12
62
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
63
|
+
* A shared batch increments its seed locally, so a single free id is not
|
|
64
|
+
* enough: start in the largest free interval. Every contiguous batch that
|
|
65
|
+
* can fit anywhere fits here, including after loaded ids shorten the tail.
|
|
66
|
+
* Continue within this interval until another producer changes the cursor.
|
|
15
67
|
*/
|
|
68
|
+
const nextRevisionIdRange = () => {
|
|
69
|
+
counter = largestFreeIntervalStart(occupiedIds);
|
|
70
|
+
return counter;
|
|
71
|
+
};
|
|
72
|
+
const validateRevisionIdRange = (first, next) => {
|
|
73
|
+
if (!Number.isInteger(first) || !Number.isInteger(next) || first < 0 || next < first || next > MAX_REVISION_ID + 1) throw new RevisionIdAllocationError({
|
|
74
|
+
message: "Revision id range exceeds the OOXML limit",
|
|
75
|
+
first,
|
|
76
|
+
next
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
/** Reserve a deterministic batch without changing its caller-supplied ids. */
|
|
80
|
+
const reserveRevisionIds = (first, next) => {
|
|
81
|
+
validateRevisionIdRange(first, next);
|
|
82
|
+
for (let id = first; id < next; id += 1) occupiedIds.add(id);
|
|
83
|
+
if (next > counter) counter = next;
|
|
84
|
+
};
|
|
85
|
+
/** Shared producers must never cross a loaded or already issued id on wrap. */
|
|
86
|
+
const claimRevisionIds = (first, next) => {
|
|
87
|
+
validateRevisionIdRange(first, next);
|
|
88
|
+
for (let id = first; id < next && id <= MAX_REVISION_ID; id += 1) if (occupiedIds.has(id)) throw new RevisionIdAllocationError({
|
|
89
|
+
message: "Revision id range overlaps an occupied id",
|
|
90
|
+
first,
|
|
91
|
+
next
|
|
92
|
+
});
|
|
93
|
+
reserveRevisionIds(first, next);
|
|
94
|
+
};
|
|
95
|
+
/** Mint a bounded id without reusing loaded or previously issued ids. */
|
|
16
96
|
function mintRevisionId() {
|
|
17
|
-
|
|
18
|
-
|
|
97
|
+
const id = nextRevisionId();
|
|
98
|
+
claimRevisionIds(id, id + 1);
|
|
99
|
+
return id;
|
|
19
100
|
}
|
|
20
|
-
/**
|
|
21
|
-
* Raise the counter above `maxId` so freshly minted ids cannot collide with
|
|
22
|
-
* ids already present in a loaded document. Only ever raises.
|
|
23
|
-
*
|
|
24
|
-
* `maxId` is derived from file content, so it is untrusted: a malformed or
|
|
25
|
-
* out-of-range value is ignored outright rather than folded into range.
|
|
26
|
-
*/
|
|
101
|
+
/** Reserve a valid loaded id and prefer the range above it. */
|
|
27
102
|
function seedRevisionIdsAbove(maxId) {
|
|
28
|
-
if (!Number.isInteger(maxId) || maxId < 0 || maxId
|
|
103
|
+
if (!Number.isInteger(maxId) || maxId < 0 || maxId > MAX_REVISION_ID) return;
|
|
104
|
+
occupiedIds.add(maxId);
|
|
29
105
|
if (maxId >= counter) counter = maxId + 1;
|
|
30
106
|
}
|
|
31
107
|
/** Node attrs that carry a revision id directly (`revisionId` field). */
|
|
@@ -33,40 +109,45 @@ const DIRECT_REVISION_ATTR_KEYS = ["trIns", "trDel"];
|
|
|
33
109
|
/**
|
|
34
110
|
* The highest id in `doc` from any part of the annotation space.
|
|
35
111
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* Both allocators seed from this, and the save-time normalization avoids the
|
|
39
|
-
* same space, so the three agree on what is taken.
|
|
112
|
+
* Preserve the editor's conservative annotation seeding: revisions reserve
|
|
113
|
+
* comment and bookmark ids too, although OOXML defines separate id spaces.
|
|
40
114
|
*/
|
|
41
|
-
|
|
115
|
+
const visitAnnotationIds = (doc, visit) => {
|
|
42
116
|
let max = 0;
|
|
43
117
|
const consider = (id) => {
|
|
44
|
-
if (typeof id === "number" && Number.isInteger(id) && id
|
|
118
|
+
if (typeof id === "number" && Number.isInteger(id) && id >= 0 && id <= MAX_REVISION_ID) {
|
|
119
|
+
visit(id);
|
|
120
|
+
max = Math.max(max, id);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
const considerMetadata = (value) => {
|
|
124
|
+
if (typeof value !== "object" || value === null) return;
|
|
125
|
+
for (const [key, child] of Object.entries(value)) if (key === "id" || key === "revisionId" || key === "commentId") consider(child);
|
|
126
|
+
else considerMetadata(child);
|
|
45
127
|
};
|
|
46
128
|
doc.descendants((node) => {
|
|
47
129
|
for (const mark of node.marks) {
|
|
48
130
|
consider(mark.attrs["revisionId"]);
|
|
49
131
|
consider(mark.attrs["commentId"]);
|
|
132
|
+
considerMetadata(mark.attrs["_docxRevisionAncestors"]);
|
|
133
|
+
considerMetadata(mark.attrs["changes"]);
|
|
50
134
|
}
|
|
51
135
|
if (node.type.name === "bookmarkBoundary") consider(node.attrs["id"]);
|
|
52
136
|
const attrs = node.attrs;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
for (const key of DIRECT_REVISION_ATTR_KEYS)
|
|
56
|
-
|
|
57
|
-
if (value) consider(value.revisionId);
|
|
58
|
-
}
|
|
59
|
-
const cellMarker = attrs["cellMarker"];
|
|
60
|
-
if (cellMarker?.info) consider(cellMarker.info.revisionId);
|
|
137
|
+
considerMetadata(attrs["_propertyChanges"]);
|
|
138
|
+
considerMetadata(attrs["pPrMark"]);
|
|
139
|
+
for (const key of DIRECT_REVISION_ATTR_KEYS) considerMetadata(attrs[key]);
|
|
140
|
+
considerMetadata(attrs["cellMarker"]);
|
|
61
141
|
});
|
|
62
142
|
return max;
|
|
63
|
-
}
|
|
143
|
+
};
|
|
144
|
+
const maxAnnotationIdInDoc = (doc) => visitAnnotationIds(doc, () => {});
|
|
64
145
|
/**
|
|
65
146
|
* Raise the counter above every annotation id already present in `doc`.
|
|
66
147
|
* Called from the suggestion-mode plugin's `state.init`.
|
|
67
148
|
*/
|
|
68
149
|
function seedRevisionIdsFromDoc(doc) {
|
|
69
|
-
|
|
150
|
+
visitAnnotationIds(doc, seedRevisionIdsAbove);
|
|
70
151
|
}
|
|
71
152
|
//#endregion
|
|
72
|
-
export { maxAnnotationIdInDoc, mintRevisionId, seedRevisionIdsAbove, seedRevisionIdsFromDoc };
|
|
153
|
+
export { RevisionIdAllocationError, claimRevisionIds, maxAnnotationIdInDoc, mintRevisionId, nextRevisionId, nextRevisionIdRange, reserveRevisionIds, revisionIdSeedAbove, seedRevisionIdsAbove, seedRevisionIdsFromDoc };
|
|
@@ -66,8 +66,8 @@ declare function handleSuggestionEnter(view: EditorView, pluginState: Suggestion
|
|
|
66
66
|
* - Delete-at-paragraph-end → current paragraph.
|
|
67
67
|
*
|
|
68
68
|
* Returns `null` when there is no adjacent sibling paragraph (the join would
|
|
69
|
-
* not produce paragraph-mark merging
|
|
70
|
-
*
|
|
69
|
+
* not produce paragraph-mark merging, e.g. doc start, doc end, or a table).
|
|
70
|
+
* Bookmark markers at an edge do not hide the adjacent paragraph break.
|
|
71
71
|
*/
|
|
72
72
|
declare function paragraphBoundaryTarget(state: EditorState, direction: "backward" | "forward"): number | null;
|
|
73
73
|
/** Apply the editor's selected-content deletion path for a host cut action. */
|