@stll/folio-core 0.55.0 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-edits/apply.js +214 -52
- package/dist/ai-edits/batch-claims.d.ts +3 -1
- package/dist/ai-edits/batch-claims.js +25 -1
- package/dist/ai-edits/headless.js +2 -2
- package/dist/ai-edits/table-row-column-mutations.js +17 -3
- package/dist/ai-edits/types.d.ts +7 -1
- package/dist/ai-suggestions/apply.js +20 -1
- package/dist/compare/compare.js +1 -0
- package/dist/compare/inline-atoms.js +40 -16
- package/dist/compare/inline-provenance.js +12 -5
- package/dist/compare/reproducible-package.d.ts +0 -17
- package/dist/compare/reproducible-package.js +12 -18
- package/dist/compat/eigenpal.d.ts +2 -1
- package/dist/compat/eigenpal.js +2 -1
- package/dist/controller/canonicalClipboard.d.ts +23 -0
- package/dist/controller/canonicalClipboard.js +482 -0
- package/dist/controller/canonicalClipboardResources.d.ts +21 -0
- package/dist/controller/canonicalClipboardResources.js +382 -0
- package/dist/controller/canonicalComments.d.ts +41 -0
- package/dist/controller/canonicalComments.js +152 -0
- package/dist/controller/canonicalComposition.d.ts +24 -3
- package/dist/controller/canonicalComposition.js +208 -48
- package/dist/controller/canonicalInlineProjection.d.ts +118 -0
- package/dist/controller/canonicalInlineProjection.js +476 -0
- package/dist/controller/canonicalInput.d.ts +13 -4
- package/dist/controller/canonicalInput.js +62 -14
- package/dist/controller/canonicalInputTimer.d.ts +16 -0
- package/dist/controller/canonicalInputTimer.js +34 -0
- package/dist/controller/canonicalPublicOperations.d.ts +48 -0
- package/dist/controller/canonicalPublicOperations.js +648 -0
- package/dist/controller/canonicalSelection.d.ts +18 -0
- package/dist/controller/canonicalSelection.js +32 -0
- package/dist/controller/canonicalSession.d.ts +27 -6
- package/dist/controller/canonicalSession.js +298 -116
- package/dist/controller/canonicalStoryEditor.d.ts +7 -3
- package/dist/controller/canonicalStoryEditor.js +27 -2
- package/dist/controller/canonicalStructure.js +57 -4
- package/dist/controller/canonicalTocSelection.d.ts +11 -0
- package/dist/controller/canonicalTocSelection.js +43 -0
- package/dist/controller/folioEditor.d.ts +2 -9
- package/dist/controller/folioEditor.js +18 -4
- package/dist/controller/headerFooterEditorManager.d.ts +2 -1
- package/dist/controller/headerFooterEditorManager.js +26 -11
- package/dist/controller/hiddenEditorApi.d.ts +24 -3
- package/dist/controller/hiddenEditorApi.js +8 -0
- package/dist/controller/hiddenEditorManager.d.ts +5 -1
- package/dist/controller/hiddenEditorManager.js +378 -43
- package/dist/controller/noteEditorManager.d.ts +2 -1
- package/dist/controller/noteEditorManager.js +29 -13
- package/dist/document-operations.d.ts +8 -1
- package/dist/document-operations.js +6 -4
- package/dist/docx/blockPlainText.d.ts +1 -1
- package/dist/docx/blockPlainText.js +11 -3
- package/dist/docx/builtInStyles.js +13 -6
- package/dist/docx/canonicalResourceSave.d.ts +16 -0
- package/dist/docx/canonicalResourceSave.js +27 -0
- package/dist/docx/canonicalSave.d.ts +29 -0
- package/dist/docx/canonicalSave.js +101 -0
- package/dist/docx/canonicalStoryRepack.d.ts +1 -1
- package/dist/docx/canonicalStoryRepack.js +38 -5
- package/dist/docx/containerChildren.gen.d.ts +3 -1
- package/dist/docx/containerChildren.gen.js +33 -1
- package/dist/docx/documentParser.d.ts +1 -13
- package/dist/docx/documentParser.js +1 -47
- package/dist/docx/ensureParaIds.js +10 -4
- package/dist/docx/fieldParser.js +14 -2
- package/dist/docx/footnoteParser.d.ts +1 -11
- package/dist/docx/footnoteParser.js +1 -16
- package/dist/docx/headerFooterParser.d.ts +1 -9
- package/dist/docx/headerFooterParser.js +1 -12
- package/dist/docx/headerFooterVerbatim.d.ts +26 -1
- package/dist/docx/headerFooterVerbatim.js +81 -3
- package/dist/docx/hyperlinkParser.d.ts +1 -1
- package/dist/docx/hyperlinkParser.js +20 -1
- package/dist/docx/imageParser.d.ts +13 -1
- package/dist/docx/imageParser.js +20 -11
- package/dist/docx/inlineWrapperContent.d.ts +4 -4
- package/dist/docx/inlineWrapperContent.js +4 -4
- package/dist/docx/linkedSdtPreservation.d.ts +10 -0
- package/dist/docx/linkedSdtPreservation.js +37 -0
- package/dist/docx/metadataPrivacy.js +6 -1
- package/dist/docx/packageParts.js +9 -3
- package/dist/docx/paragraphParser.js +88 -67
- package/dist/docx/paragraphPropertySource.d.ts +22 -1
- package/dist/docx/paragraphPropertySource.js +109 -2
- package/dist/docx/parser.js +2 -1
- package/dist/docx/preservedRunContent.js +2 -1
- package/dist/docx/relsParser.js +26 -2
- package/dist/docx/removeHeaderFooterParts.js +17 -6
- package/dist/docx/rezip.d.ts +49 -5
- package/dist/docx/rezip.js +754 -235
- package/dist/docx/saveDiagnostics.d.ts +11 -0
- package/dist/docx/selectiveSave.d.ts +2 -1
- package/dist/docx/selectiveSave.js +42 -11
- package/dist/docx/selectiveXmlPatch.js +7 -5
- package/dist/docx/serializer/commentSerializer.d.ts +4 -1
- package/dist/docx/serializer/commentSerializer.js +7 -3
- package/dist/docx/serializer/documentSerializer.d.ts +9 -2
- package/dist/docx/serializer/documentSerializer.js +29 -10
- package/dist/docx/serializer/paragraphSerializer.js +207 -94
- package/dist/docx/server/applyDocxXmlPatchProposal.js +14 -9
- package/dist/docx/server/materializeYjsDocx.js +14 -6
- package/dist/docx/server/migrateYjsAttrSchema.js +17 -5
- package/dist/docx/storyBlockReplay.d.ts +21 -1
- package/dist/docx/storyBlockReplay.js +113 -9
- package/dist/docx/storyPlainText.d.ts +20 -0
- package/dist/docx/storyPlainText.js +23 -0
- package/dist/docx/structuralXmlPatch.js +10 -22
- package/dist/docx/styleParser.d.ts +5 -1
- package/dist/docx/styleParser.js +1 -1
- package/dist/docx/tableParser.d.ts +1 -8
- package/dist/docx/tableParser.js +1 -28
- package/dist/docx/textBoxParser.d.ts +1 -5
- package/dist/docx/textBoxParser.js +1 -20
- package/dist/docx/unzip.js +6 -1
- package/dist/i18n/messages/ar.gen.js +4 -0
- package/dist/i18n/messages/catalogs.gen.d.ts +68 -0
- package/dist/i18n/messages/catalogs.gen.js +68 -0
- package/dist/i18n/messages/cs.gen.js +4 -0
- package/dist/i18n/messages/de.gen.js +4 -0
- package/dist/i18n/messages/en.gen.js +4 -0
- package/dist/i18n/messages/es.gen.js +4 -0
- package/dist/i18n/messages/et.gen.js +4 -0
- package/dist/i18n/messages/fr.gen.js +4 -0
- package/dist/i18n/messages/he.gen.js +4 -0
- package/dist/i18n/messages/hi.gen.js +4 -0
- package/dist/i18n/messages/hu.gen.js +4 -0
- package/dist/i18n/messages/lt.gen.js +4 -0
- package/dist/i18n/messages/lv.gen.js +4 -0
- package/dist/i18n/messages/messages.gen.d.ts +4 -0
- package/dist/i18n/messages/pl.gen.js +4 -0
- package/dist/i18n/messages/pt-BR.gen.js +4 -0
- package/dist/i18n/messages/sk.gen.js +4 -0
- package/dist/i18n/messages/tr.gen.js +4 -0
- package/dist/i18n/messages/zh-CN.gen.js +4 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/internal/acceptedBlockProjection.d.ts +12 -0
- package/dist/internal/acceptedBlockProjection.js +45 -0
- package/dist/internal/revisionResolutionInline.js +25 -3
- package/dist/managers/DocumentLoaderManager.js +2 -1
- package/dist/markdown/escape.d.ts +3 -1
- package/dist/markdown/escape.js +9 -2
- package/dist/markdown/renderBlock.js +5 -120
- package/dist/markdown/renderParagraph.js +4 -2
- package/dist/markdown/renderRuns.d.ts +7 -1
- package/dist/markdown/renderRuns.js +33 -24
- package/dist/panel-layout.d.ts +11 -9
- package/dist/panel-layout.js +13 -9
- package/dist/prosemirror/addTrackedDeletionMark.d.ts +18 -0
- package/dist/prosemirror/addTrackedDeletionMark.js +87 -0
- package/dist/prosemirror/attrs/index.js +5 -0
- package/dist/prosemirror/canonicalCommands.d.ts +28 -4
- package/dist/prosemirror/canonicalCommands.js +11 -4
- package/dist/prosemirror/canonicalSelectionRange.d.ts +9 -0
- package/dist/prosemirror/canonicalSelectionRange.js +15 -0
- package/dist/prosemirror/clipboardIntent.d.ts +7 -0
- package/dist/prosemirror/clipboardIntent.js +9 -0
- package/dist/prosemirror/commands/comments.js +60 -35
- package/dist/prosemirror/commands/pageBreak.js +2 -2
- package/dist/prosemirror/commands/pastePlainText.js +2 -1
- package/dist/prosemirror/commands/propertyChangeScope.js +3 -6
- package/dist/prosemirror/commands/resolveParagraphProperties.js +22 -13
- package/dist/prosemirror/commentOps.js +15 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +22 -3
- package/dist/prosemirror/conversion/hyphenTextCarriers.d.ts +8 -0
- package/dist/prosemirror/conversion/hyphenTextCarriers.js +8 -0
- package/dist/prosemirror/conversion/toProseDoc.d.ts +7 -1
- package/dist/prosemirror/conversion/toProseDoc.js +124 -22
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +61 -35
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +74 -25
- package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +11 -0
- package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +65 -29
- package/dist/prosemirror/extensions/marks/markUtils.js +11 -8
- package/dist/prosemirror/extensions/marks/noteReferenceDeletion.js +5 -2
- package/dist/prosemirror/fieldRepresentation.d.ts +8 -0
- package/dist/prosemirror/fieldRepresentation.js +18 -0
- package/dist/prosemirror/hyperlinkRemoval.d.ts +13 -1
- package/dist/prosemirror/hyperlinkRemoval.js +28 -9
- package/dist/prosemirror/insertOperations.js +2 -1
- package/dist/prosemirror/listNumbering.js +11 -5
- package/dist/prosemirror/noteReferenceOccurrenceId.d.ts +5 -0
- package/dist/prosemirror/noteReferenceOccurrenceId.js +5 -0
- package/dist/prosemirror/noteReferenceOccurrences.d.ts +21 -0
- package/dist/prosemirror/noteReferenceOccurrences.js +185 -0
- package/dist/prosemirror/noteReferenceReview.js +14 -1
- package/dist/prosemirror/paragraphPropertyCarry.d.ts +7 -1
- package/dist/prosemirror/paragraphPropertyCarry.js +8 -3
- package/dist/prosemirror/plugins/documentStyles.d.ts +4 -1
- package/dist/prosemirror/plugins/documentStyles.js +17 -10
- package/dist/prosemirror/plugins/suggestionMode.js +48 -48
- package/dist/prosemirror/preservedXmlReview.d.ts +6 -0
- package/dist/prosemirror/preservedXmlReview.js +35 -0
- package/dist/prosemirror/runFormattingFromMarks.js +2 -2
- package/dist/prosemirror/runFormattingReconciliation.js +5 -4
- package/dist/prosemirror/runPropertyChangeResolution.d.ts +8 -1
- package/dist/prosemirror/runPropertyChangeResolution.js +24 -2
- package/dist/prosemirror/runStyleFormatting.d.ts +3 -1
- package/dist/prosemirror/runStyleFormatting.js +3 -1
- package/dist/prosemirror/schema/marks.d.ts +1 -0
- package/dist/prosemirror/schema/nodes.d.ts +2 -0
- package/dist/prosemirror/styles/paragraphStyleCascade.js +4 -1
- package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +15 -15
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +69 -28
- package/dist/prosemirror/textInput.d.ts +5 -1
- package/dist/prosemirror/textInput.js +3 -3
- package/dist/prosemirror/trackedRevisionPath.d.ts +5 -1
- package/dist/prosemirror/trackedRevisionPath.js +39 -1
- package/dist/prosemirror/validation.js +3 -5
- package/dist/prosemirror/yjsDocumentMetadata.d.ts +9 -3
- package/dist/prosemirror/yjsDocumentMetadata.js +37 -8
- package/dist/types/canonicalCapabilities.d.ts +201 -0
- package/dist/types/canonicalCapabilities.js +198 -0
- package/dist/types/canonicalComments.d.ts +51 -0
- package/dist/types/canonicalComments.js +0 -0
- package/dist/types/canonicalSave.d.ts +11 -0
- package/dist/types/canonicalSave.js +0 -0
- package/dist/types/canonicalSections.d.ts +12 -0
- package/dist/types/canonicalSections.js +0 -0
- package/dist/types/docxSerialization.d.ts +14 -0
- package/dist/types/docxSerialization.js +7 -0
- package/dist/utils/headingCollector.js +45 -4
- package/dist/utils/outlineDepth.d.ts +9 -0
- package/dist/utils/outlineDepth.js +9 -0
- package/package.json +4 -4
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CanonicalGap } from "../types/canonicalCapabilities.js";
|
|
1
2
|
import { HiddenEditorApi } from "./hiddenEditorApi.js";
|
|
2
3
|
import { Transaction } from "prosemirror-state";
|
|
3
4
|
import { EditorView } from "prosemirror-view";
|
|
@@ -9,7 +10,7 @@ type CanonicalStoryEditorOptions = {
|
|
|
9
10
|
getApi: () => HiddenEditorApi | null;
|
|
10
11
|
enabled: () => boolean;
|
|
11
12
|
onSelectionChange: () => void;
|
|
12
|
-
onRefusal: ((reason: string) => void) | undefined;
|
|
13
|
+
onRefusal: ((reason: string, gap: CanonicalGap) => void) | undefined;
|
|
13
14
|
};
|
|
14
15
|
/** Secondary views compile classified native input into the shared Document journal. */
|
|
15
16
|
declare const createCanonicalStoryEditor: ({ story, getView, getApi, enabled, onRefusal, onSelectionChange }: CanonicalStoryEditorOptions) => {
|
|
@@ -18,14 +19,17 @@ declare const createCanonicalStoryEditor: ({ story, getView, getApi, enabled, on
|
|
|
18
19
|
handleKeyDown: (view: EditorView, event: KeyboardEvent) => boolean;
|
|
19
20
|
handleTextInput: (view: EditorView, from: number, to: number, text: string) => boolean;
|
|
20
21
|
handleDOMEvents: {
|
|
22
|
+
keydown: (view: EditorView, event: KeyboardEvent) => boolean;
|
|
23
|
+
keyup: (view: EditorView, event: KeyboardEvent) => boolean;
|
|
24
|
+
mouseup: (view: EditorView) => boolean;
|
|
21
25
|
beforeinput: (view: EditorView, event: InputEvent) => boolean;
|
|
22
26
|
mousedown: (view: EditorView) => boolean;
|
|
23
27
|
compositionstart: (view: EditorView) => boolean;
|
|
24
28
|
compositionend: (view: EditorView) => boolean;
|
|
25
29
|
input: (view: EditorView) => boolean;
|
|
26
30
|
blur: (view: EditorView) => boolean;
|
|
27
|
-
paste: (view: EditorView, event:
|
|
28
|
-
cut: (view: EditorView, event:
|
|
31
|
+
paste: (view: EditorView, event: ClipboardEvent) => boolean;
|
|
32
|
+
cut: (view: EditorView, event: ClipboardEvent) => boolean;
|
|
29
33
|
drop: (view: EditorView, event: Event) => boolean;
|
|
30
34
|
};
|
|
31
35
|
};
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
+
import { CANONICAL_GAP } from "../types/canonicalCapabilities.js";
|
|
1
2
|
import { createCanonicalInputBoundary } from "./canonicalInput.js";
|
|
2
3
|
import { CanonicalSessionError } from "./canonicalSession.js";
|
|
4
|
+
import { AllSelection, TextSelection } from "prosemirror-state";
|
|
3
5
|
//#region src/controller/canonicalStoryEditor.ts
|
|
4
6
|
/** Secondary views compile classified native input into the shared Document journal. */
|
|
5
7
|
const createCanonicalStoryEditor = ({ story, getView, getApi, enabled, onRefusal, onSelectionChange }) => {
|
|
6
|
-
const refuse = (
|
|
7
|
-
|
|
8
|
+
const refuse = (reason) => {
|
|
9
|
+
const gap = CANONICAL_GAP.dispatch;
|
|
10
|
+
const message = reason;
|
|
11
|
+
if (onRefusal) onRefusal(message, gap);
|
|
8
12
|
else throw new CanonicalSessionError({
|
|
13
|
+
gap,
|
|
9
14
|
message,
|
|
10
15
|
reason: "refused"
|
|
11
16
|
});
|
|
@@ -20,6 +25,17 @@ const createCanonicalStoryEditor = ({ story, getView, getApi, enabled, onRefusal
|
|
|
20
25
|
if (accepted && !view.isDestroyed) onSelectionChange();
|
|
21
26
|
return accepted;
|
|
22
27
|
};
|
|
28
|
+
const syncNativeSelection = (view) => {
|
|
29
|
+
if (boundary.isComposing || view.composing) return;
|
|
30
|
+
const selection = view.dom.ownerDocument.getSelection();
|
|
31
|
+
if (!selection?.anchorNode || !selection.focusNode || !view.dom.contains(selection.anchorNode) || !view.dom.contains(selection.focusNode)) return;
|
|
32
|
+
const anchor = view.posAtDOM(selection.anchorNode, selection.anchorOffset);
|
|
33
|
+
const head = view.posAtDOM(selection.focusNode, selection.focusOffset);
|
|
34
|
+
if (view.state.selection instanceof AllSelection && Math.min(anchor, head) === 0 && Math.max(anchor, head) === view.state.doc.content.size) return;
|
|
35
|
+
if (anchor === view.state.selection.anchor && head === view.state.selection.head) return;
|
|
36
|
+
if (!view.state.doc.resolve(anchor).parent.inlineContent || !view.state.doc.resolve(head).parent.inlineContent) return;
|
|
37
|
+
view.dispatch(view.state.tr.setSelection(TextSelection.create(view.state.doc, anchor, head)));
|
|
38
|
+
};
|
|
23
39
|
const boundary = createCanonicalInputBoundary({
|
|
24
40
|
breakUndoGroup: () => {
|
|
25
41
|
getApi()?.updateCanonicalInputLifecycle("breakUndoGroup");
|
|
@@ -65,6 +81,15 @@ const createCanonicalStoryEditor = ({ story, getView, getApi, enabled, onRefusal
|
|
|
65
81
|
handleKeyDown: (view, event) => enabled() && boundary.handleKeyDown(view, event),
|
|
66
82
|
handleTextInput: (view, from, to, text) => enabled() && boundary.handleTextInput(view, from, to, text),
|
|
67
83
|
handleDOMEvents: {
|
|
84
|
+
keydown: (view, event) => enabled() && boundary.handleDOMEvents.keydown(view, event),
|
|
85
|
+
keyup: (view, event) => {
|
|
86
|
+
if (enabled() && /^(?:Arrow|Home$|End$|Page)/u.test(event.key)) syncNativeSelection(view);
|
|
87
|
+
return false;
|
|
88
|
+
},
|
|
89
|
+
mouseup: (view) => {
|
|
90
|
+
if (enabled()) syncNativeSelection(view);
|
|
91
|
+
return false;
|
|
92
|
+
},
|
|
68
93
|
beforeinput: (view, event) => enabled() && boundary.handleDOMEvents.beforeinput(view, event),
|
|
69
94
|
mousedown: (view) => enabled() && boundary.handleDOMEvents.mousedown(view),
|
|
70
95
|
compositionstart: (view) => enabled() && boundary.handleDOMEvents.compositionstart(view),
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
+
import { BUILT_IN_STYLE_NAME, createBuiltInStyleIndex } from "../docx/builtInStyles.js";
|
|
1
2
|
import { getCachedNumberingMap, numberingLevelUsesBulletMarker } from "../docx/numberingParser.js";
|
|
2
3
|
import { listRequestsForMarker } from "../prosemirror/listAutoformatMarkers.js";
|
|
4
|
+
import { CANONICAL_GAP } from "../types/canonicalCapabilities.js";
|
|
5
|
+
import { collectHeadings } from "../utils/headingCollector.js";
|
|
3
6
|
import { CanonicalSessionError } from "./canonicalSession.js";
|
|
4
7
|
import { Result } from "better-result";
|
|
5
|
-
import { paragraphNumberingReference } from "@stll/docx-core/model";
|
|
8
|
+
import { headingOutlineLevel, paragraphNumberingReference } from "@stll/docx-core/model";
|
|
6
9
|
import { OP_STORIES } from "@stll/docx-core/ops";
|
|
7
10
|
//#region src/controller/canonicalStructure.ts
|
|
11
|
+
const DEFAULT_TOC_PAGE_WIDTH_TWIPS = 12240;
|
|
12
|
+
const DEFAULT_TOC_MARGIN_TWIPS = 1440;
|
|
8
13
|
const refuse = (message) => Result.err(new CanonicalSessionError({
|
|
14
|
+
gap: CANONICAL_GAP.commands,
|
|
9
15
|
message,
|
|
10
16
|
reason: "refused"
|
|
11
17
|
}));
|
|
@@ -84,6 +90,53 @@ const prepareCanonicalCommands = (session, state, commands) => {
|
|
|
84
90
|
const intents = [];
|
|
85
91
|
const paragraphs = selectedParagraphs(session, state);
|
|
86
92
|
for (const command of commands) switch (command.type) {
|
|
93
|
+
case "generateTOC": {
|
|
94
|
+
const at = session.projection.addressAt(command.at);
|
|
95
|
+
if (at.isErr()) return at;
|
|
96
|
+
const definitions = session.document.package.styles;
|
|
97
|
+
const styles = createBuiltInStyleIndex(definitions?.styles ?? [], definitions?.docDefaults);
|
|
98
|
+
const headings = [];
|
|
99
|
+
for (const heading of collectHeadings(session.projection.doc, styles)) {
|
|
100
|
+
const address = session.projection.addressAt(heading.pmPos + 1);
|
|
101
|
+
if (address.isErr()) return address;
|
|
102
|
+
const outline = headingOutlineLevel(heading.level);
|
|
103
|
+
if (outline?.kind !== "heading") return refuse("A TOC heading has an invalid outline level.");
|
|
104
|
+
const styleId = styles.styleIdForTableOfContentsLevel(outline.level + 1);
|
|
105
|
+
headings.push({
|
|
106
|
+
blockId: address.value.blockId,
|
|
107
|
+
text: heading.text,
|
|
108
|
+
level: outline.level,
|
|
109
|
+
...styleId === void 0 ? {} : { styleId }
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
if (headings.length === 0) break;
|
|
113
|
+
const titleStyleId = styles.styleIdForBuiltInName(BUILT_IN_STYLE_NAME.tocHeading);
|
|
114
|
+
const section = session.document.package.document.content.find((item) => item.type === "paragraph" && (item.sectionProperties?.pageWidth ?? 0) > 0);
|
|
115
|
+
const properties = section?.type === "paragraph" ? section.sectionProperties : void 0;
|
|
116
|
+
intents.push({
|
|
117
|
+
type: "generateTOC",
|
|
118
|
+
at: at.value,
|
|
119
|
+
title: command.title,
|
|
120
|
+
headings,
|
|
121
|
+
tabPosition: (properties?.pageWidth ?? DEFAULT_TOC_PAGE_WIDTH_TWIPS) - (properties?.marginLeft ?? DEFAULT_TOC_MARGIN_TWIPS) - (properties?.marginRight ?? DEFAULT_TOC_MARGIN_TWIPS),
|
|
122
|
+
...titleStyleId === void 0 ? {} : { titleStyleId }
|
|
123
|
+
});
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
case "setHyperlink":
|
|
127
|
+
case "removeHyperlink":
|
|
128
|
+
case "insertHyperlink": {
|
|
129
|
+
const from = session.projection.addressAt(command.from);
|
|
130
|
+
if (from.isErr()) return from;
|
|
131
|
+
const to = session.projection.addressAt(command.to);
|
|
132
|
+
if (to.isErr()) return to;
|
|
133
|
+
intents.push({
|
|
134
|
+
...command,
|
|
135
|
+
from: from.value,
|
|
136
|
+
to: to.value
|
|
137
|
+
});
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
87
140
|
case "insertBreak": {
|
|
88
141
|
const from = session.projection.addressAt(command.from);
|
|
89
142
|
if (from.isErr()) return from;
|
|
@@ -233,7 +286,7 @@ const prepareCanonicalCommands = (session, state, commands) => {
|
|
|
233
286
|
}
|
|
234
287
|
default: return command;
|
|
235
288
|
}
|
|
236
|
-
return session.prepareIntents(state, intents);
|
|
289
|
+
return session.prepareIntents(state, { intents });
|
|
237
290
|
};
|
|
238
291
|
/** Rules compile their replacement and paragraph change as one atomic edit. */
|
|
239
292
|
const prepareCanonicalAutoformat = (session, state, { from, to, text }) => {
|
|
@@ -254,7 +307,7 @@ const prepareCanonicalAutoformat = (session, state, { from, to, text }) => {
|
|
|
254
307
|
const request = requests?.at(0);
|
|
255
308
|
const styleId = `Heading${heading?.length ?? 1}`;
|
|
256
309
|
if (request === void 0 && !session.hasStyle(styleId)) return void 0;
|
|
257
|
-
return session.prepareIntents(state, [{
|
|
310
|
+
return session.prepareIntents(state, { intents: [{
|
|
258
311
|
type: "replaceText",
|
|
259
312
|
from: start,
|
|
260
313
|
to: at.value,
|
|
@@ -263,7 +316,7 @@ const prepareCanonicalAutoformat = (session, state, { from, to, text }) => {
|
|
|
263
316
|
type: "formatParagraph",
|
|
264
317
|
at: start,
|
|
265
318
|
patch: { styleId }
|
|
266
|
-
} : numberingIntent(session, [source], request)]);
|
|
319
|
+
} : numberingIntent(session, [source], request)] });
|
|
267
320
|
};
|
|
268
321
|
//#endregion
|
|
269
322
|
export { prepareCanonicalAutoformat, prepareCanonicalCommands };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { DocumentOp, TextPosition } from "@stll/docx-core/ops";
|
|
2
|
+
//#region src/controller/canonicalTocSelection.d.ts
|
|
3
|
+
type TocSelectionMapping = {
|
|
4
|
+
at: TextPosition;
|
|
5
|
+
after: TextPosition;
|
|
6
|
+
ops: readonly DocumentOp[];
|
|
7
|
+
};
|
|
8
|
+
/** TOC insertion retains the selected text and maps its endpoints through the canonical split. */
|
|
9
|
+
declare const mapTocSelection: (point: TextPosition, { at, after, ops }: TocSelectionMapping) => TextPosition;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { mapTocSelection };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { panic } from "better-result";
|
|
2
|
+
import { DOCUMENT_OP_TYPES, SPLIT_HALVES, compareGaps, idKey, mapTocBookmarkPosition, sameStory } from "@stll/docx-core/ops";
|
|
3
|
+
//#region src/controller/canonicalTocSelection.ts
|
|
4
|
+
/** TOC insertion retains the selected text and maps its endpoints through the canonical split. */
|
|
5
|
+
const mapTocSelection = (point, { at, after, ops }) => {
|
|
6
|
+
if (!sameStory(point.story, at.story)) return point;
|
|
7
|
+
point = mapTocBookmarkPosition({
|
|
8
|
+
...point,
|
|
9
|
+
zeroWidthBefore: point.zeroWidthBefore ?? 0
|
|
10
|
+
}, ops);
|
|
11
|
+
at = mapTocBookmarkPosition({
|
|
12
|
+
...at,
|
|
13
|
+
zeroWidthBefore: at.zeroWidthBefore ?? 0
|
|
14
|
+
}, ops);
|
|
15
|
+
if (idKey(point.blockId) !== idKey(at.blockId)) return point;
|
|
16
|
+
const split = ops.find((op) => op.type === DOCUMENT_OP_TYPES.SPLIT_BLOCK);
|
|
17
|
+
if (split === void 0) return point;
|
|
18
|
+
if (point.offset === at.offset && (point.zeroWidthBefore ?? 0) === (at.zeroWidthBefore ?? 0)) return after;
|
|
19
|
+
if (split.type !== DOCUMENT_OP_TYPES.SPLIT_BLOCK || split.newHalf !== SPLIT_HALVES.FIRST) return panic("TOC insertion must retain its following paragraph identity.");
|
|
20
|
+
const pointGap = {
|
|
21
|
+
offset: point.offset,
|
|
22
|
+
zeroWidthBefore: point.zeroWidthBefore ?? 0
|
|
23
|
+
};
|
|
24
|
+
const splitGap = {
|
|
25
|
+
offset: split.at.offset,
|
|
26
|
+
zeroWidthBefore: split.at.zeroWidthBefore ?? 0
|
|
27
|
+
};
|
|
28
|
+
if (compareGaps(pointGap, splitGap) < 0) return {
|
|
29
|
+
...point,
|
|
30
|
+
blockId: split.newBlockId
|
|
31
|
+
};
|
|
32
|
+
if (point.offset === split.at.offset) return {
|
|
33
|
+
...point,
|
|
34
|
+
offset: 0,
|
|
35
|
+
zeroWidthBefore: pointGap.zeroWidthBefore - splitGap.zeroWidthBefore
|
|
36
|
+
};
|
|
37
|
+
return {
|
|
38
|
+
...point,
|
|
39
|
+
offset: point.offset - split.at.offset
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
//#endregion
|
|
43
|
+
export { mapTocSelection };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
2
|
import { DocxInput } from "../utils/docxInput.js";
|
|
3
|
+
import { FOLIO_DOCX_SERIALIZATION_MODE, FolioDocxSerializationMode, FolioGetDocxOptions } from "../types/docxSerialization.js";
|
|
3
4
|
import { Layout } from "../layout-engine/types.js";
|
|
4
5
|
import { FolioEditorEmitter } from "./folioEditorEvents.js";
|
|
5
6
|
import { HiddenEditorApi } from "./hiddenEditorApi.js";
|
|
@@ -14,14 +15,6 @@ type FolioEditorDeps = {
|
|
|
14
15
|
getDocumentIO?: () => FolioEditorDocumentIO;
|
|
15
16
|
emitter: FolioEditorEmitter;
|
|
16
17
|
};
|
|
17
|
-
declare const FOLIO_DOCX_SERIALIZATION_MODE: Readonly<{
|
|
18
|
-
readonly full: "full";
|
|
19
|
-
readonly preferSelective: "prefer-selective";
|
|
20
|
-
}>;
|
|
21
|
-
type FolioDocxSerializationMode = (typeof FOLIO_DOCX_SERIALIZATION_MODE)[keyof typeof FOLIO_DOCX_SERIALIZATION_MODE];
|
|
22
|
-
type FolioGetDocxOptions = {
|
|
23
|
-
mode?: FolioDocxSerializationMode;
|
|
24
|
-
};
|
|
25
18
|
/**
|
|
26
19
|
* Document lifecycle operations supplied by a host integration.
|
|
27
20
|
*
|
|
@@ -45,4 +38,4 @@ type FolioEditor = HiddenEditorApi & {
|
|
|
45
38
|
};
|
|
46
39
|
declare const createFolioEditor: (deps: FolioEditorDeps) => FolioEditor;
|
|
47
40
|
//#endregion
|
|
48
|
-
export { FOLIO_DOCX_SERIALIZATION_MODE, FolioDocxSerializationMode, FolioEditor, FolioEditorDeps, FolioEditorDocumentIO, FolioGetDocxOptions, createFolioEditor };
|
|
41
|
+
export { FOLIO_DOCX_SERIALIZATION_MODE, type FolioDocxSerializationMode, FolioEditor, FolioEditorDeps, FolioEditorDocumentIO, type FolioGetDocxOptions, createFolioEditor };
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
+
import { CANONICAL_GAP } from "../types/canonicalCapabilities.js";
|
|
2
|
+
import { FOLIO_DOCX_SERIALIZATION_MODE } from "../types/docxSerialization.js";
|
|
1
3
|
import { panic } from "better-result";
|
|
2
4
|
//#region src/controller/folioEditor.ts
|
|
3
|
-
const FOLIO_DOCX_SERIALIZATION_MODE = Object.freeze({
|
|
4
|
-
full: "full",
|
|
5
|
-
preferSelective: "prefer-selective"
|
|
6
|
-
});
|
|
7
5
|
const createFolioEditor = (deps) => {
|
|
8
6
|
const getDocumentIO = () => deps.getDocumentIO?.() ?? panic("FolioEditor document I/O requires a getDocumentIO dependency");
|
|
9
7
|
return {
|
|
@@ -17,10 +15,26 @@ const createFolioEditor = (deps) => {
|
|
|
17
15
|
getDocument: () => deps.getEditorApi()?.getDocument() ?? null,
|
|
18
16
|
updateCanonicalInputLifecycle: (action) => deps.getEditorApi()?.updateCanonicalInputLifecycle(action) ?? false,
|
|
19
17
|
applyCanonicalStoryHistory: (options) => deps.getEditorApi()?.applyCanonicalStoryHistory(options) ?? false,
|
|
18
|
+
applyCanonicalComment: (request) => deps.getEditorApi()?.applyCanonicalComment(request) ?? null,
|
|
19
|
+
applyCanonicalSectionProperties: (patch) => {
|
|
20
|
+
const api = deps.getEditorApi();
|
|
21
|
+
if (!api) return {
|
|
22
|
+
status: "refused",
|
|
23
|
+
gap: CANONICAL_GAP.sectionProperties,
|
|
24
|
+
message: "The editor is not ready for section changes."
|
|
25
|
+
};
|
|
26
|
+
return api.applyCanonicalSectionProperties(patch);
|
|
27
|
+
},
|
|
20
28
|
applyCanonicalOperations: (ops) => deps.getEditorApi()?.applyCanonicalOperations(ops) ?? false,
|
|
21
29
|
getCanonicalStorySelection: (story) => deps.getEditorApi()?.getCanonicalStorySelection(story) ?? null,
|
|
22
30
|
getCanonicalStoryProjection: (story) => deps.getEditorApi()?.getCanonicalStoryProjection(story) ?? null,
|
|
23
31
|
replaceCanonicalStoryText: (options) => deps.getEditorApi()?.replaceCanonicalStoryText(options) ?? false,
|
|
32
|
+
isCanonicalSaveCurrent: (version) => deps.getEditorApi()?.isCanonicalSaveCurrent(version) ?? false,
|
|
33
|
+
captureCanonicalSave: () => deps.getEditorApi()?.captureCanonicalSave() ?? null,
|
|
34
|
+
applyCanonicalDocumentOperations: (options) => deps.getEditorApi()?.applyCanonicalDocumentOperations(options) ?? null,
|
|
35
|
+
undoCanonicalDocumentOperations: (handle) => deps.getEditorApi()?.undoCanonicalDocumentOperations(handle) ?? null,
|
|
36
|
+
getCanonicalComments: () => deps.getEditorApi()?.getCanonicalComments() ?? null,
|
|
37
|
+
getCanonicalCommittedVersion: () => deps.getEditorApi()?.getCanonicalCommittedVersion() ?? null,
|
|
24
38
|
getCanonicalDocument: () => deps.getEditorApi()?.getCanonicalDocument() ?? null,
|
|
25
39
|
setCanonicalMode: (mode) => deps.getEditorApi()?.setCanonicalMode(mode) ?? false,
|
|
26
40
|
resolveCanonicalRevisions: (revisionIds, resolution) => deps.getEditorApi()?.resolveCanonicalRevisions(revisionIds, resolution) ?? false,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { CanonicalGap } from "../types/canonicalCapabilities.js";
|
|
2
3
|
import { HiddenEditorApi } from "./hiddenEditorApi.js";
|
|
3
4
|
import { DirectEditorProps, EditorView } from "prosemirror-view";
|
|
4
5
|
//#region src/controller/headerFooterEditorManager.d.ts
|
|
@@ -19,7 +20,7 @@ type HeaderFooterEditorManagerDeps = {
|
|
|
19
20
|
getDocument: () => document_d_exports.Document | null;
|
|
20
21
|
getCanonicalApi?: (() => HiddenEditorApi | null) | undefined;
|
|
21
22
|
getExperimentalSession?: (() => "canonical" | undefined) | undefined;
|
|
22
|
-
onSessionRefusal?: ((reason: string) => void) | undefined;
|
|
23
|
+
onSessionRefusal?: ((reason: string, gap: CanonicalGap, error?: Error) => void) | undefined;
|
|
23
24
|
getHost: () => HTMLElement | null;
|
|
24
25
|
getStyles: () => document_d_exports.StyleDefinitions | null | undefined;
|
|
25
26
|
getTheme: () => document_d_exports.Theme | null | undefined;
|
|
@@ -6,10 +6,13 @@ import { ExtensionManager } from "../prosemirror/extensions/ExtensionManager.js"
|
|
|
6
6
|
import { createStarterKit } from "../prosemirror/extensions/StarterKit.js";
|
|
7
7
|
import { ensureBaseDirectionInState } from "../prosemirror/extensions/features/AutoBidiDetectionExtension.js";
|
|
8
8
|
import { ensureParaIdsInState } from "../prosemirror/extensions/features/ParaIdAllocatorExtension.js";
|
|
9
|
+
import { noteReferenceTransactionIssue } from "../prosemirror/noteReferenceOccurrences.js";
|
|
9
10
|
import { createDocumentNumberingPlugin } from "../prosemirror/plugins/documentNumbering.js";
|
|
10
|
-
import { createDocumentStylesPlugin } from "../prosemirror/plugins/documentStyles.js";
|
|
11
|
+
import { createDocumentStyleContextPlugin, createDocumentStylesPlugin } from "../prosemirror/plugins/documentStyles.js";
|
|
11
12
|
import { schema } from "../prosemirror/schema/index.js";
|
|
12
13
|
import { storyListNumbering } from "../prosemirror/storyListNumbering.js";
|
|
14
|
+
import { CANONICAL_GAP, usesCanonicalSession } from "../types/canonicalCapabilities.js";
|
|
15
|
+
import { CanonicalSessionError } from "./canonicalSession.js";
|
|
13
16
|
import { createCanonicalStoryEditor } from "./canonicalStoryEditor.js";
|
|
14
17
|
import { OP_STORIES } from "@stll/docx-core/ops";
|
|
15
18
|
import { EditorState, TextSelection } from "prosemirror-state";
|
|
@@ -84,11 +87,12 @@ const createHeaderFooterEditorManager = (deps) => {
|
|
|
84
87
|
for (const part of mounted.values()) destroyMounted(part);
|
|
85
88
|
mounted.clear();
|
|
86
89
|
};
|
|
90
|
+
const getOwnedDocument = () => usesCanonicalSession(deps.getExperimentalSession?.(), CANONICAL_GAP.authorityRouting) ? deps.getCanonicalApi?.()?.getCanonicalDocument() ?? null : deps.getDocument();
|
|
87
91
|
const sync = () => {
|
|
88
92
|
const host = deps.getHost();
|
|
89
93
|
if (!host) return;
|
|
90
|
-
if (deps.getExperimentalSession?.()
|
|
91
|
-
const document =
|
|
94
|
+
if (usesCanonicalSession(deps.getExperimentalSession?.(), CANONICAL_GAP.authorityRouting) && !deps.getCanonicalApi?.()?.getCanonicalStoryProjection(OP_STORIES.MAIN)) return;
|
|
95
|
+
const document = getOwnedDocument();
|
|
92
96
|
const styles = deps.getStyles();
|
|
93
97
|
const theme = deps.getTheme();
|
|
94
98
|
const numbering = document?.package.numbering;
|
|
@@ -104,7 +108,7 @@ const createHeaderFooterEditorManager = (deps) => {
|
|
|
104
108
|
const existing = mounted.get(part.rId);
|
|
105
109
|
if (existing) {
|
|
106
110
|
if (existing.mountNode.parentElement !== host) host.append(existing.mountNode);
|
|
107
|
-
if (deps.getExperimentalSession?.()
|
|
111
|
+
if (usesCanonicalSession(deps.getExperimentalSession?.(), CANONICAL_GAP.authorityRouting)) {
|
|
108
112
|
const projected = deps.getCanonicalApi?.()?.getCanonicalStoryProjection({
|
|
109
113
|
kind: part.kind,
|
|
110
114
|
rId: part.rId
|
|
@@ -154,7 +158,7 @@ const createHeaderFooterEditorManager = (deps) => {
|
|
|
154
158
|
},
|
|
155
159
|
getView: () => view,
|
|
156
160
|
getApi: () => deps.getCanonicalApi?.() ?? null,
|
|
157
|
-
enabled: () => deps.getExperimentalSession?.()
|
|
161
|
+
enabled: () => usesCanonicalSession(deps.getExperimentalSession?.(), CANONICAL_GAP.authorityRouting),
|
|
158
162
|
onRefusal: deps.onSessionRefusal,
|
|
159
163
|
onSelectionChange: () => deps.onTransaction?.({
|
|
160
164
|
kind: part.kind,
|
|
@@ -164,11 +168,11 @@ const createHeaderFooterEditorManager = (deps) => {
|
|
|
164
168
|
selectionChanged: true
|
|
165
169
|
})
|
|
166
170
|
});
|
|
167
|
-
const canonicalProjection = deps.getExperimentalSession?.()
|
|
171
|
+
const canonicalProjection = usesCanonicalSession(deps.getExperimentalSession?.(), CANONICAL_GAP.authorityRouting) ? deps.getCanonicalApi?.()?.getCanonicalStoryProjection({
|
|
168
172
|
kind: part.kind,
|
|
169
173
|
rId: part.rId
|
|
170
174
|
}) : null;
|
|
171
|
-
if (deps.getExperimentalSession?.()
|
|
175
|
+
if (usesCanonicalSession(deps.getExperimentalSession?.(), CANONICAL_GAP.authorityRouting) && !canonicalProjection) {
|
|
172
176
|
manager.destroy();
|
|
173
177
|
mountNode.remove();
|
|
174
178
|
continue;
|
|
@@ -177,16 +181,19 @@ const createHeaderFooterEditorManager = (deps) => {
|
|
|
177
181
|
...canonical.props,
|
|
178
182
|
state: canonicalProjection ? EditorState.create({
|
|
179
183
|
doc: canonicalProjection,
|
|
180
|
-
plugins: [
|
|
184
|
+
plugins: [createDocumentStyleContextPlugin(styles), createDocumentNumberingPlugin(numbering)]
|
|
181
185
|
}) : buildInitialState(headerFooter, styles, theme, numbering, manager),
|
|
182
186
|
dispatchTransaction(transaction) {
|
|
183
187
|
if (canonical.dispatch(transaction)) return;
|
|
184
188
|
const nextState = view.state.apply(transaction);
|
|
189
|
+
const docChanged = !nextState.doc.eq(view.state.doc);
|
|
190
|
+
const noteIssue = noteReferenceTransactionIssue(transaction);
|
|
191
|
+
if (noteIssue) deps.onSessionRefusal?.(noteIssue.message, CANONICAL_GAP.dispatch, noteIssue);
|
|
185
192
|
view.updateState(nextState);
|
|
186
193
|
const mountedPart = mounted.get(part.rId);
|
|
187
|
-
if (mountedPart &&
|
|
194
|
+
if (mountedPart && docChanged) mountedPart.dirty = true;
|
|
188
195
|
deps.onTransaction?.({
|
|
189
|
-
docChanged
|
|
196
|
+
docChanged,
|
|
190
197
|
kind: part.kind,
|
|
191
198
|
rId: part.rId,
|
|
192
199
|
selectionChanged: transaction.selectionSet,
|
|
@@ -217,7 +224,15 @@ const createHeaderFooterEditorManager = (deps) => {
|
|
|
217
224
|
rId
|
|
218
225
|
})),
|
|
219
226
|
snapshotDocument: (document) => {
|
|
220
|
-
if (deps.getExperimentalSession?.()
|
|
227
|
+
if (usesCanonicalSession(deps.getExperimentalSession?.(), CANONICAL_GAP.authorityRouting)) {
|
|
228
|
+
const canonical = deps.getCanonicalApi?.()?.getCanonicalDocument();
|
|
229
|
+
if (canonical) return canonical;
|
|
230
|
+
throw new CanonicalSessionError({
|
|
231
|
+
gap: CANONICAL_GAP.authorityRouting,
|
|
232
|
+
reason: "refused",
|
|
233
|
+
message: "Canonical story snapshot is unavailable."
|
|
234
|
+
});
|
|
235
|
+
}
|
|
221
236
|
let headers = document.package.headers;
|
|
222
237
|
let footers = document.package.footers;
|
|
223
238
|
let headersChanged = false;
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
|
-
import {
|
|
2
|
+
import { FolioDocumentOperationResult, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult } from "../document-operations.js";
|
|
3
|
+
import { Comment } from "../types/content.js";
|
|
4
|
+
import { CanonicalSaveSnapshot } from "../types/canonicalSave.js";
|
|
3
5
|
import { CanonicalSessionMode } from "./canonicalSession.js";
|
|
6
|
+
import { createCanonicalInputBoundary } from "./canonicalInput.js";
|
|
7
|
+
import { CanonicalPublicOperationOptions } from "./canonicalPublicOperations.js";
|
|
8
|
+
import { CanonicalSectionPropertiesResult } from "../types/canonicalSections.js";
|
|
9
|
+
import { CanonicalCommentRequest, CanonicalCommentResult } from "../types/canonicalComments.js";
|
|
4
10
|
import { Node } from "prosemirror-model";
|
|
5
11
|
import { Command, EditorState, Transaction } from "prosemirror-state";
|
|
6
12
|
import { EditorView } from "prosemirror-view";
|
|
7
|
-
import { DocumentOp, OpStory } from "@stll/docx-core/ops";
|
|
13
|
+
import { DocumentOp, FormattingPatch, OpStory } from "@stll/docx-core/ops";
|
|
8
14
|
//#region src/controller/hiddenEditorApi.d.ts
|
|
9
15
|
type CanonicalStoryHistoryOptions = {
|
|
10
16
|
view: EditorView;
|
|
@@ -28,7 +34,13 @@ type HiddenEditorApi = {
|
|
|
28
34
|
/** Get the current Document from PM state */
|
|
29
35
|
getDocument: () => document_d_exports.Document | null;
|
|
30
36
|
/** Canonical snapshot, or null in the default session. */
|
|
37
|
+
getCanonicalComments: () => Comment[] | null;
|
|
38
|
+
/** Committed session/version identity; safe during provisional composition. */
|
|
39
|
+
getCanonicalCommittedVersion: () => string | null;
|
|
31
40
|
getCanonicalDocument: () => document_d_exports.Document | null;
|
|
41
|
+
captureCanonicalSave: () => CanonicalSaveSnapshot | null;
|
|
42
|
+
/** A save cannot acknowledge newer edits or an unfinished composition. */
|
|
43
|
+
isCanonicalSaveCurrent: (version: number) => boolean;
|
|
32
44
|
/** Set the explicit mode for an active canonical session. */
|
|
33
45
|
setCanonicalMode: (mode: CanonicalSessionMode) => boolean;
|
|
34
46
|
/** Resolve canonical revisions as one batch and journal its exact inverse. */
|
|
@@ -36,12 +48,17 @@ type HiddenEditorApi = {
|
|
|
36
48
|
updateCanonicalInputLifecycle: (action: "beginComposition" | "endComposition" | "breakUndoGroup") => boolean;
|
|
37
49
|
applyCanonicalStoryHistory: (options: CanonicalStoryHistoryOptions) => boolean;
|
|
38
50
|
applyCanonicalOperations: (ops: readonly DocumentOp[]) => boolean;
|
|
51
|
+
applyCanonicalComment: (request: CanonicalCommentRequest) => CanonicalCommentResult | null;
|
|
52
|
+
/** Apply a final-section patch; null is reserved for default sessions. */
|
|
53
|
+
applyCanonicalSectionProperties: (patch: FormattingPatch<document_d_exports.SectionProperties>) => CanonicalSectionPropertiesResult | null;
|
|
39
54
|
getCanonicalStorySelection: (story: OpStory) => {
|
|
40
55
|
anchor: number;
|
|
41
56
|
head: number;
|
|
42
57
|
} | null;
|
|
43
58
|
getCanonicalStoryProjection: (story: OpStory) => Node | null;
|
|
44
59
|
replaceCanonicalStoryText: (options: CanonicalStoryTextOptions) => boolean;
|
|
60
|
+
applyCanonicalDocumentOperations: (options: CanonicalPublicOperationOptions) => FolioDocumentOperationResult | null;
|
|
61
|
+
undoCanonicalDocumentOperations: (handle: FolioDocumentOperationUndoHandle) => FolioDocumentOperationUndoResult | null;
|
|
45
62
|
/** Focus the hidden editor */
|
|
46
63
|
focus: () => void;
|
|
47
64
|
/** Blur the hidden editor */
|
|
@@ -72,12 +89,16 @@ type HiddenEditorApi = {
|
|
|
72
89
|
type HiddenEditorApiDeps = {
|
|
73
90
|
getView: () => EditorView | null;
|
|
74
91
|
getDocumentContext: () => document_d_exports.Document | null;
|
|
92
|
+
getCanonicalComments?: () => Comment[] | null;
|
|
93
|
+
getCanonicalCommittedVersion?: HiddenEditorApi["getCanonicalCommittedVersion"];
|
|
75
94
|
getCanonicalDocument?: () => document_d_exports.Document | null;
|
|
95
|
+
captureCanonicalSave?: HiddenEditorApi["captureCanonicalSave"];
|
|
96
|
+
isCanonicalSaveCurrent?: HiddenEditorApi["isCanonicalSaveCurrent"];
|
|
76
97
|
setCanonicalMode?: HiddenEditorApi["setCanonicalMode"];
|
|
77
98
|
resolveCanonicalRevisions?: HiddenEditorApi["resolveCanonicalRevisions"];
|
|
78
99
|
executeCanonicalCommand?: (command: Command) => boolean | undefined;
|
|
79
100
|
getCanonicalHistory?: () => Pick<HiddenEditorApi, "undo" | "redo" | "canUndo" | "canRedo"> | null;
|
|
80
|
-
canonicalOperations?: Pick<HiddenEditorApi, "updateCanonicalInputLifecycle" | "applyCanonicalOperations" | "getCanonicalStoryProjection" | "replaceCanonicalStoryText" | "applyCanonicalStoryHistory" | "getCanonicalStorySelection">;
|
|
101
|
+
canonicalOperations?: Pick<HiddenEditorApi, "updateCanonicalInputLifecycle" | "applyCanonicalOperations" | "applyCanonicalComment" | "applyCanonicalSectionProperties" | "getCanonicalStoryProjection" | "replaceCanonicalStoryText" | "applyCanonicalStoryHistory" | "getCanonicalStorySelection" | "applyCanonicalDocumentOperations" | "undoCanonicalDocumentOperations">;
|
|
81
102
|
isDestroying: () => boolean;
|
|
82
103
|
ensureView: () => void;
|
|
83
104
|
isViewRequested: () => boolean;
|
|
@@ -34,6 +34,10 @@ const createHiddenEditorApi = (deps) => {
|
|
|
34
34
|
getView: () => deps.getView() ?? null,
|
|
35
35
|
setCanonicalMode: (mode) => !deps.isDestroying() && (deps.setCanonicalMode?.(mode) ?? false),
|
|
36
36
|
resolveCanonicalRevisions: (revisionIds, resolution) => !deps.isDestroying() && (deps.resolveCanonicalRevisions?.(revisionIds, resolution) ?? false),
|
|
37
|
+
getCanonicalComments: () => deps.getCanonicalComments?.() ?? null,
|
|
38
|
+
getCanonicalCommittedVersion: () => deps.getCanonicalCommittedVersion?.() ?? null,
|
|
39
|
+
captureCanonicalSave: () => deps.captureCanonicalSave?.() ?? null,
|
|
40
|
+
isCanonicalSaveCurrent: (version) => deps.isCanonicalSaveCurrent?.(version) ?? false,
|
|
37
41
|
getCanonicalDocument: () => {
|
|
38
42
|
const canonical = deps.getCanonicalDocument?.();
|
|
39
43
|
return canonical ? cloneDocumentWithParagraphPropertySources(canonical) : null;
|
|
@@ -47,10 +51,14 @@ const createHiddenEditorApi = (deps) => {
|
|
|
47
51
|
},
|
|
48
52
|
updateCanonicalInputLifecycle: (action) => deps.canonicalOperations?.updateCanonicalInputLifecycle(action) ?? false,
|
|
49
53
|
applyCanonicalStoryHistory: (options) => deps.canonicalOperations?.applyCanonicalStoryHistory(options) ?? false,
|
|
54
|
+
applyCanonicalComment: (request) => deps.canonicalOperations?.applyCanonicalComment(request) ?? null,
|
|
55
|
+
applyCanonicalSectionProperties: (patch) => deps.canonicalOperations?.applyCanonicalSectionProperties(patch) ?? null,
|
|
50
56
|
applyCanonicalOperations: (ops) => deps.canonicalOperations?.applyCanonicalOperations(ops) ?? false,
|
|
51
57
|
getCanonicalStorySelection: (story) => deps.canonicalOperations?.getCanonicalStorySelection(story) ?? null,
|
|
52
58
|
getCanonicalStoryProjection: (story) => deps.canonicalOperations?.getCanonicalStoryProjection(story) ?? null,
|
|
53
59
|
replaceCanonicalStoryText: (options) => deps.canonicalOperations?.replaceCanonicalStoryText(options) ?? false,
|
|
60
|
+
applyCanonicalDocumentOperations: (options) => deps.canonicalOperations?.applyCanonicalDocumentOperations(options) ?? null,
|
|
61
|
+
undoCanonicalDocumentOperations: (handle) => deps.canonicalOperations?.undoCanonicalDocumentOperations(handle) ?? null,
|
|
54
62
|
focus: () => {
|
|
55
63
|
const view = deps.getView();
|
|
56
64
|
if (!view || view.hasFocus()) return;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { CanonicalGap } from "../types/canonicalCapabilities.js";
|
|
2
3
|
import { HiddenEditorApi } from "./hiddenEditorApi.js";
|
|
3
4
|
import { HiddenEditorStateReason } from "../layout-engine/layoutInstrumentation.js";
|
|
4
5
|
import { ExtensionManager } from "../prosemirror/extensions/ExtensionManager.js";
|
|
@@ -12,6 +13,7 @@ import * as YProseMirror from "y-prosemirror";
|
|
|
12
13
|
//#region src/controller/hiddenEditorManager.d.ts
|
|
13
14
|
declare const CanonicalSessionRefusalError_base: import("better-result").TaggedErrorClass<"CanonicalSessionRefusalError">;
|
|
14
15
|
declare class CanonicalSessionRefusalError extends CanonicalSessionRefusalError_base<{
|
|
16
|
+
gap: CanonicalGap;
|
|
15
17
|
message: string;
|
|
16
18
|
}> {}
|
|
17
19
|
type YProseMirrorModule = typeof YProseMirror;
|
|
@@ -63,7 +65,7 @@ type HiddenEditorManagerDeps = {
|
|
|
63
65
|
getExperimentalSession?: () => "canonical" | undefined;
|
|
64
66
|
getEditingMode?: () => EditorMode;
|
|
65
67
|
getSuggestionAuthor?: () => string;
|
|
66
|
-
onSessionRefusal?: (reason: string) => void;
|
|
68
|
+
onSessionRefusal?: (reason: string, gap: CanonicalGap, error?: Error) => void;
|
|
67
69
|
/**
|
|
68
70
|
* Identity of the loaded document as tracked by the adapter's loader: the
|
|
69
71
|
* same value across internal edits (so typing does not trigger an external
|
|
@@ -97,6 +99,8 @@ declare const createHiddenEditorClipboardHandlers: (deps: Pick<HiddenEditorManag
|
|
|
97
99
|
paste: (_view: unknown, event: PreventableDomEvent) => boolean;
|
|
98
100
|
};
|
|
99
101
|
type HiddenEditorManager = {
|
|
102
|
+
/** Whether the canonical owner still holds a provisional composition. */
|
|
103
|
+
isCanonicalComposing: () => boolean;
|
|
100
104
|
/** Request the view (sets the requested flag, then attempts creation). */
|
|
101
105
|
ensureView: () => void;
|
|
102
106
|
/** Re-attempt a previously-requested-but-deferred creation (no-op otherwise). */
|