@stll/folio-core 0.52.0 → 0.53.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 +23 -0
- package/dist/ai-edits/apply.d.ts +26 -1
- package/dist/ai-edits/apply.js +1519 -105
- package/dist/ai-edits/batch-claims.d.ts +130 -0
- package/dist/ai-edits/batch-claims.js +244 -0
- package/dist/ai-edits/blockRange.js +9 -3
- package/dist/ai-edits/character-boundaries.d.ts +43 -0
- package/dist/ai-edits/character-boundaries.js +95 -0
- package/dist/ai-edits/clean-text.d.ts +33 -3
- package/dist/ai-edits/clean-text.js +52 -6
- package/dist/ai-edits/comment-lifecycle.d.ts +18 -0
- package/dist/ai-edits/comment-lifecycle.js +52 -0
- package/dist/ai-edits/headless.d.ts +71 -7
- package/dist/ai-edits/headless.js +381 -41
- package/dist/ai-edits/index.d.ts +2 -1
- package/dist/ai-edits/index.js +2 -1
- package/dist/ai-edits/minimal-replacement.d.ts +21 -6
- package/dist/ai-edits/minimal-replacement.js +134 -15
- package/dist/ai-edits/newListNumbering.d.ts +23 -0
- package/dist/ai-edits/newListNumbering.js +94 -0
- package/dist/ai-edits/note-references.d.ts +96 -0
- package/dist/ai-edits/note-references.js +139 -0
- package/dist/ai-edits/pending-suggestions.d.ts +79 -0
- package/dist/ai-edits/pending-suggestions.js +306 -0
- package/dist/ai-edits/read.d.ts +1 -1
- package/dist/ai-edits/read.js +56 -43
- package/dist/ai-edits/result-validation.d.ts +29 -0
- package/dist/ai-edits/result-validation.js +164 -0
- package/dist/ai-edits/snapshot.d.ts +36 -3
- package/dist/ai-edits/snapshot.js +177 -23
- package/dist/ai-edits/table-cell-mutations.d.ts +1 -1
- package/dist/ai-edits/table-cell-mutations.js +4 -1
- package/dist/ai-edits/table-geometry.d.ts +1 -1
- package/dist/ai-edits/table-row-column-mutations.d.ts +38 -16
- package/dist/ai-edits/table-row-column-mutations.js +61 -26
- package/dist/ai-edits/types.d.ts +155 -16
- package/dist/compare/compare.d.ts +1 -1
- package/dist/compare/compare.js +65 -16
- package/dist/compare/content-alignment.js +13 -2
- package/dist/compare/content-types.d.ts +7 -0
- package/dist/compare/content.d.ts +4 -1
- package/dist/compare/content.js +6 -1
- package/dist/compare/formatting.js +2 -1
- package/dist/compare/inline-atoms.d.ts +21 -4
- package/dist/compare/inline-atoms.js +138 -16
- package/dist/compare/plan.js +10 -5
- package/dist/compare/scenario.js +14 -3
- package/dist/compare/section-boundary-properties.js +1 -1
- package/dist/compare/types.d.ts +4 -2
- package/dist/compare/types.js +2 -1
- package/dist/compare/verification.d.ts +1 -1
- package/dist/compare/verification.js +15 -3
- package/dist/controller/committedLayoutDiff.d.ts +25 -0
- package/dist/controller/committedLayoutDiff.js +71 -0
- package/dist/controller/contentControlWidgetController.d.ts +1 -1
- package/dist/controller/folioEditor.d.ts +1 -1
- package/dist/controller/fontReadiness.d.ts +70 -3
- package/dist/controller/fontReadiness.js +100 -10
- package/dist/controller/headerFooterEditorManager.js +6 -1
- package/dist/controller/layoutPipeline.d.ts +12 -10
- package/dist/controller/layoutPipeline.js +62 -9
- package/dist/controller/layoutRunOptions.d.ts +24 -0
- package/dist/controller/layoutRunOptions.js +17 -0
- package/dist/controller/layoutScheduler.d.ts +19 -14
- package/dist/controller/layoutScheduler.js +15 -12
- package/dist/controller/layoutSession.d.ts +26 -2
- package/dist/controller/layoutSession.js +1 -1
- package/dist/controller/noteEditorManager.js +8 -3
- package/dist/document-operations.d.ts +11 -2
- package/dist/document-operations.js +230 -21
- package/dist/docx/altChunk.d.ts +8 -0
- package/dist/docx/altChunk.js +17 -0
- package/dist/docx/attributeRemainder.d.ts +1 -1
- package/dist/docx/blockContentParser.d.ts +64 -1
- package/dist/docx/blockContentParser.js +17 -4
- package/dist/docx/blockCustomXmlShell.d.ts +7 -0
- package/dist/docx/blockCustomXmlShell.js +14 -0
- package/dist/docx/blockPlainText.js +7 -0
- package/dist/docx/commentAnchorIndex.js +1 -1
- package/dist/docx/commentRangeIntegrity.js +8 -3
- package/dist/docx/commentReferenceNormalization.js +1 -1
- package/dist/docx/commentReplyMarkers.js +20 -1
- package/dist/docx/compatibility.d.ts +1 -1
- package/dist/docx/compatibility.js +34 -13
- package/dist/docx/containerChildren.gen.d.ts +1 -1
- package/dist/docx/containerChildren.gen.js +1 -0
- package/dist/docx/documentParser.js +12 -12
- package/dist/docx/drawingIdNormalization.d.ts +3 -1
- package/dist/docx/drawingIdNormalization.js +6 -1
- package/dist/docx/ensureParaIds.js +119 -97
- package/dist/docx/footnoteParser.js +8 -4
- package/dist/docx/headerFooterParser.js +3 -3
- package/dist/docx/headerFooterReferenceNormalization.d.ts +20 -1
- package/dist/docx/headerFooterReferenceNormalization.js +52 -27
- package/dist/docx/hyperlinkParser.d.ts +1 -1
- package/dist/docx/index.d.ts +1 -1
- package/dist/docx/listNumberingInstances.d.ts +59 -0
- package/dist/docx/listNumberingInstances.js +249 -0
- package/dist/docx/normalizeBaseDirection.js +2 -1
- package/dist/docx/opaqueCarrier.d.ts +7 -0
- package/dist/docx/opaqueCarrier.js +38 -0
- package/dist/docx/packageParts.js +4 -1
- package/dist/docx/paragraphParser.js +91 -24
- package/dist/docx/paragraphPropertySource.d.ts +4 -2
- package/dist/docx/paragraphPropertySource.js +7 -1
- package/dist/docx/paragraphTraversal.js +1 -0
- package/dist/docx/parseWarningMessage.js +4 -1
- package/dist/docx/parser.js +173 -20
- package/dist/docx/rezip.js +27 -5
- package/dist/docx/sdtProperties.js +1 -1
- package/dist/docx/sdtPropertiesPatch.js +3 -0
- package/dist/docx/selectiveSave.js +16 -9
- package/dist/docx/selectiveXmlPatch.js +106 -37
- package/dist/docx/serializer/blockCustomXmlSerializer.d.ts +5 -0
- package/dist/docx/serializer/blockCustomXmlSerializer.js +4 -0
- package/dist/docx/serializer/documentSerializer.js +2 -0
- package/dist/docx/serializer/headerFooterSerializer.js +2 -0
- package/dist/docx/serializer/noteSerializer.js +3 -1
- package/dist/docx/serializer/paragraphSerializer.js +33 -9
- package/dist/docx/serializer/tableSerializer.js +25 -38
- package/dist/docx/server/createBilingualDocument.js +3 -3
- package/dist/docx/tableParser.d.ts +157 -1
- package/dist/docx/tableParser.js +89 -10
- package/dist/docx/textBoxParser.js +1 -1
- package/dist/docx/unzip.d.ts +2 -1
- package/dist/docx/unzip.js +1 -1
- package/dist/docx/wordprocessingPrefixes.d.ts +78 -0
- package/dist/docx/wordprocessingPrefixes.js +286 -0
- package/dist/i18n/messages/catalogs.gen.d.ts +136 -0
- package/dist/i18n/messages/catalogs.gen.js +153 -17
- package/dist/i18n/messages/messages.gen.d.ts +8 -0
- package/dist/internal/compare/inline-presentation.d.ts +2 -1
- package/dist/internal/compare/inline-presentation.js +11 -10
- package/dist/internal/headlessRevisionResolutionGuard.d.ts +2 -8
- package/dist/internal/headlessRevisionResolutionGuard.js +2 -11
- package/dist/internal/indexedPositionMap.d.ts +11 -0
- package/dist/internal/indexedPositionMap.js +42 -0
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +2 -1
- package/dist/internal/revisionResolutionEdits.d.ts +13 -0
- package/dist/internal/revisionResolutionEdits.js +19 -0
- package/dist/internal/revisionResolutionInline.d.ts +24 -0
- package/dist/internal/{headlessRevisionResolution.js → revisionResolutionInline.js} +61 -43
- package/dist/internal/revisionResolutionStep.d.ts +34 -0
- package/dist/internal/revisionResolutionStep.js +282 -0
- package/dist/internal/revisionResolutionTracking.d.ts +11 -0
- package/dist/internal/revisionResolutionTracking.js +124 -0
- package/dist/internal/wholeStoryRevisionResolution.d.ts +56 -0
- package/dist/internal/wholeStoryRevisionResolution.js +530 -0
- package/dist/layout-bridge/convert/markupViewFlow.d.ts +20 -0
- package/dist/layout-bridge/convert/markupViewFlow.js +123 -0
- package/dist/layout-bridge/convert/tableConversion.js +1 -1
- package/dist/layout-bridge/convert/toFlowBlocks.js +10 -1
- package/dist/layout-engine/layoutInstrumentation.d.ts +9 -1
- package/dist/layout-engine/layoutInstrumentation.js +4 -1
- package/dist/layout-engine/measure/cache.d.ts +18 -1
- package/dist/layout-engine/measure/cache.js +31 -1
- package/dist/layout-engine/measure/font-metrics.worker.js +3 -7
- package/dist/layout-engine/measure/measureContainer.js +7 -47
- package/dist/layout-engine/measure/measureHelpers.d.ts +6 -1
- package/dist/layout-engine/measure/measureHelpers.js +22 -2
- package/dist/layout-engine/measure/measureWorker.js +2 -3
- package/dist/layout-engine/measure/measureWorkerProtocol.d.ts +6 -7
- package/dist/layout-engine/measure/measureWorkerProtocol.js +1 -2
- package/dist/layout-engine/types.d.ts +6 -0
- package/dist/layout-painter/renderPage.js +1 -0
- package/dist/layout-painter/renderParagraph.js +1 -1
- package/dist/managers/ContextMenuManager.js +5 -2
- package/dist/managers/types.d.ts +3 -0
- package/dist/markdown/fromMarkdown.js +2 -1
- package/dist/markdown/internals.d.ts +11 -1
- package/dist/markdown/internals.js +24 -3
- package/dist/markdown/renderBlock.js +39 -9
- package/dist/markdown/renderParagraph.d.ts +13 -1
- package/dist/markdown/renderParagraph.js +85 -38
- package/dist/markdown/renderRuns.js +3 -10
- package/dist/markdown/renderTable.js +24 -12
- package/dist/markdown/trailers.js +2 -2
- package/dist/markdown/types.d.ts +29 -7
- package/dist/paged-layout/incrementalMeasure.d.ts +1 -2
- package/dist/paged-layout/incrementalMeasure.js +1 -9
- package/dist/paged-layout/transactionDirtyRange.d.ts +1 -3
- package/dist/paged-layout/transactionDirtyRange.js +29 -41
- package/dist/panel-layout.d.ts +83 -0
- package/dist/panel-layout.js +96 -0
- package/dist/prosemirror/anchoredTextBoxes.d.ts +37 -0
- package/dist/prosemirror/anchoredTextBoxes.js +156 -0
- package/dist/prosemirror/attrs/index.d.ts +6 -2
- package/dist/prosemirror/attrs/index.js +172 -1
- package/dist/prosemirror/commands/comments.d.ts +7 -8
- package/dist/prosemirror/commands/comments.js +241 -207
- package/dist/prosemirror/commands/contentControls.d.ts +1 -1
- package/dist/prosemirror/commands/formatPainter.d.ts +1 -1
- package/dist/prosemirror/commands/formatting.d.ts +1 -1
- package/dist/prosemirror/commands/index.d.ts +2 -2
- package/dist/prosemirror/commands/index.js +2 -2
- package/dist/prosemirror/commands/paragraph.d.ts +7 -1
- package/dist/prosemirror/commands/paragraph.js +9 -1
- package/dist/prosemirror/commands/paragraphBookmarkJoin.d.ts +13 -0
- package/dist/prosemirror/commands/paragraphBookmarkJoin.js +22 -0
- package/dist/prosemirror/commands/pastePlainText.d.ts +1 -1
- package/dist/prosemirror/commands/resolveAllTableChanges.d.ts +40 -0
- package/dist/prosemirror/commands/resolveAllTableChanges.js +615 -0
- package/dist/prosemirror/commands/resolveNodePropertyChangeAttrs.d.ts +15 -0
- package/dist/prosemirror/commands/resolveNodePropertyChangeAttrs.js +46 -0
- package/dist/prosemirror/commands/resolveParagraphProperties.d.ts +16 -0
- package/dist/prosemirror/commands/resolveParagraphProperties.js +59 -0
- package/dist/prosemirror/commands/sectionBreak.js +2 -1
- package/dist/prosemirror/commands/tableCellMergeResolution.d.ts +8 -2
- package/dist/prosemirror/commands/tableCellMergeResolution.js +1 -1
- package/dist/prosemirror/contentControlRevisions.d.ts +1 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +181 -31
- package/dist/prosemirror/conversion/toProseDoc.js +39 -4
- package/dist/prosemirror/emptyFieldResultRuns.d.ts +18 -0
- package/dist/prosemirror/emptyFieldResultRuns.js +33 -0
- package/dist/prosemirror/extensions/ExtensionManager.d.ts +1 -1
- package/dist/prosemirror/extensions/ExtensionManager.js +3 -1
- package/dist/prosemirror/extensions/StarterKit.js +3 -1
- package/dist/prosemirror/extensions/core/DocExtension.js +1 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +12 -0
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +3 -0
- package/dist/prosemirror/extensions/features/ListExtension.js +161 -123
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +19 -2
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +33 -20
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +31 -2
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +270 -99
- package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +3 -2
- package/dist/prosemirror/extensions/features/pasteCleanup.js +2 -1
- package/dist/prosemirror/extensions/features/pastedHtmlLists.d.ts +12 -0
- package/dist/prosemirror/extensions/features/pastedHtmlLists.js +126 -0
- package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +21 -5
- package/dist/prosemirror/extensions/marks/RunIdentityExtension.d.ts +21 -18
- package/dist/prosemirror/extensions/marks/RunIdentityExtension.js +37 -17
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +7 -2
- package/dist/prosemirror/extensions/marks/markUtils.js +8 -2
- package/dist/prosemirror/extensions/marks/noteReferenceDeletion.d.ts +10 -0
- package/dist/prosemirror/extensions/marks/noteReferenceDeletion.js +35 -0
- package/dist/prosemirror/extensions/nodes/BlockCustomXmlExtension.d.ts +6 -0
- package/dist/prosemirror/extensions/nodes/BlockCustomXmlExtension.js +52 -0
- package/dist/prosemirror/extensions/nodes/FieldExtension.d.ts +3 -3
- package/dist/prosemirror/extensions/nodes/FieldExtension.js +50 -15
- package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.js +4 -1
- package/dist/prosemirror/extensions/nodes/TableExtension.d.ts +1 -1
- package/dist/prosemirror/extensions/nodes/TableExtension.js +19 -18
- package/dist/prosemirror/extensions/types.d.ts +4 -1
- package/dist/prosemirror/findReplaceSelection.js +1 -1
- package/dist/prosemirror/index.d.ts +3 -2
- package/dist/prosemirror/index.js +3 -2
- package/dist/prosemirror/indexedNodeLookup.d.ts +17 -0
- package/dist/prosemirror/indexedNodeLookup.js +103 -0
- package/dist/prosemirror/listAutoformatMarkers.d.ts +19 -0
- package/dist/prosemirror/listAutoformatMarkers.js +98 -0
- package/dist/prosemirror/listInstanceReferences.d.ts +12 -0
- package/dist/prosemirror/listInstanceReferences.js +72 -0
- package/dist/prosemirror/listLabels.d.ts +24 -0
- package/dist/prosemirror/listLabels.js +111 -0
- package/dist/prosemirror/listNumbering.d.ts +110 -0
- package/dist/prosemirror/listNumbering.js +345 -0
- package/dist/prosemirror/listRenderingAttrs.d.ts +11 -2
- package/dist/prosemirror/listRenderingAttrs.js +8 -1
- package/dist/prosemirror/markupViewProjection.d.ts +95 -0
- package/dist/prosemirror/markupViewProjection.js +83 -0
- package/dist/prosemirror/numberingAttr.d.ts +9 -1
- package/dist/prosemirror/numberingAttr.js +9 -1
- package/dist/prosemirror/outlineLevelAttr.js +1 -1
- package/dist/prosemirror/paragraphIndentation.d.ts +10 -1
- package/dist/prosemirror/paragraphIndentation.js +29 -7
- package/dist/prosemirror/paragraphMarkJoin.d.ts +19 -0
- package/dist/prosemirror/paragraphMarkJoin.js +24 -0
- package/dist/prosemirror/plugins/createDocScanPlugin.d.ts +1 -1
- package/dist/prosemirror/plugins/documentNumbering.d.ts +27 -1
- package/dist/prosemirror/plugins/documentNumbering.js +97 -11
- package/dist/prosemirror/plugins/documentStyles.d.ts +10 -1
- package/dist/prosemirror/plugins/documentStyles.js +14 -1
- package/dist/prosemirror/plugins/suggestionMode.d.ts +16 -2
- package/dist/prosemirror/plugins/suggestionMode.js +116 -52
- package/dist/prosemirror/plugins/templateDirectives.d.ts +1 -1
- package/dist/prosemirror/plugins/transactionInvariants.d.ts +32 -0
- package/dist/prosemirror/plugins/transactionInvariants.js +86 -0
- package/dist/prosemirror/positionSweep.d.ts +24 -0
- package/dist/prosemirror/positionSweep.js +222 -0
- package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +1 -1
- package/dist/prosemirror/rejoinRunCarriers.d.ts +1 -1
- package/dist/prosemirror/replacedAnnotations.d.ts +33 -1
- package/dist/prosemirror/replacedAnnotations.js +170 -1
- package/dist/prosemirror/runFormattingInlineCarriers.d.ts +1 -1
- package/dist/prosemirror/schema/index.d.ts +2 -2
- package/dist/prosemirror/schema/index.js +3 -0
- package/dist/prosemirror/schema/nodes.d.ts +42 -11
- package/dist/prosemirror/sectionMarkEdits.d.ts +20 -0
- package/dist/prosemirror/sectionMarkEdits.js +59 -0
- package/dist/prosemirror/storyListNumbering.d.ts +17 -0
- package/dist/prosemirror/storyListNumbering.js +102 -0
- package/dist/prosemirror/tableGridMutation.d.ts +48 -2
- package/dist/prosemirror/tableGridMutation.js +106 -1
- package/dist/prosemirror/validation.js +5 -1
- package/dist/redline.js +93 -9
- package/dist/render-dom/BodySelectionOverlay.d.ts +4 -1
- package/dist/render-dom/BodySelectionOverlay.js +3 -2
- package/dist/utils/findReplace.js +2 -2
- package/dist/utils/mergeDocumentContent.js +1 -1
- package/dist/utils/noteReferenceLabels.d.ts +36 -0
- package/dist/utils/noteReferenceLabels.js +32 -0
- package/dist/utils/replaceText.js +1 -1
- package/dist/version-comparison.d.ts +1 -0
- package/dist/version-comparison.js +1 -0
- package/package.json +3 -2
- package/dist/internal/headlessRevisionResolution.d.ts +0 -23
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { bulletMarkerFontName, convertBulletToUnicode } from "../docx/bulletMarkers.js";
|
|
2
|
+
import { paragraphNumberingReference, paragraphNumberingReferenceId } from "../docx/numberingReference.js";
|
|
3
|
+
import { advanceListMarker, advanceVisibleListMarker, cloneListCounterState, createListCounterState } from "./listMarker.js";
|
|
4
|
+
import { hasListRendering } from "./listRenderingAttrs.js";
|
|
5
|
+
import { paragraphNumberingAttr } from "./numberingAttr.js";
|
|
6
|
+
//#region src/prosemirror/listLabels.ts
|
|
7
|
+
/**
|
|
8
|
+
* The number or bullet a paragraph shows beside its text, as a reader reports
|
|
9
|
+
* it: counted in document order by the counter the page paints its markers
|
|
10
|
+
* with (`advanceVisibleListMarker`), so a reader's labels follow every edit.
|
|
11
|
+
* The `listMarker` attr is the marker the parser resolved when the document
|
|
12
|
+
* was opened; an item inserted, deleted, moved or restarted since leaves it
|
|
13
|
+
* stale for that item and every item after it.
|
|
14
|
+
*
|
|
15
|
+
* A reader counts inside the walk it already makes over the document (the AI
|
|
16
|
+
* snapshot's, Markdown's), one step per paragraph, so an edit costs nothing
|
|
17
|
+
* until something reads the document.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* The cached text of a `LISTNUM` field the parser folded into the marker
|
|
21
|
+
* (`7.1\t(a)`). The level's template does not carry it, so it is kept as read.
|
|
22
|
+
*/
|
|
23
|
+
const foldedFieldSuffix = (attrs) => {
|
|
24
|
+
const marker = attrs.listMarker;
|
|
25
|
+
const template = attrs.listMarkerTemplate;
|
|
26
|
+
if (!marker || !template || template.includes(" ")) return "";
|
|
27
|
+
const tab = marker.indexOf(" ");
|
|
28
|
+
return tab === -1 ? "" : marker.slice(tab);
|
|
29
|
+
};
|
|
30
|
+
const withoutNumbering = (attrs) => {
|
|
31
|
+
const unnumbered = { ...attrs };
|
|
32
|
+
Reflect.deleteProperty(unnumbered, "numPr");
|
|
33
|
+
return unnumbered;
|
|
34
|
+
};
|
|
35
|
+
const staticMarker = (attrs) => {
|
|
36
|
+
const marker = attrs.listMarker;
|
|
37
|
+
if (!marker) return;
|
|
38
|
+
return (attrs.listIsBullet ? convertBulletToUnicode(marker, bulletMarkerFontName(attrs.listMarkerFormatting)) : marker).trim() || void 0;
|
|
39
|
+
};
|
|
40
|
+
/** Most paragraphs: nothing to count and no marker to show. */
|
|
41
|
+
const isPlainParagraph = (attrs) => attrs.numPr == null && attrs.listMarker == null && attrs.listMarkerTemplate == null && (attrs._propertyChanges == null || attrs._propertyChanges.length === 0);
|
|
42
|
+
const NO_PREVIOUS_LIST = {
|
|
43
|
+
abstractNumId: null,
|
|
44
|
+
fromStyle: false,
|
|
45
|
+
numId: null
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* The attrs the counter reads for a paragraph of the document model, as
|
|
49
|
+
* `toProseDoc` projects them (`listRenderingAttrPatch`), without the layout
|
|
50
|
+
* attrs no label depends on: a reader that walks the model (Markdown) counts
|
|
51
|
+
* every list paragraph through here.
|
|
52
|
+
*/
|
|
53
|
+
const listLabelAttrsFromRendering = (rendering, numPrFromStyle) => {
|
|
54
|
+
const attrs = { numPr: paragraphNumberingAttr(paragraphNumberingReference({
|
|
55
|
+
numId: rendering.numId,
|
|
56
|
+
ilvl: rendering.level
|
|
57
|
+
})) };
|
|
58
|
+
if (numPrFromStyle) attrs.numPrFromStyle = paragraphNumberingAttr(numPrFromStyle);
|
|
59
|
+
if (rendering.marker) attrs.listMarker = rendering.marker;
|
|
60
|
+
if (rendering.markerTemplate) attrs.listMarkerTemplate = rendering.markerTemplate;
|
|
61
|
+
if (rendering.isBullet) attrs.listIsBullet = true;
|
|
62
|
+
if (rendering.isLegal) attrs.listIsLegal = true;
|
|
63
|
+
if (rendering.numFmt) attrs.listNumFmt = rendering.numFmt;
|
|
64
|
+
if (rendering.markerHidden) attrs.listMarkerHidden = true;
|
|
65
|
+
if (rendering.markerFormatting) attrs.listMarkerFormatting = rendering.markerFormatting;
|
|
66
|
+
if (rendering.levelNumFmts) attrs.listLevelNumFmts = rendering.levelNumFmts;
|
|
67
|
+
if (rendering.levelStarts) attrs.listLevelStarts = rendering.levelStarts;
|
|
68
|
+
if (rendering.abstractNumId !== void 0) attrs.listAbstractNumId = rendering.abstractNumId;
|
|
69
|
+
if (rendering.startOverride !== void 0) attrs.listStartOverride = rendering.startOverride;
|
|
70
|
+
if (rendering.implicitChildLevelAdvances !== void 0) attrs.listImplicitChildLevelAdvances = rendering.implicitChildLevelAdvances;
|
|
71
|
+
return attrs;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* A counter over paragraph attrs in document order. Call it for every
|
|
75
|
+
* paragraph, numbered or not: whether a list continues depends on what stands
|
|
76
|
+
* between its items.
|
|
77
|
+
*/
|
|
78
|
+
const createListLabelCounter = () => {
|
|
79
|
+
const final = createListCounterState();
|
|
80
|
+
let streams = null;
|
|
81
|
+
let originalPreviousList = NO_PREVIOUS_LIST;
|
|
82
|
+
const advance = (counted) => {
|
|
83
|
+
const tracked = counted.pPrMark != null || counted._propertyChanges != null && counted._propertyChanges.length > 0;
|
|
84
|
+
if (streams === null && tracked) {
|
|
85
|
+
const original = cloneListCounterState(final);
|
|
86
|
+
original.previousList = { ...originalPreviousList };
|
|
87
|
+
streams = {
|
|
88
|
+
final,
|
|
89
|
+
original
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
if (streams !== null) return advanceVisibleListMarker(counted, streams).marker;
|
|
93
|
+
const marker = advanceListMarker(counted, final);
|
|
94
|
+
if (counted.numPr) originalPreviousList = final.previousList ?? NO_PREVIOUS_LIST;
|
|
95
|
+
return marker;
|
|
96
|
+
};
|
|
97
|
+
return (attrs) => {
|
|
98
|
+
if (isPlainParagraph(attrs)) {
|
|
99
|
+
final.previousList = NO_PREVIOUS_LIST;
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const rendered = hasListRendering(attrs);
|
|
103
|
+
const marker = advance(rendered ? attrs : withoutNumbering(attrs));
|
|
104
|
+
if (attrs.listMarkerHidden === true || !rendered) return;
|
|
105
|
+
const counted = paragraphNumberingReferenceId(attrs.numPr) === void 0 ? null : marker?.trim();
|
|
106
|
+
if (counted) return `${counted}${foldedFieldSuffix(attrs)}`;
|
|
107
|
+
return staticMarker(attrs);
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
//#endregion
|
|
111
|
+
export { createListLabelCounter, listLabelAttrsFromRendering };
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { ListKind, ListLevelFormat } from "../docx/listNumberingInstances.js";
|
|
2
|
+
import { ParagraphAttrs, ParagraphPropertyChangeAttrs } from "./schema/nodes.js";
|
|
3
|
+
import { NumberingMap } from "../docx/numberingParser.js";
|
|
4
|
+
import { Node, ResolvedPos } from "prosemirror-model";
|
|
5
|
+
import { Command, EditorState, Transaction } from "prosemirror-state";
|
|
6
|
+
//#region src/prosemirror/listNumbering.d.ts
|
|
7
|
+
/** What a list command or typed marker asks for. */
|
|
8
|
+
type ListRequest = {
|
|
9
|
+
kind: ListKind;
|
|
10
|
+
/**
|
|
11
|
+
* The first level's format. A neighbouring list is continued only when its
|
|
12
|
+
* level has this format; a new list is defined with it.
|
|
13
|
+
*/
|
|
14
|
+
format?: ListLevelFormat | undefined;
|
|
15
|
+
/** The value a new list's first item shows. */
|
|
16
|
+
start?: number | undefined;
|
|
17
|
+
};
|
|
18
|
+
type PreviousFormatting = NonNullable<ParagraphPropertyChangeAttrs["previousFormatting"]>;
|
|
19
|
+
/**
|
|
20
|
+
* The list rendering a paragraph takes when a `w:pPrChange` is rejected. A
|
|
21
|
+
* reject restores the recorded numbering, but the rendering attrs sit outside
|
|
22
|
+
* the scope it restores wholesale, so a record that does not state them (one
|
|
23
|
+
* written by an operation, or read from a file) would leave the rendering of
|
|
24
|
+
* the numbering it undoes: a paragraph restored to no numbering still showed
|
|
25
|
+
* the marker it was given. When the reject changes the numbering, the
|
|
26
|
+
* rendering is recomputed from the restored numbering; otherwise it stays.
|
|
27
|
+
*/
|
|
28
|
+
type RejectedListRenderingOptions = {
|
|
29
|
+
/** The paragraph's attrs before the reject. */
|
|
30
|
+
current: Pick<ParagraphAttrs, "numPr">;
|
|
31
|
+
/** The previous state the rejected record restores. */
|
|
32
|
+
previousFormatting: PreviousFormatting | null | undefined;
|
|
33
|
+
numbering: NumberingMap | null;
|
|
34
|
+
};
|
|
35
|
+
declare const rejectedListRenderingPatch: ({ current, previousFormatting, numbering }: RejectedListRenderingOptions) => Record<string, unknown>;
|
|
36
|
+
/** Where the paragraphs a command numbers go. */
|
|
37
|
+
type ListTarget = {
|
|
38
|
+
numId: number;
|
|
39
|
+
/** The level a paragraph that is not yet a list item takes. */
|
|
40
|
+
ilvl: number;
|
|
41
|
+
/** Definitions the target is resolved in, including one minted for it. */
|
|
42
|
+
numbering: NumberingMap;
|
|
43
|
+
};
|
|
44
|
+
type ResolveListTargetOptions = {
|
|
45
|
+
numbering: NumberingMap | null;
|
|
46
|
+
$from: ResolvedPos;
|
|
47
|
+
$to: ResolvedPos;
|
|
48
|
+
/** Candidate requests, most likely first (see `listRequestsForMarker`). */
|
|
49
|
+
requests: readonly ListRequest[];
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* The list a paragraph range joins: the list directly above it, else the one
|
|
53
|
+
* directly below it, when it matches one of `requests`; otherwise a new list:
|
|
54
|
+
* an unused instance the package already defines for the first request, or
|
|
55
|
+
* one defined for it.
|
|
56
|
+
*/
|
|
57
|
+
declare const resolveListTarget: ({ numbering, $from, $to, requests }: ResolveListTargetOptions) => ListTarget | null;
|
|
58
|
+
/** A paragraph's attrs as an item of `numId` at `ilvl`, resolved in `numbering`. */
|
|
59
|
+
declare const listItemAttrs: (attrs: Record<string, unknown>, { numId, ilvl }: {
|
|
60
|
+
numId: number;
|
|
61
|
+
ilvl: number;
|
|
62
|
+
}, numbering: NumberingMap) => Record<string, unknown>;
|
|
63
|
+
type ParagraphUpdate = {
|
|
64
|
+
pos: number;
|
|
65
|
+
node: Node;
|
|
66
|
+
next: Record<string, unknown>;
|
|
67
|
+
};
|
|
68
|
+
type ApplyParagraphUpdatesOptions = {
|
|
69
|
+
tr: Transaction;
|
|
70
|
+
state: EditorState;
|
|
71
|
+
updates: readonly ParagraphUpdate[];
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Write `updates` into `tr`, each recorded as a tracked change while the
|
|
75
|
+
* editor is suggesting. `pos` is a position in `tr.doc`.
|
|
76
|
+
*/
|
|
77
|
+
declare const applyParagraphUpdates: ({ tr, state, updates }: ApplyParagraphUpdatesOptions) => void;
|
|
78
|
+
/**
|
|
79
|
+
* Start the list over at `value` from the selected item: *Set Numbering
|
|
80
|
+
* Value* with *Start new list*. The item and every later item of
|
|
81
|
+
* its list move to a new instance of the same definition, whose
|
|
82
|
+
* `w:startOverride` at the item's level is `value`.
|
|
83
|
+
*/
|
|
84
|
+
declare const setNumberingValue: (value: number) => Command;
|
|
85
|
+
/** *Restart at 1*: the selected item starts its list over at one. */
|
|
86
|
+
declare const restartNumbering: Command;
|
|
87
|
+
/**
|
|
88
|
+
* *Continue Numbering*: the selected item and the rest of its list
|
|
89
|
+
* join the nearest earlier list of the same kind, so their numbers carry on
|
|
90
|
+
* from it. Not applicable when no such list precedes the item.
|
|
91
|
+
*/
|
|
92
|
+
declare const continueNumbering: Command;
|
|
93
|
+
/** What a context menu offers for the item the selection is in. */
|
|
94
|
+
type ListNumberingMenuState = {
|
|
95
|
+
readonly type: "none";
|
|
96
|
+
} | {
|
|
97
|
+
readonly type: "listItem";
|
|
98
|
+
readonly canContinue: boolean;
|
|
99
|
+
};
|
|
100
|
+
declare const NO_LIST_NUMBERING_MENU: {
|
|
101
|
+
readonly type: "none";
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Whether the selection is in a list item whose numbering can be restarted
|
|
105
|
+
* or set, and whether an earlier list lets it continue: the enabled state of
|
|
106
|
+
* those menu entries.
|
|
107
|
+
*/
|
|
108
|
+
declare const listNumberingMenuState: (state: EditorState) => ListNumberingMenuState;
|
|
109
|
+
//#endregion
|
|
110
|
+
export { ListNumberingMenuState, ListRequest, NO_LIST_NUMBERING_MENU, RejectedListRenderingOptions, applyParagraphUpdates, continueNumbering, listItemAttrs, listNumberingMenuState, rejectedListRenderingPatch, resolveListTarget, restartNumbering, setNumberingValue };
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import { mintListInstance, restartListInstance } from "../docx/listNumberingInstances.js";
|
|
2
|
+
import { createNumberingMap, isBulletLevel } from "../docx/numberingParser.js";
|
|
3
|
+
import { paragraphNumberingLevel, paragraphNumberingReferenceId, sameStatedParagraphNumbering } from "../docx/numberingReference.js";
|
|
4
|
+
import { expectParagraphAttrs } from "./attrs/index.js";
|
|
5
|
+
import { paragraphPropertiesSnapshot } from "./commands/propertyChangeScope.js";
|
|
6
|
+
import { CLEARED_LIST_RENDERING_ATTRS } from "./listMarker.js";
|
|
7
|
+
import { LIST_RENDERING_ATTR_KEYS } from "./listRenderingAttrs.js";
|
|
8
|
+
import { getDocumentNumbering } from "./plugins/documentNumbering.js";
|
|
9
|
+
import { SUGGESTION_META, makeRevisionInfo } from "./plugins/suggestionMode.js";
|
|
10
|
+
import { listAttrsFromNumbering } from "./styles/resolvedStyleAttrs.js";
|
|
11
|
+
//#region src/prosemirror/listNumbering.ts
|
|
12
|
+
const PARAGRAPH_NODE = "paragraph";
|
|
13
|
+
/**
|
|
14
|
+
* The paragraph's properties as a `w:pPrChange` records them before a list
|
|
15
|
+
* change: every non-null in-scope attr (a reject restores the scope
|
|
16
|
+
* wholesale, so an unrecorded one would be wiped), plus the numbering and the
|
|
17
|
+
* list-rendering bookkeeping with explicit nulls (those sit outside the
|
|
18
|
+
* wholesale scope, so only recorded keys restore).
|
|
19
|
+
*/
|
|
20
|
+
const listChangeSnapshot = (node, attrs) => {
|
|
21
|
+
const previousFormatting = paragraphPropertiesSnapshot(node.type.create(attrs, node.content, node.marks));
|
|
22
|
+
previousFormatting["numPr"] = attrs["numPr"] ?? null;
|
|
23
|
+
for (const key of LIST_RENDERING_ATTR_KEYS) previousFormatting[key] = attrs[key] ?? null;
|
|
24
|
+
return previousFormatting;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* The original state a pending record describes, completed with the list
|
|
28
|
+
* attrs it may not state. A record written by a list command states them all.
|
|
29
|
+
* One written for another property (or read from a file) states the scope
|
|
30
|
+
* only: its numbering is the original's, and an absent one means the original
|
|
31
|
+
* had none, so the rendering is recomputed from it rather than copied from
|
|
32
|
+
* the live paragraph, whose list may since have changed.
|
|
33
|
+
*/
|
|
34
|
+
const originalListFormatting = (record, numbering) => {
|
|
35
|
+
const original = { ...record };
|
|
36
|
+
if (recordsListRendering(record)) return original;
|
|
37
|
+
Object.assign(original, listRenderingFor(record.numPr, numbering));
|
|
38
|
+
original["numPr"] = record.numPr ?? null;
|
|
39
|
+
return original;
|
|
40
|
+
};
|
|
41
|
+
/** Whether a `w:pPrChange` record states the list rendering it had (a list command's does). */
|
|
42
|
+
const recordsListRendering = (record) => LIST_RENDERING_ATTR_KEYS.some((key) => Object.hasOwn(record, key));
|
|
43
|
+
/** Every list-rendering attr for `numPr`: its level's, or all cleared when it numbers nothing. */
|
|
44
|
+
const listRenderingFor = (numPr, numbering) => {
|
|
45
|
+
const numId = paragraphNumberingReferenceId(numPr ?? void 0);
|
|
46
|
+
const rendering = numId === void 0 ? CLEARED_LIST_RENDERING_ATTRS : listAttrsFromNumbering({
|
|
47
|
+
numId,
|
|
48
|
+
ilvl: paragraphNumberingLevel(numPr ?? void 0) ?? 0
|
|
49
|
+
}, numbering);
|
|
50
|
+
const attrs = {};
|
|
51
|
+
for (const key of LIST_RENDERING_ATTR_KEYS) attrs[key] = rendering[key] ?? null;
|
|
52
|
+
return attrs;
|
|
53
|
+
};
|
|
54
|
+
const rejectedListRenderingPatch = ({ current, previousFormatting, numbering }) => {
|
|
55
|
+
const record = previousFormatting ?? {};
|
|
56
|
+
if (recordsListRendering(record)) return {};
|
|
57
|
+
const restored = record.numPr ?? void 0;
|
|
58
|
+
if (sameStatedParagraphNumbering(restored, current.numPr ?? void 0)) return {};
|
|
59
|
+
return listRenderingFor(restored, numbering);
|
|
60
|
+
};
|
|
61
|
+
const canonicalJson = (value) => JSON.stringify(value, (_key, nested) => nested !== null && typeof nested === "object" && !Array.isArray(nested) ? Object.fromEntries(Object.entries(nested).filter(([, entry]) => entry !== null && entry !== void 0).toSorted(([left], [right]) => left.localeCompare(right))) : nested);
|
|
62
|
+
/**
|
|
63
|
+
* `next` with the list change recorded as a tracked paragraph-property change.
|
|
64
|
+
*
|
|
65
|
+
* A paragraph holds at most one serializable `w:pPrChange`. When it already
|
|
66
|
+
* has one, the record is replaced by one that keeps the original previous
|
|
67
|
+
* state: a second change under tracking is a further change to the same
|
|
68
|
+
* paragraph, and rejecting it must restore the paragraph as it was before
|
|
69
|
+
* either. When the change brings the paragraph back to that original, there
|
|
70
|
+
* is nothing left to track and the author's own record is dropped.
|
|
71
|
+
*
|
|
72
|
+
* A pending record by another author (another reviewer's, or one read from
|
|
73
|
+
* the file) keeps its author, id and date: the change joins that revision
|
|
74
|
+
* rather than re-attributing it, and it is never dropped.
|
|
75
|
+
*/
|
|
76
|
+
const trackListChange = ({ current, next, rev, numbering }) => {
|
|
77
|
+
const currentAttrs = expectParagraphAttrs(current);
|
|
78
|
+
const existing = currentAttrs._propertyChanges ?? [];
|
|
79
|
+
const pending = existing.find(({ info }) => info.provenance !== "suggested");
|
|
80
|
+
const retained = existing.filter((change) => change !== pending);
|
|
81
|
+
const previousFormatting = pending?.previousFormatting ? originalListFormatting(pending.previousFormatting, numbering) : listChangeSnapshot(current, currentAttrs);
|
|
82
|
+
const ownPending = pending !== void 0 && pending.info.author === rev.author;
|
|
83
|
+
if (ownPending && canonicalJson(previousFormatting) === canonicalJson(listChangeSnapshot(current, next))) return {
|
|
84
|
+
...next,
|
|
85
|
+
_propertyChanges: retained.length > 0 ? retained : null
|
|
86
|
+
};
|
|
87
|
+
const record = pending && !ownPending ? {
|
|
88
|
+
...pending,
|
|
89
|
+
previousFormatting
|
|
90
|
+
} : {
|
|
91
|
+
type: "paragraphPropertyChange",
|
|
92
|
+
info: {
|
|
93
|
+
id: rev.id,
|
|
94
|
+
author: rev.author,
|
|
95
|
+
date: rev.date
|
|
96
|
+
},
|
|
97
|
+
previousFormatting
|
|
98
|
+
};
|
|
99
|
+
return {
|
|
100
|
+
...next,
|
|
101
|
+
_propertyChanges: [...retained, record]
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
const levelKind = (level) => isBulletLevel(level) ? "bullet" : "numbered";
|
|
105
|
+
/** A level's text with its placeholders blanked: `%1.` and `%3.` read alike. */
|
|
106
|
+
const levelTextShape = (lvlText) => lvlText.replaceAll(/%\d/gu, "%");
|
|
107
|
+
const levelMatches = (level, request) => {
|
|
108
|
+
if (levelKind(level) !== request.kind) return false;
|
|
109
|
+
const { format } = request;
|
|
110
|
+
return format === void 0 || level.numFmt === format.numFmt && levelTextShape(level.lvlText) === levelTextShape(format.lvlText);
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* The list `node` is an item of, when the paragraph states it directly. A
|
|
114
|
+
* numbering its style supplies is the style's, and is not offered to the
|
|
115
|
+
* paragraphs around it.
|
|
116
|
+
*/
|
|
117
|
+
const directListMembership = (node, numbering) => {
|
|
118
|
+
if (!node || node.type.name !== PARAGRAPH_NODE) return null;
|
|
119
|
+
const attrs = expectParagraphAttrs(node);
|
|
120
|
+
const numId = paragraphNumberingReferenceId(attrs.numPr);
|
|
121
|
+
if (numId === void 0 || numId === paragraphNumberingReferenceId(attrs.numPrFromStyle)) return null;
|
|
122
|
+
const ilvl = paragraphNumberingLevel(attrs.numPr) ?? 0;
|
|
123
|
+
const level = numbering?.getLevel(numId, ilvl) ?? null;
|
|
124
|
+
return level ? {
|
|
125
|
+
numId,
|
|
126
|
+
ilvl,
|
|
127
|
+
level
|
|
128
|
+
} : null;
|
|
129
|
+
};
|
|
130
|
+
/** The block directly before or after the paragraph `$pos` sits in. */
|
|
131
|
+
const siblingOf = ($pos, direction) => {
|
|
132
|
+
const depth = $pos.depth;
|
|
133
|
+
if (depth === 0) return null;
|
|
134
|
+
const index = $pos.index(depth - 1);
|
|
135
|
+
return $pos.node(depth - 1).maybeChild(direction === "before" ? index - 1 : index + 1);
|
|
136
|
+
};
|
|
137
|
+
/** Every instance a paragraph of `doc` names: directly, through its style, or as a tracked change's previous state. */
|
|
138
|
+
const referencedNumIds = (doc) => {
|
|
139
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
140
|
+
const add = (numPr) => {
|
|
141
|
+
const numId = paragraphNumberingReferenceId(numPr ?? void 0);
|
|
142
|
+
if (numId !== void 0) referenced.add(numId);
|
|
143
|
+
};
|
|
144
|
+
doc.descendants((node) => {
|
|
145
|
+
if (node.type.name !== PARAGRAPH_NODE) return true;
|
|
146
|
+
const attrs = expectParagraphAttrs(node);
|
|
147
|
+
add(attrs.numPr);
|
|
148
|
+
add(attrs.numPrFromStyle);
|
|
149
|
+
for (const change of attrs._propertyChanges ?? []) add(change.previousFormatting?.numPr);
|
|
150
|
+
return false;
|
|
151
|
+
});
|
|
152
|
+
return referenced;
|
|
153
|
+
};
|
|
154
|
+
/**
|
|
155
|
+
* An instance the package defines for `request` that nothing uses yet: a host
|
|
156
|
+
* that prepares a document with an empty list of each kind means the first
|
|
157
|
+
* list of that kind to be it. An instance tied to a paragraph style (a level
|
|
158
|
+
* naming a `w:pStyle`, or a style link) belongs to that style and is never
|
|
159
|
+
* offered.
|
|
160
|
+
*/
|
|
161
|
+
const unusedInstanceFor = (numbering, doc, request) => {
|
|
162
|
+
const referenced = referencedNumIds(doc);
|
|
163
|
+
return numbering.definitions.nums.find(({ numId, abstractNumId }) => {
|
|
164
|
+
const abstract = numbering.getAbstract(abstractNumId);
|
|
165
|
+
const level = numbering.getLevel(numId, 0);
|
|
166
|
+
return !referenced.has(numId) && abstract !== null && abstract.styleLink === void 0 && abstract.numStyleLink === void 0 && abstract.levels.every(({ pStyle }) => pStyle === void 0) && level !== null && levelMatches(level, request) && (level.start ?? 1) === (request.start ?? level.start ?? 1);
|
|
167
|
+
})?.numId;
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* The list a paragraph range joins: the list directly above it, else the one
|
|
171
|
+
* directly below it, when it matches one of `requests`; otherwise a new list:
|
|
172
|
+
* an unused instance the package already defines for the first request, or
|
|
173
|
+
* one defined for it.
|
|
174
|
+
*/
|
|
175
|
+
const resolveListTarget = ({ numbering, $from, $to, requests }) => {
|
|
176
|
+
const [first] = requests;
|
|
177
|
+
if (!first) return null;
|
|
178
|
+
for (const neighbour of [siblingOf($from, "before"), siblingOf($to, "after")]) {
|
|
179
|
+
const membership = directListMembership(neighbour, numbering);
|
|
180
|
+
if (numbering && membership && requests.some((request) => levelMatches(membership.level, request))) return {
|
|
181
|
+
numId: membership.numId,
|
|
182
|
+
ilvl: membership.ilvl,
|
|
183
|
+
numbering
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
const unused = numbering ? unusedInstanceFor(numbering, $from.doc, first) : void 0;
|
|
187
|
+
if (numbering && unused !== void 0) return {
|
|
188
|
+
numId: unused,
|
|
189
|
+
ilvl: 0,
|
|
190
|
+
numbering
|
|
191
|
+
};
|
|
192
|
+
const minted = mintListInstance(numbering?.definitions, first);
|
|
193
|
+
return {
|
|
194
|
+
numId: minted.numId,
|
|
195
|
+
ilvl: 0,
|
|
196
|
+
numbering: createNumberingMap(minted.definitions)
|
|
197
|
+
};
|
|
198
|
+
};
|
|
199
|
+
/** A paragraph's attrs as an item of `numId` at `ilvl`, resolved in `numbering`. */
|
|
200
|
+
const listItemAttrs = (attrs, { numId, ilvl }, numbering) => ({
|
|
201
|
+
...attrs,
|
|
202
|
+
...listAttrsFromNumbering({
|
|
203
|
+
numId,
|
|
204
|
+
ilvl
|
|
205
|
+
}, numbering),
|
|
206
|
+
listImplicitChildLevelAdvances: attrs["listImplicitChildLevelAdvances"] ?? null,
|
|
207
|
+
listMarkerSecondSlotOffsetTwips: attrs["listMarkerSecondSlotOffsetTwips"] ?? null
|
|
208
|
+
});
|
|
209
|
+
/**
|
|
210
|
+
* Write `updates` into `tr`, each recorded as a tracked change while the
|
|
211
|
+
* editor is suggesting. `pos` is a position in `tr.doc`.
|
|
212
|
+
*/
|
|
213
|
+
const applyParagraphUpdates = ({ tr, state, updates }) => {
|
|
214
|
+
const rev = makeRevisionInfo(state);
|
|
215
|
+
const numbering = getDocumentNumbering(state);
|
|
216
|
+
for (const { pos, node, next } of updates) {
|
|
217
|
+
const attrs = rev ? trackListChange({
|
|
218
|
+
current: node,
|
|
219
|
+
next,
|
|
220
|
+
rev,
|
|
221
|
+
numbering
|
|
222
|
+
}) : next;
|
|
223
|
+
tr.setNodeMarkup(pos, void 0, attrs);
|
|
224
|
+
}
|
|
225
|
+
if (rev) tr.setMeta(SUGGESTION_META, true);
|
|
226
|
+
};
|
|
227
|
+
/** The paragraph the selection starts in, when it is a direct list item. */
|
|
228
|
+
const selectedListParagraph = (state) => {
|
|
229
|
+
const { $from } = state.selection;
|
|
230
|
+
if ($from.parent.type.name !== PARAGRAPH_NODE || $from.depth === 0) return null;
|
|
231
|
+
const membership = directListMembership($from.parent, getDocumentNumbering(state));
|
|
232
|
+
return membership ? {
|
|
233
|
+
pos: $from.before(),
|
|
234
|
+
node: $from.parent,
|
|
235
|
+
membership
|
|
236
|
+
} : null;
|
|
237
|
+
};
|
|
238
|
+
/** Every direct item of `numId` from `fromPos` to the end of the document. */
|
|
239
|
+
const itemsFrom = (state, numId, fromPos) => {
|
|
240
|
+
const numbering = getDocumentNumbering(state);
|
|
241
|
+
const items = [];
|
|
242
|
+
state.doc.descendants((node, pos) => {
|
|
243
|
+
if (node.type.name !== PARAGRAPH_NODE) return true;
|
|
244
|
+
if (pos >= fromPos) {
|
|
245
|
+
const membership = directListMembership(node, numbering);
|
|
246
|
+
if (membership?.numId === numId) items.push({
|
|
247
|
+
pos,
|
|
248
|
+
node,
|
|
249
|
+
membership
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
return false;
|
|
253
|
+
});
|
|
254
|
+
return items;
|
|
255
|
+
};
|
|
256
|
+
const moveItems = ({ state, items, numId, numbering }) => {
|
|
257
|
+
const tr = state.tr;
|
|
258
|
+
applyParagraphUpdates({
|
|
259
|
+
tr,
|
|
260
|
+
state,
|
|
261
|
+
updates: items.map(({ pos, node, membership }) => ({
|
|
262
|
+
pos,
|
|
263
|
+
node,
|
|
264
|
+
next: listItemAttrs(node.attrs, {
|
|
265
|
+
numId,
|
|
266
|
+
ilvl: membership.ilvl
|
|
267
|
+
}, numbering)
|
|
268
|
+
}))
|
|
269
|
+
});
|
|
270
|
+
return tr.scrollIntoView();
|
|
271
|
+
};
|
|
272
|
+
/**
|
|
273
|
+
* Start the list over at `value` from the selected item: *Set Numbering
|
|
274
|
+
* Value* with *Start new list*. The item and every later item of
|
|
275
|
+
* its list move to a new instance of the same definition, whose
|
|
276
|
+
* `w:startOverride` at the item's level is `value`.
|
|
277
|
+
*/
|
|
278
|
+
const setNumberingValue = (value) => (state, dispatch) => {
|
|
279
|
+
if (!Number.isSafeInteger(value) || value < 0) return false;
|
|
280
|
+
const selected = selectedListParagraph(state);
|
|
281
|
+
const numbering = getDocumentNumbering(state);
|
|
282
|
+
const abstractNumId = selected ? numbering?.getAbstractNumId(selected.membership.numId) : null;
|
|
283
|
+
if (!selected || !numbering || abstractNumId === null || abstractNumId === void 0) return false;
|
|
284
|
+
if (!dispatch) return true;
|
|
285
|
+
const restarted = restartListInstance(numbering.definitions, {
|
|
286
|
+
abstractNumId,
|
|
287
|
+
ilvl: selected.membership.ilvl,
|
|
288
|
+
start: value
|
|
289
|
+
});
|
|
290
|
+
dispatch(moveItems({
|
|
291
|
+
state,
|
|
292
|
+
items: itemsFrom(state, selected.membership.numId, selected.pos),
|
|
293
|
+
numId: restarted.numId,
|
|
294
|
+
numbering: createNumberingMap(restarted.definitions)
|
|
295
|
+
}));
|
|
296
|
+
return true;
|
|
297
|
+
};
|
|
298
|
+
/** *Restart at 1*: the selected item starts its list over at one. */
|
|
299
|
+
const restartNumbering = (state, dispatch) => setNumberingValue(1)(state, dispatch);
|
|
300
|
+
/** The nearest list before `beforePos` of the kind `membership` has, other than its own. */
|
|
301
|
+
const previousListOfKind = (state, beforePos, membership) => {
|
|
302
|
+
const numbering = getDocumentNumbering(state);
|
|
303
|
+
const kind = levelKind(membership.level);
|
|
304
|
+
let found = null;
|
|
305
|
+
state.doc.descendants((node, pos) => {
|
|
306
|
+
if (pos >= beforePos) return false;
|
|
307
|
+
if (node.type.name !== PARAGRAPH_NODE) return true;
|
|
308
|
+
const candidate = directListMembership(node, numbering);
|
|
309
|
+
if (candidate && candidate.numId !== membership.numId && levelKind(candidate.level) === kind) found = candidate.numId;
|
|
310
|
+
return false;
|
|
311
|
+
});
|
|
312
|
+
return found;
|
|
313
|
+
};
|
|
314
|
+
/**
|
|
315
|
+
* *Continue Numbering*: the selected item and the rest of its list
|
|
316
|
+
* join the nearest earlier list of the same kind, so their numbers carry on
|
|
317
|
+
* from it. Not applicable when no such list precedes the item.
|
|
318
|
+
*/
|
|
319
|
+
const continueNumbering = (state, dispatch) => {
|
|
320
|
+
const selected = selectedListParagraph(state);
|
|
321
|
+
const numbering = getDocumentNumbering(state);
|
|
322
|
+
if (!selected || !numbering) return false;
|
|
323
|
+
const previous = previousListOfKind(state, selected.pos, selected.membership);
|
|
324
|
+
if (previous === null) return false;
|
|
325
|
+
if (!dispatch) return true;
|
|
326
|
+
dispatch(moveItems({
|
|
327
|
+
state,
|
|
328
|
+
items: itemsFrom(state, selected.membership.numId, selected.pos),
|
|
329
|
+
numId: previous,
|
|
330
|
+
numbering
|
|
331
|
+
}));
|
|
332
|
+
return true;
|
|
333
|
+
};
|
|
334
|
+
const NO_LIST_NUMBERING_MENU = { type: "none" };
|
|
335
|
+
/**
|
|
336
|
+
* Whether the selection is in a list item whose numbering can be restarted
|
|
337
|
+
* or set, and whether an earlier list lets it continue: the enabled state of
|
|
338
|
+
* those menu entries.
|
|
339
|
+
*/
|
|
340
|
+
const listNumberingMenuState = (state) => restartNumbering(state) ? {
|
|
341
|
+
type: "listItem",
|
|
342
|
+
canContinue: continueNumbering(state)
|
|
343
|
+
} : NO_LIST_NUMBERING_MENU;
|
|
344
|
+
//#endregion
|
|
345
|
+
export { NO_LIST_NUMBERING_MENU, applyParagraphUpdates, continueNumbering, listItemAttrs, listNumberingMenuState, rejectedListRenderingPatch, resolveListTarget, restartNumbering, setNumberingValue };
|
|
@@ -30,8 +30,17 @@ declare const LIST_RENDERING_ATTR_KEYS: readonly ListRenderingAttrKey[];
|
|
|
30
30
|
* never authors them as `false` or `""` deliberately.
|
|
31
31
|
*/
|
|
32
32
|
declare const listRenderingAttrPatch: (rendering: document_d_exports.ListRendering) => Partial<ParagraphAttrs>;
|
|
33
|
+
/**
|
|
34
|
+
* Whether `attrs` carry what their numbering level renders as. Only a level
|
|
35
|
+
* the numbering defines gets a rendering (`toProseDoc` projects the parser's,
|
|
36
|
+
* a list command or operation writes the level's), so a reference without one
|
|
37
|
+
* names a level nothing defines: Word paints no marker for it.
|
|
38
|
+
*/
|
|
39
|
+
declare const hasListRendering: (attrs: Pick<ParagraphAttrs, "listMarker" | "listIsBullet" | "listNumFmt">) => boolean;
|
|
40
|
+
/** The attrs a rendering is read back from: a paragraph's, or a recorded previous state's. */
|
|
41
|
+
type ListRenderingSourceAttrs = Pick<ParagraphAttrs, ListRenderingAttrKey | "numPr">;
|
|
33
42
|
type ListRenderingFromAttrsOptions = {
|
|
34
|
-
attrs:
|
|
43
|
+
attrs: ListRenderingSourceAttrs;
|
|
35
44
|
numId: number;
|
|
36
45
|
};
|
|
37
46
|
/**
|
|
@@ -40,4 +49,4 @@ type ListRenderingFromAttrsOptions = {
|
|
|
40
49
|
*/
|
|
41
50
|
declare const listRenderingFromAttrs: ({ attrs, numId }: ListRenderingFromAttrsOptions) => document_d_exports.ListRendering;
|
|
42
51
|
//#endregion
|
|
43
|
-
export { LIST_RENDERING_ATTR_BY_FIELD, LIST_RENDERING_ATTR_KEYS, ListRenderingAttrField, ListRenderingAttrKey, listRenderingAttrPatch, listRenderingFromAttrs };
|
|
52
|
+
export { LIST_RENDERING_ATTR_BY_FIELD, LIST_RENDERING_ATTR_KEYS, ListRenderingAttrField, ListRenderingAttrKey, ListRenderingSourceAttrs, hasListRendering, listRenderingAttrPatch, listRenderingFromAttrs };
|
|
@@ -60,6 +60,13 @@ const listRenderingAttrPatch = (rendering) => {
|
|
|
60
60
|
return definedAttrs(patch);
|
|
61
61
|
};
|
|
62
62
|
/**
|
|
63
|
+
* Whether `attrs` carry what their numbering level renders as. Only a level
|
|
64
|
+
* the numbering defines gets a rendering (`toProseDoc` projects the parser's,
|
|
65
|
+
* a list command or operation writes the level's), so a reference without one
|
|
66
|
+
* names a level nothing defines: Word paints no marker for it.
|
|
67
|
+
*/
|
|
68
|
+
const hasListRendering = (attrs) => attrs.listMarker != null || attrs.listIsBullet === true || attrs.listNumFmt != null;
|
|
69
|
+
/**
|
|
63
70
|
* Inverse of `listRenderingAttrPatch`. The caller decides whether the
|
|
64
71
|
* paragraph is a list item at all; this only reassembles the fields.
|
|
65
72
|
*/
|
|
@@ -90,4 +97,4 @@ const listRenderingFromAttrs = ({ attrs, numId }) => {
|
|
|
90
97
|
};
|
|
91
98
|
};
|
|
92
99
|
//#endregion
|
|
93
|
-
export { LIST_RENDERING_ATTR_BY_FIELD, LIST_RENDERING_ATTR_KEYS, listRenderingAttrPatch, listRenderingFromAttrs };
|
|
100
|
+
export { LIST_RENDERING_ATTR_BY_FIELD, LIST_RENDERING_ATTR_KEYS, hasListRendering, listRenderingAttrPatch, listRenderingFromAttrs };
|