@stll/folio-core 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-edits/apply.d.ts +2 -1
- package/dist/ai-edits/apply.js +693 -63
- 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 +68 -2
- package/dist/ai-edits/clean-text.js +2 -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/snapshot.js +21 -3
- package/dist/ai-edits/table-cell-mutations.d.ts +48 -0
- package/dist/ai-edits/table-cell-mutations.js +238 -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 +108 -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 +62 -1
- package/dist/ai-edits/word-diff.js +21 -0
- package/dist/compat/eigenpal.d.ts +3 -3
- package/dist/compat/eigenpal.js +3 -3
- 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/contentControlWidgetController.d.ts +55 -0
- package/dist/controller/contentControlWidgetController.js +141 -0
- package/dist/controller/fontReadiness.js +2 -0
- package/dist/controller/headerFooterEditorManager.js +2 -2
- package/dist/controller/hiddenEditorApi.js +2 -2
- package/dist/controller/hiddenEditorManager.d.ts +12 -1
- package/dist/controller/hiddenEditorManager.js +44 -12
- package/dist/controller/layoutPipeline.d.ts +2 -0
- package/dist/controller/layoutPipeline.js +17 -2
- package/dist/controller/noteEditorManager.d.ts +36 -0
- package/dist/controller/noteEditorManager.js +210 -0
- package/dist/document-operations.d.ts +43 -11
- package/dist/document-operations.js +186 -18
- package/dist/docx/blockContentParser.js +21 -7
- package/dist/docx/commentParser.js +6 -1
- package/dist/docx/commentRangeIntegrity.d.ts +6 -0
- package/dist/docx/commentRangeIntegrity.js +186 -0
- package/dist/docx/conformance.js +62 -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/encryption/agileDecryption.js +12 -2
- package/dist/docx/encryption/compoundFile.js +6 -1
- package/dist/docx/encryption/encryptionInfo.d.ts +9 -1
- package/dist/docx/encryption/encryptionInfo.js +18 -2
- package/dist/docx/encryption/openEncryptedDocx.js +1 -1
- package/dist/docx/ensureParaIds.js +8 -7
- package/dist/docx/fieldParser.js +1 -1
- package/dist/docx/groupDrawingParser.js +10 -5
- package/dist/docx/hyperlinkParser.js +1 -1
- package/dist/docx/imageParser.js +10 -6
- package/dist/docx/metadataPrivacy.js +17 -3
- package/dist/docx/notePropertiesParser.js +1 -1
- package/dist/docx/numberingParser.js +1 -1
- package/dist/docx/paragraphParser.js +70 -61
- 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 +20 -9
- package/dist/docx/runParser.js +17 -6
- package/dist/docx/sdtProperties.js +1 -1
- package/dist/docx/sectionParser.js +18 -5
- package/dist/docx/selectiveSave.js +5 -1
- package/dist/docx/selectiveXmlPatch.d.ts +22 -1
- package/dist/docx/selectiveXmlPatch.js +61 -1
- package/dist/docx/serializer/blockSdtSerializer.js +3 -2
- package/dist/docx/serializer/commentSerializer.js +5 -6
- 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 +23 -15
- package/dist/docx/serializer/runSerializer.js +25 -21
- package/dist/docx/serializer/sectionPropertiesSerializer.js +2 -1
- package/dist/docx/serializer/stylesSerializer.js +1 -1
- package/dist/docx/serializer/tableSerializer.d.ts +5 -4
- package/dist/docx/serializer/tableSerializer.js +26 -20
- package/dist/docx/serializer/xmlUtils.d.ts +13 -1
- package/dist/docx/serializer/xmlUtils.js +27 -1
- 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/extractDocxText.js +55 -8
- 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 +26 -3
- package/dist/docx/shapeParser.js +1 -1
- package/dist/docx/styleParser.js +4 -2
- package/dist/docx/tableParser.d.ts +8 -1
- package/dist/docx/tableParser.js +31 -10
- package/dist/docx/textBoxParser.d.ts +3 -3
- package/dist/docx/textBoxParser.js +16 -12
- package/dist/docx/unzip.js +1 -0
- package/dist/docx/vmlImageParser.js +11 -3
- package/dist/docx/xmlParser.js +11 -1
- package/dist/docx/xmlSafety.d.ts +5 -0
- package/dist/docx/xmlSafety.js +9 -0
- package/dist/fields/resolveFieldValues.js +1 -3
- package/dist/fonts/embeddedFonts.d.ts +33 -5
- package/dist/fonts/embeddedFonts.js +37 -8
- 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.d.ts +3 -3
- package/dist/index.js +3 -3
- 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 +151 -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 +58 -30
- 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 +23 -5
- package/dist/layout-engine/measure/effectiveLineBreakPolicy.js +8 -2
- package/dist/layout-engine/measure/lineBreakProvider.d.ts +2 -2
- package/dist/layout-engine/measure/lineBreakProvider.js +56 -37
- package/dist/layout-engine/measure/measureBlocks.js +15 -4
- package/dist/layout-engine/measure/measureContainer.js +1 -1
- package/dist/layout-engine/measure/measureHelpers.d.ts +11 -2
- package/dist/layout-engine/measure/measureHelpers.js +15 -4
- package/dist/layout-engine/measure/measureParagraph.js +85 -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 +48 -15
- package/dist/layout-painter/registry/modules/textBox.js +5 -1
- package/dist/layout-painter/renderImage.d.ts +12 -1
- package/dist/layout-painter/renderImage.js +21 -4
- package/dist/layout-painter/renderPage.d.ts +5 -2
- package/dist/layout-painter/renderPage.js +59 -14
- package/dist/layout-painter/renderParagraph.js +55 -15
- package/dist/layout-painter/renderTable.d.ts +5 -1
- package/dist/layout-painter/renderTable.js +7 -3
- package/dist/layout-painter/renderTextBox.d.ts +2 -1
- package/dist/layout-painter/renderTextBox.js +25 -14
- package/dist/layout-painter/renderWatermark.d.ts +1 -1
- package/dist/layout-painter/renderWatermark.js +2 -1
- package/dist/managers/DocumentLoaderManager.js +1 -1
- package/dist/markdown/fromMarkdown.js +1 -1
- package/dist/model.js +1 -1
- package/dist/prosemirror/attrs/index.d.ts +4 -2
- package/dist/prosemirror/attrs/index.js +175 -18
- package/dist/prosemirror/commands/comments.d.ts +79 -4
- package/dist/prosemirror/commands/comments.js +622 -13
- package/dist/prosemirror/commands/contentControls.js +1 -1
- package/dist/prosemirror/commands/hyperlink.js +15 -1
- package/dist/prosemirror/commands/image.js +7 -1
- package/dist/prosemirror/commands/index.d.ts +2 -2
- package/dist/prosemirror/commands/index.js +2 -2
- 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/commentIdAllocator.js +13 -3
- package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +404 -62
- package/dist/prosemirror/conversion/index.js +1 -1
- 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 +364 -103
- package/dist/prosemirror/extensions/ExtensionManager.js +1 -1
- package/dist/prosemirror/extensions/StarterKit.js +6 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +6 -2
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +1 -0
- package/dist/prosemirror/extensions/features/ImagePasteExtension.js +10 -2
- 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/features/pasteCleanup.js +15 -2
- package/dist/prosemirror/extensions/marks/CharacterSpacingExtension.js +1 -1
- package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +30 -4
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.d.ts +9 -1
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +70 -11
- 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.d.ts +1 -1
- package/dist/prosemirror/extensions/nodes/TableExtension.js +14 -6
- 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/index.d.ts +1 -1
- package/dist/prosemirror/index.js +1 -1
- package/dist/prosemirror/plugins/contentControlWidgets.d.ts +36 -10
- package/dist/prosemirror/plugins/contentControlWidgets.js +128 -94
- package/dist/prosemirror/plugins/revisionIds.d.ts +23 -0
- package/dist/prosemirror/plugins/revisionIds.js +57 -0
- package/dist/prosemirror/plugins/selectionTracker.js +1 -0
- package/dist/prosemirror/plugins/suggestionMode.js +5 -4
- package/dist/prosemirror/runFormattingMarkNames.d.ts +14 -0
- package/dist/prosemirror/runFormattingMarkNames.js +40 -0
- package/dist/prosemirror/schema/index.d.ts +2 -2
- package/dist/prosemirror/schema/marks.d.ts +30 -3
- package/dist/prosemirror/schema/marks.js +15 -0
- package/dist/prosemirror/schema/nodes.d.ts +111 -6
- 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/RemoteSelectionOverlay.js +2 -2
- package/dist/server.d.ts +7 -3
- package/dist/server.js +7 -3
- package/dist/utils/clipboard.d.ts +10 -1
- package/dist/utils/clipboard.js +33 -6
- package/dist/utils/colorResolver.d.ts +8 -1
- package/dist/utils/colorResolver.js +35 -5
- package/dist/utils/fontFamilyMerge.js +9 -11
- package/dist/utils/fontLoader.js +3 -2
- package/dist/utils/fontResolver.d.ts +2 -1
- package/dist/utils/fontResolver.js +31 -7
- package/dist/utils/fontWeights.d.ts +1 -1
- package/dist/utils/fontWeights.js +1 -1
- package/dist/utils/hexId.d.ts +11 -1
- package/dist/utils/hexId.js +11 -1
- package/dist/utils/paragraphFormattingMerge.js +1 -0
- package/dist/utils/sanitizeImageSrc.d.ts +21 -0
- package/dist/utils/sanitizeImageSrc.js +30 -0
- package/dist/utils/stripXmlDeclarations.d.ts +11 -0
- package/dist/utils/stripXmlDeclarations.js +35 -0
- package/dist/version-comparison.d.ts +22 -2
- package/dist/version-comparison.js +41 -12
- package/dist/watermark/index.d.ts +11 -1
- package/dist/watermark/index.js +22 -1
- package/package.json +3 -2
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_WIDTH_TYPE_VALUES } from "../../../types/documentEnumValues.js";
|
|
2
2
|
import { expectTableAttrs, expectTableCellAttrs, expectTableRowAttrs, mergeTableAttrs, mergeTableCellAttrs, mergeTableRowAttrs } from "../../attrs/index.js";
|
|
3
3
|
import { createExtension, createNodeExtension } from "../create.js";
|
|
4
|
-
import { resolveColor } from "../../../utils/colorResolver.js";
|
|
4
|
+
import { isValidHexColor, resolveColor } from "../../../utils/colorResolver.js";
|
|
5
5
|
import { panic } from "better-result";
|
|
6
|
-
import { Plugin, PluginKey, Selection, TextSelection } from "prosemirror-state";
|
|
7
6
|
import { CellSelection, TableMap, columnResizing, mergeCells, removeRow, selectedRect, splitCell, tableEditing } from "prosemirror-tables";
|
|
7
|
+
import { Plugin, PluginKey, Selection, TextSelection } from "prosemirror-state";
|
|
8
8
|
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
9
9
|
//#region src/prosemirror/extensions/nodes/TableExtension.ts
|
|
10
10
|
/**
|
|
@@ -127,7 +127,8 @@ function parseCellAttrsFromDOM(element) {
|
|
|
127
127
|
const margins = extractCellMarginsFromCSS(style);
|
|
128
128
|
const rawValign = element.dataset["valign"];
|
|
129
129
|
const verticalAlign = (rawValign === "top" || rawValign === "center" || rawValign === "bottom" ? rawValign : void 0) ?? mapCssVerticalAlign(style.verticalAlign) ?? void 0;
|
|
130
|
-
const
|
|
130
|
+
const rawBgColor = element.dataset["bgcolor"];
|
|
131
|
+
const backgroundColor = (isValidHexColor(rawBgColor) ? rawBgColor : void 0) || parseCssColorToHex(style.backgroundColor) || void 0;
|
|
131
132
|
return {
|
|
132
133
|
colspan: Number(element.getAttribute("colspan") ?? "1") || 1,
|
|
133
134
|
rowspan: Number(element.getAttribute("rowspan") ?? "1") || 1,
|
|
@@ -154,7 +155,8 @@ const tableSpec = {
|
|
|
154
155
|
borders: { default: null },
|
|
155
156
|
_resolvedIndent: { default: null },
|
|
156
157
|
_originalFormatting: { default: null },
|
|
157
|
-
tblPrChange: { default: null }
|
|
158
|
+
tblPrChange: { default: null },
|
|
159
|
+
_suggestedInsert: { default: null }
|
|
158
160
|
},
|
|
159
161
|
parseDOM: [{
|
|
160
162
|
tag: "table",
|
|
@@ -190,7 +192,7 @@ const tableSpec = {
|
|
|
190
192
|
}
|
|
191
193
|
};
|
|
192
194
|
const tableRowSpec = {
|
|
193
|
-
content: "(tableCell | tableHeader)
|
|
195
|
+
content: "(tableCell | tableHeader)*",
|
|
194
196
|
tableRole: "row",
|
|
195
197
|
attrs: {
|
|
196
198
|
height: { default: null },
|
|
@@ -198,7 +200,9 @@ const tableRowSpec = {
|
|
|
198
200
|
isHeader: { default: false },
|
|
199
201
|
hidden: { default: false },
|
|
200
202
|
_originalFormatting: { default: null },
|
|
201
|
-
trPrChange: { default: null }
|
|
203
|
+
trPrChange: { default: null },
|
|
204
|
+
trIns: { default: null },
|
|
205
|
+
trDel: { default: null }
|
|
202
206
|
},
|
|
203
207
|
parseDOM: [{ tag: "tr" }],
|
|
204
208
|
toDOM(node) {
|
|
@@ -315,8 +319,10 @@ const tableCellSpec = {
|
|
|
315
319
|
margins: { default: null },
|
|
316
320
|
textDirection: { default: null },
|
|
317
321
|
noWrap: { default: false },
|
|
322
|
+
hideMark: { default: false },
|
|
318
323
|
_originalFormatting: { default: null },
|
|
319
324
|
tcPrChange: { default: null },
|
|
325
|
+
cellMarker: { default: null },
|
|
320
326
|
_preserveVMergeRestart: { default: null },
|
|
321
327
|
_docxVMergeContinuationCells: { default: null }
|
|
322
328
|
},
|
|
@@ -369,8 +375,10 @@ const tableHeaderSpec = {
|
|
|
369
375
|
margins: { default: null },
|
|
370
376
|
textDirection: { default: null },
|
|
371
377
|
noWrap: { default: false },
|
|
378
|
+
hideMark: { default: false },
|
|
372
379
|
_originalFormatting: { default: null },
|
|
373
380
|
tcPrChange: { default: null },
|
|
381
|
+
cellMarker: { default: null },
|
|
374
382
|
_preserveVMergeRestart: { default: null },
|
|
375
383
|
_docxVMergeContinuationCells: { default: null }
|
|
376
384
|
},
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { NodeExtension } from "../types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/prosemirror/extensions/nodes/TextBoxAnchorExtension.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Zero-width inline anchor for a text box extracted to a sibling PM block.
|
|
6
|
+
*
|
|
7
|
+
* Keeping the anchor in the paragraph lets ordinary ProseMirror transactions
|
|
8
|
+
* map its position as surrounding text is edited. The save conversion consumes
|
|
9
|
+
* it when the sibling text box is restored to the DOCX run stream.
|
|
10
|
+
*/
|
|
11
|
+
declare const TextBoxAnchorExtension: (options?: Partial<Record<string, unknown>> | undefined) => NodeExtension;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { TextBoxAnchorExtension };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { expectTextBoxAnchorAttrs } from "../../textBoxAnchorAttrs.js";
|
|
2
|
+
import { createNodeExtension } from "../create.js";
|
|
3
|
+
//#region src/prosemirror/extensions/nodes/TextBoxAnchorExtension.ts
|
|
4
|
+
/**
|
|
5
|
+
* Zero-width inline anchor for a text box extracted to a sibling PM block.
|
|
6
|
+
*
|
|
7
|
+
* Keeping the anchor in the paragraph lets ordinary ProseMirror transactions
|
|
8
|
+
* map its position as surrounding text is edited. The save conversion consumes
|
|
9
|
+
* it when the sibling text box is restored to the DOCX run stream.
|
|
10
|
+
*/
|
|
11
|
+
const TextBoxAnchorExtension = createNodeExtension({
|
|
12
|
+
name: "textBoxAnchor",
|
|
13
|
+
schemaNodeName: "textBoxAnchor",
|
|
14
|
+
nodeSpec: {
|
|
15
|
+
inline: true,
|
|
16
|
+
group: "inline",
|
|
17
|
+
marks: "_",
|
|
18
|
+
atom: true,
|
|
19
|
+
selectable: false,
|
|
20
|
+
attrs: { anchorId: {} },
|
|
21
|
+
parseDOM: [{
|
|
22
|
+
tag: "span[data-docx-textbox-anchor]",
|
|
23
|
+
getAttrs(dom) {
|
|
24
|
+
if (!(dom instanceof HTMLElement)) return false;
|
|
25
|
+
const anchorId = dom.dataset["docxTextboxAnchor"];
|
|
26
|
+
return anchorId ? { anchorId } : false;
|
|
27
|
+
}
|
|
28
|
+
}],
|
|
29
|
+
toDOM(node) {
|
|
30
|
+
const { anchorId } = expectTextBoxAnchorAttrs(node);
|
|
31
|
+
return ["span", {
|
|
32
|
+
"data-docx-textbox-anchor": anchorId,
|
|
33
|
+
"aria-hidden": "true",
|
|
34
|
+
contenteditable: "false",
|
|
35
|
+
style: "display: inline-block; width: 0; height: 0; overflow: hidden; pointer-events: none;"
|
|
36
|
+
}];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
//#endregion
|
|
41
|
+
export { TextBoxAnchorExtension };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { document_d_exports } from "../../../types/document.js";
|
|
2
2
|
import { OutlineStyleAttr } from "../../../types/documentEnumValues.js";
|
|
3
3
|
import { NodeExtension } from "../types.js";
|
|
4
|
-
import { ImagePositionAttrs } from "../../schema/nodes.js";
|
|
4
|
+
import { ImagePositionAttrs, TextBoxAttrs as TextBoxAttrs$1 } from "../../schema/nodes.js";
|
|
5
5
|
|
|
6
6
|
//#region src/prosemirror/extensions/nodes/TextBoxExtension.d.ts
|
|
7
7
|
type TextBoxAttrs = {
|
|
@@ -28,7 +28,10 @@ type TextBoxAttrs = {
|
|
|
28
28
|
distRight?: number; /** Position for floating/anchored text boxes. */
|
|
29
29
|
position?: ImagePositionAttrs; /** Original DOCX placement hint for save-path reconstruction. */
|
|
30
30
|
_docxPlacement?: "standalone" | "inlineWithPrevious"; /** Original DOCX paragraph group for standalone text-box reconstruction. */
|
|
31
|
-
_docxGroupId?: string;
|
|
31
|
+
_docxGroupId?: string; /** Inline anchor linking this block node to its source run position. */
|
|
32
|
+
_docxAnchorId?: string; /** Original run-level revision wrapper for save-path reconstruction. */
|
|
33
|
+
_docxTrackedChange?: TextBoxAttrs$1["_docxTrackedChange"]; /** Original inline content-control ancestry for save-path reconstruction. */
|
|
34
|
+
_docxInlineSdts?: TextBoxAttrs$1["_docxInlineSdts"];
|
|
32
35
|
};
|
|
33
36
|
declare const TextBoxExtension: (options?: Partial<Record<string, unknown>> | undefined) => NodeExtension;
|
|
34
37
|
//#endregion
|
|
@@ -50,7 +50,10 @@ const TextBoxExtension = createNodeExtension({
|
|
|
50
50
|
distRight: { default: null },
|
|
51
51
|
position: { default: null },
|
|
52
52
|
_docxPlacement: { default: null },
|
|
53
|
-
_docxGroupId: { default: null }
|
|
53
|
+
_docxGroupId: { default: null },
|
|
54
|
+
_docxAnchorId: { default: null },
|
|
55
|
+
_docxTrackedChange: { default: null },
|
|
56
|
+
_docxInlineSdts: { default: null }
|
|
54
57
|
},
|
|
55
58
|
parseDOM: [{
|
|
56
59
|
tag: "div.docx-textbox",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ImageAttrs, ParagraphAttrs } from "./schema/nodes.js";
|
|
2
1
|
import { FontFamilyAttrs, FontSizeAttrs, HyperlinkAttrs, TextColorAttrs, UnderlineAttrs } from "./schema/marks.js";
|
|
2
|
+
import { ImageAttrs, ParagraphAttrs } from "./schema/nodes.js";
|
|
3
3
|
import { schema, singletonManager } from "./schema/index.js";
|
|
4
4
|
import { PAINTABLE_MARK_NAMES, applyFormatMarks, captureFormatMarks } from "./commands/formatPainter.js";
|
|
5
5
|
import { clearFormatting, getMarkAttr, isMarkActive } from "./extensions/marks/markUtils.js";
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { assertValidProseMirrorDocument, formatProseMirrorDocumentIssues, validateProseMirrorDocument } from "./validation.js";
|
|
2
|
-
import { fromProseDoc, updateDocumentContent } from "./conversion/fromProseDoc.js";
|
|
3
2
|
import { StyleResolver, createStyleResolver } from "./styles/styleResolver.js";
|
|
4
3
|
import { getParagraphAlignment, getParagraphBidi, getStyleId } from "./extensions/core/ParagraphExtension.js";
|
|
5
4
|
import { createDocumentStylesPlugin, documentStylesKey, getDocumentStyleResolver } from "./plugins/documentStyles.js";
|
|
@@ -11,6 +10,7 @@ import { createSelectionTrackerPlugin, extractSelectionContext, getSelectionCont
|
|
|
11
10
|
import { getHyperlinkAttrs, getSelectedText, isHyperlinkActive } from "./extensions/marks/HyperlinkExtension.js";
|
|
12
11
|
import { schema, singletonManager } from "./schema/index.js";
|
|
13
12
|
import { createEmptyDoc, toProseDoc } from "./conversion/toProseDoc.js";
|
|
13
|
+
import { fromProseDoc, updateDocumentContent } from "./conversion/fromProseDoc.js";
|
|
14
14
|
import { addColumnLeft, addColumnRight, addRowAbove, addRowBelow, applyTableStyle, autoFitContents, deleteColumn, deleteRow, deleteTable, distributeColumns, insertTable, mergeCells, removeTableBorders, selectColumn, selectRow, selectTable, setAllTableBorders, setCellBorder, setCellFillColor, setCellMargins, setCellTextDirection, setCellVerticalAlign, setInsideTableBorders, setOutsideTableBorders, setRowHeight, setTableBorderColor, setTableBorderPreset, setTableBorderWidth, setTableBorders, setTableProperties, splitCell, toggleHeaderRow, toggleNoWrap } from "./commands/table.js";
|
|
15
15
|
import { extractSelectionState } from "./selectionState.js";
|
|
16
16
|
import { clearFontFamily, clearFontSize, clearHighlight, clearTextColor, insertHyperlink, removeHyperlink, setFontFamily, setFontSize, setHighlight, setHyperlink, setTextColor, toggleBold, toggleItalic, toggleStrike, toggleSubscript, toggleSuperscript, toggleUnderline } from "./commands/formatting.js";
|
|
@@ -1,20 +1,26 @@
|
|
|
1
|
-
import { ContentControlLockedError, ContentControlTypeError } from "../../content-controls/errors.js";
|
|
1
|
+
import { ContentControlBoundError, ContentControlLockedError, ContentControlTypeError } from "../../content-controls/errors.js";
|
|
2
2
|
import { Plugin, PluginKey } from "prosemirror-state";
|
|
3
3
|
import { EditorView } from "prosemirror-view";
|
|
4
4
|
|
|
5
5
|
//#region src/prosemirror/plugins/contentControlWidgets.d.ts
|
|
6
|
+
type ContentControlWidgetAnchor = {
|
|
7
|
+
getBoundingClientRect: () => {
|
|
8
|
+
bottom: number;
|
|
9
|
+
left: number;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
6
12
|
type ContentControlWidgetEvent = {
|
|
7
13
|
kind: "dropdownOpen";
|
|
8
14
|
tag: string; /** PM position of the clicked SDT instance — disambiguates duplicates. */
|
|
9
15
|
pmPos: number;
|
|
10
16
|
sdtType: "dropdown" | "comboBox";
|
|
11
|
-
anchor:
|
|
17
|
+
anchor: ContentControlWidgetAnchor;
|
|
12
18
|
listItemsJson: string | undefined;
|
|
13
19
|
} | {
|
|
14
20
|
kind: "datePick";
|
|
15
21
|
tag: string;
|
|
16
22
|
pmPos: number;
|
|
17
|
-
anchor:
|
|
23
|
+
anchor: ContentControlWidgetAnchor;
|
|
18
24
|
currentValue: string | undefined;
|
|
19
25
|
} | {
|
|
20
26
|
/**
|
|
@@ -26,21 +32,41 @@ type ContentControlWidgetEvent = {
|
|
|
26
32
|
tag: string;
|
|
27
33
|
pmPos: number;
|
|
28
34
|
sdtType: string;
|
|
29
|
-
anchor:
|
|
30
|
-
error: ContentControlLockedError | ContentControlTypeError;
|
|
35
|
+
anchor: ContentControlWidgetAnchor;
|
|
36
|
+
error: ContentControlLockedError | ContentControlTypeError | ContentControlBoundError;
|
|
31
37
|
};
|
|
32
38
|
type ContentControlWidgetCallback = (event: ContentControlWidgetEvent) => void;
|
|
39
|
+
type ContentControlWidgetClickEvent = {
|
|
40
|
+
preventDefault: () => void;
|
|
41
|
+
target: unknown;
|
|
42
|
+
};
|
|
43
|
+
type ContentControlWidgetView = Pick<EditorView, "dispatch" | "state">;
|
|
44
|
+
type HandleContentControlWidgetClickOptions = {
|
|
45
|
+
event: ContentControlWidgetClickEvent;
|
|
46
|
+
onEvent: ContentControlWidgetCallback;
|
|
47
|
+
view: ContentControlWidgetView;
|
|
48
|
+
};
|
|
33
49
|
declare const contentControlWidgetsPluginKey: PluginKey<unknown>;
|
|
34
50
|
/**
|
|
35
51
|
* CustomEvent name dispatched on the editor view DOM whenever the plugin
|
|
36
|
-
* needs to surface a `ContentControlWidgetEvent` to
|
|
37
|
-
*
|
|
52
|
+
* needs to surface a `ContentControlWidgetEvent` to an adapter shell. The
|
|
53
|
+
* adapter subscribes via `addEventListener` and renders the matching chrome.
|
|
38
54
|
*
|
|
39
|
-
* Using a CustomEvent keeps the plugin
|
|
40
|
-
*
|
|
55
|
+
* Using a CustomEvent keeps the plugin framework-neutral and makes the
|
|
56
|
+
* adapter's responsibility explicit: receive event → render UI →
|
|
41
57
|
* call dispatchDropdownPick / dispatchDatePick.
|
|
42
58
|
*/
|
|
43
59
|
declare const CONTENT_CONTROL_WIDGET_EVENT_NAME = "folio:content-control-widget";
|
|
60
|
+
/**
|
|
61
|
+
* Interpret one click from either the live ProseMirror DOM or the painted page
|
|
62
|
+
* tree. Both surfaces carry the same `data-sdt-*` projection, so adapters only
|
|
63
|
+
* need to forward the click and render the resulting typed event.
|
|
64
|
+
*/
|
|
65
|
+
declare const handleContentControlWidgetClick: ({
|
|
66
|
+
event,
|
|
67
|
+
onEvent,
|
|
68
|
+
view
|
|
69
|
+
}: HandleContentControlWidgetClickOptions) => boolean;
|
|
44
70
|
declare function createContentControlWidgetsPlugin(onEvent?: ContentControlWidgetCallback): Plugin;
|
|
45
71
|
/**
|
|
46
72
|
* Stable resolver helpers exposed for the UI shell so a popover menu or
|
|
@@ -53,4 +79,4 @@ declare function createContentControlWidgetsPlugin(onEvent?: ContentControlWidge
|
|
|
53
79
|
declare function dispatchDropdownPick(view: EditorView, pmPos: number, value: string): boolean;
|
|
54
80
|
declare function dispatchDatePick(view: EditorView, pmPos: number, date: string): boolean;
|
|
55
81
|
//#endregion
|
|
56
|
-
export { CONTENT_CONTROL_WIDGET_EVENT_NAME, ContentControlWidgetCallback, ContentControlWidgetEvent, contentControlWidgetsPluginKey, createContentControlWidgetsPlugin, dispatchDatePick, dispatchDropdownPick };
|
|
82
|
+
export { CONTENT_CONTROL_WIDGET_EVENT_NAME, ContentControlWidgetAnchor, ContentControlWidgetCallback, ContentControlWidgetEvent, contentControlWidgetsPluginKey, createContentControlWidgetsPlugin, dispatchDatePick, dispatchDropdownPick, handleContentControlWidgetClick };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ContentControlLockedError, ContentControlTypeError } from "../../content-controls/errors.js";
|
|
1
|
+
import { ContentControlBoundError, ContentControlLockedError, ContentControlTypeError } from "../../content-controls/errors.js";
|
|
2
2
|
import { findBlockSdtMatch, setContentControlValueTr } from "../commands/contentControls.js";
|
|
3
3
|
import { Plugin, PluginKey } from "prosemirror-state";
|
|
4
4
|
//#region src/prosemirror/plugins/contentControlWidgets.ts
|
|
@@ -19,18 +19,129 @@ import { Plugin, PluginKey } from "prosemirror-state";
|
|
|
19
19
|
const contentControlWidgetsPluginKey = new PluginKey("contentControlWidgets");
|
|
20
20
|
/**
|
|
21
21
|
* CustomEvent name dispatched on the editor view DOM whenever the plugin
|
|
22
|
-
* needs to surface a `ContentControlWidgetEvent` to
|
|
23
|
-
*
|
|
22
|
+
* needs to surface a `ContentControlWidgetEvent` to an adapter shell. The
|
|
23
|
+
* adapter subscribes via `addEventListener` and renders the matching chrome.
|
|
24
24
|
*
|
|
25
|
-
* Using a CustomEvent keeps the plugin
|
|
26
|
-
*
|
|
25
|
+
* Using a CustomEvent keeps the plugin framework-neutral and makes the
|
|
26
|
+
* adapter's responsibility explicit: receive event → render UI →
|
|
27
27
|
* call dispatchDropdownPick / dispatchDatePick.
|
|
28
28
|
*/
|
|
29
29
|
const CONTENT_CONTROL_WIDGET_EVENT_NAME = "folio:content-control-widget";
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
const SDT_DATASET_KEY = {
|
|
31
|
+
checked: "sdtChecked",
|
|
32
|
+
listItems: "sdtListItems",
|
|
33
|
+
pmPos: "sdtPmPos",
|
|
34
|
+
tag: "sdtTag",
|
|
35
|
+
type: "sdtType"
|
|
36
|
+
};
|
|
37
|
+
const SDT_TYPE = {
|
|
38
|
+
checkbox: "checkbox",
|
|
39
|
+
comboBox: "comboBox",
|
|
40
|
+
date: "date",
|
|
41
|
+
dropdown: "dropdown"
|
|
42
|
+
};
|
|
43
|
+
const SDT_TYPE_SELECTOR = "[data-sdt-type]";
|
|
44
|
+
const findClosest = (target, selector) => {
|
|
45
|
+
if (typeof target !== "object" || target === null || !("closest" in target) || typeof target.closest !== "function") return null;
|
|
46
|
+
return target.closest(selector);
|
|
47
|
+
};
|
|
48
|
+
const isContentControlWidgetElement = (value) => {
|
|
49
|
+
if (typeof value !== "object" || value === null || !("dataset" in value) || typeof value.dataset !== "object" || value.dataset === null || !("getBoundingClientRect" in value) || typeof value.getBoundingClientRect !== "function") return false;
|
|
50
|
+
return true;
|
|
51
|
+
};
|
|
52
|
+
const findSdtAncestor = (target) => {
|
|
53
|
+
const candidate = findClosest(target, SDT_TYPE_SELECTOR);
|
|
54
|
+
return isContentControlWidgetElement(candidate) ? candidate : null;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Interpret one click from either the live ProseMirror DOM or the painted page
|
|
58
|
+
* tree. Both surfaces carry the same `data-sdt-*` projection, so adapters only
|
|
59
|
+
* need to forward the click and render the resulting typed event.
|
|
60
|
+
*/
|
|
61
|
+
const handleContentControlWidgetClick = ({ event, onEvent, view }) => {
|
|
62
|
+
const anchor = findSdtAncestor(event.target);
|
|
63
|
+
if (!anchor) return false;
|
|
64
|
+
const tag = anchor.dataset[SDT_DATASET_KEY.tag] ?? "";
|
|
65
|
+
const sdtType = anchor.dataset[SDT_DATASET_KEY.type];
|
|
66
|
+
const pmPosRaw = anchor.dataset[SDT_DATASET_KEY.pmPos];
|
|
67
|
+
const pmPos = pmPosRaw ? Number.parseInt(pmPosRaw, 10) : NaN;
|
|
68
|
+
if (!sdtType || Number.isNaN(pmPos)) return false;
|
|
69
|
+
try {
|
|
70
|
+
if (sdtType === SDT_TYPE.checkbox) {
|
|
71
|
+
const current = anchor.dataset[SDT_DATASET_KEY.checked] === "true";
|
|
72
|
+
const tr = setContentControlValueTr(view.state, { pmPos }, {
|
|
73
|
+
kind: SDT_TYPE.checkbox,
|
|
74
|
+
checked: !current
|
|
75
|
+
});
|
|
76
|
+
if (tr) {
|
|
77
|
+
view.dispatch(tr);
|
|
78
|
+
event.preventDefault();
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
} else if (sdtType === SDT_TYPE.dropdown || sdtType === SDT_TYPE.comboBox) {
|
|
82
|
+
const refusal = lockRefusalFor(view, pmPos);
|
|
83
|
+
if (refusal) {
|
|
84
|
+
onEvent({
|
|
85
|
+
kind: "refused",
|
|
86
|
+
tag,
|
|
87
|
+
pmPos,
|
|
88
|
+
sdtType,
|
|
89
|
+
anchor,
|
|
90
|
+
error: refusal
|
|
91
|
+
});
|
|
92
|
+
event.preventDefault();
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
onEvent({
|
|
96
|
+
kind: "dropdownOpen",
|
|
97
|
+
tag,
|
|
98
|
+
pmPos,
|
|
99
|
+
sdtType,
|
|
100
|
+
anchor,
|
|
101
|
+
listItemsJson: anchor.dataset[SDT_DATASET_KEY.listItems]
|
|
102
|
+
});
|
|
103
|
+
event.preventDefault();
|
|
104
|
+
return true;
|
|
105
|
+
} else if (sdtType === SDT_TYPE.date) {
|
|
106
|
+
const refusal = lockRefusalFor(view, pmPos);
|
|
107
|
+
if (refusal) {
|
|
108
|
+
onEvent({
|
|
109
|
+
kind: "refused",
|
|
110
|
+
tag,
|
|
111
|
+
pmPos,
|
|
112
|
+
sdtType,
|
|
113
|
+
anchor,
|
|
114
|
+
error: refusal
|
|
115
|
+
});
|
|
116
|
+
event.preventDefault();
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
onEvent({
|
|
120
|
+
kind: "datePick",
|
|
121
|
+
tag,
|
|
122
|
+
pmPos,
|
|
123
|
+
anchor,
|
|
124
|
+
currentValue: findBlockSdtMatch(view.state.doc, { pmPos })?.node.textContent
|
|
125
|
+
});
|
|
126
|
+
event.preventDefault();
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
} catch (error) {
|
|
130
|
+
if (error instanceof ContentControlLockedError || error instanceof ContentControlTypeError || error instanceof ContentControlBoundError) {
|
|
131
|
+
onEvent({
|
|
132
|
+
kind: "refused",
|
|
133
|
+
tag,
|
|
134
|
+
pmPos,
|
|
135
|
+
sdtType,
|
|
136
|
+
anchor,
|
|
137
|
+
error
|
|
138
|
+
});
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
throw error;
|
|
142
|
+
}
|
|
143
|
+
return false;
|
|
144
|
+
};
|
|
34
145
|
function createContentControlWidgetsPlugin(onEvent = () => void 0) {
|
|
35
146
|
const emit = (view, payload) => {
|
|
36
147
|
onEvent(payload);
|
|
@@ -42,88 +153,11 @@ function createContentControlWidgetsPlugin(onEvent = () => void 0) {
|
|
|
42
153
|
return new Plugin({
|
|
43
154
|
key: contentControlWidgetsPluginKey,
|
|
44
155
|
props: { handleDOMEvents: { click(view, event) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const pmPos = pmPosRaw ? Number.parseInt(pmPosRaw, 10) : NaN;
|
|
51
|
-
if (!sdtType || Number.isNaN(pmPos)) return false;
|
|
52
|
-
try {
|
|
53
|
-
if (sdtType === "checkbox") {
|
|
54
|
-
const current = anchor.dataset["sdtChecked"] === "true";
|
|
55
|
-
const tr = setContentControlValueTr(view.state, { pmPos }, {
|
|
56
|
-
kind: "checkbox",
|
|
57
|
-
checked: !current
|
|
58
|
-
});
|
|
59
|
-
if (tr) {
|
|
60
|
-
view.dispatch(tr);
|
|
61
|
-
event.preventDefault();
|
|
62
|
-
return true;
|
|
63
|
-
}
|
|
64
|
-
} else if (sdtType === "dropdown" || sdtType === "comboBox") {
|
|
65
|
-
const refusal = lockRefusalFor(view, pmPos);
|
|
66
|
-
if (refusal) {
|
|
67
|
-
emit(view, {
|
|
68
|
-
kind: "refused",
|
|
69
|
-
tag,
|
|
70
|
-
pmPos,
|
|
71
|
-
sdtType,
|
|
72
|
-
anchor,
|
|
73
|
-
error: refusal
|
|
74
|
-
});
|
|
75
|
-
event.preventDefault();
|
|
76
|
-
return true;
|
|
77
|
-
}
|
|
78
|
-
emit(view, {
|
|
79
|
-
kind: "dropdownOpen",
|
|
80
|
-
tag,
|
|
81
|
-
pmPos,
|
|
82
|
-
sdtType,
|
|
83
|
-
anchor,
|
|
84
|
-
listItemsJson: anchor.dataset["sdtListItems"]
|
|
85
|
-
});
|
|
86
|
-
event.preventDefault();
|
|
87
|
-
return true;
|
|
88
|
-
} else if (sdtType === "date") {
|
|
89
|
-
const refusal = lockRefusalFor(view, pmPos);
|
|
90
|
-
if (refusal) {
|
|
91
|
-
emit(view, {
|
|
92
|
-
kind: "refused",
|
|
93
|
-
tag,
|
|
94
|
-
pmPos,
|
|
95
|
-
sdtType,
|
|
96
|
-
anchor,
|
|
97
|
-
error: refusal
|
|
98
|
-
});
|
|
99
|
-
event.preventDefault();
|
|
100
|
-
return true;
|
|
101
|
-
}
|
|
102
|
-
emit(view, {
|
|
103
|
-
kind: "datePick",
|
|
104
|
-
tag,
|
|
105
|
-
pmPos,
|
|
106
|
-
anchor,
|
|
107
|
-
currentValue: void 0
|
|
108
|
-
});
|
|
109
|
-
event.preventDefault();
|
|
110
|
-
return true;
|
|
111
|
-
}
|
|
112
|
-
} catch (error) {
|
|
113
|
-
if (error instanceof ContentControlLockedError || error instanceof ContentControlTypeError) {
|
|
114
|
-
emit(view, {
|
|
115
|
-
kind: "refused",
|
|
116
|
-
tag,
|
|
117
|
-
pmPos,
|
|
118
|
-
sdtType,
|
|
119
|
-
anchor,
|
|
120
|
-
error
|
|
121
|
-
});
|
|
122
|
-
return true;
|
|
123
|
-
}
|
|
124
|
-
throw error;
|
|
125
|
-
}
|
|
126
|
-
return false;
|
|
156
|
+
return handleContentControlWidgetClick({
|
|
157
|
+
view,
|
|
158
|
+
event,
|
|
159
|
+
onEvent: (payload) => emit(view, payload)
|
|
160
|
+
});
|
|
127
161
|
} } },
|
|
128
162
|
view() {
|
|
129
163
|
return {};
|
|
@@ -149,7 +183,7 @@ function dispatchDropdownPick(view, pmPos, value) {
|
|
|
149
183
|
view.dispatch(tr);
|
|
150
184
|
return true;
|
|
151
185
|
} catch (error) {
|
|
152
|
-
if (error instanceof ContentControlLockedError || error instanceof ContentControlTypeError) return false;
|
|
186
|
+
if (error instanceof ContentControlLockedError || error instanceof ContentControlTypeError || error instanceof ContentControlBoundError) return false;
|
|
153
187
|
throw error;
|
|
154
188
|
}
|
|
155
189
|
}
|
|
@@ -163,7 +197,7 @@ function dispatchDatePick(view, pmPos, date) {
|
|
|
163
197
|
view.dispatch(tr);
|
|
164
198
|
return true;
|
|
165
199
|
} catch (error) {
|
|
166
|
-
if (error instanceof ContentControlLockedError || error instanceof ContentControlTypeError) return false;
|
|
200
|
+
if (error instanceof ContentControlLockedError || error instanceof ContentControlTypeError || error instanceof ContentControlBoundError) return false;
|
|
167
201
|
throw error;
|
|
168
202
|
}
|
|
169
203
|
}
|
|
@@ -189,4 +223,4 @@ function lockRefusalFor(view, pmPos) {
|
|
|
189
223
|
});
|
|
190
224
|
}
|
|
191
225
|
//#endregion
|
|
192
|
-
export { CONTENT_CONTROL_WIDGET_EVENT_NAME, contentControlWidgetsPluginKey, createContentControlWidgetsPlugin, dispatchDatePick, dispatchDropdownPick };
|
|
226
|
+
export { CONTENT_CONTROL_WIDGET_EVENT_NAME, contentControlWidgetsPluginKey, createContentControlWidgetsPlugin, dispatchDatePick, dispatchDropdownPick, handleContentControlWidgetClick };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Node } from "prosemirror-model";
|
|
2
|
+
|
|
3
|
+
//#region src/prosemirror/plugins/revisionIds.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Mint the next tracked-revision id (`w:id`). Strictly monotonic per realm,
|
|
6
|
+
* and always inside the range serialized `w:id` may occupy.
|
|
7
|
+
*/
|
|
8
|
+
declare function mintRevisionId(): number;
|
|
9
|
+
/**
|
|
10
|
+
* Raise the counter above `maxId` so freshly minted ids cannot collide with
|
|
11
|
+
* ids already present in a loaded document. Only ever raises.
|
|
12
|
+
*
|
|
13
|
+
* `maxId` is derived from file content, so it is untrusted: a malformed or
|
|
14
|
+
* out-of-range value is ignored outright rather than folded into range.
|
|
15
|
+
*/
|
|
16
|
+
declare function seedRevisionIdsAbove(maxId: number): void;
|
|
17
|
+
/**
|
|
18
|
+
* Raise the counter above every revision id already present in `doc`.
|
|
19
|
+
* Called from the suggestion-mode plugin's `state.init`.
|
|
20
|
+
*/
|
|
21
|
+
declare function seedRevisionIdsFromDoc(doc: Node): void;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { mintRevisionId, seedRevisionIdsAbove, seedRevisionIdsFromDoc };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { MAX_REVISION_ID } from "@stll/docx-core/model";
|
|
2
|
+
//#region src/prosemirror/plugins/revisionIds.ts
|
|
3
|
+
/**
|
|
4
|
+
* Next id to hand out. Starts at 1 (0 is the serializer's "unusable metadata"
|
|
5
|
+
* fallback) and is raised past a loaded document's existing ids by
|
|
6
|
+
* `seedRevisionIdsAbove`.
|
|
7
|
+
*
|
|
8
|
+
* NOT seeded from a clock. `Date.now()` (~1.8e12) overflows the signed 32-bit
|
|
9
|
+
* int consumers read `w:id` into.
|
|
10
|
+
*/
|
|
11
|
+
let counter = 1;
|
|
12
|
+
/**
|
|
13
|
+
* Mint the next tracked-revision id (`w:id`). Strictly monotonic per realm,
|
|
14
|
+
* and always inside the range serialized `w:id` may occupy.
|
|
15
|
+
*/
|
|
16
|
+
function mintRevisionId() {
|
|
17
|
+
if (counter > MAX_REVISION_ID) counter = 1;
|
|
18
|
+
return counter++;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Raise the counter above `maxId` so freshly minted ids cannot collide with
|
|
22
|
+
* ids already present in a loaded document. Only ever raises.
|
|
23
|
+
*
|
|
24
|
+
* `maxId` is derived from file content, so it is untrusted: a malformed or
|
|
25
|
+
* out-of-range value is ignored outright rather than folded into range.
|
|
26
|
+
*/
|
|
27
|
+
function seedRevisionIdsAbove(maxId) {
|
|
28
|
+
if (!Number.isInteger(maxId) || maxId < 0 || maxId >= MAX_REVISION_ID) return;
|
|
29
|
+
if (maxId >= counter) counter = maxId + 1;
|
|
30
|
+
}
|
|
31
|
+
/** Node attrs that carry a revision id directly (`revisionId` field). */
|
|
32
|
+
const DIRECT_REVISION_ATTR_KEYS = ["trIns", "trDel"];
|
|
33
|
+
/**
|
|
34
|
+
* Raise the counter above every revision id already present in `doc`.
|
|
35
|
+
* Called from the suggestion-mode plugin's `state.init`.
|
|
36
|
+
*/
|
|
37
|
+
function seedRevisionIdsFromDoc(doc) {
|
|
38
|
+
let max = 0;
|
|
39
|
+
const consider = (id) => {
|
|
40
|
+
if (typeof id === "number" && Number.isInteger(id) && id > max && id <= MAX_REVISION_ID) max = id;
|
|
41
|
+
};
|
|
42
|
+
doc.descendants((node) => {
|
|
43
|
+
for (const mark of node.marks) consider(mark.attrs["revisionId"]);
|
|
44
|
+
const attrs = node.attrs;
|
|
45
|
+
const pPrMark = attrs["pPrMark"];
|
|
46
|
+
if (pPrMark?.info) consider(pPrMark.info.id);
|
|
47
|
+
for (const key of DIRECT_REVISION_ATTR_KEYS) {
|
|
48
|
+
const value = attrs[key];
|
|
49
|
+
if (value) consider(value.revisionId);
|
|
50
|
+
}
|
|
51
|
+
const cellMarker = attrs["cellMarker"];
|
|
52
|
+
if (cellMarker?.info) consider(cellMarker.info.revisionId);
|
|
53
|
+
});
|
|
54
|
+
seedRevisionIdsAbove(max);
|
|
55
|
+
}
|
|
56
|
+
//#endregion
|
|
57
|
+
export { mintRevisionId, seedRevisionIdsAbove, seedRevisionIdsFromDoc };
|
|
@@ -36,6 +36,7 @@ function extractSelectionContext(state) {
|
|
|
36
36
|
paragraphFormatting.lineSpacing = paragraph.attrs["lineSpacing"];
|
|
37
37
|
paragraphFormatting.lineSpacingRule = paragraph.attrs["lineSpacingRule"];
|
|
38
38
|
}
|
|
39
|
+
if (typeof paragraph.attrs["snapToGrid"] === "boolean") paragraphFormatting.snapToGrid = paragraph.attrs["snapToGrid"];
|
|
39
40
|
if (paragraph.attrs["indentLeft"]) paragraphFormatting.indentLeft = paragraph.attrs["indentLeft"];
|
|
40
41
|
if (paragraph.attrs["indentRight"]) paragraphFormatting.indentRight = paragraph.attrs["indentRight"];
|
|
41
42
|
if (paragraph.attrs["indentFirstLine"]) paragraphFormatting.indentFirstLine = paragraph.attrs["indentFirstLine"];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { splitBlockClearBorders } from "../extensions/features/BaseKeymapExtension.js";
|
|
2
|
-
import {
|
|
2
|
+
import { mintRevisionId, seedRevisionIdsFromDoc } from "./revisionIds.js";
|
|
3
3
|
import { isHistoryTransaction } from "prosemirror-history";
|
|
4
|
+
import { Plugin, PluginKey, TextSelection } from "prosemirror-state";
|
|
4
5
|
//#region src/prosemirror/plugins/suggestionMode.ts
|
|
5
6
|
/**
|
|
6
7
|
* Suggestion Mode Plugin
|
|
@@ -17,10 +18,9 @@ import { isHistoryTransaction } from "prosemirror-history";
|
|
|
17
18
|
const suggestionModeKey = new PluginKey("suggestionMode");
|
|
18
19
|
const SUGGESTION_META = "suggestionModeApplied";
|
|
19
20
|
const SUGGESTION_BYPASS_META = "suggestionModeBypass";
|
|
20
|
-
let nextRevisionId = Date.now();
|
|
21
21
|
function makeMarkAttrs(pluginState) {
|
|
22
22
|
return {
|
|
23
|
-
revisionId:
|
|
23
|
+
revisionId: mintRevisionId(),
|
|
24
24
|
author: pluginState.author,
|
|
25
25
|
date: (/* @__PURE__ */ new Date()).toISOString()
|
|
26
26
|
};
|
|
@@ -340,7 +340,8 @@ function createSuggestionModePlugin(initialActive = false, author = "User") {
|
|
|
340
340
|
return new Plugin({
|
|
341
341
|
key: suggestionModeKey,
|
|
342
342
|
state: {
|
|
343
|
-
init() {
|
|
343
|
+
init(_config, instance) {
|
|
344
|
+
seedRevisionIdsFromDoc(instance.doc);
|
|
344
345
|
return {
|
|
345
346
|
active: initialActive,
|
|
346
347
|
author
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/prosemirror/runFormattingMarkNames.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Names of the marks that carry run-level (character) formatting.
|
|
4
|
+
*
|
|
5
|
+
* Single source of truth shared by every place that must swap a run's live
|
|
6
|
+
* formatting back to a previously recorded set: rejecting a `runPropertyChange`
|
|
7
|
+
* (commands/comments.ts) and stripping a *suggested* `runPropertyChange` at the
|
|
8
|
+
* serialization boundary (conversion/fromProseDoc.ts). Keeping one list makes
|
|
9
|
+
* it structurally impossible for the two paths to drift and let a formatting
|
|
10
|
+
* mark survive a revert.
|
|
11
|
+
*/
|
|
12
|
+
declare const RUN_FORMATTING_MARK_NAMES: Set<string>;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { RUN_FORMATTING_MARK_NAMES };
|