@stll/folio-core 0.10.0 → 0.12.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 +602 -50
- package/dist/ai-edits/block-identity.d.ts +4 -0
- package/dist/ai-edits/block-identity.js +9 -0
- package/dist/ai-edits/blockRange.d.ts +28 -1
- package/dist/ai-edits/blockRange.js +67 -1
- package/dist/ai-edits/headless.d.ts +4 -4
- package/dist/ai-edits/headless.js +9 -9
- package/dist/ai-edits/index.d.ts +2 -2
- package/dist/ai-edits/index.js +2 -2
- package/dist/ai-edits/read.d.ts +7 -7
- package/dist/ai-edits/read.js +110 -3
- package/dist/ai-edits/table-cell-mutations.d.ts +48 -0
- package/dist/ai-edits/table-cell-mutations.js +237 -0
- package/dist/ai-edits/table-mutation-plan.d.ts +38 -0
- package/dist/ai-edits/table-mutation-plan.js +90 -0
- package/dist/ai-edits/table-row-column-mutations.d.ts +100 -0
- package/dist/ai-edits/table-row-column-mutations.js +300 -0
- package/dist/ai-edits/table-targets.d.ts +32 -0
- package/dist/ai-edits/table-targets.js +70 -0
- package/dist/ai-edits/types.d.ts +34 -0
- package/dist/compat/eigenpal.js +1 -1
- package/dist/content-controls/mutateContentControls.js +1 -1
- package/dist/controller/activeEditorStory.d.ts +36 -0
- package/dist/controller/activeEditorStory.js +30 -0
- package/dist/controller/collaborationModules.d.ts +7 -0
- package/dist/controller/collaborationModules.js +15 -0
- package/dist/controller/contentControlWidgetController.d.ts +55 -0
- package/dist/controller/contentControlWidgetController.js +141 -0
- package/dist/controller/folioEditor.d.ts +1 -1
- package/dist/controller/fontReadiness.js +2 -0
- package/dist/controller/headerFooterEditorManager.d.ts +41 -0
- package/dist/controller/headerFooterEditorManager.js +182 -0
- package/dist/controller/hiddenEditorApi.js +2 -2
- package/dist/controller/hiddenEditorManager.d.ts +13 -2
- package/dist/controller/hiddenEditorManager.js +32 -11
- package/dist/controller/layoutPipeline.d.ts +2 -0
- package/dist/controller/layoutPipeline.js +16 -1
- package/dist/controller/noteEditorManager.d.ts +36 -0
- package/dist/controller/noteEditorManager.js +210 -0
- package/dist/document-operations.d.ts +35 -3
- package/dist/document-operations.js +161 -3
- package/dist/docx/blockContentParser.js +2 -2
- package/dist/docx/commentParser.js +6 -1
- package/dist/docx/conformance.js +8 -1
- package/dist/docx/documentGrid.d.ts +8 -0
- package/dist/docx/documentGrid.js +8 -0
- package/dist/docx/drawingUtils.js +1 -1
- package/dist/docx/ensureParaIds.js +1 -1
- package/dist/docx/fieldParser.js +1 -1
- package/dist/docx/notePropertiesParser.js +1 -1
- package/dist/docx/numberingParser.js +1 -1
- package/dist/docx/paragraphParser.js +63 -58
- package/dist/docx/paragraphTextBoxEnrichment.d.ts +2 -1
- package/dist/docx/paragraphTextBoxEnrichment.js +67 -13
- package/dist/docx/paragraphTraversal.js +1 -1
- package/dist/docx/parser.js +3 -3
- package/dist/docx/rezip.js +1 -1
- package/dist/docx/runParser.js +4 -2
- package/dist/docx/sdtProperties.js +1 -1
- package/dist/docx/sectionParser.js +1 -1
- package/dist/docx/selectiveSave.js +1 -1
- package/dist/docx/serializer/commentSerializer.js +1 -2
- package/dist/docx/serializer/documentSerializer.js +2 -2
- package/dist/docx/serializer/headerFooterSerializer.js +2 -2
- package/dist/docx/serializer/noteSerializer.js +2 -2
- package/dist/docx/serializer/paragraphSerializer.js +7 -1
- package/dist/docx/serializer/runSerializer.js +4 -2
- package/dist/docx/serializer/stylesSerializer.js +1 -1
- package/dist/docx/serializer/tableSerializer.d.ts +5 -4
- package/dist/docx/serializer/tableSerializer.js +17 -13
- package/dist/docx/server/applyDocxXmlPatchProposal.d.ts +87 -0
- package/dist/docx/server/applyDocxXmlPatchProposal.js +204 -0
- package/dist/docx/server/boundedArchive.d.ts +14 -3
- package/dist/docx/server/boundedArchive.js +56 -11
- package/dist/docx/server/evaluateDocxXmlPatchProposal.d.ts +85 -0
- package/dist/docx/server/evaluateDocxXmlPatchProposal.js +361 -0
- package/dist/docx/server/inspectDocxPackage.d.ts +70 -0
- package/dist/docx/server/inspectDocxPackage.js +217 -0
- package/dist/docx/server/validateDocxConformance.d.ts +41 -0
- package/dist/docx/server/validateDocxConformance.js +336 -0
- package/dist/docx/settingsParser.js +11 -1
- package/dist/docx/shapeParser.js +1 -1
- package/dist/docx/styleParser.js +4 -2
- package/dist/docx/tableParser.js +18 -7
- package/dist/docx/textBoxParser.d.ts +3 -3
- package/dist/docx/textBoxParser.js +16 -12
- package/dist/docx/xmlSafety.d.ts +5 -0
- package/dist/docx/xmlSafety.js +9 -0
- package/dist/fields/resolveFieldValues.js +1 -3
- package/dist/i18n/messages/catalogs.gen.d.ts +17 -0
- package/dist/i18n/messages/catalogs.gen.js +17 -0
- package/dist/i18n/messages/messages.gen.d.ts +1 -0
- package/dist/index.js +1 -1
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +47 -40
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +3 -0
- package/dist/layout-bridge/convert/templatePreviewFlow.js +3 -3
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +4 -2
- package/dist/layout-bridge/convert/toFlowBlocks.js +136 -20
- package/dist/layout-bridge/dom/noteStoryDom.d.ts +6 -0
- package/dist/layout-bridge/dom/noteStoryDom.js +17 -0
- package/dist/layout-bridge/engine/clickToPosition.js +2 -2
- package/dist/layout-engine/index.d.ts +2 -2
- package/dist/layout-engine/index.js +43 -28
- package/dist/layout-engine/justificationCompatibility.d.ts +6 -0
- package/dist/layout-engine/justificationCompatibility.js +8 -0
- package/dist/layout-engine/keep-together.js +11 -1
- package/dist/layout-engine/measure/cache.js +21 -5
- package/dist/layout-engine/measure/lineBreakProvider.js +53 -34
- package/dist/layout-engine/measure/measureBlocks.js +6 -3
- package/dist/layout-engine/measure/measureContainer.js +1 -1
- package/dist/layout-engine/measure/measureHelpers.d.ts +1 -1
- package/dist/layout-engine/measure/measureHelpers.js +3 -3
- package/dist/layout-engine/measure/measureParagraph.js +69 -25
- package/dist/layout-engine/measure/measureProvider.js +4 -3
- package/dist/layout-engine/measure/tableCellFlow.js +5 -2
- package/dist/layout-engine/measure/textBoxParagraphLayout.d.ts +9 -7
- package/dist/layout-engine/measure/textBoxParagraphLayout.js +22 -6
- package/dist/layout-engine/measure/textMeasurementPolicy.d.ts +3 -1
- package/dist/layout-engine/measure/textMeasurementPolicy.js +7 -1
- package/dist/layout-engine/paginator.js +5 -1
- package/dist/layout-engine/paragraphSpacing.d.ts +28 -4
- package/dist/layout-engine/paragraphSpacing.js +107 -13
- package/dist/layout-engine/renderedBreakReconciliation.js +1 -1
- package/dist/layout-engine/types.d.ts +26 -13
- package/dist/layout-painter/registry/modules/textBox.js +5 -1
- package/dist/layout-painter/renderPage.d.ts +5 -2
- package/dist/layout-painter/renderPage.js +56 -12
- package/dist/layout-painter/renderParagraph.js +22 -6
- package/dist/layout-painter/renderTable.d.ts +5 -1
- package/dist/layout-painter/renderTable.js +5 -2
- package/dist/layout-painter/renderTextBox.d.ts +2 -1
- package/dist/layout-painter/renderTextBox.js +25 -14
- package/dist/managers/DocumentLoaderManager.js +1 -1
- package/dist/managers/FindReplaceManager.d.ts +8 -0
- package/dist/managers/FindReplaceManager.js +18 -0
- package/dist/managers/TableSelectionManager.d.ts +6 -0
- package/dist/managers/TableSelectionManager.js +14 -0
- package/dist/model.js +1 -1
- package/dist/prosemirror/attrs/index.d.ts +4 -2
- package/dist/prosemirror/attrs/index.js +154 -18
- package/dist/prosemirror/commands/comments.d.ts +3 -3
- package/dist/prosemirror/commands/comments.js +248 -12
- package/dist/prosemirror/commands/contentControls.js +1 -1
- package/dist/prosemirror/commands/index.js +1 -1
- package/dist/prosemirror/commands/pageBreak.js +1 -1
- package/dist/prosemirror/commands/propertyChangeScope.d.ts +2 -2
- package/dist/prosemirror/commands/propertyChangeScope.js +3 -2
- package/dist/prosemirror/commands/tableCellMergeResolution.d.ts +9 -0
- package/dist/prosemirror/commands/tableCellMergeResolution.js +181 -0
- package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +286 -61
- package/dist/prosemirror/conversion/sdtAttrs.d.ts +9 -0
- package/dist/prosemirror/conversion/sdtAttrs.js +49 -0
- package/dist/prosemirror/conversion/toProseDoc.d.ts +2 -1
- package/dist/prosemirror/conversion/toProseDoc.js +347 -98
- package/dist/prosemirror/extensions/ExtensionManager.js +1 -1
- package/dist/prosemirror/extensions/StarterKit.js +6 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +4 -1
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +1 -0
- package/dist/prosemirror/extensions/features/ListExtension.js +1 -1
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +10 -1
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +93 -2
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +2 -1
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +6 -2
- package/dist/prosemirror/extensions/marks/CharacterSpacingExtension.js +1 -1
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.d.ts +9 -1
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +24 -1
- package/dist/prosemirror/extensions/nodes/FieldExtension.js +1 -1
- package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.d.ts +7 -0
- package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.js +22 -0
- package/dist/prosemirror/extensions/nodes/TableExtension.js +9 -3
- package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.d.ts +13 -0
- package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.js +41 -0
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.d.ts +5 -2
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +4 -1
- package/dist/prosemirror/findReplaceSelection.d.ts +6 -1
- package/dist/prosemirror/findReplaceSelection.js +57 -13
- package/dist/prosemirror/plugins/contentControlWidgets.d.ts +34 -8
- package/dist/prosemirror/plugins/contentControlWidgets.js +125 -91
- package/dist/prosemirror/plugins/selectionTracker.js +1 -0
- package/dist/prosemirror/plugins/suggestionMode.js +1 -1
- package/dist/prosemirror/schema/index.d.ts +2 -2
- package/dist/prosemirror/schema/marks.d.ts +5 -1
- package/dist/prosemirror/schema/nodes.d.ts +64 -7
- package/dist/prosemirror/selectionState.js +1 -0
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
- package/dist/prosemirror/tableCellMergeRevision.d.ts +9 -0
- package/dist/prosemirror/tableCellMergeRevision.js +22 -0
- package/dist/prosemirror/textBoxAnchorAttrs.d.ts +9 -0
- package/dist/prosemirror/textBoxAnchorAttrs.js +33 -0
- package/dist/prosemirror/utils/extractTrackedChanges.d.ts +1 -1
- package/dist/prosemirror/utils/extractTrackedChanges.js +62 -14
- package/dist/prosemirror/validation.js +9 -1
- package/dist/render-dom/BodySelectionOverlay.d.ts +31 -0
- package/dist/render-dom/BodySelectionOverlay.js +76 -0
- package/dist/render-dom/HeaderFooterSelectionOverlay.d.ts +28 -0
- package/dist/render-dom/HeaderFooterSelectionOverlay.js +121 -0
- package/dist/render-dom/RemoteSelectionOverlay.d.ts +30 -0
- package/dist/render-dom/RemoteSelectionOverlay.js +67 -0
- package/dist/render-dom/RenderedDomContext.d.ts +40 -0
- package/dist/render-dom/RenderedDomContext.js +126 -0
- package/dist/render-dom/resolveSidebarItemPositions.d.ts +33 -0
- package/dist/render-dom/resolveSidebarItemPositions.js +45 -0
- package/dist/server.d.ts +6 -2
- package/dist/server.js +5 -1
- package/dist/utils/findReplace.d.ts +32 -0
- package/dist/utils/findReplace.js +118 -0
- package/dist/utils/fontFamilyMerge.js +9 -11
- package/dist/utils/fontLoader.js +3 -2
- package/dist/utils/fontResolver.js +22 -4
- package/dist/utils/fontWeights.d.ts +1 -1
- package/dist/utils/fontWeights.js +1 -1
- package/dist/utils/headerFooter.js +24 -1
- package/dist/utils/paragraphFormattingMerge.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { CONTENT_CONTROL_WIDGET_EVENT_NAME, dispatchDatePick, dispatchDropdownPick, handleContentControlWidgetClick } from "../prosemirror/plugins/contentControlWidgets.js";
|
|
2
|
+
import { Subscribable } from "../managers/Subscribable.js";
|
|
3
|
+
//#region src/controller/contentControlWidgetController.ts
|
|
4
|
+
const CLOSED_SNAPSHOT = { status: "closed" };
|
|
5
|
+
const PICKER_GAP_PX = 4;
|
|
6
|
+
const isListItem = (value) => {
|
|
7
|
+
if (typeof value !== "object" || value === null) return false;
|
|
8
|
+
if (!("displayText" in value) || !("value" in value)) return false;
|
|
9
|
+
return typeof value.displayText === "string" && typeof value.value === "string";
|
|
10
|
+
};
|
|
11
|
+
const parseContentControlListItems = (raw) => {
|
|
12
|
+
if (!raw) return [];
|
|
13
|
+
let parsed;
|
|
14
|
+
try {
|
|
15
|
+
parsed = JSON.parse(raw);
|
|
16
|
+
} catch {
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
if (!Array.isArray(parsed)) return [];
|
|
20
|
+
return parsed.filter(isListItem);
|
|
21
|
+
};
|
|
22
|
+
const pickerPosition = (event) => {
|
|
23
|
+
const rect = event.anchor.getBoundingClientRect();
|
|
24
|
+
return {
|
|
25
|
+
x: rect.left,
|
|
26
|
+
y: rect.bottom + PICKER_GAP_PX
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
const isContentControlWidgetEvent = (value) => {
|
|
30
|
+
if (typeof value !== "object" || value === null || !("kind" in value)) return false;
|
|
31
|
+
if (!("tag" in value) || typeof value.tag !== "string" || !("pmPos" in value) || typeof value.pmPos !== "number" || !("anchor" in value) || typeof value.anchor !== "object" || value.anchor === null || !("getBoundingClientRect" in value.anchor) || typeof value.anchor.getBoundingClientRect !== "function") return false;
|
|
32
|
+
if (value.kind === "dropdownOpen") return "sdtType" in value && (value.sdtType === "dropdown" || value.sdtType === "comboBox") && "listItemsJson" in value && (value.listItemsJson === void 0 || typeof value.listItemsJson === "string");
|
|
33
|
+
if (value.kind === "datePick") return "currentValue" in value && (value.currentValue === void 0 || typeof value.currentValue === "string");
|
|
34
|
+
return value.kind === "refused" && "sdtType" in value && "error" in value;
|
|
35
|
+
};
|
|
36
|
+
var ContentControlWidgetController = class extends Subscribable {
|
|
37
|
+
options;
|
|
38
|
+
view = null;
|
|
39
|
+
viewDom = null;
|
|
40
|
+
eventRoot = null;
|
|
41
|
+
ownerWindow = null;
|
|
42
|
+
constructor(options = {}) {
|
|
43
|
+
super(CLOSED_SNAPSHOT);
|
|
44
|
+
this.options = options;
|
|
45
|
+
}
|
|
46
|
+
bind(view, eventRoot = null) {
|
|
47
|
+
if (this.view === view && this.eventRoot === eventRoot) return;
|
|
48
|
+
this.unbindView();
|
|
49
|
+
this.view = view;
|
|
50
|
+
this.viewDom = view?.dom ?? null;
|
|
51
|
+
this.eventRoot = eventRoot;
|
|
52
|
+
this.viewDom?.addEventListener(CONTENT_CONTROL_WIDGET_EVENT_NAME, this.onDomEvent);
|
|
53
|
+
this.eventRoot?.addEventListener("click", this.onPaintedClick);
|
|
54
|
+
}
|
|
55
|
+
handleWidgetEvent(event) {
|
|
56
|
+
if (event.kind === "refused") {
|
|
57
|
+
this.close();
|
|
58
|
+
this.options.onRefused?.(event);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (event.kind === "dropdownOpen") {
|
|
62
|
+
this.open({
|
|
63
|
+
status: "dropdown",
|
|
64
|
+
items: parseContentControlListItems(event.listItemsJson),
|
|
65
|
+
pmPos: event.pmPos,
|
|
66
|
+
position: pickerPosition(event)
|
|
67
|
+
});
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
this.open({
|
|
71
|
+
status: "date",
|
|
72
|
+
currentValue: event.currentValue ?? null,
|
|
73
|
+
pmPos: event.pmPos,
|
|
74
|
+
position: pickerPosition(event)
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
pickDropdown(value) {
|
|
78
|
+
const snapshot = this.getSnapshot();
|
|
79
|
+
if (snapshot.status !== "dropdown" || !this.view) return false;
|
|
80
|
+
const changed = dispatchDropdownPick(this.view, snapshot.pmPos, value);
|
|
81
|
+
this.close();
|
|
82
|
+
return changed;
|
|
83
|
+
}
|
|
84
|
+
pickDate(value) {
|
|
85
|
+
const snapshot = this.getSnapshot();
|
|
86
|
+
if (snapshot.status !== "date" || !this.view || value.length === 0) return false;
|
|
87
|
+
const changed = dispatchDatePick(this.view, snapshot.pmPos, value);
|
|
88
|
+
this.close();
|
|
89
|
+
return changed;
|
|
90
|
+
}
|
|
91
|
+
close() {
|
|
92
|
+
this.removeDismissListeners();
|
|
93
|
+
if (this.getSnapshot().status !== "closed") this.setSnapshot(CLOSED_SNAPSHOT);
|
|
94
|
+
}
|
|
95
|
+
destroy() {
|
|
96
|
+
this.unbindView();
|
|
97
|
+
this.view = null;
|
|
98
|
+
}
|
|
99
|
+
onDomEvent = (event) => {
|
|
100
|
+
if (!("detail" in event)) return;
|
|
101
|
+
const detail = event.detail;
|
|
102
|
+
if (isContentControlWidgetEvent(detail)) this.handleWidgetEvent(detail);
|
|
103
|
+
};
|
|
104
|
+
onPaintedClick = (event) => {
|
|
105
|
+
if (!this.view || !isPaintedBodyClick(event.target)) return;
|
|
106
|
+
handleContentControlWidgetClick({
|
|
107
|
+
view: this.view,
|
|
108
|
+
event,
|
|
109
|
+
onEvent: (widgetEvent) => this.handleWidgetEvent(widgetEvent)
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
onKeyDown = (event) => {
|
|
113
|
+
if (event.key === "Escape") this.close();
|
|
114
|
+
};
|
|
115
|
+
onScroll = () => this.close();
|
|
116
|
+
open(snapshot) {
|
|
117
|
+
this.removeDismissListeners();
|
|
118
|
+
this.ownerWindow = this.viewDom?.ownerDocument.defaultView ?? null;
|
|
119
|
+
this.ownerWindow?.addEventListener("keydown", this.onKeyDown);
|
|
120
|
+
this.ownerWindow?.addEventListener("scroll", this.onScroll, true);
|
|
121
|
+
this.setSnapshot(snapshot);
|
|
122
|
+
}
|
|
123
|
+
removeDismissListeners() {
|
|
124
|
+
this.ownerWindow?.removeEventListener("keydown", this.onKeyDown);
|
|
125
|
+
this.ownerWindow?.removeEventListener("scroll", this.onScroll, true);
|
|
126
|
+
this.ownerWindow = null;
|
|
127
|
+
}
|
|
128
|
+
unbindView() {
|
|
129
|
+
this.close();
|
|
130
|
+
this.viewDom?.removeEventListener(CONTENT_CONTROL_WIDGET_EVENT_NAME, this.onDomEvent);
|
|
131
|
+
this.eventRoot?.removeEventListener("click", this.onPaintedClick);
|
|
132
|
+
this.viewDom = null;
|
|
133
|
+
this.eventRoot = null;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
const isPaintedBodyClick = (target) => {
|
|
137
|
+
if (typeof target !== "object" || target === null || !("closest" in target) || typeof target.closest !== "function") return false;
|
|
138
|
+
return target.closest(".layout-page-content") !== null;
|
|
139
|
+
};
|
|
140
|
+
//#endregion
|
|
141
|
+
export { ContentControlWidgetController, parseContentControlListItems };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Layout } from "../layout-engine/types.js";
|
|
2
|
-
import { FolioEditorEmitter } from "./folioEditorEvents.js";
|
|
3
2
|
import { HiddenEditorApi } from "./hiddenEditorApi.js";
|
|
3
|
+
import { FolioEditorEmitter } from "./folioEditorEvents.js";
|
|
4
4
|
import { LayoutRunOptions } from "./layoutScheduler.js";
|
|
5
5
|
import { EditorState } from "prosemirror-state";
|
|
6
6
|
|
|
@@ -11,6 +11,8 @@ function documentFontsAreLoaded() {
|
|
|
11
11
|
const INITIAL_LAYOUT_FONT_TIMEOUT_MS = 2e3;
|
|
12
12
|
const DEFAULT_LAYOUT_FONT_FAMILY = "Calibri";
|
|
13
13
|
const OFFICE_FONT_FAMILY_MAP = {
|
|
14
|
+
Aptos: "Lato",
|
|
15
|
+
"Aptos Display": "Lato",
|
|
14
16
|
Arial: "Arimo",
|
|
15
17
|
Calibri: "Carlito",
|
|
16
18
|
Cambria: "Caladea",
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { EditorView } from "prosemirror-view";
|
|
3
|
+
|
|
4
|
+
//#region src/controller/headerFooterEditorManager.d.ts
|
|
5
|
+
type HeaderFooterPartKind = "header" | "footer";
|
|
6
|
+
type HeaderFooterPartKey = {
|
|
7
|
+
kind: HeaderFooterPartKind;
|
|
8
|
+
rId: string;
|
|
9
|
+
};
|
|
10
|
+
type HeaderFooterEditorTransaction = {
|
|
11
|
+
docChanged: boolean;
|
|
12
|
+
kind: HeaderFooterPartKind;
|
|
13
|
+
rId: string;
|
|
14
|
+
selectionChanged: boolean;
|
|
15
|
+
view: EditorView;
|
|
16
|
+
};
|
|
17
|
+
type HeaderFooterEditorManagerDeps = {
|
|
18
|
+
getDocument: () => document_d_exports.Document | null;
|
|
19
|
+
getHost: () => HTMLElement | null;
|
|
20
|
+
getStyles: () => document_d_exports.StyleDefinitions | null | undefined;
|
|
21
|
+
getTheme: () => document_d_exports.Theme | null | undefined;
|
|
22
|
+
onTransaction?: ((transaction: HeaderFooterEditorTransaction) => void) | undefined;
|
|
23
|
+
};
|
|
24
|
+
type HeaderFooterEditorManager = {
|
|
25
|
+
destroy: () => void;
|
|
26
|
+
getView: (rId: string) => EditorView | null;
|
|
27
|
+
listSlots: () => HeaderFooterPartKey[];
|
|
28
|
+
snapshotDocument: (document: document_d_exports.Document) => document_d_exports.Document;
|
|
29
|
+
sync: () => void;
|
|
30
|
+
};
|
|
31
|
+
declare const enumerateHeaderFooterParts: ({
|
|
32
|
+
headers,
|
|
33
|
+
footers
|
|
34
|
+
}: {
|
|
35
|
+
headers: Map<string, document_d_exports.HeaderFooter> | undefined;
|
|
36
|
+
footers: Map<string, document_d_exports.HeaderFooter> | undefined;
|
|
37
|
+
}) => HeaderFooterPartKey[];
|
|
38
|
+
declare const enumerateDocumentHeaderFooterParts: (document: document_d_exports.Document | null) => HeaderFooterPartKey[];
|
|
39
|
+
declare const createHeaderFooterEditorManager: (deps: HeaderFooterEditorManagerDeps) => HeaderFooterEditorManager;
|
|
40
|
+
//#endregion
|
|
41
|
+
export { HeaderFooterEditorManager, HeaderFooterEditorManagerDeps, HeaderFooterEditorTransaction, HeaderFooterPartKey, HeaderFooterPartKind, createHeaderFooterEditorManager, enumerateDocumentHeaderFooterParts, enumerateHeaderFooterParts };
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { proseDocToBlocks } from "../prosemirror/conversion/fromProseDoc.js";
|
|
2
|
+
import { ExtensionManager } from "../prosemirror/extensions/ExtensionManager.js";
|
|
3
|
+
import { ensureBaseDirectionInState } from "../prosemirror/extensions/features/AutoBidiDetectionExtension.js";
|
|
4
|
+
import { createDocumentStylesPlugin } from "../prosemirror/plugins/documentStyles.js";
|
|
5
|
+
import { ensureParaIdsInState } from "../prosemirror/extensions/features/ParaIdAllocatorExtension.js";
|
|
6
|
+
import { createStarterKit } from "../prosemirror/extensions/StarterKit.js";
|
|
7
|
+
import { schema } from "../prosemirror/schema/index.js";
|
|
8
|
+
import { headerFooterToProseDoc } from "../prosemirror/conversion/toProseDoc.js";
|
|
9
|
+
import { clearHeaderFooterVerbatimXml } from "../docx/headerFooterVerbatim.js";
|
|
10
|
+
import { EditorState } from "prosemirror-state";
|
|
11
|
+
import { EditorView } from "prosemirror-view";
|
|
12
|
+
//#region src/controller/headerFooterEditorManager.ts
|
|
13
|
+
/**
|
|
14
|
+
* Framework-neutral lifecycle owner for persistent header/footer EditorViews.
|
|
15
|
+
*
|
|
16
|
+
* Each distinct relationship id owns one off-screen ProseMirror view. Painted
|
|
17
|
+
* header/footer instances that share that relationship therefore share live
|
|
18
|
+
* editor state, and adapters only decide when to synchronize or destroy the
|
|
19
|
+
* manager.
|
|
20
|
+
*/
|
|
21
|
+
const buildInitialState = (headerFooter, styles, theme, manager) => {
|
|
22
|
+
const proseDocOptions = {};
|
|
23
|
+
if (styles) proseDocOptions.styles = styles;
|
|
24
|
+
if (theme !== void 0) proseDocOptions.theme = theme;
|
|
25
|
+
const document = headerFooterToProseDoc(headerFooter.content, proseDocOptions);
|
|
26
|
+
return ensureBaseDirectionInState(ensureParaIdsInState(EditorState.create({
|
|
27
|
+
doc: document,
|
|
28
|
+
schema,
|
|
29
|
+
plugins: [...manager.getPlugins(), createDocumentStylesPlugin(styles)]
|
|
30
|
+
})));
|
|
31
|
+
};
|
|
32
|
+
const enumerateHeaderFooterParts = ({ headers, footers }) => {
|
|
33
|
+
const parts = [];
|
|
34
|
+
if (headers) for (const rId of headers.keys()) parts.push({
|
|
35
|
+
kind: "header",
|
|
36
|
+
rId
|
|
37
|
+
});
|
|
38
|
+
if (footers) {
|
|
39
|
+
for (const rId of footers.keys()) if (!headers?.has(rId)) parts.push({
|
|
40
|
+
kind: "footer",
|
|
41
|
+
rId
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return parts;
|
|
45
|
+
};
|
|
46
|
+
const enumerateDocumentHeaderFooterParts = (document) => {
|
|
47
|
+
if (!document?.package) return [];
|
|
48
|
+
return enumerateHeaderFooterParts({
|
|
49
|
+
headers: document.package.headers,
|
|
50
|
+
footers: document.package.footers
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
const resolveHeaderFooter = (document, { kind, rId }) => {
|
|
54
|
+
return (kind === "header" ? document?.package.headers : document?.package.footers)?.get(rId) ?? null;
|
|
55
|
+
};
|
|
56
|
+
const createHeaderFooterEditorManager = (deps) => {
|
|
57
|
+
const mounted = /* @__PURE__ */ new Map();
|
|
58
|
+
const destroyMounted = (part) => {
|
|
59
|
+
part.view.destroy();
|
|
60
|
+
part.manager.destroy();
|
|
61
|
+
part.mountNode.remove();
|
|
62
|
+
};
|
|
63
|
+
const destroy = () => {
|
|
64
|
+
for (const part of mounted.values()) destroyMounted(part);
|
|
65
|
+
mounted.clear();
|
|
66
|
+
};
|
|
67
|
+
const sync = () => {
|
|
68
|
+
const host = deps.getHost();
|
|
69
|
+
if (!host) return;
|
|
70
|
+
const document = deps.getDocument();
|
|
71
|
+
const styles = deps.getStyles();
|
|
72
|
+
const theme = deps.getTheme();
|
|
73
|
+
const wanted = new Map(enumerateDocumentHeaderFooterParts(document).map((part) => [part.rId, part]));
|
|
74
|
+
for (const [rId, part] of mounted) {
|
|
75
|
+
if (wanted.has(rId)) continue;
|
|
76
|
+
destroyMounted(part);
|
|
77
|
+
mounted.delete(rId);
|
|
78
|
+
}
|
|
79
|
+
for (const part of wanted.values()) {
|
|
80
|
+
const headerFooter = resolveHeaderFooter(document, part);
|
|
81
|
+
if (!headerFooter) continue;
|
|
82
|
+
const existing = mounted.get(part.rId);
|
|
83
|
+
if (existing) {
|
|
84
|
+
if (existing.mountNode.parentElement !== host) host.append(existing.mountNode);
|
|
85
|
+
const contentIsCurrent = existing.appliedHeaderFooter === headerFooter && existing.appliedContent === headerFooter.content;
|
|
86
|
+
const contextIsCurrent = existing.appliedStyles === styles && existing.appliedTheme === theme;
|
|
87
|
+
if (contentIsCurrent && contextIsCurrent) continue;
|
|
88
|
+
existing.view.updateState(buildInitialState(headerFooter, styles, theme, existing.manager));
|
|
89
|
+
existing.appliedHeaderFooter = headerFooter;
|
|
90
|
+
existing.appliedContent = headerFooter.content;
|
|
91
|
+
existing.appliedStyles = styles;
|
|
92
|
+
existing.appliedTheme = theme;
|
|
93
|
+
existing.dirty = false;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const manager = new ExtensionManager(createStarterKit());
|
|
97
|
+
manager.buildSchema();
|
|
98
|
+
manager.initializeRuntime();
|
|
99
|
+
const mountNode = host.ownerDocument.createElement("div");
|
|
100
|
+
mountNode.dataset["hfRId"] = part.rId;
|
|
101
|
+
mountNode.dataset["hfKind"] = part.kind;
|
|
102
|
+
host.append(mountNode);
|
|
103
|
+
const view = new EditorView(mountNode, {
|
|
104
|
+
state: buildInitialState(headerFooter, styles, theme, manager),
|
|
105
|
+
dispatchTransaction(transaction) {
|
|
106
|
+
const nextState = view.state.apply(transaction);
|
|
107
|
+
view.updateState(nextState);
|
|
108
|
+
const mountedPart = mounted.get(part.rId);
|
|
109
|
+
if (mountedPart && transaction.docChanged) mountedPart.dirty = true;
|
|
110
|
+
deps.onTransaction?.({
|
|
111
|
+
docChanged: transaction.docChanged,
|
|
112
|
+
kind: part.kind,
|
|
113
|
+
rId: part.rId,
|
|
114
|
+
selectionChanged: transaction.selectionSet,
|
|
115
|
+
view
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
mounted.set(part.rId, {
|
|
120
|
+
appliedContent: headerFooter.content,
|
|
121
|
+
appliedHeaderFooter: headerFooter,
|
|
122
|
+
appliedStyles: styles,
|
|
123
|
+
appliedTheme: theme,
|
|
124
|
+
dirty: false,
|
|
125
|
+
kind: part.kind,
|
|
126
|
+
manager,
|
|
127
|
+
mountNode,
|
|
128
|
+
rId: part.rId,
|
|
129
|
+
view
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
return {
|
|
134
|
+
destroy,
|
|
135
|
+
getView: (rId) => mounted.get(rId)?.view ?? null,
|
|
136
|
+
listSlots: () => [...mounted.values()].map(({ kind, rId }) => ({
|
|
137
|
+
kind,
|
|
138
|
+
rId
|
|
139
|
+
})),
|
|
140
|
+
snapshotDocument: (document) => {
|
|
141
|
+
let headers = document.package.headers;
|
|
142
|
+
let footers = document.package.footers;
|
|
143
|
+
let headersChanged = false;
|
|
144
|
+
let footersChanged = false;
|
|
145
|
+
for (const { dirty, kind, rId, view } of mounted.values()) {
|
|
146
|
+
if (!dirty) continue;
|
|
147
|
+
const source = kind === "header" ? headers : footers;
|
|
148
|
+
const existing = source?.get(rId);
|
|
149
|
+
if (!source || !existing) continue;
|
|
150
|
+
const updated = {
|
|
151
|
+
...existing,
|
|
152
|
+
content: proseDocToBlocks(view.state.doc)
|
|
153
|
+
};
|
|
154
|
+
clearHeaderFooterVerbatimXml(updated);
|
|
155
|
+
if (kind === "header") {
|
|
156
|
+
if (!headersChanged) {
|
|
157
|
+
headers = new Map(headers);
|
|
158
|
+
headersChanged = true;
|
|
159
|
+
}
|
|
160
|
+
headers?.set(rId, updated);
|
|
161
|
+
} else {
|
|
162
|
+
if (!footersChanged) {
|
|
163
|
+
footers = new Map(footers);
|
|
164
|
+
footersChanged = true;
|
|
165
|
+
}
|
|
166
|
+
footers?.set(rId, updated);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (!headersChanged && !footersChanged) return document;
|
|
170
|
+
const packageWithSnapshots = { ...document.package };
|
|
171
|
+
if (headersChanged && headers) packageWithSnapshots.headers = headers;
|
|
172
|
+
if (footersChanged && footers) packageWithSnapshots.footers = footers;
|
|
173
|
+
return {
|
|
174
|
+
...document,
|
|
175
|
+
package: packageWithSnapshots
|
|
176
|
+
};
|
|
177
|
+
},
|
|
178
|
+
sync
|
|
179
|
+
};
|
|
180
|
+
};
|
|
181
|
+
//#endregion
|
|
182
|
+
export { createHeaderFooterEditorManager, enumerateDocumentHeaderFooterParts, enumerateHeaderFooterParts };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { fromProseDoc } from "../prosemirror/conversion/fromProseDoc.js";
|
|
2
|
-
import { NodeSelection, Selection, TextSelection } from "prosemirror-state";
|
|
3
|
-
import { redo, undo } from "prosemirror-history";
|
|
4
2
|
import { CellSelection } from "prosemirror-tables";
|
|
3
|
+
import { redo, undo } from "prosemirror-history";
|
|
4
|
+
import { NodeSelection, Selection, TextSelection } from "prosemirror-state";
|
|
5
5
|
//#region src/controller/hiddenEditorApi.ts
|
|
6
6
|
/**
|
|
7
7
|
* Hidden-editor imperative API
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
|
-
import { HiddenEditorApi } from "./hiddenEditorApi.js";
|
|
3
2
|
import { HiddenEditorStateReason } from "../layout-engine/layoutInstrumentation.js";
|
|
4
3
|
import { ExtensionManager } from "../prosemirror/extensions/ExtensionManager.js";
|
|
4
|
+
import { HiddenEditorApi } from "./hiddenEditorApi.js";
|
|
5
5
|
import { EditorState, Plugin, Transaction } from "prosemirror-state";
|
|
6
6
|
import { EditorView } from "prosemirror-view";
|
|
7
7
|
import * as YProseMirror from "y-prosemirror";
|
|
@@ -72,11 +72,22 @@ type HiddenEditorManagerDeps = {
|
|
|
72
72
|
onTransaction: (transaction: Transaction, newState: EditorState) => void;
|
|
73
73
|
onSelectionChange: (state: EditorState) => void;
|
|
74
74
|
onKeyDown: (view: EditorView, event: KeyboardEvent) => boolean;
|
|
75
|
+
onCopy?: () => void;
|
|
76
|
+
onCut?: () => void;
|
|
77
|
+
onPaste?: () => void;
|
|
75
78
|
onReadOnlyEditAttempt: () => void;
|
|
76
79
|
onEditorViewReady: (view: EditorView) => void;
|
|
77
80
|
onEditorViewDestroy: () => void;
|
|
78
81
|
onRemoteSelectionsChange: (selections: HiddenProseMirrorRemoteSelection[]) => void;
|
|
79
82
|
};
|
|
83
|
+
type PreventableDomEvent = {
|
|
84
|
+
preventDefault: () => void;
|
|
85
|
+
};
|
|
86
|
+
declare const createHiddenEditorClipboardHandlers: (deps: Pick<HiddenEditorManagerDeps, "getReadOnly" | "onCopy" | "onCut" | "onPaste" | "onReadOnlyEditAttempt">) => {
|
|
87
|
+
copy: () => boolean;
|
|
88
|
+
cut: (_view: unknown, event: PreventableDomEvent) => boolean;
|
|
89
|
+
paste: (_view: unknown, event: PreventableDomEvent) => boolean;
|
|
90
|
+
};
|
|
80
91
|
type HiddenEditorManager = {
|
|
81
92
|
/** Request the view (sets the requested flag, then attempts creation). */ensureView: () => void; /** Re-attempt a previously-requested-but-deferred creation (no-op otherwise). */
|
|
82
93
|
retryViewCreation: () => void;
|
|
@@ -90,4 +101,4 @@ type HiddenEditorManager = {
|
|
|
90
101
|
};
|
|
91
102
|
declare const createHiddenEditorManager: (deps: HiddenEditorManagerDeps) => HiddenEditorManager;
|
|
92
103
|
//#endregion
|
|
93
|
-
export { CollaborationModules, CreateHiddenEditorStateOptions, HiddenEditorManager, HiddenEditorManagerDeps, HiddenProseMirrorCollaboration, HiddenProseMirrorRemoteSelection, collectRemoteSelections, createHiddenEditorManager, createHiddenEditorState };
|
|
104
|
+
export { CollaborationModules, CreateHiddenEditorStateOptions, HiddenEditorManager, HiddenEditorManagerDeps, HiddenProseMirrorCollaboration, HiddenProseMirrorRemoteSelection, collectRemoteSelections, createHiddenEditorClipboardHandlers, createHiddenEditorManager, createHiddenEditorState };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ensureBaseDirectionInState } from "../prosemirror/extensions/features/AutoBidiDetectionExtension.js";
|
|
2
2
|
import { createDocumentStylesPlugin } from "../prosemirror/plugins/documentStyles.js";
|
|
3
|
-
import { ensureParaIdsInState } from "../prosemirror/extensions/features/ParaIdAllocatorExtension.js";
|
|
3
|
+
import { ensureParaIdsInDoc, ensureParaIdsInState } from "../prosemirror/extensions/features/ParaIdAllocatorExtension.js";
|
|
4
4
|
import { schema } from "../prosemirror/schema/index.js";
|
|
5
5
|
import { createEmptyDoc, toProseDoc } from "../prosemirror/conversion/toProseDoc.js";
|
|
6
6
|
import { createHiddenEditorApi } from "./hiddenEditorApi.js";
|
|
@@ -23,6 +23,7 @@ import { EditorView } from "prosemirror-view";
|
|
|
23
23
|
* *when* to act) and drives this manager through the methods below.
|
|
24
24
|
*/
|
|
25
25
|
const normalizeSeedState = (state) => ensureBaseDirectionInState(ensureParaIdsInState(state));
|
|
26
|
+
const normalizeLocalSeedState = (state) => ensureBaseDirectionInState(state);
|
|
26
27
|
const isObjectRecord = (value) => typeof value === "object" && value !== null;
|
|
27
28
|
const isYSyncState = (value, yjs) => {
|
|
28
29
|
if (!isObjectRecord(value)) return false;
|
|
@@ -92,8 +93,9 @@ function createHiddenEditorState(options) {
|
|
|
92
93
|
if (document) {
|
|
93
94
|
const startedAt = performance.now();
|
|
94
95
|
localDoc = styles === void 0 || styles === null ? toProseDoc(document) : toProseDoc(document, { styles });
|
|
96
|
+
localDoc = ensureParaIdsInDoc(localDoc);
|
|
95
97
|
recordHiddenEditorPhase(reason, "to-prose-doc", performance.now() - startedAt);
|
|
96
|
-
}
|
|
98
|
+
} else localDoc = ensureParaIdsInDoc(localDoc);
|
|
97
99
|
const styleResolverPlugin = createDocumentStylesPlugin(styles ?? document?.package.styles);
|
|
98
100
|
const plugins = [
|
|
99
101
|
...externalPlugins,
|
|
@@ -103,7 +105,7 @@ function createHiddenEditorState(options) {
|
|
|
103
105
|
if (collaboration) {
|
|
104
106
|
if (!collaborationModules) panic("Collaboration modules must be loaded before creating collaborative editor state.");
|
|
105
107
|
if (collaboration.shouldSeed && collaboration.yXmlFragment.length === 0) {
|
|
106
|
-
const seedState =
|
|
108
|
+
const seedState = normalizeLocalSeedState(EditorState.create({
|
|
107
109
|
doc: localDoc,
|
|
108
110
|
schema: activeSchema,
|
|
109
111
|
plugins
|
|
@@ -131,7 +133,7 @@ function createHiddenEditorState(options) {
|
|
|
131
133
|
return state;
|
|
132
134
|
}
|
|
133
135
|
const startedAt = performance.now();
|
|
134
|
-
const state =
|
|
136
|
+
const state = normalizeLocalSeedState(EditorState.create({
|
|
135
137
|
doc: localDoc,
|
|
136
138
|
schema: activeSchema,
|
|
137
139
|
plugins
|
|
@@ -149,6 +151,30 @@ function syncHiddenEditorAccessibility(view, readOnly) {
|
|
|
149
151
|
if (!dom.hasAttribute("tabindex")) dom.tabIndex = 0;
|
|
150
152
|
dom.setAttribute("aria-readonly", readOnly ? "true" : "false");
|
|
151
153
|
}
|
|
154
|
+
const createHiddenEditorClipboardHandlers = (deps) => ({
|
|
155
|
+
copy: () => {
|
|
156
|
+
deps.onCopy?.();
|
|
157
|
+
return false;
|
|
158
|
+
},
|
|
159
|
+
cut: (_view, event) => {
|
|
160
|
+
if (!deps.getReadOnly()) {
|
|
161
|
+
deps.onCut?.();
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
deps.onReadOnlyEditAttempt();
|
|
165
|
+
event.preventDefault();
|
|
166
|
+
return true;
|
|
167
|
+
},
|
|
168
|
+
paste: (_view, event) => {
|
|
169
|
+
if (!deps.getReadOnly()) {
|
|
170
|
+
deps.onPaste?.();
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
deps.onReadOnlyEditAttempt();
|
|
174
|
+
event.preventDefault();
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
});
|
|
152
178
|
const createHiddenEditorManager = (deps) => {
|
|
153
179
|
let view = null;
|
|
154
180
|
let isDestroying = false;
|
|
@@ -207,18 +233,13 @@ const createHiddenEditorManager = (deps) => {
|
|
|
207
233
|
handleDOMEvents: {
|
|
208
234
|
focus: () => false,
|
|
209
235
|
blur: () => false,
|
|
236
|
+
...createHiddenEditorClipboardHandlers(deps),
|
|
210
237
|
beforeinput: (_view, event) => {
|
|
211
238
|
if (!deps.getReadOnly()) return false;
|
|
212
239
|
deps.onReadOnlyEditAttempt();
|
|
213
240
|
event.preventDefault();
|
|
214
241
|
return true;
|
|
215
242
|
},
|
|
216
|
-
paste: (_view, event) => {
|
|
217
|
-
if (!deps.getReadOnly()) return false;
|
|
218
|
-
deps.onReadOnlyEditAttempt();
|
|
219
|
-
event.preventDefault();
|
|
220
|
-
return true;
|
|
221
|
-
},
|
|
222
243
|
drop: (_view, event) => {
|
|
223
244
|
if (!deps.getReadOnly()) return false;
|
|
224
245
|
deps.onReadOnlyEditAttempt();
|
|
@@ -305,4 +326,4 @@ const createHiddenEditorManager = (deps) => {
|
|
|
305
326
|
};
|
|
306
327
|
};
|
|
307
328
|
//#endregion
|
|
308
|
-
export { collectRemoteSelections, createHiddenEditorManager, createHiddenEditorState };
|
|
329
|
+
export { collectRemoteSelections, createHiddenEditorClipboardHandlers, createHiddenEditorManager, createHiddenEditorState };
|
|
@@ -31,6 +31,8 @@ type LayoutPipelineDeps<THfPMs> = {
|
|
|
31
31
|
};
|
|
32
32
|
margins: PageMargins;
|
|
33
33
|
pageGap: number;
|
|
34
|
+
showMarginGuides: boolean;
|
|
35
|
+
marginGuideColor: string | undefined;
|
|
34
36
|
syncCoordinator: LayoutSelectionGate;
|
|
35
37
|
headerContent: document_d_exports.HeaderFooter | null | undefined;
|
|
36
38
|
footerContent: document_d_exports.HeaderFooter | null | undefined;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import "../layout-engine/types.js";
|
|
2
|
+
import { resolveEffectiveParagraphSpacingTree } from "../layout-engine/paragraphSpacing.js";
|
|
2
3
|
import { renderPages } from "../layout-painter/renderPage.js";
|
|
3
4
|
import { templatePreviewValuesKey } from "../prosemirror/plugins/templatePreviewValues.js";
|
|
5
|
+
import { resolveDocumentGridLinePitch } from "../docx/documentGrid.js";
|
|
4
6
|
import { getMargins, getPageSize, twipsToPixels } from "../paged-layout/sectionGeometry.js";
|
|
5
7
|
import { getColumns } from "../layout-bridge/sectionColumns.js";
|
|
6
8
|
import { toFlowBlocks } from "../layout-bridge/convert/toFlowBlocks.js";
|
|
@@ -14,6 +16,7 @@ import { installCanvasMeasureProvider } from "../layout-engine/measure/measureCo
|
|
|
14
16
|
import { buildFootnoteContentMap, collectEndnoteRefs, collectFootnoteRefs, computeNoteDisplayNumbers, remapNoteMarkerText } from "../layout-bridge/convert/footnoteLayout.js";
|
|
15
17
|
import { applyTemplatePreviewToBlocks } from "../layout-bridge/convert/templatePreviewFlow.js";
|
|
16
18
|
import { layoutDocument } from "../layout-engine/index.js";
|
|
19
|
+
import { resolveJustificationCompatibility } from "../layout-engine/justificationCompatibility.js";
|
|
17
20
|
import { measureBlocks, measureSingleBlockWithoutFloatingZones } from "../layout-engine/measure/measureBlocks.js";
|
|
18
21
|
import { tryBuildIncrementalMeasures } from "../paged-layout/incrementalMeasure.js";
|
|
19
22
|
import { computePerBlockMeasureInputs } from "../paged-layout/sectionBlockWidths.js";
|
|
@@ -56,7 +59,7 @@ function bodyBlocksClearSectionHeaderFooter(blocks, { authoredMargins, sectionHe
|
|
|
56
59
|
return changed ? nextBlocks : blocks;
|
|
57
60
|
}
|
|
58
61
|
function runLayoutPipeline(deps, state, options = {}) {
|
|
59
|
-
const { contentWidth, columns, pageSize, margins, pageGap, syncCoordinator, headerContent, footerContent, firstPageHeaderContent, firstPageFooterContent, headerContentRId, footerContentRId, firstPageHeaderContentRId, firstPageFooterContentRId, sectionHeaderFooterRefs, theme: _theme, sectionProperties, document, defaultTabStop, mirrorMargins, styles, layout, hfPMs, painter, pagesContainer, session, renderHfFromContentOrPm, renderHeaderFooterContentByRId, documentFontsAreLoaded, buildFootnoteRenderItems, describeInvalidHighlightMarks, emptyTemplatePreviewEntries: EMPTY_TEMPLATE_PREVIEW_ENTRIES } = deps;
|
|
62
|
+
const { contentWidth, columns, pageSize, margins, pageGap, showMarginGuides, marginGuideColor, syncCoordinator, headerContent, footerContent, firstPageHeaderContent, firstPageFooterContent, headerContentRId, footerContentRId, firstPageHeaderContentRId, firstPageFooterContentRId, sectionHeaderFooterRefs, theme: _theme, sectionProperties, document, defaultTabStop, mirrorMargins, styles, layout, hfPMs, painter, pagesContainer, session, renderHfFromContentOrPm, renderHeaderFooterContentByRId, documentFontsAreLoaded, buildFootnoteRenderItems, describeInvalidHighlightMarks, emptyTemplatePreviewEntries: EMPTY_TEMPLATE_PREVIEW_ENTRIES } = deps;
|
|
60
63
|
let outcome = {};
|
|
61
64
|
let pendingArtifacts;
|
|
62
65
|
let pendingTemplatePreview;
|
|
@@ -75,12 +78,16 @@ function runLayoutPipeline(deps, state, options = {}) {
|
|
|
75
78
|
if (defaultTabStop !== void 0) flowOpts.defaultTabStopTwips = defaultTabStop;
|
|
76
79
|
if (document?.package.settings?.lineBreakRules) flowOpts.lineBreakRules = document.package.settings.lineBreakRules;
|
|
77
80
|
const documentSettings = document?.package.settings;
|
|
81
|
+
const justificationCompatibility = resolveJustificationCompatibility(documentSettings?.compatibilityMode);
|
|
82
|
+
if (justificationCompatibility) flowOpts.justificationCompatibility = justificationCompatibility;
|
|
78
83
|
if (documentSettings?.autoHyphenation === true) flowOpts.automaticHyphenation = {
|
|
79
84
|
enabled: true,
|
|
80
85
|
...documentSettings.doNotHyphenateCaps !== void 0 ? { doNotHyphenateCaps: documentSettings.doNotHyphenateCaps } : {},
|
|
81
86
|
...documentSettings.consecutiveHyphenLimit !== void 0 ? { consecutiveLineLimit: documentSettings.consecutiveHyphenLimit } : {},
|
|
82
87
|
...documentSettings.hyphenationZoneTwips !== void 0 ? { hyphenationZoneTwips: documentSettings.hyphenationZoneTwips } : {}
|
|
83
88
|
};
|
|
89
|
+
const finalSectionDocumentGridLinePitchTwips = resolveDocumentGridLinePitch(document?.package.document.sections?.at(-1)?.properties.docGrid);
|
|
90
|
+
if (finalSectionDocumentGridLinePitchTwips !== void 0) flowOpts.finalSectionDocumentGridLinePitchTwips = finalSectionDocumentGridLinePitchTwips;
|
|
84
91
|
let newBlocks = toFlowBlocks(state.doc, flowOpts);
|
|
85
92
|
const previewState = templatePreviewValuesKey.getState(state);
|
|
86
93
|
const previewEntries = previewState?.entries ?? EMPTY_TEMPLATE_PREVIEW_ENTRIES;
|
|
@@ -127,6 +134,7 @@ function runLayoutPipeline(deps, state, options = {}) {
|
|
|
127
134
|
measureBlocks: hfMeasureBlocks,
|
|
128
135
|
...defaultTabStop !== void 0 ? { defaultTabStopTwips: defaultTabStop } : {},
|
|
129
136
|
...flowOpts.lineBreakRules ? { lineBreakRules: flowOpts.lineBreakRules } : {},
|
|
137
|
+
...flowOpts.justificationCompatibility ? { justificationCompatibility: flowOpts.justificationCompatibility } : {},
|
|
130
138
|
...flowOpts.automaticHyphenation ? { automaticHyphenation: flowOpts.automaticHyphenation } : {}
|
|
131
139
|
};
|
|
132
140
|
};
|
|
@@ -209,6 +217,8 @@ function runLayoutPipeline(deps, state, options = {}) {
|
|
|
209
217
|
marginRight: blockMeasureInputs.marginRights,
|
|
210
218
|
marginBottom: blockMeasureInputs.marginBottoms
|
|
211
219
|
});
|
|
220
|
+
newBlocks = resolveEffectiveParagraphSpacingTree(newBlocks);
|
|
221
|
+
outcome.blocks = newBlocks;
|
|
212
222
|
pendingArtifacts = {
|
|
213
223
|
blocks: newBlocks,
|
|
214
224
|
blockWidths,
|
|
@@ -256,6 +266,7 @@ function runLayoutPipeline(deps, state, options = {}) {
|
|
|
256
266
|
if (_theme !== void 0) footnoteOptions.theme = _theme;
|
|
257
267
|
if (defaultTabStop !== void 0) footnoteOptions.defaultTabStopTwips = defaultTabStop;
|
|
258
268
|
if (flowOpts.lineBreakRules) footnoteOptions.lineBreakRules = flowOpts.lineBreakRules;
|
|
269
|
+
if (flowOpts.justificationCompatibility) footnoteOptions.justificationCompatibility = flowOpts.justificationCompatibility;
|
|
259
270
|
if (flowOpts.automaticHyphenation) footnoteOptions.automaticHyphenation = flowOpts.automaticHyphenation;
|
|
260
271
|
return footnoteOptions;
|
|
261
272
|
})());
|
|
@@ -372,6 +383,10 @@ function runLayoutPipeline(deps, state, options = {}) {
|
|
|
372
383
|
blockLookup,
|
|
373
384
|
titlePg: hasTitlePg
|
|
374
385
|
};
|
|
386
|
+
if (showMarginGuides) {
|
|
387
|
+
renderOpts.showMarginGuides = true;
|
|
388
|
+
if (marginGuideColor !== void 0) renderOpts.marginGuideColor = marginGuideColor;
|
|
389
|
+
}
|
|
375
390
|
if (headerContentForRender) renderOpts.headerContent = headerContentForRender;
|
|
376
391
|
if (footerContentForRender) renderOpts.footerContent = footerContentForRender;
|
|
377
392
|
if (firstPageHeaderForRender) renderOpts.firstPageHeaderContent = firstPageHeaderForRender;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { Plugin } from "prosemirror-state";
|
|
3
|
+
import { EditorView } from "prosemirror-view";
|
|
4
|
+
|
|
5
|
+
//#region src/controller/noteEditorManager.d.ts
|
|
6
|
+
type NoteStoryKind = "footnote" | "endnote";
|
|
7
|
+
type NoteStoryKey = {
|
|
8
|
+
kind: NoteStoryKind;
|
|
9
|
+
noteId: number;
|
|
10
|
+
};
|
|
11
|
+
type NoteEditorTransaction = NoteStoryKey & {
|
|
12
|
+
docChanged: boolean;
|
|
13
|
+
selectionChanged: boolean;
|
|
14
|
+
view: EditorView;
|
|
15
|
+
};
|
|
16
|
+
type NoteEditorManagerDeps = {
|
|
17
|
+
getDocument: () => document_d_exports.Document | null;
|
|
18
|
+
getHost: () => HTMLElement | null;
|
|
19
|
+
getPlugins?: (() => Plugin[]) | undefined;
|
|
20
|
+
getStyles: () => document_d_exports.StyleDefinitions | null | undefined;
|
|
21
|
+
getTheme: () => document_d_exports.Theme | null | undefined;
|
|
22
|
+
onTransaction?: ((transaction: NoteEditorTransaction) => void) | undefined;
|
|
23
|
+
};
|
|
24
|
+
type NoteEditorManager = {
|
|
25
|
+
activate: (story: NoteStoryKey | null) => EditorView | null;
|
|
26
|
+
destroy: () => void;
|
|
27
|
+
getActive: () => NoteStoryKey | null;
|
|
28
|
+
getView: (story: NoteStoryKey) => EditorView | null;
|
|
29
|
+
listStories: () => NoteStoryKey[];
|
|
30
|
+
snapshotDocument: (document: document_d_exports.Document) => document_d_exports.Document;
|
|
31
|
+
sync: () => void;
|
|
32
|
+
};
|
|
33
|
+
declare const enumerateDocumentNoteStories: (document: document_d_exports.Document | null) => NoteStoryKey[];
|
|
34
|
+
declare const createNoteEditorManager: (deps: NoteEditorManagerDeps) => NoteEditorManager;
|
|
35
|
+
//#endregion
|
|
36
|
+
export { NoteEditorManager, NoteEditorManagerDeps, NoteEditorTransaction, NoteStoryKey, NoteStoryKind, createNoteEditorManager, enumerateDocumentNoteStories };
|