@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,59 @@
|
|
|
1
|
+
import { sectionPropertiesOf } from "./sectionCarrier.js";
|
|
2
|
+
import { Mapping, ReplaceStep } from "prosemirror-transform";
|
|
3
|
+
//#region src/prosemirror/sectionMarkEdits.ts
|
|
4
|
+
const isParagraph = (node) => node.type.name === "paragraph";
|
|
5
|
+
/** Read `transactions`, applied in order and ending at `finalDoc`. */
|
|
6
|
+
const sectionMarkEditsOf = (transactions, finalDoc) => {
|
|
7
|
+
const deletedMarks = /* @__PURE__ */ new Set();
|
|
8
|
+
const carriers = [];
|
|
9
|
+
const replacements = [];
|
|
10
|
+
const mapping = new Mapping();
|
|
11
|
+
for (const transaction of transactions) for (const [index, step] of transaction.steps.entries()) {
|
|
12
|
+
const doc = transaction.docs[index];
|
|
13
|
+
if (step instanceof ReplaceStep && step.from < step.to && doc) replacements.push({
|
|
14
|
+
step,
|
|
15
|
+
doc,
|
|
16
|
+
mapIndex: mapping.maps.length
|
|
17
|
+
});
|
|
18
|
+
const map = transaction.mapping.maps[index];
|
|
19
|
+
if (map) mapping.appendMap(map);
|
|
20
|
+
}
|
|
21
|
+
for (const { step, doc, mapIndex } of replacements) {
|
|
22
|
+
const { from, to } = step;
|
|
23
|
+
doc.nodesBetween(from, to, (node, position) => {
|
|
24
|
+
if (!isParagraph(node)) return true;
|
|
25
|
+
const record = sectionPropertiesOf(node);
|
|
26
|
+
const markFrom = position + node.nodeSize - 1;
|
|
27
|
+
if (record && markFrom >= from && markFrom + 1 <= to) deletedMarks.add(record);
|
|
28
|
+
return false;
|
|
29
|
+
});
|
|
30
|
+
const $from = doc.resolve(from);
|
|
31
|
+
const $to = doc.resolve(to);
|
|
32
|
+
if (!isParagraph($from.parent) || !isParagraph($to.parent) || $from.start() === $to.start()) continue;
|
|
33
|
+
const leftRecord = sectionPropertiesOf($from.parent);
|
|
34
|
+
const rightRecord = sectionPropertiesOf($to.parent);
|
|
35
|
+
if (leftRecord === null && rightRecord === null) continue;
|
|
36
|
+
const after = mapping.slice(mapIndex);
|
|
37
|
+
const left = after.mapResult(from, -1);
|
|
38
|
+
const right = after.mapResult(to, 1);
|
|
39
|
+
if (right.deleted) continue;
|
|
40
|
+
const $right = finalDoc.resolve(right.pos);
|
|
41
|
+
if (!isParagraph($right.parent)) continue;
|
|
42
|
+
carriers.push({
|
|
43
|
+
position: $right.before(),
|
|
44
|
+
record: rightRecord
|
|
45
|
+
});
|
|
46
|
+
if (left.deleted) continue;
|
|
47
|
+
const $left = finalDoc.resolve(left.pos);
|
|
48
|
+
if (isParagraph($left.parent) && $left.start() !== $right.start()) carriers.push({
|
|
49
|
+
position: $left.before(),
|
|
50
|
+
record: null
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
deletedMarks,
|
|
55
|
+
carriers
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
//#endregion
|
|
59
|
+
export { sectionMarkEditsOf };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { Node } from "prosemirror-model";
|
|
3
|
+
import { EditorState } from "prosemirror-state";
|
|
4
|
+
//#region src/prosemirror/storyListNumbering.d.ts
|
|
5
|
+
type StoryListNumbering = {
|
|
6
|
+
/** The story with every colliding list moved to its own ids. */
|
|
7
|
+
doc: Node;
|
|
8
|
+
/** `numbering` plus the lists the story defines. */
|
|
9
|
+
numbering: document_d_exports.NumberingDefinitions | undefined;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* The story in `state` as it should be written into a package whose numbering
|
|
13
|
+
* is now `numbering`, and that numbering completed with the story's lists.
|
|
14
|
+
*/
|
|
15
|
+
declare const storyListNumbering: (state: EditorState, numbering: document_d_exports.NumberingDefinitions | undefined) => StoryListNumbering;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { storyListNumbering };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { getCachedNumberingMap, isBulletLevel } from "../docx/numberingParser.js";
|
|
2
|
+
import { paragraphNumberingLevel, paragraphNumberingReference, paragraphNumberingReferenceId } from "../docx/numberingReference.js";
|
|
3
|
+
import { expectParagraphAttrs } from "./attrs/index.js";
|
|
4
|
+
import { completeNumberingForDoc, paragraphListReferences } from "./listInstanceReferences.js";
|
|
5
|
+
import { paragraphNumberingAttr } from "./numberingAttr.js";
|
|
6
|
+
import { getPackageNumberingDefinitions } from "./plugins/documentNumbering.js";
|
|
7
|
+
import { Transform } from "prosemirror-transform";
|
|
8
|
+
//#region src/prosemirror/storyListNumbering.ts
|
|
9
|
+
const remappedNumPr = (numPr, numIds) => {
|
|
10
|
+
const numId = paragraphNumberingReferenceId(numPr ?? void 0);
|
|
11
|
+
const next = numId === void 0 ? void 0 : numIds.get(numId);
|
|
12
|
+
if (next === void 0) return numPr;
|
|
13
|
+
const ilvl = paragraphNumberingLevel(numPr ?? void 0);
|
|
14
|
+
return paragraphNumberingAttr(paragraphNumberingReference(ilvl === void 0 ? { numId: next } : {
|
|
15
|
+
numId: next,
|
|
16
|
+
ilvl
|
|
17
|
+
}));
|
|
18
|
+
};
|
|
19
|
+
const remappedAbstractNumId = (abstractNumId, remap) => {
|
|
20
|
+
if (abstractNumId === null || abstractNumId === void 0 || remap.baseAbstractNumIds.has(abstractNumId)) return abstractNumId;
|
|
21
|
+
let next = remap.abstractNumIds.get(abstractNumId);
|
|
22
|
+
if (next === void 0) {
|
|
23
|
+
next = remap.nextAbstractNumId++;
|
|
24
|
+
remap.abstractNumIds.set(abstractNumId, next);
|
|
25
|
+
}
|
|
26
|
+
return next;
|
|
27
|
+
};
|
|
28
|
+
const maxOf = (ids, floor) => {
|
|
29
|
+
let max = floor;
|
|
30
|
+
for (const id of ids) max = Math.max(max, id);
|
|
31
|
+
return max;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* The story in `state` as it should be written into a package whose numbering
|
|
35
|
+
* is now `numbering`, and that numbering completed with the story's lists.
|
|
36
|
+
*/
|
|
37
|
+
const storyListNumbering = (state, numbering) => {
|
|
38
|
+
const packageDefinitions = getPackageNumberingDefinitions(state);
|
|
39
|
+
const storyBase = new Set((packageDefinitions?.nums ?? []).map(({ numId }) => numId));
|
|
40
|
+
const defined = new Set((numbering?.nums ?? []).map(({ numId }) => numId));
|
|
41
|
+
const definedMap = numbering ? getCachedNumberingMap(numbering) : null;
|
|
42
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
43
|
+
const colliding = /* @__PURE__ */ new Set();
|
|
44
|
+
state.doc.descendants((node) => {
|
|
45
|
+
if (node.type.name !== "paragraph") return true;
|
|
46
|
+
for (const numId of paragraphListReferences(node)) referenced.add(numId);
|
|
47
|
+
const attrs = expectParagraphAttrs(node);
|
|
48
|
+
const numId = paragraphNumberingReferenceId(attrs.numPr);
|
|
49
|
+
if (numId !== void 0 && !storyBase.has(numId) && definedMap?.hasNumbering(numId)) {
|
|
50
|
+
const level = definedMap.getLevel(numId, paragraphNumberingLevel(attrs.numPr) ?? 0);
|
|
51
|
+
if (!(level !== null && isBulletLevel(level) === (attrs.listIsBullet === true) && (attrs.listAbstractNumId ?? void 0) === (definedMap.getAbstractNumId(numId) ?? void 0))) colliding.add(numId);
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
});
|
|
55
|
+
if (colliding.size === 0) return {
|
|
56
|
+
doc: state.doc,
|
|
57
|
+
numbering: completeNumberingForDoc(numbering, state.doc)
|
|
58
|
+
};
|
|
59
|
+
let nextNumId = maxOf([...defined, ...referenced], 0) + 1;
|
|
60
|
+
const remap = {
|
|
61
|
+
numIds: new Map([...colliding].map((numId) => [numId, nextNumId++])),
|
|
62
|
+
baseAbstractNumIds: new Set((packageDefinitions?.abstractNums ?? []).map(({ abstractNumId }) => abstractNumId)),
|
|
63
|
+
abstractNumIds: /* @__PURE__ */ new Map(),
|
|
64
|
+
nextAbstractNumId: maxOf((numbering?.abstractNums ?? []).map(({ abstractNumId }) => abstractNumId), -1) + 1
|
|
65
|
+
};
|
|
66
|
+
const tr = new Transform(state.doc);
|
|
67
|
+
state.doc.descendants((node, pos) => {
|
|
68
|
+
if (node.type.name !== "paragraph") return true;
|
|
69
|
+
const attrs = expectParagraphAttrs(node);
|
|
70
|
+
const numId = paragraphNumberingReferenceId(attrs.numPr);
|
|
71
|
+
const moves = numId !== void 0 && remap.numIds.has(numId);
|
|
72
|
+
const changes = attrs._propertyChanges?.map((change) => {
|
|
73
|
+
const previous = change.previousFormatting;
|
|
74
|
+
const previousNumId = paragraphNumberingReferenceId(previous?.numPr ?? void 0);
|
|
75
|
+
if (!previous || previousNumId === void 0 || !remap.numIds.has(previousNumId)) return change;
|
|
76
|
+
return {
|
|
77
|
+
...change,
|
|
78
|
+
previousFormatting: {
|
|
79
|
+
...previous,
|
|
80
|
+
numPr: remappedNumPr(previous.numPr, remap.numIds),
|
|
81
|
+
listAbstractNumId: remappedAbstractNumId(previous.listAbstractNumId, remap) ?? void 0
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
const changesMoved = changes?.some((change, index) => change !== attrs._propertyChanges?.[index]);
|
|
86
|
+
if (moves || changesMoved) tr.setNodeMarkup(pos, void 0, {
|
|
87
|
+
...node.attrs,
|
|
88
|
+
...moves ? {
|
|
89
|
+
numPr: remappedNumPr(attrs.numPr, remap.numIds),
|
|
90
|
+
listAbstractNumId: remappedAbstractNumId(attrs.listAbstractNumId, remap) ?? null
|
|
91
|
+
} : {},
|
|
92
|
+
...changesMoved ? { _propertyChanges: changes } : {}
|
|
93
|
+
});
|
|
94
|
+
return false;
|
|
95
|
+
});
|
|
96
|
+
return {
|
|
97
|
+
doc: tr.doc,
|
|
98
|
+
numbering: completeNumberingForDoc(numbering, tr.doc)
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
//#endregion
|
|
102
|
+
export { storyListNumbering };
|
|
@@ -1,6 +1,38 @@
|
|
|
1
|
-
import { Transaction } from "prosemirror-state";
|
|
2
1
|
import { Node } from "prosemirror-model";
|
|
2
|
+
import { Transaction } from "prosemirror-state";
|
|
3
|
+
import { TableMap } from "prosemirror-tables";
|
|
3
4
|
//#region src/prosemirror/tableGridMutation.d.ts
|
|
5
|
+
type RemoveTableRowOptions = {
|
|
6
|
+
map: TableMap;
|
|
7
|
+
table: Node;
|
|
8
|
+
tableStart: number;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Remove one row, keeping every vertical merge that touches it whole: a merge
|
|
12
|
+
* reaching through the row from above closes one row sooner, and a cell that
|
|
13
|
+
* starts in the row and spans down moves into the row below, one row shorter.
|
|
14
|
+
*
|
|
15
|
+
* `prosemirror-tables` exports the same operation as `removeRow`, but its walk
|
|
16
|
+
* across the row skips a cell's extra columns without moving its map index
|
|
17
|
+
* along with them, so after a cell wider than one column it reads the wrong
|
|
18
|
+
* slots: a merge reaching through the row further right is never shortened,
|
|
19
|
+
* and the table is left one row shorter than that merge.
|
|
20
|
+
*/
|
|
21
|
+
declare const removeTableRow: (tr: Transaction, { map, table, tableStart }: RemoveTableRowOptions, row: number) => void;
|
|
22
|
+
/**
|
|
23
|
+
* Remove every row a structural edit left without a cell of its own, closing
|
|
24
|
+
* the vertical merges that reached through it over one row fewer.
|
|
25
|
+
*
|
|
26
|
+
* Deleting the only column a row still had a cell in, or merging whole rows
|
|
27
|
+
* together, leaves a row holding nothing but the merges from above. The
|
|
28
|
+
* editable model can carry such a row, but nothing else agrees with it: a
|
|
29
|
+
* package spells it as a row of `w:vMerge` continuations, which the reader
|
|
30
|
+
* gives a cell of its own by splitting the merge apart, so the reopened table
|
|
31
|
+
* differs from the one the operation reported. Accepting the same deletion
|
|
32
|
+
* tracked removes the cells one at a time and the row with its last one,
|
|
33
|
+
* which is this result; the two modes have to leave the same table.
|
|
34
|
+
*/
|
|
35
|
+
declare const removeRowsWithoutCells: (tr: Transaction, tablePosition: number) => void;
|
|
4
36
|
type ReconcileTableGridAfterColumnRemovalOptions = {
|
|
5
37
|
tr: Transaction;
|
|
6
38
|
tablePosition: number;
|
|
@@ -16,5 +48,19 @@ type ReconcileTableGridAfterColumnRemovalOptions = {
|
|
|
16
48
|
* the old grid; reopening then has to interpret surviving cells as spans.
|
|
17
49
|
*/
|
|
18
50
|
declare const reconcileTableGridAfterColumnRemoval: ({ tr, tablePosition, previousTable, removedColumn }: ReconcileTableGridAfterColumnRemovalOptions) => void;
|
|
51
|
+
type ReconcileTableGridAfterColumnInsertionOptions = {
|
|
52
|
+
tr: Transaction;
|
|
53
|
+
tablePosition: number;
|
|
54
|
+
previousTable: Node;
|
|
55
|
+
insertedColumn: number;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* The same for a physical column insertion: the new grid column takes the
|
|
59
|
+
* width of the column beside it, and the table grows by it.
|
|
60
|
+
*
|
|
61
|
+
* Without it the table keeps the grid it had, so every row spans one column
|
|
62
|
+
* more than `w:tblGrid` declares.
|
|
63
|
+
*/
|
|
64
|
+
declare const reconcileTableGridAfterColumnInsertion: ({ tr, tablePosition, previousTable, insertedColumn }: ReconcileTableGridAfterColumnInsertionOptions) => void;
|
|
19
65
|
//#endregion
|
|
20
|
-
export { reconcileTableGridAfterColumnRemoval };
|
|
66
|
+
export { reconcileTableGridAfterColumnInsertion, reconcileTableGridAfterColumnRemoval, removeRowsWithoutCells, removeTableRow };
|
|
@@ -2,6 +2,77 @@ import { expectTableAttrs, mergeTableAttrs } from "./attrs/index.js";
|
|
|
2
2
|
import { TableMap } from "prosemirror-tables";
|
|
3
3
|
//#region src/prosemirror/tableGridMutation.ts
|
|
4
4
|
/**
|
|
5
|
+
* Remove one row, keeping every vertical merge that touches it whole: a merge
|
|
6
|
+
* reaching through the row from above closes one row sooner, and a cell that
|
|
7
|
+
* starts in the row and spans down moves into the row below, one row shorter.
|
|
8
|
+
*
|
|
9
|
+
* `prosemirror-tables` exports the same operation as `removeRow`, but its walk
|
|
10
|
+
* across the row skips a cell's extra columns without moving its map index
|
|
11
|
+
* along with them, so after a cell wider than one column it reads the wrong
|
|
12
|
+
* slots: a merge reaching through the row further right is never shortened,
|
|
13
|
+
* and the table is left one row shorter than that merge.
|
|
14
|
+
*/
|
|
15
|
+
const removeTableRow = (tr, { map, table, tableStart }, row) => {
|
|
16
|
+
let rowPosition = 0;
|
|
17
|
+
for (let index = 0; index < row; index++) rowPosition += table.child(index).nodeSize;
|
|
18
|
+
const nextRow = rowPosition + table.child(row).nodeSize;
|
|
19
|
+
const mapFrom = tr.mapping.maps.length;
|
|
20
|
+
tr.delete(tableStart + rowPosition, tableStart + nextRow);
|
|
21
|
+
for (let column = 0; column < map.width;) {
|
|
22
|
+
const index = row * map.width + column;
|
|
23
|
+
const position = map.map[index];
|
|
24
|
+
const cell = position === void 0 ? null : table.nodeAt(position);
|
|
25
|
+
if (position === void 0 || !cell) {
|
|
26
|
+
column += 1;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
const colspan = Math.max(1, Number(cell.attrs["colspan"]) || 1);
|
|
30
|
+
const rowspan = Math.max(1, Number(cell.attrs["rowspan"]) || 1);
|
|
31
|
+
if (row > 0 && position === map.map[index - map.width]) tr.setNodeMarkup(tr.mapping.slice(mapFrom).map(tableStart + position), null, {
|
|
32
|
+
...cell.attrs,
|
|
33
|
+
rowspan: rowspan - 1
|
|
34
|
+
});
|
|
35
|
+
else if (row + 1 < map.height && position === map.map[index + map.width]) {
|
|
36
|
+
const moved = cell.type.create({
|
|
37
|
+
...cell.attrs,
|
|
38
|
+
rowspan: rowspan - 1
|
|
39
|
+
}, cell.content);
|
|
40
|
+
const below = map.positionAt(row + 1, column, table);
|
|
41
|
+
tr.insert(tr.mapping.slice(mapFrom).map(tableStart + below), moved);
|
|
42
|
+
}
|
|
43
|
+
column += colspan;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Remove every row a structural edit left without a cell of its own, closing
|
|
48
|
+
* the vertical merges that reached through it over one row fewer.
|
|
49
|
+
*
|
|
50
|
+
* Deleting the only column a row still had a cell in, or merging whole rows
|
|
51
|
+
* together, leaves a row holding nothing but the merges from above. The
|
|
52
|
+
* editable model can carry such a row, but nothing else agrees with it: a
|
|
53
|
+
* package spells it as a row of `w:vMerge` continuations, which the reader
|
|
54
|
+
* gives a cell of its own by splitting the merge apart, so the reopened table
|
|
55
|
+
* differs from the one the operation reported. Accepting the same deletion
|
|
56
|
+
* tracked removes the cells one at a time and the row with its last one,
|
|
57
|
+
* which is this result; the two modes have to leave the same table.
|
|
58
|
+
*/
|
|
59
|
+
const removeRowsWithoutCells = (tr, tablePosition) => {
|
|
60
|
+
for (;;) {
|
|
61
|
+
const table = tr.doc.nodeAt(tablePosition);
|
|
62
|
+
if (!table || table.type.spec["tableRole"] !== "table" || table.childCount < 2) return;
|
|
63
|
+
let emptyRow = -1;
|
|
64
|
+
table.forEach((row, _offset, index) => {
|
|
65
|
+
if (emptyRow === -1 && row.childCount === 0) emptyRow = index;
|
|
66
|
+
});
|
|
67
|
+
if (emptyRow === -1) return;
|
|
68
|
+
removeTableRow(tr, {
|
|
69
|
+
map: TableMap.get(table),
|
|
70
|
+
table,
|
|
71
|
+
tableStart: tablePosition + 1
|
|
72
|
+
}, emptyRow);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
5
76
|
* Keep the editable table grid aligned with a physical column removal.
|
|
6
77
|
*
|
|
7
78
|
* `prosemirror-tables` owns cell topology, but Folio separately retains the
|
|
@@ -18,6 +89,40 @@ const reconcileTableGridAfterColumnRemoval = ({ tr, tablePosition, previousTable
|
|
|
18
89
|
const removedColumnCount = previousColumnCount - columnCount;
|
|
19
90
|
const previousWidths = expectTableAttrs(previousTable).columnWidths;
|
|
20
91
|
const columnWidths = previousWidths?.length === previousColumnCount ? previousWidths.toSpliced(removedColumn, removedColumnCount) : void 0;
|
|
92
|
+
setTableGrid({
|
|
93
|
+
tr,
|
|
94
|
+
tablePosition,
|
|
95
|
+
table,
|
|
96
|
+
columnWidths,
|
|
97
|
+
columnCount
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* The same for a physical column insertion: the new grid column takes the
|
|
102
|
+
* width of the column beside it, and the table grows by it.
|
|
103
|
+
*
|
|
104
|
+
* Without it the table keeps the grid it had, so every row spans one column
|
|
105
|
+
* more than `w:tblGrid` declares.
|
|
106
|
+
*/
|
|
107
|
+
const reconcileTableGridAfterColumnInsertion = ({ tr, tablePosition, previousTable, insertedColumn }) => {
|
|
108
|
+
const previousColumnCount = TableMap.get(previousTable).width;
|
|
109
|
+
const table = tr.doc.nodeAt(tablePosition);
|
|
110
|
+
if (!table || table.type.spec["tableRole"] !== "table") return;
|
|
111
|
+
const columnCount = TableMap.get(table).width;
|
|
112
|
+
if (columnCount <= previousColumnCount) return;
|
|
113
|
+
const insertedColumnCount = columnCount - previousColumnCount;
|
|
114
|
+
const previousWidths = expectTableAttrs(previousTable).columnWidths;
|
|
115
|
+
const neighbourWidth = previousWidths?.[Math.max(0, Math.min(insertedColumn, previousColumnCount) - 1)] ?? previousWidths?.[0];
|
|
116
|
+
const columnWidths = previousWidths?.length === previousColumnCount && neighbourWidth !== void 0 ? previousWidths.toSpliced(insertedColumn, 0, ...Array.from({ length: insertedColumnCount }, () => neighbourWidth)) : void 0;
|
|
117
|
+
setTableGrid({
|
|
118
|
+
tr,
|
|
119
|
+
tablePosition,
|
|
120
|
+
table,
|
|
121
|
+
columnWidths,
|
|
122
|
+
columnCount
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
const setTableGrid = ({ tr, tablePosition, table, columnWidths, columnCount }) => {
|
|
21
126
|
const formatting = expectTableAttrs(table)._originalFormatting;
|
|
22
127
|
const originalFormatting = formatting ? { ...formatting } : void 0;
|
|
23
128
|
if (originalFormatting) delete originalFormatting.gridSourceXml;
|
|
@@ -27,4 +132,4 @@ const reconcileTableGridAfterColumnRemoval = ({ tr, tablePosition, previousTable
|
|
|
27
132
|
}));
|
|
28
133
|
};
|
|
29
134
|
//#endregion
|
|
30
|
-
export { reconcileTableGridAfterColumnRemoval };
|
|
135
|
+
export { reconcileTableGridAfterColumnInsertion, reconcileTableGridAfterColumnRemoval, removeRowsWithoutCells, removeTableRow };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readBlockSdtAttrs, readCharacterSpacingMarkAttrs, readCharacterStyleMarkAttrs, readCommentMarkAttrs, readEmphasisMarkAttrs, readFieldAttrs, readFontFamilyMarkAttrs, readFontSizeMarkAttrs, readFootnoteRefMarkAttrs, readHardBreakAttrs, readHighlightMarkAttrs, readHyperlinkMarkAttrs, readImageAttrs, readInlineWrapperMarkAttrs, readLanguageMarkAttrs, readMathAttrs, readPageBreakRunAttrs, readParagraphAttrs, readPreservedBlockAttrs, readPreservedXmlAttrs, readRunFormattingOverrideMarkAttrs, readRunIdentityMarkAttrs, readRunPropertyChangeMarkAttrs, readRunShadingMarkAttrs, readSdtAttrs, readShapeAttrs, readStrikeMarkAttrs, readSymbolAttrs, readTabAttrs, readTableAttrs, readTableCellAttrs, readTableRowAttrs, readTextBoxAttrs, readTextColorMarkAttrs, readTextEffectMarkAttrs, readTrackedChangeMarkAttrs, readUnderlineMarkAttrs } from "./attrs/index.js";
|
|
1
|
+
import { readBlockCustomXmlAttrs, readBlockSdtAttrs, readCharacterSpacingMarkAttrs, readCharacterStyleMarkAttrs, readCommentMarkAttrs, readEmphasisMarkAttrs, readFieldAttrs, readFontFamilyMarkAttrs, readFontSizeMarkAttrs, readFootnoteRefMarkAttrs, readHardBreakAttrs, readHighlightMarkAttrs, readHyperlinkMarkAttrs, readImageAttrs, readInlineWrapperMarkAttrs, readLanguageMarkAttrs, readMathAttrs, readPageBreakRunAttrs, readParagraphAttrs, readPreservedBlockAttrs, readPreservedXmlAttrs, readRunFormattingOverrideMarkAttrs, readRunIdentityMarkAttrs, readRunPropertyChangeMarkAttrs, readRunShadingMarkAttrs, readSdtAttrs, readShapeAttrs, readStrikeMarkAttrs, readSymbolAttrs, readTabAttrs, readTableAttrs, readTableCellAttrs, readTableRowAttrs, readTextBoxAttrs, readTextColorMarkAttrs, readTextEffectMarkAttrs, readTrackedChangeMarkAttrs, readUnderlineMarkAttrs } from "./attrs/index.js";
|
|
2
2
|
import { readBookmarkBoundaryAttrs } from "./bookmarkBoundaryAttrs.js";
|
|
3
3
|
import { readCommentReferenceAttrs } from "./commentReferenceAttrs.js";
|
|
4
4
|
import { INLINE_WRAPPER_MARK_NAME } from "./extensions/marks/InlineWrapperExtension.js";
|
|
@@ -288,6 +288,10 @@ const validateNodeAttrs = (node, path, issues) => {
|
|
|
288
288
|
appendAttrIssues(path, readBlockSdtAttrs(node), issues);
|
|
289
289
|
for (let i = 0; i < node.childCount; i += 1) validateNode(node.child(i), `${path}.content[${i}]`, issues);
|
|
290
290
|
return;
|
|
291
|
+
case "blockCustomXml":
|
|
292
|
+
appendAttrIssues(path, readBlockCustomXmlAttrs(node), issues);
|
|
293
|
+
for (let i = 0; i < node.childCount; i += 1) validateNode(node.child(i), `${path}.content[${i}]`, issues);
|
|
294
|
+
return;
|
|
291
295
|
case "shape":
|
|
292
296
|
appendAttrIssues(path, readShapeAttrs(node), issues);
|
|
293
297
|
return;
|
package/dist/redline.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FolioDocxReviewer, isFolioResolvedReviewedView } from "./ai-edits/headless.js";
|
|
1
|
+
import { FolioDocxReviewer, getFolioDocxComparisonAccess, isFolioResolvedReviewedView } from "./ai-edits/headless.js";
|
|
2
2
|
import { createFolioAITextRangeHandle, trailingBodyBlockId } from "./ai-edits/snapshot.js";
|
|
3
3
|
import { createScopedWordDiffOptions } from "./ai-edits/word-diff.js";
|
|
4
4
|
import { FolioContentInlinePresentationProjectionError } from "./compare/content.js";
|
|
@@ -77,6 +77,7 @@ const buildRedlineOperations = ({ baseSnapshot, revisedBlocks, nextOperationId }
|
|
|
77
77
|
const operations = [];
|
|
78
78
|
const trailingAdditions = [];
|
|
79
79
|
const lastBaseBlockId = trailingBodyBlockId(baseSnapshot);
|
|
80
|
+
const baseBlocksById = new Map(baseSnapshot.blocks.map((block) => [block.id, block]));
|
|
80
81
|
events.forEach((event, eventIndex) => {
|
|
81
82
|
if (event.type === "pair") {
|
|
82
83
|
if (event.baseBlock.text !== event.revisedBlock.text) operations.push({
|
|
@@ -102,10 +103,7 @@ const buildRedlineOperations = ({ baseSnapshot, revisedBlocks, nextOperationId }
|
|
|
102
103
|
}
|
|
103
104
|
const anchorId = anchorIds[eventIndex] ?? null;
|
|
104
105
|
if (anchorId === null) {
|
|
105
|
-
trailingAdditions.push(
|
|
106
|
-
text: event.block.text,
|
|
107
|
-
...event.block.styleId !== void 0 && { styleId: event.block.styleId }
|
|
108
|
-
});
|
|
106
|
+
trailingAdditions.push(event.block);
|
|
109
107
|
return;
|
|
110
108
|
}
|
|
111
109
|
operations.push({
|
|
@@ -113,7 +111,7 @@ const buildRedlineOperations = ({ baseSnapshot, revisedBlocks, nextOperationId }
|
|
|
113
111
|
type: "insertBeforeBlock",
|
|
114
112
|
blockId: anchorId,
|
|
115
113
|
text: event.block.text,
|
|
116
|
-
...event.block
|
|
114
|
+
...insertedParagraphProperties(event.block, baseBlocksById.get(anchorId))
|
|
117
115
|
});
|
|
118
116
|
});
|
|
119
117
|
for (const addition of trailingAdditions) operations.push({
|
|
@@ -121,10 +119,85 @@ const buildRedlineOperations = ({ baseSnapshot, revisedBlocks, nextOperationId }
|
|
|
121
119
|
type: "insertAfterBlock",
|
|
122
120
|
blockId: lastBaseBlockId ?? "redline-unanchored",
|
|
123
121
|
text: addition.text,
|
|
124
|
-
...addition
|
|
122
|
+
...insertedParagraphProperties(addition, lastBaseBlockId === null ? void 0 : baseBlocksById.get(lastBaseBlockId))
|
|
125
123
|
});
|
|
126
124
|
return operations;
|
|
127
125
|
};
|
|
126
|
+
/**
|
|
127
|
+
* The revised value, or `null` to clear one the anchor would pass on, or
|
|
128
|
+
* `undefined` when neither has one: an explicit `null` costs a restyle pass.
|
|
129
|
+
*/
|
|
130
|
+
const statedOrCleared = (revised, anchor) => revised ?? (anchor === void 0 ? void 0 : null);
|
|
131
|
+
/**
|
|
132
|
+
* The paragraph properties an inserted block states. An insertion that says
|
|
133
|
+
* nothing takes the properties of its anchor, which is whichever base block
|
|
134
|
+
* happens to follow it, so whatever the anchor states and the revised block
|
|
135
|
+
* does not is cleared: a list item keeps its numbering, and a plain paragraph
|
|
136
|
+
* beside a list item stays plain.
|
|
137
|
+
*/
|
|
138
|
+
const insertedParagraphProperties = (block, anchor) => {
|
|
139
|
+
const properties = {};
|
|
140
|
+
const styleId = statedOrCleared(block.styleId, anchor?.styleId);
|
|
141
|
+
if (styleId !== void 0) properties.styleId = styleId;
|
|
142
|
+
const alignment = statedOrCleared(block.directAlignment, anchor?.directAlignment);
|
|
143
|
+
if (alignment !== void 0) properties.alignment = alignment;
|
|
144
|
+
const spacing = statedOrCleared(block.directSpacing, anchor?.directSpacing);
|
|
145
|
+
if (spacing !== void 0) properties.spacing = spacing;
|
|
146
|
+
const indentation = statedOrCleared(block.directIndentation, anchor?.directIndentation);
|
|
147
|
+
if (indentation !== void 0) properties.indentation = indentation;
|
|
148
|
+
if (block.listReference !== void 0 || anchor?.listReference !== void 0 || anchor?.listLevel !== void 0) {
|
|
149
|
+
properties.numbering = block.listReference ?? null;
|
|
150
|
+
properties.listLevel = block.listLevel ?? null;
|
|
151
|
+
} else if (block.listLevel !== void 0) properties.listLevel = block.listLevel;
|
|
152
|
+
return properties;
|
|
153
|
+
};
|
|
154
|
+
const insertedNumbering = (operation) => {
|
|
155
|
+
if (operation.type !== "insertBeforeBlock" && operation.type !== "insertAfterBlock") return null;
|
|
156
|
+
const numbering = operation.numbering;
|
|
157
|
+
return numbering && !("start" in numbering) ? numbering : null;
|
|
158
|
+
};
|
|
159
|
+
/** The `w:numId`s whose `w:num` and abstract definition both exist. */
|
|
160
|
+
const definedNumIds = (numbering) => {
|
|
161
|
+
const abstractIds = new Set(numbering?.abstractNums.map((entry) => entry.abstractNumId));
|
|
162
|
+
return new Set((numbering?.nums ?? []).filter((entry) => abstractIds.has(entry.abstractNumId)).map((entry) => entry.numId));
|
|
163
|
+
};
|
|
164
|
+
/**
|
|
165
|
+
* Rebind every inserted list item to numbering the redline package defines.
|
|
166
|
+
* The redline is the base package, where the revised version's `w:numId` may
|
|
167
|
+
* name nothing, or another list: the referenced definitions are copied in,
|
|
168
|
+
* under a fresh id wherever the base uses that one for different numbering.
|
|
169
|
+
* A reference the revised package cannot resolve shows no number there
|
|
170
|
+
* either, and is inserted without one.
|
|
171
|
+
*/
|
|
172
|
+
const bindInsertedNumbering = (baseReviewer, revisedReviewer, operationsByStory) => {
|
|
173
|
+
const baseAccess = getFolioDocxComparisonAccess(baseReviewer);
|
|
174
|
+
const revisedNumbering = getFolioDocxComparisonAccess(revisedReviewer).numberingDefinitions();
|
|
175
|
+
const resolvable = definedNumIds(revisedNumbering);
|
|
176
|
+
const references = operationsByStory.flatMap((operations) => operations.flatMap((operation) => {
|
|
177
|
+
const numbering = insertedNumbering(operation);
|
|
178
|
+
return numbering && resolvable.has(numbering.numId) ? [numbering] : [];
|
|
179
|
+
}));
|
|
180
|
+
const remapped = baseAccess.planTargetNumberingReferences(revisedNumbering, references) ?? panic("Resolvable revised numbering references could not be planned");
|
|
181
|
+
baseAccess.stageTargetNumbering(revisedNumbering, references, remapped);
|
|
182
|
+
const defined = definedNumIds(baseAccess.numberingDefinitions());
|
|
183
|
+
return operationsByStory.map((operations) => operations.map((operation) => {
|
|
184
|
+
const numbering = insertedNumbering(operation);
|
|
185
|
+
if (numbering === null) return operation;
|
|
186
|
+
const numId = remapped.get(numbering.numId) ?? numbering.numId;
|
|
187
|
+
if (!resolvable.has(numbering.numId) || !defined.has(numId)) return {
|
|
188
|
+
...operation,
|
|
189
|
+
numbering: null,
|
|
190
|
+
listLevel: null
|
|
191
|
+
};
|
|
192
|
+
return {
|
|
193
|
+
...operation,
|
|
194
|
+
numbering: {
|
|
195
|
+
numId,
|
|
196
|
+
level: numbering.level
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
}));
|
|
200
|
+
};
|
|
128
201
|
const resolveInputView = (value, option) => {
|
|
129
202
|
if (value === void 0) return "final";
|
|
130
203
|
if (!isFolioResolvedReviewedView(value)) throw new InvalidGenerateRedlineDocxOptionsError({
|
|
@@ -155,6 +228,7 @@ const generateRedlineDocx = async (base, revised, options = {}) => {
|
|
|
155
228
|
if (operationSequence >= 1e4) throw new GenerateRedlineDocxOperationLimitError({ message: "The document comparison exceeds the generated operation limit." });
|
|
156
229
|
return `redline-${++operationSequence}`;
|
|
157
230
|
};
|
|
231
|
+
const plannedStories = [];
|
|
158
232
|
for (const pair of pairFolioDocumentStories(baseStories, revisedStories)) {
|
|
159
233
|
if (!pair.baseStory) {
|
|
160
234
|
unprocessedStories.push({
|
|
@@ -182,15 +256,25 @@ const generateRedlineDocx = async (base, revised, options = {}) => {
|
|
|
182
256
|
nextOperationId
|
|
183
257
|
});
|
|
184
258
|
if (operations.length === 0) continue;
|
|
185
|
-
|
|
259
|
+
plannedStories.push({
|
|
186
260
|
story: pair.baseStory,
|
|
187
261
|
snapshot: baseSnapshot,
|
|
262
|
+
operations
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
const boundOperations = bindInsertedNumbering(baseReviewer, revisedReviewer, plannedStories.map(({ operations }) => operations));
|
|
266
|
+
for (const [index, { story, snapshot }] of plannedStories.entries()) {
|
|
267
|
+
const operations = boundOperations[index] ?? panic("A planned story lost its operations");
|
|
268
|
+
const result = baseReviewer.applyDocumentOperationsToStory({
|
|
269
|
+
story,
|
|
270
|
+
snapshot,
|
|
188
271
|
batch: {
|
|
189
272
|
version: 1,
|
|
190
273
|
mode: "tracked-changes",
|
|
191
274
|
operations
|
|
192
275
|
},
|
|
193
|
-
wordDiff
|
|
276
|
+
wordDiff,
|
|
277
|
+
undefinedStyles: "keep"
|
|
194
278
|
});
|
|
195
279
|
applied.push(...result.applied);
|
|
196
280
|
skipped.push(...result.skipped);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DisplayMode } from "../managers/EditorModeManager.js";
|
|
1
2
|
import { EditorState } from "prosemirror-state";
|
|
2
3
|
//#region src/render-dom/BodySelectionOverlay.d.ts
|
|
3
4
|
type BodySelectionOverlayResult = {
|
|
@@ -10,6 +11,8 @@ type BodySelectionOverlayResult = {
|
|
|
10
11
|
type SyncBodySelectionOverlayOptions = {
|
|
11
12
|
pagesContainer: HTMLElement;
|
|
12
13
|
state: EditorState;
|
|
14
|
+
/** The review view the pages were laid out for; a caret in text it hides paints at its edge. */
|
|
15
|
+
markupView: DisplayMode;
|
|
13
16
|
zoom: number;
|
|
14
17
|
zIndex?: number;
|
|
15
18
|
caretColor?: string;
|
|
@@ -17,7 +20,7 @@ type SyncBodySelectionOverlayOptions = {
|
|
|
17
20
|
};
|
|
18
21
|
declare class BodySelectionOverlay {
|
|
19
22
|
clear(pagesContainer: HTMLElement): void;
|
|
20
|
-
sync({ pagesContainer, state, zoom, zIndex, caretColor, selectionColor }: SyncBodySelectionOverlayOptions): BodySelectionOverlayResult;
|
|
23
|
+
sync({ pagesContainer, state, markupView, zoom, zIndex, caretColor, selectionColor }: SyncBodySelectionOverlayOptions): BodySelectionOverlayResult;
|
|
21
24
|
}
|
|
22
25
|
//#endregion
|
|
23
26
|
export { BodySelectionOverlay, BodySelectionOverlayResult, SyncBodySelectionOverlayOptions };
|
|
@@ -2,6 +2,7 @@ import { applyCellSelectionHighlight } from "../layout-bridge/cellSelectionHighl
|
|
|
2
2
|
import { getCaretPositionFromDom, getSelectionRectsFromDom } from "../layout-bridge/dom/clickToPositionDom.js";
|
|
3
3
|
import { findBodyPmAnchor } from "../layout-bridge/dom/findBodyPmSpans.js";
|
|
4
4
|
import { findImageElement } from "../layout-painter/imageLayout.js";
|
|
5
|
+
import { projectMarkupView, visibleCaretPosition } from "../prosemirror/markupViewProjection.js";
|
|
5
6
|
import { NodeSelection } from "prosemirror-state";
|
|
6
7
|
//#region src/render-dom/BodySelectionOverlay.ts
|
|
7
8
|
/**
|
|
@@ -23,7 +24,7 @@ var BodySelectionOverlay = class {
|
|
|
23
24
|
clear(pagesContainer) {
|
|
24
25
|
for (const element of pagesContainer.querySelectorAll(OWNED_OVERLAY_SELECTOR)) element.remove();
|
|
25
26
|
}
|
|
26
|
-
sync({ pagesContainer, state, zoom, zIndex = 10, caretColor = "var(--doc-caret, #000)", selectionColor = "var(--doc-selection, rgba(66, 133, 244, 0.3))" }) {
|
|
27
|
+
sync({ pagesContainer, state, markupView, zoom, zIndex = 10, caretColor = "var(--doc-caret, #000)", selectionColor = "var(--doc-selection, rgba(66, 133, 244, 0.3))" }) {
|
|
27
28
|
this.clear(pagesContainer);
|
|
28
29
|
applyCellSelectionHighlight(pagesContainer, state);
|
|
29
30
|
const { selection } = state;
|
|
@@ -37,7 +38,7 @@ var BodySelectionOverlay = class {
|
|
|
37
38
|
};
|
|
38
39
|
}
|
|
39
40
|
if (selection.empty) {
|
|
40
|
-
const caret = getCaretPositionFromDom(pagesContainer, selection.from, pagesContainer.getBoundingClientRect());
|
|
41
|
+
const caret = getCaretPositionFromDom(pagesContainer, visibleCaretPosition(projectMarkupView(state, markupView), selection.from), pagesContainer.getBoundingClientRect());
|
|
41
42
|
if (!caret) return { type: "text" };
|
|
42
43
|
const element = pagesContainer.ownerDocument.createElement("div");
|
|
43
44
|
element.className = CARET_CLASS;
|
|
@@ -66,7 +66,7 @@ const forEachParagraph = (blocks, visit) => {
|
|
|
66
66
|
walkTable(block);
|
|
67
67
|
continue;
|
|
68
68
|
}
|
|
69
|
-
if (
|
|
69
|
+
if (isBlockContainer(block)) walkBlocks(block.content);
|
|
70
70
|
}
|
|
71
71
|
};
|
|
72
72
|
const walkTable = (table) => {
|
|
@@ -172,6 +172,6 @@ const isParagraph = (value) => isRecord(value) && value["type"] === "paragraph"
|
|
|
172
172
|
const isTable = (value) => isRecord(value) && value["type"] === "table" && Array.isArray(value["rows"]);
|
|
173
173
|
const isTableRow = (value) => isRecord(value) && Array.isArray(value["cells"]);
|
|
174
174
|
const isTableCell = (value) => isRecord(value) && Array.isArray(value["content"]);
|
|
175
|
-
const
|
|
175
|
+
const isBlockContainer = (value) => isRecord(value) && (value["type"] === "blockSdt" || value["type"] === "blockCustomXml") && Array.isArray(value["content"]);
|
|
176
176
|
//#endregion
|
|
177
177
|
export { createDefaultFindOptions, createSearchPattern, escapeRegexString, findAllMatches, findInDocument, findInParagraph };
|
|
@@ -86,7 +86,7 @@ function mergeDocumentContent(target, source) {
|
|
|
86
86
|
function remapBlock(block, numIdRemap, abstractNumIdRemap) {
|
|
87
87
|
if (block.type === "paragraph") return remapParagraph(block, numIdRemap, abstractNumIdRemap);
|
|
88
88
|
if (block.type === "table") return remapTable(block, numIdRemap, abstractNumIdRemap);
|
|
89
|
-
if (block.type === "blockSdt" && Array.isArray(block.content)) return {
|
|
89
|
+
if ((block.type === "blockSdt" || block.type === "blockCustomXml") && Array.isArray(block.content)) return {
|
|
90
90
|
...block,
|
|
91
91
|
content: block.content.map((child) => remapBlock(child, numIdRemap, abstractNumIdRemap))
|
|
92
92
|
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//#region src/utils/noteReferenceLabels.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* How a reader shows a footnote or endnote reference.
|
|
4
|
+
*
|
|
5
|
+
* A reference's `w:id` is a package key, not something a reader sees: the
|
|
6
|
+
* rendered document numbers notes by the order they are first referenced
|
|
7
|
+
* (1, 2, 3 …), whatever ids the package gave them. Every reader that puts a reference in a line of
|
|
8
|
+
* text — the Markdown export, `getContent()`, the AI snapshot and the agent
|
|
9
|
+
* tools built on it — numbers through {@link createNoteReferenceNumbering}, so
|
|
10
|
+
* the same reference reads as the same marker everywhere.
|
|
11
|
+
*
|
|
12
|
+
* Footnotes and endnotes are numbered in separate sequences; an
|
|
13
|
+
* endnote's token carries an `e` so the two sequences never collide
|
|
14
|
+
* (`[^1]` is footnote 1, `[^e1]` is endnote 1).
|
|
15
|
+
*/
|
|
16
|
+
type NoteReferenceKind = "footnote" | "endnote";
|
|
17
|
+
/** The bare token: `1` for footnote 1, `e1` for endnote 1. */
|
|
18
|
+
declare const noteReferenceToken: (kind: NoteReferenceKind, displayNumber: number) => string;
|
|
19
|
+
/** The marker a text reader shows in the line: `[^1]`, `[^e1]`. */
|
|
20
|
+
declare const noteReferenceMarker: (kind: NoteReferenceKind, displayNumber: number) => string;
|
|
21
|
+
type NoteReferenceNumber = {
|
|
22
|
+
displayNumber: number;
|
|
23
|
+
/** Whether this is the note's first reference in reading order. */
|
|
24
|
+
first: boolean;
|
|
25
|
+
};
|
|
26
|
+
type NoteReferenceNumbering = {
|
|
27
|
+
/** Number one reference, in reading order. */
|
|
28
|
+
next: (kind: NoteReferenceKind, noteId: string | number) => NoteReferenceNumber;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* A reading-order numbering: each note takes the next number of its kind the
|
|
32
|
+
* first time it is referenced, and a repeated reference reuses it.
|
|
33
|
+
*/
|
|
34
|
+
declare const createNoteReferenceNumbering: () => NoteReferenceNumbering;
|
|
35
|
+
//#endregion
|
|
36
|
+
export { NoteReferenceKind, NoteReferenceNumber, NoteReferenceNumbering, createNoteReferenceNumbering, noteReferenceMarker, noteReferenceToken };
|