@harbour-enterprises/superdoc 0.22.0-next.8 → 0.22.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/chunks/{PdfViewer-C1tow4Hk.es.js → PdfViewer-BNWaI4WI.es.js} +1 -1
- package/dist/chunks/{PdfViewer-BBQm50V3.cjs → PdfViewer-DpkgwUPi.cjs} +1 -1
- package/dist/chunks/{index-BkpP-c9A.cjs → index-BbGPYtNy.cjs} +16 -9
- package/dist/chunks/{index-CJUwCOxd.es.js → index-DWKEKmiB.es.js} +16 -9
- package/dist/chunks/{super-editor.es-Bg0-F_x5.es.js → super-editor.es-BVxfhpAJ.es.js} +1562 -1267
- package/dist/chunks/{super-editor.es-D6u8E2n4.cjs → super-editor.es-BoUJEZaF.cjs} +1562 -1267
- package/dist/core/types/index.d.ts.map +1 -1
- package/dist/stores/comments-store.d.ts +4 -1
- package/dist/stores/comments-store.d.ts.map +1 -1
- package/dist/style.css +45 -44
- package/dist/super-editor/ai-writer.es.js +2 -2
- package/dist/super-editor/chunks/{converter-BgedUNCW.js → converter-C-yWLpFM.js} +150 -105
- package/dist/super-editor/chunks/{docx-zipper-ByLK3trM.js → docx-zipper-CmGlSUQM.js} +1 -1
- package/dist/super-editor/chunks/{editor-M2L6bDyC.js → editor-BBnC1DzI.js} +1532 -1280
- package/dist/super-editor/chunks/{toolbar-DsPK5x8a.js → toolbar-QJANo61B.js} +2 -2
- package/dist/super-editor/converter.es.js +1 -1
- package/dist/super-editor/docx-zipper.es.js +2 -2
- package/dist/super-editor/editor.es.js +3 -3
- package/dist/super-editor/file-zipper.es.js +1 -1
- package/dist/super-editor/src/core/helpers/generateDocxRandomId.d.ts +5 -0
- package/dist/super-editor/src/extensions/index.d.ts +2 -1
- package/dist/super-editor/src/extensions/structured-content/index.d.ts +1 -0
- package/dist/super-editor/src/extensions/structured-content/structured-content-commands.d.ts +67 -0
- package/dist/super-editor/src/extensions/structured-content/structuredContentHelpers/getStructuredContentBlockTags.d.ts +6 -0
- package/dist/super-editor/src/extensions/structured-content/structuredContentHelpers/getStructuredContentInlineTags.d.ts +6 -0
- package/dist/super-editor/src/extensions/structured-content/structuredContentHelpers/getStructuredContentTags.d.ts +6 -0
- package/dist/super-editor/src/extensions/structured-content/structuredContentHelpers/getStructuredContentTagsById.d.ts +7 -0
- package/dist/super-editor/src/extensions/structured-content/structuredContentHelpers/index.d.ts +4 -0
- package/dist/super-editor/style.css +1 -0
- package/dist/super-editor/super-editor.es.js +7 -7
- package/dist/super-editor/toolbar.es.js +2 -2
- package/dist/super-editor.cjs +1 -1
- package/dist/super-editor.es.js +1 -1
- package/dist/superdoc.cjs +2 -2
- package/dist/superdoc.es.js +2 -2
- package/dist/superdoc.umd.js +1573 -1271
- package/dist/superdoc.umd.js.map +1 -1
- package/package.json +1 -1
|
@@ -9,12 +9,12 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
|
|
|
9
9
|
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
10
10
|
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
11
11
|
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
12
|
-
var _Attribute_static, getGlobalAttributes_fn, getNodeAndMarksAttributes_fn, _Schema_static, createNodesSchema_fn, createMarksSchema_fn, _events, _ExtensionService_instances, setupExtensions_fn, attachEditorEvents_fn, _editor, _stateValidators, _xmlValidators, _requiredNodeTypes, _requiredMarkTypes, _SuperValidator_instances, initializeValidators_fn, collectValidatorRequirements_fn, analyzeDocument_fn, _commandService, _Editor_instances, initContainerElement_fn, init_fn, initRichText_fn, onFocus_fn, checkHeadless_fn, registerCopyHandler_fn, insertNewFileData_fn, registerPluginByNameIfNotExists_fn, createExtensionService_fn, createCommandService_fn, createConverter_fn, initMedia_fn, initFonts_fn, createSchema_fn, generatePmData_fn, createView_fn, onCollaborationReady_fn, initComments_fn, initPagination_fn, dispatchTransaction_fn, handleNodeSelection_fn, prepareDocumentForImport_fn, prepareDocumentForExport_fn, endCollaboration_fn, validateDocumentInit_fn, validateDocumentExport_fn, initDevTools_fn,
|
|
12
|
+
var _Attribute_static, getGlobalAttributes_fn, getNodeAndMarksAttributes_fn, _Schema_static, createNodesSchema_fn, createMarksSchema_fn, _events, _ExtensionService_instances, setupExtensions_fn, attachEditorEvents_fn, _editor, _stateValidators, _xmlValidators, _requiredNodeTypes, _requiredMarkTypes, _SuperValidator_instances, initializeValidators_fn, collectValidatorRequirements_fn, analyzeDocument_fn, _commandService, _Editor_instances, initContainerElement_fn, init_fn, initRichText_fn, onFocus_fn, checkHeadless_fn, registerCopyHandler_fn, insertNewFileData_fn, registerPluginByNameIfNotExists_fn, createExtensionService_fn, createCommandService_fn, createConverter_fn, initMedia_fn, initFonts_fn, createSchema_fn, generatePmData_fn, createView_fn, onCollaborationReady_fn, initComments_fn, initPagination_fn, dispatchTransaction_fn, handleNodeSelection_fn, prepareDocumentForImport_fn, prepareDocumentForExport_fn, endCollaboration_fn, validateDocumentInit_fn, validateDocumentExport_fn, initDevTools_fn, _DocumentSectionView_instances, init_fn2, addToolTip_fn, _ListItemNodeView_instances, init_fn3, _FieldAnnotationView_instances, createAnnotation_fn, _AutoPageNumberNodeView_instances, renderDom_fn, scheduleUpdateNodeStyle_fn;
|
|
13
13
|
import * as Y from "yjs";
|
|
14
14
|
import { UndoManager, Item as Item$1, ContentType, Text as Text$1, XmlElement, encodeStateAsUpdate } from "yjs";
|
|
15
|
-
import { P as PluginKey, a as Plugin, M as Mapping, N as NodeSelection, S as Selection, T as TextSelection, b as Slice, D as DOMSerializer, F as Fragment, c as DOMParser$1, d as Mark$1, e as dropPoint, A as AllSelection, p as process$1, B as Buffer2, f as callOrGet, g as getExtensionConfigField, h as getMarkType, i as getMarksFromSelection, j as getNodeType, k as getSchemaTypeNameByName, l as Schema$1, m as cleanSchemaItem, n as canSplit, o as defaultBlockAt$1, q as liftTarget, r as canJoin, s as joinPoint, t as replaceStep$1, R as ReplaceAroundStep$1, u as isTextSelection, v as getMarkRange, w as isMarkActive, x as isNodeActive, y as deleteProps, z as processContent, C as ReplaceStep, E as NodeRange, G as findWrapping, L as ListHelpers, H as findParentNode, I as isMacOS, J as isIOS, K as getSchemaTypeByName, O as inputRulesPlugin, Q as TrackDeleteMarkName, U as TrackInsertMarkName, V as v4, W as TrackFormatMarkName, X as comments_module_events, Y as findMark, Z as objectIncludes, _ as AddMarkStep, $ as RemoveMarkStep, a0 as twipsToLines, a1 as pixelsToTwips, a2 as helpers, a3 as posToDOMRect, a4 as CommandService, a5 as SuperConverter, a6 as createDocument, a7 as createDocFromMarkdown, a8 as createDocFromHTML, a9 as EditorState, aa as hasSomeParentWithClass, ab as isActive, ac as unflattenListsInHtml, ad as parseSizeUnit, ae as minMax, af as getLineHeightValueString, ag as
|
|
15
|
+
import { P as PluginKey, a as Plugin, M as Mapping, N as NodeSelection, S as Selection, T as TextSelection, b as Slice, D as DOMSerializer, F as Fragment, c as DOMParser$1, d as Mark$1, e as dropPoint, A as AllSelection, p as process$1, B as Buffer2, f as callOrGet, g as getExtensionConfigField, h as getMarkType, i as getMarksFromSelection, j as getNodeType, k as getSchemaTypeNameByName, l as Schema$1, m as cleanSchemaItem, n as canSplit, o as defaultBlockAt$1, q as liftTarget, r as canJoin, s as joinPoint, t as replaceStep$1, R as ReplaceAroundStep$1, u as isTextSelection, v as getMarkRange, w as isMarkActive, x as isNodeActive, y as deleteProps, z as processContent, C as ReplaceStep, E as NodeRange, G as findWrapping, L as ListHelpers, H as findParentNode, I as isMacOS, J as isIOS, K as getSchemaTypeByName, O as inputRulesPlugin, Q as TrackDeleteMarkName, U as TrackInsertMarkName, V as v4, W as TrackFormatMarkName, X as comments_module_events, Y as findMark, Z as objectIncludes, _ as AddMarkStep, $ as RemoveMarkStep, a0 as twipsToLines, a1 as pixelsToTwips, a2 as helpers, a3 as posToDOMRect, a4 as CommandService, a5 as SuperConverter, a6 as createDocument, a7 as createDocFromMarkdown, a8 as createDocFromHTML, a9 as EditorState, aa as hasSomeParentWithClass, ab as isActive, ac as unflattenListsInHtml, ad as parseSizeUnit, ae as minMax, af as getLineHeightValueString, ag as updateDOMAttributes, ah as findChildren$5, ai as htmlHandler, aj as generateRandomSigned32BitIntStrId, ak as InputRule, al as kebabCase, am as findParentNodeClosestToPos, an as getListItemStyleDefinitions, ao as docxNumberigHelpers, ap as parseIndentElement, aq as combineIndents, ar as SelectionRange, as as Transform, at as isInTable$1, au as generateDocxRandomId, av as insertNewRelationship } from "./converter-C-yWLpFM.js";
|
|
16
16
|
import { ref, computed, createElementBlock, openBlock, withModifiers, Fragment as Fragment$1, renderList, normalizeClass, createCommentVNode, toDisplayString, createElementVNode, createApp } from "vue";
|
|
17
|
-
import { D as DocxZipper } from "./docx-zipper-
|
|
17
|
+
import { D as DocxZipper } from "./docx-zipper-CmGlSUQM.js";
|
|
18
18
|
var GOOD_LEAF_SIZE = 200;
|
|
19
19
|
var RopeSequence = function RopeSequence2() {
|
|
20
20
|
};
|
|
@@ -12107,28 +12107,25 @@ const handleTrackedChangeTransaction = (trackedChangeMeta, trackedChanges, newEd
|
|
|
12107
12107
|
if (emitParams) editor.emit("commentsUpdate", emitParams);
|
|
12108
12108
|
return newTrackedChanges;
|
|
12109
12109
|
};
|
|
12110
|
-
const getTrackedChangeText = ({
|
|
12110
|
+
const getTrackedChangeText = ({ nodes, mark, trackedChangeType, isDeletionInsertion }) => {
|
|
12111
12111
|
let trackedChangeText = "";
|
|
12112
12112
|
let deletionText = "";
|
|
12113
12113
|
if (trackedChangeType === TrackInsertMarkName) {
|
|
12114
|
-
trackedChangeText = node
|
|
12114
|
+
trackedChangeText = nodes.reduce((acc, node) => {
|
|
12115
|
+
if (!node.marks.find((nodeMark) => nodeMark.type.name === mark.type.name)) return acc;
|
|
12116
|
+
acc += node?.text || node?.textContent || "";
|
|
12117
|
+
return acc;
|
|
12118
|
+
}, "");
|
|
12115
12119
|
}
|
|
12116
12120
|
if (trackedChangeType === TrackFormatMarkName) {
|
|
12117
12121
|
trackedChangeText = translateFormatChangesToEnglish(mark.attrs);
|
|
12118
12122
|
}
|
|
12119
12123
|
if (trackedChangeType === TrackDeleteMarkName || isDeletionInsertion) {
|
|
12120
|
-
deletionText = node
|
|
12121
|
-
|
|
12122
|
-
|
|
12123
|
-
|
|
12124
|
-
|
|
12125
|
-
const changeMarks = marks2.filter((mark2) => TRACK_CHANGE_MARKS.includes(mark2.type.name));
|
|
12126
|
-
if (!changeMarks.length) return false;
|
|
12127
|
-
const hasMatchingId = changeMarks.find((mark2) => mark2.attrs.id === id);
|
|
12128
|
-
if (hasMatchingId) return true;
|
|
12129
|
-
});
|
|
12130
|
-
deletionText = deletionNode?.node.text ?? "";
|
|
12131
|
-
}
|
|
12124
|
+
deletionText = nodes.reduce((acc, node) => {
|
|
12125
|
+
if (!node.marks.find((nodeMark) => nodeMark.type.name === TrackDeleteMarkName)) return acc;
|
|
12126
|
+
acc += node?.text || node?.textContent || "";
|
|
12127
|
+
return acc;
|
|
12128
|
+
}, "");
|
|
12132
12129
|
}
|
|
12133
12130
|
return {
|
|
12134
12131
|
deletionText,
|
|
@@ -12143,20 +12140,17 @@ const createOrUpdateTrackedChangeComment = ({ event, marks, deletionNodes, nodes
|
|
|
12143
12140
|
const id = attrs.id;
|
|
12144
12141
|
const node = nodes[0];
|
|
12145
12142
|
const isDeletionInsertion = !!(marks.insertedMark && marks.deletionMark);
|
|
12146
|
-
let
|
|
12143
|
+
let nodesWithMark = [];
|
|
12147
12144
|
newEditorState.doc.descendants((node2) => {
|
|
12148
12145
|
const { marks: marks2 = [] } = node2;
|
|
12149
12146
|
const changeMarks = marks2.filter((mark) => TRACK_CHANGE_MARKS.includes(mark.type.name));
|
|
12150
12147
|
if (!changeMarks.length) return;
|
|
12151
12148
|
const hasMatchingId = changeMarks.find((mark) => mark.attrs.id === id);
|
|
12152
|
-
if (hasMatchingId)
|
|
12153
|
-
if (existingNode) return false;
|
|
12149
|
+
if (hasMatchingId) nodesWithMark.push(node2);
|
|
12154
12150
|
});
|
|
12155
12151
|
const { deletionText, trackedChangeText } = getTrackedChangeText({
|
|
12156
|
-
|
|
12157
|
-
node: existingNode || node,
|
|
12152
|
+
nodes: nodesWithMark.length ? nodesWithMark : [node],
|
|
12158
12153
|
mark: trackedMark,
|
|
12159
|
-
marks,
|
|
12160
12154
|
trackedChangeType,
|
|
12161
12155
|
isDeletionInsertion
|
|
12162
12156
|
});
|
|
@@ -12184,14 +12178,6 @@ const createOrUpdateTrackedChangeComment = ({ event, marks, deletionNodes, nodes
|
|
|
12184
12178
|
else if (event === "update") params2.event = comments_module_events.UPDATE;
|
|
12185
12179
|
return params2;
|
|
12186
12180
|
};
|
|
12187
|
-
function findNode$1(node, predicate) {
|
|
12188
|
-
let found = null;
|
|
12189
|
-
node.descendants((node2, pos) => {
|
|
12190
|
-
if (predicate(node2)) found = { node: node2, pos };
|
|
12191
|
-
if (found) return false;
|
|
12192
|
-
});
|
|
12193
|
-
return found;
|
|
12194
|
-
}
|
|
12195
12181
|
function findRangeById(doc2, id) {
|
|
12196
12182
|
let from2 = null, to = null;
|
|
12197
12183
|
doc2.descendants((node, pos) => {
|
|
@@ -16979,223 +16965,1218 @@ const SlashMenu = Extension.create({
|
|
|
16979
16965
|
return this.editor.options.isHeadless ? [] : [slashMenuPlugin];
|
|
16980
16966
|
}
|
|
16981
16967
|
});
|
|
16982
|
-
|
|
16983
|
-
|
|
16984
|
-
|
|
16985
|
-
|
|
16986
|
-
|
|
16987
|
-
|
|
16988
|
-
|
|
16989
|
-
|
|
16990
|
-
|
|
16991
|
-
|
|
16992
|
-
|
|
16993
|
-
|
|
16994
|
-
|
|
16995
|
-
|
|
16996
|
-
|
|
16997
|
-
|
|
16998
|
-
|
|
16999
|
-
|
|
17000
|
-
|
|
17001
|
-
|
|
17002
|
-
|
|
17003
|
-
|
|
17004
|
-
|
|
17005
|
-
|
|
17006
|
-
|
|
17007
|
-
|
|
17008
|
-
|
|
17009
|
-
|
|
17010
|
-
|
|
17011
|
-
|
|
17012
|
-
|
|
17013
|
-
|
|
17014
|
-
|
|
17015
|
-
|
|
17016
|
-
|
|
17017
|
-
|
|
17018
|
-
|
|
17019
|
-
|
|
17020
|
-
|
|
17021
|
-
|
|
17022
|
-
|
|
17023
|
-
|
|
17024
|
-
|
|
17025
|
-
|
|
17026
|
-
|
|
17027
|
-
|
|
17028
|
-
|
|
17029
|
-
|
|
17030
|
-
|
|
16968
|
+
class StructuredContentViewBase {
|
|
16969
|
+
constructor(props) {
|
|
16970
|
+
__publicField(this, "node");
|
|
16971
|
+
__publicField(this, "view");
|
|
16972
|
+
__publicField(this, "getPos");
|
|
16973
|
+
__publicField(this, "decorations");
|
|
16974
|
+
__publicField(this, "innerDecorations");
|
|
16975
|
+
__publicField(this, "editor");
|
|
16976
|
+
__publicField(this, "extension");
|
|
16977
|
+
__publicField(this, "htmlAttributes");
|
|
16978
|
+
__publicField(this, "root");
|
|
16979
|
+
__publicField(this, "isDragging", false);
|
|
16980
|
+
this.node = props.node;
|
|
16981
|
+
this.view = props.editor.view;
|
|
16982
|
+
this.getPos = props.getPos;
|
|
16983
|
+
this.decorations = props.decorations;
|
|
16984
|
+
this.innerDecorations = props.innerDecorations;
|
|
16985
|
+
this.editor = props.editor;
|
|
16986
|
+
this.extension = props.extension;
|
|
16987
|
+
this.htmlAttributes = props.htmlAttributes;
|
|
16988
|
+
this.mount(props);
|
|
16989
|
+
}
|
|
16990
|
+
mount() {
|
|
16991
|
+
return;
|
|
16992
|
+
}
|
|
16993
|
+
get dom() {
|
|
16994
|
+
return this.root;
|
|
16995
|
+
}
|
|
16996
|
+
get contentDOM() {
|
|
16997
|
+
return null;
|
|
16998
|
+
}
|
|
16999
|
+
update(node, decorations, innerDecorations) {
|
|
17000
|
+
if (node.type !== this.node.type) {
|
|
17001
|
+
return false;
|
|
17002
|
+
}
|
|
17003
|
+
this.node = node;
|
|
17004
|
+
this.decorations = decorations;
|
|
17005
|
+
this.innerDecorations = innerDecorations;
|
|
17006
|
+
this.updateHTMLAttributes();
|
|
17007
|
+
return true;
|
|
17008
|
+
}
|
|
17009
|
+
stopEvent(event) {
|
|
17010
|
+
if (!this.dom) return false;
|
|
17011
|
+
const target = event.target;
|
|
17012
|
+
const isInElement = this.dom.contains(target) && !this.contentDOM?.contains(target);
|
|
17013
|
+
if (!isInElement) return false;
|
|
17014
|
+
const isDragEvent = event.type.startsWith("drag");
|
|
17015
|
+
const isDropEvent = event.type === "drop";
|
|
17016
|
+
const isInput = ["INPUT", "BUTTON", "SELECT", "TEXTAREA"].includes(target.tagName) || target.isContentEditable;
|
|
17017
|
+
if (isInput && !isDropEvent && !isDragEvent) return true;
|
|
17018
|
+
const { isEditable } = this.editor;
|
|
17019
|
+
const { isDragging } = this;
|
|
17020
|
+
const isDraggable = !!this.node.type.spec.draggable;
|
|
17021
|
+
const isSelectable = NodeSelection.isSelectable(this.node);
|
|
17022
|
+
const isCopyEvent = event.type === "copy";
|
|
17023
|
+
const isPasteEvent = event.type === "paste";
|
|
17024
|
+
const isCutEvent = event.type === "cut";
|
|
17025
|
+
const isClickEvent = event.type === "mousedown";
|
|
17026
|
+
if (!isDraggable && isSelectable && isDragEvent && event.target === this.dom) {
|
|
17027
|
+
event.preventDefault();
|
|
17028
|
+
}
|
|
17029
|
+
if (isDraggable && isDragEvent && !isDragging && event.target === this.dom) {
|
|
17030
|
+
event.preventDefault();
|
|
17031
|
+
return false;
|
|
17032
|
+
}
|
|
17033
|
+
if (isDraggable && isEditable && !isDragging && isClickEvent) {
|
|
17034
|
+
const dragHandle = target.closest("[data-drag-handle]");
|
|
17035
|
+
const isValidDragHandle = dragHandle && (this.dom === dragHandle || this.dom.contains(dragHandle));
|
|
17036
|
+
if (isValidDragHandle) {
|
|
17037
|
+
this.isDragging = true;
|
|
17038
|
+
document.addEventListener(
|
|
17039
|
+
"dragend",
|
|
17040
|
+
() => {
|
|
17041
|
+
this.isDragging = false;
|
|
17042
|
+
},
|
|
17043
|
+
{ once: true }
|
|
17044
|
+
);
|
|
17045
|
+
document.addEventListener(
|
|
17046
|
+
"drop",
|
|
17047
|
+
() => {
|
|
17048
|
+
this.isDragging = false;
|
|
17049
|
+
},
|
|
17050
|
+
{ once: true }
|
|
17051
|
+
);
|
|
17052
|
+
document.addEventListener(
|
|
17053
|
+
"mouseup",
|
|
17054
|
+
() => {
|
|
17055
|
+
this.isDragging = false;
|
|
17056
|
+
},
|
|
17057
|
+
{ once: true }
|
|
17058
|
+
);
|
|
17031
17059
|
}
|
|
17032
|
-
}
|
|
17060
|
+
}
|
|
17061
|
+
if (isDragging || isDropEvent || isCopyEvent || isPasteEvent || isCutEvent || isClickEvent && isSelectable) {
|
|
17062
|
+
return false;
|
|
17063
|
+
}
|
|
17064
|
+
return true;
|
|
17033
17065
|
}
|
|
17034
|
-
|
|
17035
|
-
|
|
17036
|
-
|
|
17037
|
-
|
|
17038
|
-
|
|
17039
|
-
|
|
17040
|
-
return
|
|
17066
|
+
ignoreMutation(mutation) {
|
|
17067
|
+
if (!this.dom || !this.contentDOM) return true;
|
|
17068
|
+
if (this.node.isLeaf || this.node.isAtom) return true;
|
|
17069
|
+
if (mutation.type === "selection") return false;
|
|
17070
|
+
if (this.contentDOM === mutation.target && mutation.type === "attributes") return true;
|
|
17071
|
+
if (this.contentDOM.contains(mutation.target)) return false;
|
|
17072
|
+
return true;
|
|
17041
17073
|
}
|
|
17042
|
-
|
|
17043
|
-
|
|
17044
|
-
|
|
17045
|
-
|
|
17046
|
-
|
|
17047
|
-
|
|
17048
|
-
|
|
17074
|
+
destroy() {
|
|
17075
|
+
this.dom.remove();
|
|
17076
|
+
this.contentDOM?.remove();
|
|
17077
|
+
}
|
|
17078
|
+
updateAttributes(attrs) {
|
|
17079
|
+
const pos = this.getPos();
|
|
17080
|
+
if (typeof pos !== "number") {
|
|
17081
|
+
return;
|
|
17082
|
+
}
|
|
17083
|
+
return this.view.dispatch(
|
|
17084
|
+
this.view.state.tr.setNodeMarkup(pos, void 0, {
|
|
17085
|
+
...this.node.attrs,
|
|
17086
|
+
...attrs
|
|
17087
|
+
})
|
|
17088
|
+
);
|
|
17089
|
+
}
|
|
17090
|
+
updateHTMLAttributes() {
|
|
17091
|
+
const { extensionService } = this.editor;
|
|
17092
|
+
const { attributes } = extensionService;
|
|
17093
|
+
const extensionAttrs = attributes.filter((i) => i.type === this.node.type.name);
|
|
17094
|
+
this.htmlAttributes = Attribute.getAttributesToRender(this.node, extensionAttrs);
|
|
17095
|
+
}
|
|
17096
|
+
createDragHandle() {
|
|
17097
|
+
const dragHandle = document.createElement("span");
|
|
17098
|
+
dragHandle.classList.add("sd-structured-content-draggable");
|
|
17099
|
+
dragHandle.draggable = true;
|
|
17100
|
+
dragHandle.contentEditable = "false";
|
|
17101
|
+
dragHandle.dataset.dragHandle = "";
|
|
17102
|
+
const textElement = document.createElement("span");
|
|
17103
|
+
textElement.textContent = this.node.attrs.alias || "Structured content";
|
|
17104
|
+
dragHandle.append(textElement);
|
|
17105
|
+
return dragHandle;
|
|
17106
|
+
}
|
|
17107
|
+
onDragStart(event) {
|
|
17108
|
+
const { view } = this.editor;
|
|
17109
|
+
const target = event.target;
|
|
17110
|
+
const dragHandle = target.nodeType === 3 ? target.parentElement?.closest("[data-drag-handle]") : target.closest("[data-drag-handle]");
|
|
17111
|
+
if (!this.dom || this.contentDOM?.contains(target) || !dragHandle) {
|
|
17112
|
+
return;
|
|
17113
|
+
}
|
|
17114
|
+
let x = 0;
|
|
17115
|
+
let y = 0;
|
|
17116
|
+
if (this.dom !== dragHandle) {
|
|
17117
|
+
const domBox = this.dom.getBoundingClientRect();
|
|
17118
|
+
const handleBox = dragHandle.getBoundingClientRect();
|
|
17119
|
+
const offsetX = event.offsetX ?? event.nativeEvent?.offsetX;
|
|
17120
|
+
const offsetY = event.offsetY ?? event.nativeEvent?.offsetY;
|
|
17121
|
+
x = handleBox.x - domBox.x + offsetX;
|
|
17122
|
+
y = handleBox.y - domBox.y + offsetY;
|
|
17123
|
+
}
|
|
17124
|
+
event.dataTransfer?.setDragImage(this.dom, x, y);
|
|
17125
|
+
const pos = this.getPos();
|
|
17126
|
+
if (typeof pos !== "number") {
|
|
17127
|
+
return;
|
|
17128
|
+
}
|
|
17129
|
+
const selection = NodeSelection.create(view.state.doc, pos);
|
|
17130
|
+
const transaction = view.state.tr.setSelection(selection);
|
|
17049
17131
|
view.dispatch(transaction);
|
|
17050
|
-
});
|
|
17051
|
-
if (handled) {
|
|
17052
|
-
tr.setMeta("preventDispatch", true);
|
|
17053
17132
|
}
|
|
17054
|
-
|
|
17055
|
-
|
|
17056
|
-
|
|
17057
|
-
|
|
17058
|
-
|
|
17059
|
-
|
|
17133
|
+
}
|
|
17134
|
+
class StructuredContentInlineView extends StructuredContentViewBase {
|
|
17135
|
+
constructor(props) {
|
|
17136
|
+
super(props);
|
|
17137
|
+
}
|
|
17138
|
+
mount() {
|
|
17139
|
+
this.buildView();
|
|
17140
|
+
}
|
|
17141
|
+
get contentDOM() {
|
|
17142
|
+
const contentElement = this.dom?.querySelector(`.${structuredContentInnerClass$1}`);
|
|
17143
|
+
return contentElement || null;
|
|
17144
|
+
}
|
|
17145
|
+
createElement() {
|
|
17146
|
+
const element = document.createElement("span");
|
|
17147
|
+
element.classList.add(structuredContentClass$1);
|
|
17148
|
+
element.setAttribute("data-structured-content", "");
|
|
17149
|
+
const contentElement = document.createElement("span");
|
|
17150
|
+
contentElement.classList.add(structuredContentInnerClass$1);
|
|
17151
|
+
element.append(contentElement);
|
|
17152
|
+
const domAttrs = Attribute.mergeAttributes(this.htmlAttributes);
|
|
17153
|
+
updateDOMAttributes(element, { ...domAttrs });
|
|
17154
|
+
return { element, contentElement };
|
|
17155
|
+
}
|
|
17156
|
+
buildView() {
|
|
17157
|
+
const { element } = this.createElement();
|
|
17158
|
+
const dragHandle = this.createDragHandle();
|
|
17159
|
+
element.prepend(dragHandle);
|
|
17160
|
+
element.addEventListener("dragstart", (e) => this.onDragStart(e));
|
|
17161
|
+
this.root = element;
|
|
17162
|
+
}
|
|
17163
|
+
updateView() {
|
|
17164
|
+
const domAttrs = Attribute.mergeAttributes(this.htmlAttributes);
|
|
17165
|
+
updateDOMAttributes(this.dom, { ...domAttrs });
|
|
17166
|
+
}
|
|
17167
|
+
update(node, decorations, innerDecorations) {
|
|
17168
|
+
const result = super.update(node, decorations, innerDecorations);
|
|
17169
|
+
if (!result) return false;
|
|
17170
|
+
this.updateView();
|
|
17171
|
+
return true;
|
|
17172
|
+
}
|
|
17173
|
+
}
|
|
17174
|
+
const structuredContentClass$1 = "sd-structured-content";
|
|
17175
|
+
const structuredContentInnerClass$1 = "sd-structured-content__content";
|
|
17176
|
+
const StructuredContent = Node$1.create({
|
|
17177
|
+
name: "structuredContent",
|
|
17178
|
+
group: "inline structuredContent",
|
|
17060
17179
|
inline: true,
|
|
17061
17180
|
content: "inline*",
|
|
17062
|
-
|
|
17063
|
-
|
|
17181
|
+
isolating: true,
|
|
17182
|
+
atom: false,
|
|
17183
|
+
// false - has editable content.
|
|
17184
|
+
draggable: true,
|
|
17064
17185
|
addOptions() {
|
|
17065
17186
|
return {
|
|
17066
17187
|
htmlAttributes: {
|
|
17067
|
-
|
|
17188
|
+
class: structuredContentClass$1,
|
|
17189
|
+
"aria-label": "Structured content node"
|
|
17068
17190
|
}
|
|
17069
17191
|
};
|
|
17070
17192
|
},
|
|
17071
17193
|
addAttributes() {
|
|
17072
17194
|
return {
|
|
17073
|
-
|
|
17195
|
+
id: {
|
|
17074
17196
|
default: null,
|
|
17075
|
-
|
|
17076
|
-
|
|
17197
|
+
parseDOM: (elem) => elem.getAttribute("data-id"),
|
|
17198
|
+
renderDOM: (attrs) => {
|
|
17199
|
+
if (!attrs.id) return {};
|
|
17200
|
+
return { "data-id": attrs.id };
|
|
17201
|
+
}
|
|
17077
17202
|
},
|
|
17078
|
-
|
|
17203
|
+
tag: {
|
|
17079
17204
|
default: null,
|
|
17080
|
-
|
|
17081
|
-
|
|
17205
|
+
parseDOM: (elem) => elem.getAttribute("data-tag"),
|
|
17206
|
+
renderDOM: (attrs) => {
|
|
17207
|
+
if (!attrs.tag) return {};
|
|
17208
|
+
return { "data-tag": attrs.tag };
|
|
17209
|
+
}
|
|
17082
17210
|
},
|
|
17083
|
-
|
|
17211
|
+
alias: {
|
|
17084
17212
|
default: null,
|
|
17085
|
-
|
|
17086
|
-
|
|
17213
|
+
parseDOM: (elem) => elem.getAttribute("data-alias"),
|
|
17214
|
+
renderDOM: (attrs) => {
|
|
17215
|
+
if (!attrs.alias) return {};
|
|
17216
|
+
return { "data-alias": attrs.alias };
|
|
17217
|
+
}
|
|
17087
17218
|
},
|
|
17088
|
-
|
|
17089
|
-
|
|
17090
|
-
rendered: false,
|
|
17091
|
-
keepOnSplit: true
|
|
17219
|
+
sdtPr: {
|
|
17220
|
+
rendered: false
|
|
17092
17221
|
}
|
|
17093
17222
|
};
|
|
17094
17223
|
},
|
|
17095
|
-
addCommands() {
|
|
17096
|
-
return {
|
|
17097
|
-
splitRun
|
|
17098
|
-
};
|
|
17099
|
-
},
|
|
17100
17224
|
parseDOM() {
|
|
17101
|
-
return [{ tag: "span[data-
|
|
17225
|
+
return [{ tag: "span[data-structured-content]" }];
|
|
17102
17226
|
},
|
|
17103
17227
|
renderDOM({ htmlAttributes }) {
|
|
17104
|
-
|
|
17105
|
-
|
|
17228
|
+
return [
|
|
17229
|
+
"span",
|
|
17230
|
+
Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes, {
|
|
17231
|
+
"data-structured-content": ""
|
|
17232
|
+
}),
|
|
17233
|
+
0
|
|
17234
|
+
];
|
|
17235
|
+
},
|
|
17236
|
+
addNodeView() {
|
|
17237
|
+
return (props) => {
|
|
17238
|
+
return new StructuredContentInlineView({ ...props });
|
|
17239
|
+
};
|
|
17106
17240
|
}
|
|
17107
17241
|
});
|
|
17108
|
-
|
|
17109
|
-
|
|
17110
|
-
|
|
17111
|
-
|
|
17112
|
-
|
|
17113
|
-
|
|
17114
|
-
|
|
17115
|
-
|
|
17242
|
+
class StructuredContentBlockView extends StructuredContentViewBase {
|
|
17243
|
+
constructor(props) {
|
|
17244
|
+
super(props);
|
|
17245
|
+
}
|
|
17246
|
+
mount() {
|
|
17247
|
+
this.buildView();
|
|
17248
|
+
}
|
|
17249
|
+
get contentDOM() {
|
|
17250
|
+
const contentElement = this.dom?.querySelector(`.${structuredContentInnerClass}`);
|
|
17251
|
+
return contentElement || null;
|
|
17252
|
+
}
|
|
17253
|
+
createElement() {
|
|
17254
|
+
const element = document.createElement("div");
|
|
17255
|
+
element.classList.add(structuredContentClass);
|
|
17256
|
+
element.setAttribute("data-structured-content-block", "");
|
|
17257
|
+
const contentElement = document.createElement("div");
|
|
17258
|
+
contentElement.classList.add(structuredContentInnerClass);
|
|
17259
|
+
element.append(contentElement);
|
|
17260
|
+
const domAttrs = Attribute.mergeAttributes(this.htmlAttributes);
|
|
17261
|
+
updateDOMAttributes(element, { ...domAttrs });
|
|
17262
|
+
return { element, contentElement };
|
|
17263
|
+
}
|
|
17264
|
+
buildView() {
|
|
17265
|
+
const { element } = this.createElement();
|
|
17266
|
+
const dragHandle = this.createDragHandle();
|
|
17267
|
+
element.prepend(dragHandle);
|
|
17268
|
+
element.addEventListener("dragstart", (e) => this.onDragStart(e));
|
|
17269
|
+
this.root = element;
|
|
17270
|
+
}
|
|
17271
|
+
updateView() {
|
|
17272
|
+
const domAttrs = Attribute.mergeAttributes(this.htmlAttributes);
|
|
17273
|
+
updateDOMAttributes(this.dom, { ...domAttrs });
|
|
17274
|
+
}
|
|
17275
|
+
update(node, decorations, innerDecorations) {
|
|
17276
|
+
const result = super.update(node, decorations, innerDecorations);
|
|
17277
|
+
if (!result) return false;
|
|
17278
|
+
this.updateView();
|
|
17279
|
+
return true;
|
|
17280
|
+
}
|
|
17281
|
+
}
|
|
17282
|
+
const structuredContentClass = "sd-structured-content-block";
|
|
17283
|
+
const structuredContentInnerClass = "sd-structured-content-block__content";
|
|
17284
|
+
const StructuredContentBlock = Node$1.create({
|
|
17285
|
+
name: "structuredContentBlock",
|
|
17286
|
+
group: "block structuredContent",
|
|
17287
|
+
content: "block*",
|
|
17288
|
+
isolating: true,
|
|
17289
|
+
atom: false,
|
|
17290
|
+
// false - has editable content.
|
|
17291
|
+
draggable: true,
|
|
17116
17292
|
addOptions() {
|
|
17117
17293
|
return {
|
|
17118
|
-
itemTypeName: "listItem",
|
|
17119
17294
|
htmlAttributes: {
|
|
17120
|
-
|
|
17121
|
-
|
|
17122
|
-
|
|
17123
|
-
keepAttributes: false
|
|
17295
|
+
class: structuredContentClass,
|
|
17296
|
+
"aria-label": "Structured content block node"
|
|
17297
|
+
}
|
|
17124
17298
|
};
|
|
17125
17299
|
},
|
|
17126
|
-
parseDOM() {
|
|
17127
|
-
return [{ tag: "ul" }];
|
|
17128
|
-
},
|
|
17129
|
-
renderDOM({ htmlAttributes }) {
|
|
17130
|
-
const attributes = Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes);
|
|
17131
|
-
return ["ul", attributes, 0];
|
|
17132
|
-
},
|
|
17133
17300
|
addAttributes() {
|
|
17134
17301
|
return {
|
|
17135
|
-
|
|
17136
|
-
default:
|
|
17137
|
-
|
|
17302
|
+
id: {
|
|
17303
|
+
default: null,
|
|
17304
|
+
parseDOM: (elem) => elem.getAttribute("data-id"),
|
|
17305
|
+
renderDOM: (attrs) => {
|
|
17306
|
+
if (!attrs.id) return {};
|
|
17307
|
+
return { "data-id": attrs.id };
|
|
17308
|
+
}
|
|
17138
17309
|
},
|
|
17139
|
-
|
|
17140
|
-
|
|
17310
|
+
tag: {
|
|
17311
|
+
default: null,
|
|
17312
|
+
parseDOM: (elem) => elem.getAttribute("data-tag"),
|
|
17313
|
+
renderDOM: (attrs) => {
|
|
17314
|
+
if (!attrs.tag) return {};
|
|
17315
|
+
return { "data-tag": attrs.tag };
|
|
17316
|
+
}
|
|
17141
17317
|
},
|
|
17142
|
-
|
|
17318
|
+
alias: {
|
|
17143
17319
|
default: null,
|
|
17144
|
-
|
|
17145
|
-
parseDOM: (elem) => elem.getAttribute("data-sd-block-id"),
|
|
17320
|
+
parseDOM: (elem) => elem.getAttribute("data-alias"),
|
|
17146
17321
|
renderDOM: (attrs) => {
|
|
17147
|
-
|
|
17322
|
+
if (!attrs.alias) return {};
|
|
17323
|
+
return { "data-alias": attrs.alias };
|
|
17148
17324
|
}
|
|
17149
17325
|
},
|
|
17150
|
-
|
|
17151
|
-
rendered: false
|
|
17152
|
-
keepOnSplit: true
|
|
17326
|
+
sdtPr: {
|
|
17327
|
+
rendered: false
|
|
17153
17328
|
}
|
|
17154
17329
|
};
|
|
17155
17330
|
},
|
|
17331
|
+
parseDOM() {
|
|
17332
|
+
return [{ tag: "div[data-structured-content-block]" }];
|
|
17333
|
+
},
|
|
17334
|
+
renderDOM({ htmlAttributes }) {
|
|
17335
|
+
return [
|
|
17336
|
+
"div",
|
|
17337
|
+
Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes, {
|
|
17338
|
+
"data-structured-content-block": ""
|
|
17339
|
+
}),
|
|
17340
|
+
0
|
|
17341
|
+
];
|
|
17342
|
+
},
|
|
17343
|
+
addNodeView() {
|
|
17344
|
+
return (props) => {
|
|
17345
|
+
return new StructuredContentBlockView({ ...props });
|
|
17346
|
+
};
|
|
17347
|
+
}
|
|
17348
|
+
});
|
|
17349
|
+
function getStructuredContentTagsById(idOrIds, state) {
|
|
17350
|
+
const result = findChildren$5(state.doc, (node) => {
|
|
17351
|
+
const isStructuredContent = ["structuredContent", "structuredContentBlock"].includes(node.type.name);
|
|
17352
|
+
if (Array.isArray(idOrIds)) {
|
|
17353
|
+
return isStructuredContent && idOrIds.includes(node.attrs.id);
|
|
17354
|
+
} else {
|
|
17355
|
+
return isStructuredContent && node.attrs.id === idOrIds;
|
|
17356
|
+
}
|
|
17357
|
+
});
|
|
17358
|
+
return result;
|
|
17359
|
+
}
|
|
17360
|
+
function getStructuredContentTags(state) {
|
|
17361
|
+
const result = findChildren$5(state.doc, (node) => {
|
|
17362
|
+
return node.type.name === "structuredContent" || node.type.name === "structuredContentBlock";
|
|
17363
|
+
});
|
|
17364
|
+
return result;
|
|
17365
|
+
}
|
|
17366
|
+
function getStructuredContentInlineTags(state) {
|
|
17367
|
+
const result = findChildren$5(state.doc, (node) => node.type.name === "structuredContent");
|
|
17368
|
+
return result;
|
|
17369
|
+
}
|
|
17370
|
+
function getStructuredContentBlockTags(state) {
|
|
17371
|
+
const result = findChildren$5(state.doc, (node) => node.type.name === "structuredContentBlock");
|
|
17372
|
+
return result;
|
|
17373
|
+
}
|
|
17374
|
+
const structuredContentHelpers = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
17375
|
+
__proto__: null,
|
|
17376
|
+
getStructuredContentBlockTags,
|
|
17377
|
+
getStructuredContentInlineTags,
|
|
17378
|
+
getStructuredContentTags,
|
|
17379
|
+
getStructuredContentTagsById
|
|
17380
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
17381
|
+
const STRUCTURED_CONTENT_NAMES = ["structuredContent", "structuredContentBlock"];
|
|
17382
|
+
const StructuredContentCommands = Extension.create({
|
|
17383
|
+
name: "structuredContentCommands",
|
|
17156
17384
|
addCommands() {
|
|
17157
17385
|
return {
|
|
17158
17386
|
/**
|
|
17159
|
-
*
|
|
17387
|
+
* Inserts a structured content inline at selection.
|
|
17160
17388
|
* @category Command
|
|
17161
|
-
* @
|
|
17162
|
-
* // Toggle bullet list on selected text
|
|
17163
|
-
* editor.commands.toggleBulletList()
|
|
17164
|
-
* @note Converts selected paragraphs to list items or removes list formatting
|
|
17389
|
+
* @param {StructuredContentInlineInsert} options
|
|
17165
17390
|
*/
|
|
17166
|
-
|
|
17167
|
-
|
|
17168
|
-
|
|
17169
|
-
|
|
17170
|
-
|
|
17171
|
-
|
|
17172
|
-
|
|
17173
|
-
|
|
17174
|
-
return this.editor.commands.toggleBulletList();
|
|
17175
|
-
}
|
|
17176
|
-
};
|
|
17177
|
-
},
|
|
17178
|
-
addInputRules() {
|
|
17179
|
-
return [
|
|
17180
|
-
new InputRule({
|
|
17181
|
-
match: inputRegex$1,
|
|
17182
|
-
handler: ({ state, range }) => {
|
|
17183
|
-
const $pos = state.selection.$from;
|
|
17184
|
-
const listItemType = state.schema.nodes.listItem;
|
|
17185
|
-
for (let depth = $pos.depth; depth >= 0; depth--) {
|
|
17186
|
-
if ($pos.node(depth).type === listItemType) {
|
|
17187
|
-
return null;
|
|
17188
|
-
}
|
|
17391
|
+
insertStructuredContentInline: (options = {}) => ({ editor, dispatch, state, tr }) => {
|
|
17392
|
+
const { schema } = editor;
|
|
17393
|
+
let { from: from2, to } = state.selection;
|
|
17394
|
+
if (dispatch) {
|
|
17395
|
+
const selectionText = state.doc.textBetween(from2, to);
|
|
17396
|
+
let content = null;
|
|
17397
|
+
if (selectionText) {
|
|
17398
|
+
content = schema.text(selectionText);
|
|
17189
17399
|
}
|
|
17190
|
-
|
|
17191
|
-
|
|
17192
|
-
|
|
17193
|
-
|
|
17194
|
-
|
|
17195
|
-
|
|
17196
|
-
|
|
17197
|
-
|
|
17198
|
-
|
|
17400
|
+
if (options.text) {
|
|
17401
|
+
content = schema.text(options.text);
|
|
17402
|
+
}
|
|
17403
|
+
if (options.json) {
|
|
17404
|
+
content = schema.nodeFromJSON(options.json);
|
|
17405
|
+
}
|
|
17406
|
+
if (!content) {
|
|
17407
|
+
content = schema.text(" ");
|
|
17408
|
+
}
|
|
17409
|
+
const attrs = {
|
|
17410
|
+
...options.attrs,
|
|
17411
|
+
id: options.attrs?.id || generateRandomSigned32BitIntStrId(),
|
|
17412
|
+
tag: "inline_text_sdt",
|
|
17413
|
+
alias: options.attrs?.alias || "Structured content"
|
|
17414
|
+
};
|
|
17415
|
+
const node = schema.nodes.structuredContent.create(attrs, content, null);
|
|
17416
|
+
const parent = findParentNode((node2) => node2.type.name === "structuredContent")(state.selection);
|
|
17417
|
+
if (parent) {
|
|
17418
|
+
const insertPos = parent.pos + parent.node.nodeSize;
|
|
17419
|
+
from2 = to = insertPos;
|
|
17420
|
+
}
|
|
17421
|
+
tr.replaceWith(from2, to, node);
|
|
17422
|
+
}
|
|
17423
|
+
return true;
|
|
17424
|
+
},
|
|
17425
|
+
/**
|
|
17426
|
+
* Inserts a structured content block at selection.
|
|
17427
|
+
* @category Command
|
|
17428
|
+
* @param {StructuredContentBlockInsert} options
|
|
17429
|
+
*/
|
|
17430
|
+
insertStructuredContentBlock: (options = {}) => ({ editor, dispatch, state, tr }) => {
|
|
17431
|
+
const { schema } = editor;
|
|
17432
|
+
let { from: from2, to } = state.selection;
|
|
17433
|
+
if (dispatch) {
|
|
17434
|
+
const selectionContent = state.selection.content();
|
|
17435
|
+
let content = null;
|
|
17436
|
+
if (selectionContent.size) {
|
|
17437
|
+
content = selectionContent.content;
|
|
17438
|
+
}
|
|
17439
|
+
if (options.html) {
|
|
17440
|
+
const html = htmlHandler(options.html, editor);
|
|
17441
|
+
const doc2 = DOMParser$1.fromSchema(schema).parse(html);
|
|
17442
|
+
content = doc2.content;
|
|
17443
|
+
}
|
|
17444
|
+
if (options.json) {
|
|
17445
|
+
content = schema.nodeFromJSON(options.json);
|
|
17446
|
+
}
|
|
17447
|
+
if (!content) {
|
|
17448
|
+
content = schema.nodeFromJSON({ type: "paragraph", content: [] });
|
|
17449
|
+
}
|
|
17450
|
+
const attrs = {
|
|
17451
|
+
...options.attrs,
|
|
17452
|
+
id: options.attrs?.id || generateRandomSigned32BitIntStrId(),
|
|
17453
|
+
tag: "block_table_sdt",
|
|
17454
|
+
alias: options.attrs?.alias || "Structured content"
|
|
17455
|
+
};
|
|
17456
|
+
const node = schema.nodes.structuredContentBlock.create(attrs, content, null);
|
|
17457
|
+
const parent = findParentNode((node2) => node2.type.name === "structuredContentBlock")(state.selection);
|
|
17458
|
+
if (parent) {
|
|
17459
|
+
const insertPos = parent.pos + parent.node.nodeSize;
|
|
17460
|
+
from2 = to = insertPos;
|
|
17461
|
+
}
|
|
17462
|
+
tr.replaceRangeWith(from2, to, node);
|
|
17463
|
+
}
|
|
17464
|
+
return true;
|
|
17465
|
+
},
|
|
17466
|
+
/**
|
|
17467
|
+
* Updates a structured content attributes or content.
|
|
17468
|
+
* If the updated node does not match the schema, it will not be updated.
|
|
17469
|
+
* @category Command
|
|
17470
|
+
* @param {string} id
|
|
17471
|
+
* @param {StructuredContentUpdate} options
|
|
17472
|
+
*/
|
|
17473
|
+
updateStructuredContentById: (id, options = {}) => ({ editor, dispatch, state, tr }) => {
|
|
17474
|
+
const structuredContentTags = getStructuredContentTagsById(id, state);
|
|
17475
|
+
if (!structuredContentTags.length) {
|
|
17476
|
+
return true;
|
|
17477
|
+
}
|
|
17478
|
+
const { schema } = editor;
|
|
17479
|
+
if (dispatch) {
|
|
17480
|
+
const structuredContent = structuredContentTags[0];
|
|
17481
|
+
const { pos, node } = structuredContent;
|
|
17482
|
+
const posFrom = pos;
|
|
17483
|
+
const posTo = pos + node.nodeSize;
|
|
17484
|
+
let content = null;
|
|
17485
|
+
if (options.text) {
|
|
17486
|
+
content = schema.text(options.text);
|
|
17487
|
+
}
|
|
17488
|
+
if (options.html) {
|
|
17489
|
+
const html = htmlHandler(options.html, editor);
|
|
17490
|
+
const doc2 = DOMParser$1.fromSchema(schema).parse(html);
|
|
17491
|
+
content = doc2.content;
|
|
17492
|
+
}
|
|
17493
|
+
if (options.json) {
|
|
17494
|
+
content = schema.nodeFromJSON(options.json);
|
|
17495
|
+
}
|
|
17496
|
+
if (!content) {
|
|
17497
|
+
content = node.content;
|
|
17498
|
+
}
|
|
17499
|
+
const updatedNode = node.type.create({ ...node.attrs, ...options.attrs }, content, node.marks);
|
|
17500
|
+
try {
|
|
17501
|
+
updatedNode.check();
|
|
17502
|
+
} catch {
|
|
17503
|
+
console.error("Updated node does not conform to the schema");
|
|
17504
|
+
return false;
|
|
17505
|
+
}
|
|
17506
|
+
tr.replaceWith(posFrom, posTo, updatedNode);
|
|
17507
|
+
}
|
|
17508
|
+
return true;
|
|
17509
|
+
},
|
|
17510
|
+
/**
|
|
17511
|
+
* Removes a structured content.
|
|
17512
|
+
* @category Command
|
|
17513
|
+
* @param {Array<{ node: Node, pos: number }>} structuredContentTags
|
|
17514
|
+
*/
|
|
17515
|
+
deleteStructuredContent: (structuredContentTags) => ({ dispatch, tr }) => {
|
|
17516
|
+
if (!structuredContentTags.length) {
|
|
17517
|
+
return true;
|
|
17518
|
+
}
|
|
17519
|
+
if (dispatch) {
|
|
17520
|
+
structuredContentTags.forEach((structuredContent) => {
|
|
17521
|
+
const { pos, node } = structuredContent;
|
|
17522
|
+
const posFrom = tr.mapping.map(pos);
|
|
17523
|
+
const posTo = tr.mapping.map(pos + node.nodeSize);
|
|
17524
|
+
const currentNode = tr.doc.nodeAt(posFrom);
|
|
17525
|
+
if (currentNode && node.eq(currentNode)) {
|
|
17526
|
+
tr.delete(posFrom, posTo);
|
|
17527
|
+
}
|
|
17528
|
+
});
|
|
17529
|
+
}
|
|
17530
|
+
return true;
|
|
17531
|
+
},
|
|
17532
|
+
/**
|
|
17533
|
+
* Removes a structured content by ID.
|
|
17534
|
+
* @category Command
|
|
17535
|
+
* @param {string | string[]} idOrIds
|
|
17536
|
+
*/
|
|
17537
|
+
deleteStructuredContentById: (idOrIds) => ({ dispatch, state, tr }) => {
|
|
17538
|
+
const structuredContentTags = getStructuredContentTagsById(idOrIds, state);
|
|
17539
|
+
if (!structuredContentTags.length) {
|
|
17540
|
+
return true;
|
|
17541
|
+
}
|
|
17542
|
+
if (dispatch) {
|
|
17543
|
+
structuredContentTags.forEach((structuredContent) => {
|
|
17544
|
+
const { pos, node } = structuredContent;
|
|
17545
|
+
const posFrom = tr.mapping.map(pos);
|
|
17546
|
+
const posTo = tr.mapping.map(pos + node.nodeSize);
|
|
17547
|
+
const currentNode = tr.doc.nodeAt(posFrom);
|
|
17548
|
+
if (currentNode && node.eq(currentNode)) {
|
|
17549
|
+
tr.delete(posFrom, posTo);
|
|
17550
|
+
}
|
|
17551
|
+
});
|
|
17552
|
+
}
|
|
17553
|
+
return true;
|
|
17554
|
+
},
|
|
17555
|
+
/**
|
|
17556
|
+
* Removes a structured content at cursor, preserving its content.
|
|
17557
|
+
* @category Command
|
|
17558
|
+
*/
|
|
17559
|
+
deleteStructuredContentAtSelection: () => ({ dispatch, state, tr }) => {
|
|
17560
|
+
const predicate = (node) => STRUCTURED_CONTENT_NAMES.includes(node.type.name);
|
|
17561
|
+
const structuredContent = findParentNode(predicate)(state.selection);
|
|
17562
|
+
if (!structuredContent) {
|
|
17563
|
+
return true;
|
|
17564
|
+
}
|
|
17565
|
+
if (dispatch) {
|
|
17566
|
+
const { node, pos } = structuredContent;
|
|
17567
|
+
const posFrom = pos;
|
|
17568
|
+
const posTo = posFrom + node.nodeSize;
|
|
17569
|
+
const content = node.content;
|
|
17570
|
+
tr.replaceWith(posFrom, posTo, content);
|
|
17571
|
+
}
|
|
17572
|
+
return true;
|
|
17573
|
+
}
|
|
17574
|
+
};
|
|
17575
|
+
},
|
|
17576
|
+
addHelpers() {
|
|
17577
|
+
return {
|
|
17578
|
+
...structuredContentHelpers
|
|
17579
|
+
};
|
|
17580
|
+
}
|
|
17581
|
+
});
|
|
17582
|
+
class DocumentSectionView {
|
|
17583
|
+
constructor(node, getPos, decorations, editor) {
|
|
17584
|
+
__privateAdd(this, _DocumentSectionView_instances);
|
|
17585
|
+
this.node = node;
|
|
17586
|
+
this.editor = editor;
|
|
17587
|
+
this.decorations = decorations;
|
|
17588
|
+
this.view = editor.view;
|
|
17589
|
+
this.getPos = getPos;
|
|
17590
|
+
__privateMethod(this, _DocumentSectionView_instances, init_fn2).call(this);
|
|
17591
|
+
}
|
|
17592
|
+
}
|
|
17593
|
+
_DocumentSectionView_instances = new WeakSet();
|
|
17594
|
+
init_fn2 = function() {
|
|
17595
|
+
const { attrs } = this.node;
|
|
17596
|
+
const { id, title, description } = attrs;
|
|
17597
|
+
this.dom = document.createElement("div");
|
|
17598
|
+
this.dom.className = "sd-document-section-block";
|
|
17599
|
+
this.dom.setAttribute("data-id", id);
|
|
17600
|
+
this.dom.setAttribute("data-title", title);
|
|
17601
|
+
this.dom.setAttribute("data-description", description);
|
|
17602
|
+
this.dom.setAttribute("aria-label", "Document section");
|
|
17603
|
+
__privateMethod(this, _DocumentSectionView_instances, addToolTip_fn).call(this);
|
|
17604
|
+
this.contentDOM = document.createElement("div");
|
|
17605
|
+
this.contentDOM.className = "sd-document-section-block-content";
|
|
17606
|
+
this.contentDOM.setAttribute("contenteditable", "true");
|
|
17607
|
+
this.dom.appendChild(this.contentDOM);
|
|
17608
|
+
};
|
|
17609
|
+
addToolTip_fn = function() {
|
|
17610
|
+
const { title } = this.node.attrs;
|
|
17611
|
+
this.infoDiv = document.createElement("div");
|
|
17612
|
+
this.infoDiv.className = "sd-document-section-block-info";
|
|
17613
|
+
const textSpan = document.createElement("span");
|
|
17614
|
+
textSpan.textContent = title || "Document section";
|
|
17615
|
+
this.infoDiv.appendChild(textSpan);
|
|
17616
|
+
this.infoDiv.setAttribute("contenteditable", "false");
|
|
17617
|
+
this.dom.appendChild(this.infoDiv);
|
|
17618
|
+
};
|
|
17619
|
+
const getAllSections = (editor) => {
|
|
17620
|
+
if (!editor) return [];
|
|
17621
|
+
const type = editor.schema.nodes.documentSection;
|
|
17622
|
+
if (!type) return [];
|
|
17623
|
+
const sections = [];
|
|
17624
|
+
const { state } = editor;
|
|
17625
|
+
state.doc.descendants((node, pos) => {
|
|
17626
|
+
if (node.type.name === type.name) {
|
|
17627
|
+
sections.push({ node, pos });
|
|
17628
|
+
}
|
|
17629
|
+
});
|
|
17630
|
+
return sections;
|
|
17631
|
+
};
|
|
17632
|
+
const exportSectionsToHTML = (editor) => {
|
|
17633
|
+
const sections = getAllSections(editor);
|
|
17634
|
+
const processedSections = /* @__PURE__ */ new Set();
|
|
17635
|
+
const result = [];
|
|
17636
|
+
sections.forEach(({ node }) => {
|
|
17637
|
+
const { attrs } = node;
|
|
17638
|
+
const { id, title, description } = attrs;
|
|
17639
|
+
if (processedSections.has(id)) return;
|
|
17640
|
+
processedSections.add(id);
|
|
17641
|
+
const html = getHTMLFromNode(node, editor);
|
|
17642
|
+
result.push({
|
|
17643
|
+
id,
|
|
17644
|
+
title,
|
|
17645
|
+
description,
|
|
17646
|
+
html
|
|
17647
|
+
});
|
|
17648
|
+
});
|
|
17649
|
+
return result;
|
|
17650
|
+
};
|
|
17651
|
+
const getHTMLFromNode = (node, editor) => {
|
|
17652
|
+
const tempDocument = document.implementation.createHTMLDocument();
|
|
17653
|
+
const container = tempDocument.createElement("div");
|
|
17654
|
+
const fragment = DOMSerializer.fromSchema(editor.schema).serializeFragment(node.content);
|
|
17655
|
+
container.appendChild(fragment);
|
|
17656
|
+
let html = container.innerHTML;
|
|
17657
|
+
return html;
|
|
17658
|
+
};
|
|
17659
|
+
const exportSectionsToJSON = (editor) => {
|
|
17660
|
+
const sections = getAllSections(editor);
|
|
17661
|
+
const processedSections = /* @__PURE__ */ new Set();
|
|
17662
|
+
const result = [];
|
|
17663
|
+
sections.forEach(({ node }) => {
|
|
17664
|
+
const { attrs } = node;
|
|
17665
|
+
const { id, title, description } = attrs;
|
|
17666
|
+
if (processedSections.has(id)) return;
|
|
17667
|
+
processedSections.add(id);
|
|
17668
|
+
result.push({
|
|
17669
|
+
id,
|
|
17670
|
+
title,
|
|
17671
|
+
description,
|
|
17672
|
+
content: node.toJSON()
|
|
17673
|
+
});
|
|
17674
|
+
});
|
|
17675
|
+
return result;
|
|
17676
|
+
};
|
|
17677
|
+
const getLinkedSectionEditor = (id, options, editor) => {
|
|
17678
|
+
const sections = getAllSections(editor);
|
|
17679
|
+
const section = sections.find((s) => s.node.attrs.id === id);
|
|
17680
|
+
if (!section) return null;
|
|
17681
|
+
const child = editor.createChildEditor({
|
|
17682
|
+
...options,
|
|
17683
|
+
onUpdate: ({ editor: childEditor, transaction }) => {
|
|
17684
|
+
const isFromtLinkedParent = transaction.getMeta("fromLinkedParent");
|
|
17685
|
+
if (isFromtLinkedParent) return;
|
|
17686
|
+
const updatedContent = childEditor.state.doc.content;
|
|
17687
|
+
const sectionNode = getAllSections(editor)?.find((s) => s.node.attrs.id === id);
|
|
17688
|
+
if (!sectionNode) return;
|
|
17689
|
+
const { pos, node } = sectionNode;
|
|
17690
|
+
const newNode = node.type.create(node.attrs, updatedContent, node.marks);
|
|
17691
|
+
const tr = editor.state.tr.replaceWith(pos, pos + node.nodeSize, newNode);
|
|
17692
|
+
tr.setMeta("fromLinkedChild", true);
|
|
17693
|
+
editor.view.dispatch(tr);
|
|
17694
|
+
}
|
|
17695
|
+
});
|
|
17696
|
+
editor.on("update", ({ transaction }) => {
|
|
17697
|
+
const isFromLinkedChild = transaction.getMeta("fromLinkedChild");
|
|
17698
|
+
if (isFromLinkedChild) return;
|
|
17699
|
+
const sectionNode = getAllSections(editor)?.find((s) => s.node.attrs.id === id);
|
|
17700
|
+
if (!sectionNode) return;
|
|
17701
|
+
const sectionContent = sectionNode.node.content;
|
|
17702
|
+
const json = {
|
|
17703
|
+
type: "doc",
|
|
17704
|
+
content: sectionContent.content.map((node) => node.toJSON())
|
|
17705
|
+
};
|
|
17706
|
+
const childTr = child.state.tr;
|
|
17707
|
+
childTr.setMeta("fromLinkedParent", true);
|
|
17708
|
+
childTr.replaceWith(0, child.state.doc.content.size, child.schema.nodeFromJSON(json));
|
|
17709
|
+
child.view.dispatch(childTr);
|
|
17710
|
+
});
|
|
17711
|
+
return child;
|
|
17712
|
+
};
|
|
17713
|
+
const SectionHelpers = {
|
|
17714
|
+
getAllSections,
|
|
17715
|
+
exportSectionsToHTML,
|
|
17716
|
+
exportSectionsToJSON,
|
|
17717
|
+
getLinkedSectionEditor
|
|
17718
|
+
};
|
|
17719
|
+
const DocumentSection = Node$1.create({
|
|
17720
|
+
name: "documentSection",
|
|
17721
|
+
group: "block",
|
|
17722
|
+
content: "block*",
|
|
17723
|
+
atom: true,
|
|
17724
|
+
isolating: true,
|
|
17725
|
+
addOptions() {
|
|
17726
|
+
return {
|
|
17727
|
+
htmlAttributes: {
|
|
17728
|
+
class: "sd-document-section-block",
|
|
17729
|
+
"aria-label": "Structured content block"
|
|
17730
|
+
}
|
|
17731
|
+
};
|
|
17732
|
+
},
|
|
17733
|
+
parseDOM() {
|
|
17734
|
+
return [
|
|
17735
|
+
{
|
|
17736
|
+
tag: "div.sd-document-section-block",
|
|
17737
|
+
priority: 60
|
|
17738
|
+
}
|
|
17739
|
+
];
|
|
17740
|
+
},
|
|
17741
|
+
renderDOM({ htmlAttributes }) {
|
|
17742
|
+
return ["div", Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes), 0];
|
|
17743
|
+
},
|
|
17744
|
+
addAttributes() {
|
|
17745
|
+
return {
|
|
17746
|
+
id: {},
|
|
17747
|
+
sdBlockId: {
|
|
17748
|
+
default: null,
|
|
17749
|
+
keepOnSplit: false,
|
|
17750
|
+
parseDOM: (elem) => elem.getAttribute("data-sd-block-id"),
|
|
17751
|
+
renderDOM: (attrs) => {
|
|
17752
|
+
return attrs.sdBlockId ? { "data-sd-block-id": attrs.sdBlockId } : {};
|
|
17753
|
+
}
|
|
17754
|
+
},
|
|
17755
|
+
title: {},
|
|
17756
|
+
description: {},
|
|
17757
|
+
sectionType: {},
|
|
17758
|
+
isLocked: { default: false }
|
|
17759
|
+
};
|
|
17760
|
+
},
|
|
17761
|
+
addNodeView() {
|
|
17762
|
+
return ({ node, editor, getPos, decorations }) => {
|
|
17763
|
+
return new DocumentSectionView(node, getPos, decorations, editor);
|
|
17764
|
+
};
|
|
17765
|
+
},
|
|
17766
|
+
addCommands() {
|
|
17767
|
+
return {
|
|
17768
|
+
/**
|
|
17769
|
+
* Create a lockable content section
|
|
17770
|
+
* @category Command
|
|
17771
|
+
* @param {SectionCreate} [options={}] - Section configuration
|
|
17772
|
+
* @example
|
|
17773
|
+
* editor.commands.createDocumentSection({
|
|
17774
|
+
* id: 1,
|
|
17775
|
+
* title: 'Terms & Conditions',
|
|
17776
|
+
* isLocked: true,
|
|
17777
|
+
* html: '<p>Legal content...</p>'
|
|
17778
|
+
* })
|
|
17779
|
+
*/
|
|
17780
|
+
createDocumentSection: (options = {}) => ({ tr, state, dispatch, editor }) => {
|
|
17781
|
+
const { selection } = state;
|
|
17782
|
+
let { from: from2, to } = selection;
|
|
17783
|
+
let content = selection.content().content;
|
|
17784
|
+
const { html: optionsHTML, json: optionsJSON } = options;
|
|
17785
|
+
if (optionsHTML) {
|
|
17786
|
+
const html = htmlHandler(optionsHTML, this.editor);
|
|
17787
|
+
const doc2 = DOMParser$1.fromSchema(this.editor.schema).parse(html);
|
|
17788
|
+
content = doc2.content;
|
|
17789
|
+
}
|
|
17790
|
+
if (optionsJSON) {
|
|
17791
|
+
content = this.editor.schema.nodeFromJSON(optionsJSON);
|
|
17792
|
+
}
|
|
17793
|
+
if (!content?.content?.length) {
|
|
17794
|
+
content = this.editor.schema.nodeFromJSON({ type: "paragraph", content: [] });
|
|
17795
|
+
}
|
|
17796
|
+
if (!options.id) {
|
|
17797
|
+
const allSections = SectionHelpers.getAllSections(editor);
|
|
17798
|
+
options.id = allSections.length + 1;
|
|
17799
|
+
}
|
|
17800
|
+
if (!options.title) {
|
|
17801
|
+
options.title = "Document section";
|
|
17802
|
+
}
|
|
17803
|
+
const node = this.type.createAndFill(options, content);
|
|
17804
|
+
if (!node) return false;
|
|
17805
|
+
const isAlreadyInSdtBlock = findParentNode((node2) => node2.type.name === "documentSection")(selection);
|
|
17806
|
+
if (isAlreadyInSdtBlock && isAlreadyInSdtBlock.node) {
|
|
17807
|
+
const insertPos2 = isAlreadyInSdtBlock.pos + isAlreadyInSdtBlock.node.nodeSize;
|
|
17808
|
+
from2 = insertPos2;
|
|
17809
|
+
to = insertPos2;
|
|
17810
|
+
}
|
|
17811
|
+
tr.replaceRangeWith(from2, to, node);
|
|
17812
|
+
const nodeEnd = from2 + node.nodeSize;
|
|
17813
|
+
let shouldInsertParagraph = true;
|
|
17814
|
+
let insertPos = nodeEnd;
|
|
17815
|
+
if (nodeEnd >= tr.doc.content.size) {
|
|
17816
|
+
insertPos = tr.doc.content.size;
|
|
17817
|
+
if (insertPos > 0) {
|
|
17818
|
+
const $endPos = tr.doc.resolve(insertPos);
|
|
17819
|
+
if ($endPos.nodeBefore && $endPos.nodeBefore.type.name === "paragraph") {
|
|
17820
|
+
shouldInsertParagraph = false;
|
|
17821
|
+
}
|
|
17822
|
+
}
|
|
17823
|
+
}
|
|
17824
|
+
if (shouldInsertParagraph) {
|
|
17825
|
+
const emptyParagraph = tr.doc.type.schema.nodes.paragraph.create();
|
|
17826
|
+
tr.insert(insertPos, emptyParagraph);
|
|
17827
|
+
}
|
|
17828
|
+
if (dispatch) {
|
|
17829
|
+
tr.setMeta("documentSection", { action: "create" });
|
|
17830
|
+
dispatch(tr);
|
|
17831
|
+
setTimeout(() => {
|
|
17832
|
+
try {
|
|
17833
|
+
const currentState = editor.state;
|
|
17834
|
+
const docSize = currentState.doc.content.size;
|
|
17835
|
+
let targetPos = from2 + node.nodeSize;
|
|
17836
|
+
if (shouldInsertParagraph) {
|
|
17837
|
+
targetPos += 1;
|
|
17838
|
+
}
|
|
17839
|
+
targetPos = Math.min(targetPos, docSize);
|
|
17840
|
+
if (targetPos < docSize && targetPos > 0) {
|
|
17841
|
+
const newSelection = Selection.near(currentState.doc.resolve(targetPos));
|
|
17842
|
+
const newTr = currentState.tr.setSelection(newSelection);
|
|
17843
|
+
editor.view.dispatch(newTr);
|
|
17844
|
+
}
|
|
17845
|
+
} catch (e) {
|
|
17846
|
+
console.warn("Could not set delayed selection:", e);
|
|
17847
|
+
}
|
|
17848
|
+
}, 0);
|
|
17849
|
+
}
|
|
17850
|
+
return true;
|
|
17851
|
+
},
|
|
17852
|
+
/**
|
|
17853
|
+
* Remove section wrapper at cursor, preserving its content
|
|
17854
|
+
* @category Command
|
|
17855
|
+
* @example
|
|
17856
|
+
* editor.commands.removeSectionAtSelection()
|
|
17857
|
+
* @note Content stays in document, only section wrapper is removed
|
|
17858
|
+
*/
|
|
17859
|
+
removeSectionAtSelection: () => ({ tr, dispatch }) => {
|
|
17860
|
+
const sdtNode = findParentNode((node2) => node2.type.name === "documentSection")(tr.selection);
|
|
17861
|
+
if (!sdtNode) return false;
|
|
17862
|
+
const { node, pos } = sdtNode;
|
|
17863
|
+
const nodeStart = pos;
|
|
17864
|
+
const nodeEnd = nodeStart + node.nodeSize;
|
|
17865
|
+
const contentToPreserve = node.content;
|
|
17866
|
+
tr.delete(nodeStart, nodeEnd);
|
|
17867
|
+
if (contentToPreserve.size > 0) {
|
|
17868
|
+
tr.insert(nodeStart, contentToPreserve);
|
|
17869
|
+
}
|
|
17870
|
+
const newPos = Math.min(nodeStart, tr.doc.content.size);
|
|
17871
|
+
tr.setSelection(Selection.near(tr.doc.resolve(newPos)));
|
|
17872
|
+
if (dispatch) {
|
|
17873
|
+
tr.setMeta("documentSection", { action: "delete" });
|
|
17874
|
+
dispatch(tr);
|
|
17875
|
+
}
|
|
17876
|
+
return true;
|
|
17877
|
+
},
|
|
17878
|
+
/**
|
|
17879
|
+
* Delete section and all its content
|
|
17880
|
+
* @category Command
|
|
17881
|
+
* @param {number} id - Section to delete
|
|
17882
|
+
* @example
|
|
17883
|
+
* editor.commands.removeSectionById(123)
|
|
17884
|
+
*/
|
|
17885
|
+
removeSectionById: (id) => ({ tr, dispatch }) => {
|
|
17886
|
+
const sections = SectionHelpers.getAllSections(this.editor);
|
|
17887
|
+
const sectionToRemove = sections.find(({ node: node2 }) => node2.attrs.id === id);
|
|
17888
|
+
if (!sectionToRemove) return false;
|
|
17889
|
+
const { pos, node } = sectionToRemove;
|
|
17890
|
+
const nodeStart = pos;
|
|
17891
|
+
const nodeEnd = nodeStart + node.nodeSize;
|
|
17892
|
+
tr.delete(nodeStart, nodeEnd);
|
|
17893
|
+
if (dispatch) {
|
|
17894
|
+
tr.setMeta("documentSection", { action: "delete", id });
|
|
17895
|
+
dispatch(tr);
|
|
17896
|
+
}
|
|
17897
|
+
return true;
|
|
17898
|
+
},
|
|
17899
|
+
/**
|
|
17900
|
+
* Lock section against edits
|
|
17901
|
+
* @category Command
|
|
17902
|
+
* @param {number} id - Section to lock
|
|
17903
|
+
* @example
|
|
17904
|
+
* editor.commands.lockSectionById(123)
|
|
17905
|
+
*/
|
|
17906
|
+
lockSectionById: (id) => ({ tr, dispatch }) => {
|
|
17907
|
+
const sections = SectionHelpers.getAllSections(this.editor);
|
|
17908
|
+
const sectionToLock = sections.find(({ node }) => node.attrs.id === id);
|
|
17909
|
+
if (!sectionToLock) return false;
|
|
17910
|
+
tr.setNodeMarkup(sectionToLock.pos, null, { ...sectionToLock.node.attrs, isLocked: true });
|
|
17911
|
+
if (dispatch) {
|
|
17912
|
+
tr.setMeta("documentSection", { action: "lock", id });
|
|
17913
|
+
dispatch(tr);
|
|
17914
|
+
}
|
|
17915
|
+
return true;
|
|
17916
|
+
},
|
|
17917
|
+
/**
|
|
17918
|
+
* Modify section attributes or content
|
|
17919
|
+
* @category Command
|
|
17920
|
+
* @param {SectionUpdate} options - Changes to apply
|
|
17921
|
+
* @example
|
|
17922
|
+
* editor.commands.updateSectionById({ id: 123, attrs: { isLocked: false } })
|
|
17923
|
+
* editor.commands.updateSectionById({ id: 123, html: '<p>New content</p>' })
|
|
17924
|
+
* editor.commands.updateSectionById({
|
|
17925
|
+
* id: 123,
|
|
17926
|
+
* html: '<p>Updated</p>',
|
|
17927
|
+
* attrs: { title: 'New Title' }
|
|
17928
|
+
* })
|
|
17929
|
+
*/
|
|
17930
|
+
updateSectionById: ({ id, html, json, attrs }) => ({ tr, dispatch, editor }) => {
|
|
17931
|
+
const sections = SectionHelpers.getAllSections(editor || this.editor);
|
|
17932
|
+
const sectionToUpdate = sections.find(({ node: node2 }) => node2.attrs.id === id);
|
|
17933
|
+
if (!sectionToUpdate) return false;
|
|
17934
|
+
const { pos, node } = sectionToUpdate;
|
|
17935
|
+
let newContent = null;
|
|
17936
|
+
if (html) {
|
|
17937
|
+
const htmlDoc = htmlHandler(html, editor || this.editor);
|
|
17938
|
+
const doc2 = DOMParser$1.fromSchema((editor || this.editor).schema).parse(htmlDoc);
|
|
17939
|
+
newContent = doc2.content;
|
|
17940
|
+
}
|
|
17941
|
+
if (json) {
|
|
17942
|
+
newContent = (editor || this.editor).schema.nodeFromJSON(json);
|
|
17943
|
+
}
|
|
17944
|
+
if (!newContent) {
|
|
17945
|
+
newContent = node.content;
|
|
17946
|
+
}
|
|
17947
|
+
const updatedNode = node.type.create({ ...node.attrs, ...attrs }, newContent, node.marks);
|
|
17948
|
+
tr.replaceWith(pos, pos + node.nodeSize, updatedNode);
|
|
17949
|
+
if (dispatch) {
|
|
17950
|
+
tr.setMeta("documentSection", { action: "update", id, attrs });
|
|
17951
|
+
dispatch(tr);
|
|
17952
|
+
}
|
|
17953
|
+
return true;
|
|
17954
|
+
}
|
|
17955
|
+
};
|
|
17956
|
+
},
|
|
17957
|
+
addHelpers() {
|
|
17958
|
+
return {
|
|
17959
|
+
...SectionHelpers
|
|
17960
|
+
};
|
|
17961
|
+
}
|
|
17962
|
+
});
|
|
17963
|
+
const Document = Node$1.create({
|
|
17964
|
+
name: "doc",
|
|
17965
|
+
topNode: true,
|
|
17966
|
+
content: "block+",
|
|
17967
|
+
parseDOM() {
|
|
17968
|
+
return [{ tag: "doc" }];
|
|
17969
|
+
},
|
|
17970
|
+
renderDOM() {
|
|
17971
|
+
return ["doc", 0];
|
|
17972
|
+
},
|
|
17973
|
+
addAttributes() {
|
|
17974
|
+
return {
|
|
17975
|
+
attributes: {
|
|
17976
|
+
rendered: false,
|
|
17977
|
+
"aria-label": "Document node"
|
|
17978
|
+
}
|
|
17979
|
+
};
|
|
17980
|
+
},
|
|
17981
|
+
addCommands() {
|
|
17982
|
+
return {
|
|
17983
|
+
/**
|
|
17984
|
+
* Get document statistics
|
|
17985
|
+
* @category Command
|
|
17986
|
+
* @example
|
|
17987
|
+
* // Get word and character count
|
|
17988
|
+
* const stats = editor.commands.getDocumentStats()
|
|
17989
|
+
* console.log(`${stats.words} words, ${stats.characters} characters`)
|
|
17990
|
+
* @note Returns word count, character count, and paragraph count
|
|
17991
|
+
*/
|
|
17992
|
+
getDocumentStats: () => ({ editor }) => {
|
|
17993
|
+
const text = editor.getText();
|
|
17994
|
+
const words = text.split(/\s+/).filter((word) => word.length > 0).length;
|
|
17995
|
+
const characters = text.length;
|
|
17996
|
+
const paragraphs = editor.state.doc.content.childCount;
|
|
17997
|
+
return {
|
|
17998
|
+
words,
|
|
17999
|
+
characters,
|
|
18000
|
+
paragraphs
|
|
18001
|
+
};
|
|
18002
|
+
},
|
|
18003
|
+
/**
|
|
18004
|
+
* Clear entire document
|
|
18005
|
+
* @category Command
|
|
18006
|
+
* @example
|
|
18007
|
+
* editor.commands.clearDocument()
|
|
18008
|
+
* @note Replaces all content with an empty paragraph
|
|
18009
|
+
*/
|
|
18010
|
+
clearDocument: () => ({ commands: commands2 }) => {
|
|
18011
|
+
return commands2.setContent("<p></p>");
|
|
18012
|
+
}
|
|
18013
|
+
};
|
|
18014
|
+
}
|
|
18015
|
+
});
|
|
18016
|
+
const Text = Node$1.create({
|
|
18017
|
+
name: "text",
|
|
18018
|
+
group: "inline",
|
|
18019
|
+
inline: true,
|
|
18020
|
+
addOptions() {
|
|
18021
|
+
return {};
|
|
18022
|
+
}
|
|
18023
|
+
});
|
|
18024
|
+
const splitRun = () => (props) => {
|
|
18025
|
+
const { state, view, tr } = props;
|
|
18026
|
+
const { $from, empty: empty2 } = state.selection;
|
|
18027
|
+
if (!empty2) return false;
|
|
18028
|
+
if ($from.parent.type.name !== "run") return false;
|
|
18029
|
+
const handled = splitBlock(state, (transaction) => {
|
|
18030
|
+
view.dispatch(transaction);
|
|
18031
|
+
});
|
|
18032
|
+
if (handled) {
|
|
18033
|
+
tr.setMeta("preventDispatch", true);
|
|
18034
|
+
}
|
|
18035
|
+
return handled;
|
|
18036
|
+
};
|
|
18037
|
+
const Run = OxmlNode.create({
|
|
18038
|
+
name: "run",
|
|
18039
|
+
oXmlName: "w:r",
|
|
18040
|
+
group: "inline",
|
|
18041
|
+
inline: true,
|
|
18042
|
+
content: "inline*",
|
|
18043
|
+
selectable: false,
|
|
18044
|
+
childToAttributes: ["runProperties"],
|
|
18045
|
+
addOptions() {
|
|
18046
|
+
return {
|
|
18047
|
+
htmlAttributes: {
|
|
18048
|
+
"data-run": "1"
|
|
18049
|
+
}
|
|
18050
|
+
};
|
|
18051
|
+
},
|
|
18052
|
+
addAttributes() {
|
|
18053
|
+
return {
|
|
18054
|
+
runProperties: {
|
|
18055
|
+
default: null,
|
|
18056
|
+
rendered: false,
|
|
18057
|
+
keepOnSplit: true
|
|
18058
|
+
},
|
|
18059
|
+
rsidR: {
|
|
18060
|
+
default: null,
|
|
18061
|
+
rendered: false,
|
|
18062
|
+
keepOnSplit: true
|
|
18063
|
+
},
|
|
18064
|
+
rsidRPr: {
|
|
18065
|
+
default: null,
|
|
18066
|
+
rendered: false,
|
|
18067
|
+
keepOnSplit: true
|
|
18068
|
+
},
|
|
18069
|
+
rsidDel: {
|
|
18070
|
+
default: null,
|
|
18071
|
+
rendered: false,
|
|
18072
|
+
keepOnSplit: true
|
|
18073
|
+
}
|
|
18074
|
+
};
|
|
18075
|
+
},
|
|
18076
|
+
addCommands() {
|
|
18077
|
+
return {
|
|
18078
|
+
splitRun
|
|
18079
|
+
};
|
|
18080
|
+
},
|
|
18081
|
+
parseDOM() {
|
|
18082
|
+
return [{ tag: "span[data-run]" }];
|
|
18083
|
+
},
|
|
18084
|
+
renderDOM({ htmlAttributes }) {
|
|
18085
|
+
const base2 = Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes);
|
|
18086
|
+
return ["span", base2, 0];
|
|
18087
|
+
}
|
|
18088
|
+
});
|
|
18089
|
+
const inputRegex$1 = /^\s*([-+*])\s$/;
|
|
18090
|
+
const BulletList = Node$1.create({
|
|
18091
|
+
name: "bulletList",
|
|
18092
|
+
group: "block list",
|
|
18093
|
+
selectable: false,
|
|
18094
|
+
content() {
|
|
18095
|
+
return `${this.options.itemTypeName}+`;
|
|
18096
|
+
},
|
|
18097
|
+
addOptions() {
|
|
18098
|
+
return {
|
|
18099
|
+
itemTypeName: "listItem",
|
|
18100
|
+
htmlAttributes: {
|
|
18101
|
+
"aria-label": "Bullet list node"
|
|
18102
|
+
},
|
|
18103
|
+
keepMarks: true,
|
|
18104
|
+
keepAttributes: false
|
|
18105
|
+
};
|
|
18106
|
+
},
|
|
18107
|
+
parseDOM() {
|
|
18108
|
+
return [{ tag: "ul" }];
|
|
18109
|
+
},
|
|
18110
|
+
renderDOM({ htmlAttributes }) {
|
|
18111
|
+
const attributes = Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes);
|
|
18112
|
+
return ["ul", attributes, 0];
|
|
18113
|
+
},
|
|
18114
|
+
addAttributes() {
|
|
18115
|
+
return {
|
|
18116
|
+
"list-style-type": {
|
|
18117
|
+
default: "bullet",
|
|
18118
|
+
rendered: false
|
|
18119
|
+
},
|
|
18120
|
+
listId: {
|
|
18121
|
+
rendered: false
|
|
18122
|
+
},
|
|
18123
|
+
sdBlockId: {
|
|
18124
|
+
default: null,
|
|
18125
|
+
keepOnSplit: false,
|
|
18126
|
+
parseDOM: (elem) => elem.getAttribute("data-sd-block-id"),
|
|
18127
|
+
renderDOM: (attrs) => {
|
|
18128
|
+
return attrs.sdBlockId ? { "data-sd-block-id": attrs.sdBlockId } : {};
|
|
18129
|
+
}
|
|
18130
|
+
},
|
|
18131
|
+
attributes: {
|
|
18132
|
+
rendered: false,
|
|
18133
|
+
keepOnSplit: true
|
|
18134
|
+
}
|
|
18135
|
+
};
|
|
18136
|
+
},
|
|
18137
|
+
addCommands() {
|
|
18138
|
+
return {
|
|
18139
|
+
/**
|
|
18140
|
+
* Toggle a bullet list at the current selection
|
|
18141
|
+
* @category Command
|
|
18142
|
+
* @example
|
|
18143
|
+
* // Toggle bullet list on selected text
|
|
18144
|
+
* editor.commands.toggleBulletList()
|
|
18145
|
+
* @note Converts selected paragraphs to list items or removes list formatting
|
|
18146
|
+
*/
|
|
18147
|
+
toggleBulletList: () => (params2) => {
|
|
18148
|
+
return toggleList(this.type)(params2);
|
|
18149
|
+
}
|
|
18150
|
+
};
|
|
18151
|
+
},
|
|
18152
|
+
addShortcuts() {
|
|
18153
|
+
return {
|
|
18154
|
+
"Mod-Shift-8": () => {
|
|
18155
|
+
return this.editor.commands.toggleBulletList();
|
|
18156
|
+
}
|
|
18157
|
+
};
|
|
18158
|
+
},
|
|
18159
|
+
addInputRules() {
|
|
18160
|
+
return [
|
|
18161
|
+
new InputRule({
|
|
18162
|
+
match: inputRegex$1,
|
|
18163
|
+
handler: ({ state, range }) => {
|
|
18164
|
+
const $pos = state.selection.$from;
|
|
18165
|
+
const listItemType = state.schema.nodes.listItem;
|
|
18166
|
+
for (let depth = $pos.depth; depth >= 0; depth--) {
|
|
18167
|
+
if ($pos.node(depth).type === listItemType) {
|
|
18168
|
+
return null;
|
|
18169
|
+
}
|
|
18170
|
+
}
|
|
18171
|
+
const { tr } = state;
|
|
18172
|
+
tr.delete(range.from, range.to);
|
|
18173
|
+
ListHelpers.createNewList({
|
|
18174
|
+
listType: this.type,
|
|
18175
|
+
tr,
|
|
18176
|
+
editor: this.editor
|
|
18177
|
+
});
|
|
18178
|
+
}
|
|
18179
|
+
})
|
|
17199
18180
|
];
|
|
17200
18181
|
}
|
|
17201
18182
|
});
|
|
@@ -18561,7 +19542,7 @@ class ListItemNodeView {
|
|
|
18561
19542
|
this.decorations = decorations;
|
|
18562
19543
|
this.view = editor.view;
|
|
18563
19544
|
this.getPos = getPos;
|
|
18564
|
-
__privateMethod(this, _ListItemNodeView_instances,
|
|
19545
|
+
__privateMethod(this, _ListItemNodeView_instances, init_fn3).call(this);
|
|
18565
19546
|
activeListItemNodeViews.add(this);
|
|
18566
19547
|
}
|
|
18567
19548
|
refreshIndentStyling() {
|
|
@@ -18622,7 +19603,7 @@ class ListItemNodeView {
|
|
|
18622
19603
|
}
|
|
18623
19604
|
}
|
|
18624
19605
|
_ListItemNodeView_instances = new WeakSet();
|
|
18625
|
-
|
|
19606
|
+
init_fn3 = function() {
|
|
18626
19607
|
const { attrs } = this.node;
|
|
18627
19608
|
const { listLevel, listNumberingType, lvlText, numId, level, customFormat } = attrs;
|
|
18628
19609
|
let orderMarker = "";
|
|
@@ -25731,984 +26712,335 @@ const PageNumber = Node$1.create({
|
|
|
25731
26712
|
}
|
|
25732
26713
|
};
|
|
25733
26714
|
},
|
|
25734
|
-
addAttributes() {
|
|
25735
|
-
return {
|
|
25736
|
-
marksAsAttrs: {
|
|
25737
|
-
default: null,
|
|
25738
|
-
rendered: false
|
|
25739
|
-
}
|
|
25740
|
-
};
|
|
25741
|
-
},
|
|
25742
|
-
addNodeView() {
|
|
25743
|
-
return ({ node, editor, getPos, decorations }) => {
|
|
25744
|
-
const htmlAttributes = this.options.htmlAttributes;
|
|
25745
|
-
return new AutoPageNumberNodeView(node, getPos, decorations, editor, htmlAttributes);
|
|
25746
|
-
};
|
|
25747
|
-
},
|
|
25748
|
-
parseDOM() {
|
|
25749
|
-
return [{ tag: 'span[data-id="auto-page-number"' }];
|
|
25750
|
-
},
|
|
25751
|
-
renderDOM({ htmlAttributes }) {
|
|
25752
|
-
return ["span", Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes)];
|
|
25753
|
-
},
|
|
25754
|
-
addCommands() {
|
|
25755
|
-
return {
|
|
25756
|
-
/**
|
|
25757
|
-
* Insert an automatic page number
|
|
25758
|
-
* @category Command
|
|
25759
|
-
* @returns {Function} Command function
|
|
25760
|
-
* @example
|
|
25761
|
-
* editor.commands.addAutoPageNumber()
|
|
25762
|
-
* @note Only works in header/footer contexts
|
|
25763
|
-
*/
|
|
25764
|
-
addAutoPageNumber: () => ({ tr, dispatch, state, editor }) => {
|
|
25765
|
-
const { options } = editor;
|
|
25766
|
-
if (!options.isHeaderOrFooter) return false;
|
|
25767
|
-
const { schema } = state;
|
|
25768
|
-
const pageNumberType = schema?.nodes?.["page-number"];
|
|
25769
|
-
if (!pageNumberType) return false;
|
|
25770
|
-
const pageNumberNodeJSON = { type: "page-number" };
|
|
25771
|
-
const pageNumberNode = schema.nodeFromJSON(pageNumberNodeJSON);
|
|
25772
|
-
if (dispatch) {
|
|
25773
|
-
tr.replaceSelectionWith(pageNumberNode, false);
|
|
25774
|
-
tr.setMeta("forceUpdatePagination", true);
|
|
25775
|
-
}
|
|
25776
|
-
return true;
|
|
25777
|
-
}
|
|
25778
|
-
};
|
|
25779
|
-
},
|
|
25780
|
-
addShortcuts() {
|
|
25781
|
-
return {
|
|
25782
|
-
"Mod-Shift-alt-p": () => this.editor.commands.addAutoPageNumber()
|
|
25783
|
-
};
|
|
25784
|
-
}
|
|
25785
|
-
});
|
|
25786
|
-
const TotalPageCount = Node$1.create({
|
|
25787
|
-
name: "total-page-number",
|
|
25788
|
-
group: "inline",
|
|
25789
|
-
inline: true,
|
|
25790
|
-
atom: true,
|
|
25791
|
-
draggable: false,
|
|
25792
|
-
selectable: false,
|
|
25793
|
-
content: "text*",
|
|
25794
|
-
addOptions() {
|
|
25795
|
-
return {
|
|
25796
|
-
htmlAttributes: {
|
|
25797
|
-
contenteditable: false,
|
|
25798
|
-
"data-id": "auto-total-pages",
|
|
25799
|
-
"aria-label": "Total page count node",
|
|
25800
|
-
class: "sd-editor-auto-total-pages"
|
|
25801
|
-
}
|
|
25802
|
-
};
|
|
25803
|
-
},
|
|
25804
|
-
addAttributes() {
|
|
25805
|
-
return {
|
|
25806
|
-
marksAsAttrs: {
|
|
25807
|
-
default: null,
|
|
25808
|
-
rendered: false
|
|
25809
|
-
}
|
|
25810
|
-
};
|
|
25811
|
-
},
|
|
25812
|
-
addNodeView() {
|
|
25813
|
-
return ({ node, editor, getPos, decorations }) => {
|
|
25814
|
-
const htmlAttributes = this.options.htmlAttributes;
|
|
25815
|
-
return new AutoPageNumberNodeView(node, getPos, decorations, editor, htmlAttributes);
|
|
25816
|
-
};
|
|
25817
|
-
},
|
|
25818
|
-
parseDOM() {
|
|
25819
|
-
return [{ tag: 'span[data-id="auto-total-pages"' }];
|
|
25820
|
-
},
|
|
25821
|
-
renderDOM({ htmlAttributes }) {
|
|
25822
|
-
return ["span", Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes), 0];
|
|
25823
|
-
},
|
|
25824
|
-
addCommands() {
|
|
25825
|
-
return {
|
|
25826
|
-
/**
|
|
25827
|
-
* Insert total page count
|
|
25828
|
-
* @category Command
|
|
25829
|
-
* @returns {Function} Command function
|
|
25830
|
-
* @example
|
|
25831
|
-
* editor.commands.addTotalPageCount()
|
|
25832
|
-
* @note Only works in header/footer contexts
|
|
25833
|
-
*/
|
|
25834
|
-
addTotalPageCount: () => ({ tr, dispatch, state, editor }) => {
|
|
25835
|
-
const { options } = editor;
|
|
25836
|
-
if (!options.isHeaderOrFooter) return false;
|
|
25837
|
-
const { schema } = state;
|
|
25838
|
-
const pageNumberType = schema.nodes?.["total-page-number"];
|
|
25839
|
-
if (!pageNumberType) return false;
|
|
25840
|
-
const currentPages = editor?.options?.parentEditor?.currentTotalPages || 1;
|
|
25841
|
-
const pageNumberNode = {
|
|
25842
|
-
type: "total-page-number",
|
|
25843
|
-
content: [{ type: "text", text: String(currentPages) }]
|
|
25844
|
-
};
|
|
25845
|
-
const pageNode = schema.nodeFromJSON(pageNumberNode);
|
|
25846
|
-
if (dispatch) {
|
|
25847
|
-
tr.replaceSelectionWith(pageNode, false);
|
|
25848
|
-
}
|
|
25849
|
-
return true;
|
|
25850
|
-
}
|
|
25851
|
-
};
|
|
25852
|
-
},
|
|
25853
|
-
addShortcuts() {
|
|
25854
|
-
return {
|
|
25855
|
-
"Mod-Shift-alt-c": () => this.editor.commands.addTotalPageCount()
|
|
25856
|
-
};
|
|
25857
|
-
}
|
|
25858
|
-
});
|
|
25859
|
-
const getNodeAttributes = (nodeName, editor) => {
|
|
25860
|
-
switch (nodeName) {
|
|
25861
|
-
case "page-number":
|
|
25862
|
-
return {
|
|
25863
|
-
text: editor.options.currentPageNumber || "1",
|
|
25864
|
-
className: "sd-editor-auto-page-number",
|
|
25865
|
-
dataId: "auto-page-number",
|
|
25866
|
-
ariaLabel: "Page number node"
|
|
25867
|
-
};
|
|
25868
|
-
case "total-page-number":
|
|
25869
|
-
return {
|
|
25870
|
-
text: editor.options.parentEditor?.currentTotalPages || "1",
|
|
25871
|
-
className: "sd-editor-auto-total-pages",
|
|
25872
|
-
dataId: "auto-total-pages",
|
|
25873
|
-
ariaLabel: "Total page count node"
|
|
25874
|
-
};
|
|
25875
|
-
default:
|
|
25876
|
-
return {};
|
|
25877
|
-
}
|
|
25878
|
-
};
|
|
25879
|
-
class AutoPageNumberNodeView {
|
|
25880
|
-
constructor(node, getPos, decorations, editor, htmlAttributes = {}) {
|
|
25881
|
-
__privateAdd(this, _AutoPageNumberNodeView_instances);
|
|
25882
|
-
this.node = node;
|
|
25883
|
-
this.editor = editor;
|
|
25884
|
-
this.view = editor.view;
|
|
25885
|
-
this.getPos = getPos;
|
|
25886
|
-
this.editor = editor;
|
|
25887
|
-
this.dom = __privateMethod(this, _AutoPageNumberNodeView_instances, renderDom_fn).call(this, node, htmlAttributes);
|
|
25888
|
-
}
|
|
25889
|
-
update(node) {
|
|
25890
|
-
const incomingType = node?.type?.name;
|
|
25891
|
-
const currentType = this.node?.type?.name;
|
|
25892
|
-
if (!incomingType || incomingType !== currentType) return false;
|
|
25893
|
-
this.node = node;
|
|
25894
|
-
return true;
|
|
25895
|
-
}
|
|
25896
|
-
}
|
|
25897
|
-
_AutoPageNumberNodeView_instances = new WeakSet();
|
|
25898
|
-
renderDom_fn = function(node, htmlAttributes) {
|
|
25899
|
-
const attrs = getNodeAttributes(this.node.type.name, this.editor);
|
|
25900
|
-
const content = document.createTextNode(String(attrs.text));
|
|
25901
|
-
const nodeContent = document.createElement("span");
|
|
25902
|
-
nodeContent.className = attrs.className;
|
|
25903
|
-
nodeContent.setAttribute("data-id", attrs.dataId);
|
|
25904
|
-
nodeContent.setAttribute("aria-label", attrs.ariaLabel);
|
|
25905
|
-
const currentPos = this.getPos();
|
|
25906
|
-
const { styles, marks } = getMarksFromNeighbors(currentPos, this.view);
|
|
25907
|
-
__privateMethod(this, _AutoPageNumberNodeView_instances, scheduleUpdateNodeStyle_fn).call(this, currentPos, marks);
|
|
25908
|
-
Object.assign(nodeContent.style, styles);
|
|
25909
|
-
nodeContent.appendChild(content);
|
|
25910
|
-
Object.entries(htmlAttributes).forEach(([key2, value]) => {
|
|
25911
|
-
if (value) nodeContent.setAttribute(key2, value);
|
|
25912
|
-
});
|
|
25913
|
-
return nodeContent;
|
|
25914
|
-
};
|
|
25915
|
-
scheduleUpdateNodeStyle_fn = function(pos, marks) {
|
|
25916
|
-
setTimeout(() => {
|
|
25917
|
-
const { state } = this.editor;
|
|
25918
|
-
const { dispatch } = this.view;
|
|
25919
|
-
const node = state.doc.nodeAt(pos);
|
|
25920
|
-
if (!node || node.isText) return;
|
|
25921
|
-
const currentMarks = node.attrs.marksAsAttrs || [];
|
|
25922
|
-
const newMarks = marks.map((m) => ({ type: m.type.name, attrs: m.attrs }));
|
|
25923
|
-
const isEqual = JSON.stringify(currentMarks) === JSON.stringify(newMarks);
|
|
25924
|
-
if (isEqual) return;
|
|
25925
|
-
const newAttrs = {
|
|
25926
|
-
...node.attrs,
|
|
25927
|
-
marksAsAttrs: newMarks
|
|
25928
|
-
};
|
|
25929
|
-
const tr = state.tr.setNodeMarkup(pos, void 0, newAttrs);
|
|
25930
|
-
dispatch(tr);
|
|
25931
|
-
}, 0);
|
|
25932
|
-
};
|
|
25933
|
-
const getMarksFromNeighbors = (currentPos, view) => {
|
|
25934
|
-
const $pos = view.state.doc.resolve(currentPos);
|
|
25935
|
-
const styles = {};
|
|
25936
|
-
const marks = [];
|
|
25937
|
-
const before = $pos.nodeBefore;
|
|
25938
|
-
if (before) {
|
|
25939
|
-
Object.assign(styles, processMarks(before.marks));
|
|
25940
|
-
marks.push(...before.marks);
|
|
25941
|
-
}
|
|
25942
|
-
const after = $pos.nodeAfter;
|
|
25943
|
-
if (after) {
|
|
25944
|
-
Object.assign(styles, { ...styles, ...processMarks(after.marks) });
|
|
25945
|
-
marks.push(...after.marks);
|
|
25946
|
-
}
|
|
25947
|
-
return {
|
|
25948
|
-
styles,
|
|
25949
|
-
marks
|
|
25950
|
-
};
|
|
25951
|
-
};
|
|
25952
|
-
const processMarks = (marks) => {
|
|
25953
|
-
const styles = {};
|
|
25954
|
-
marks.forEach((mark) => {
|
|
25955
|
-
const { type, attrs } = mark;
|
|
25956
|
-
switch (type.name) {
|
|
25957
|
-
case "textStyle":
|
|
25958
|
-
if (attrs.fontFamily) styles["font-family"] = attrs.fontFamily;
|
|
25959
|
-
if (attrs.fontSize) styles["font-size"] = attrs.fontSize;
|
|
25960
|
-
if (attrs.color) styles["color"] = attrs.color;
|
|
25961
|
-
if (attrs.backgroundColor) styles["background-color"] = attrs.backgroundColor;
|
|
25962
|
-
break;
|
|
25963
|
-
case "bold":
|
|
25964
|
-
styles["font-weight"] = "bold";
|
|
25965
|
-
break;
|
|
25966
|
-
case "italic":
|
|
25967
|
-
styles["font-style"] = "italic";
|
|
25968
|
-
break;
|
|
25969
|
-
case "underline":
|
|
25970
|
-
styles["text-decoration"] = (styles["text-decoration"] || "") + " underline";
|
|
25971
|
-
break;
|
|
25972
|
-
case "strike":
|
|
25973
|
-
styles["text-decoration"] = (styles["text-decoration"] || "") + " line-through";
|
|
25974
|
-
break;
|
|
25975
|
-
default:
|
|
25976
|
-
if (attrs?.style) {
|
|
25977
|
-
Object.entries(attrs.style).forEach(([key2, value]) => {
|
|
25978
|
-
styles[key2] = value;
|
|
25979
|
-
});
|
|
25980
|
-
}
|
|
25981
|
-
break;
|
|
25982
|
-
}
|
|
25983
|
-
});
|
|
25984
|
-
return styles;
|
|
25985
|
-
};
|
|
25986
|
-
const ShapeContainer = Node$1.create({
|
|
25987
|
-
name: "shapeContainer",
|
|
25988
|
-
group: "block",
|
|
25989
|
-
content: "block+",
|
|
25990
|
-
isolating: true,
|
|
25991
|
-
addOptions() {
|
|
25992
|
-
return {
|
|
25993
|
-
htmlAttributes: {
|
|
25994
|
-
class: "sd-editor-shape-container",
|
|
25995
|
-
"aria-label": "Shape container node"
|
|
25996
|
-
}
|
|
25997
|
-
};
|
|
25998
|
-
},
|
|
25999
|
-
addAttributes() {
|
|
26000
|
-
return {
|
|
26001
|
-
fillcolor: {
|
|
26002
|
-
renderDOM: (attrs) => {
|
|
26003
|
-
if (!attrs.fillcolor) return {};
|
|
26004
|
-
return {
|
|
26005
|
-
style: `background-color: ${attrs.fillcolor}`
|
|
26006
|
-
};
|
|
26007
|
-
}
|
|
26008
|
-
},
|
|
26009
|
-
sdBlockId: {
|
|
26010
|
-
default: null,
|
|
26011
|
-
keepOnSplit: false,
|
|
26012
|
-
parseDOM: (elem) => elem.getAttribute("data-sd-block-id"),
|
|
26013
|
-
renderDOM: (attrs) => {
|
|
26014
|
-
return attrs.sdBlockId ? { "data-sd-block-id": attrs.sdBlockId } : {};
|
|
26015
|
-
}
|
|
26016
|
-
},
|
|
26017
|
-
style: {
|
|
26018
|
-
renderDOM: (attrs) => {
|
|
26019
|
-
if (!attrs.style) return {};
|
|
26020
|
-
return {
|
|
26021
|
-
style: attrs.style
|
|
26022
|
-
};
|
|
26023
|
-
}
|
|
26024
|
-
},
|
|
26025
|
-
wrapAttributes: {
|
|
26026
|
-
rendered: false
|
|
26027
|
-
},
|
|
26028
|
-
attributes: {
|
|
26029
|
-
rendered: false
|
|
26030
|
-
}
|
|
26031
|
-
};
|
|
26032
|
-
},
|
|
26033
|
-
parseDOM() {
|
|
26034
|
-
return [
|
|
26035
|
-
{
|
|
26036
|
-
tag: `div[data-type="${this.name}"]`
|
|
26037
|
-
}
|
|
26038
|
-
];
|
|
26039
|
-
},
|
|
26040
|
-
renderDOM({ htmlAttributes }) {
|
|
26041
|
-
return [
|
|
26042
|
-
"div",
|
|
26043
|
-
Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes, { "data-type": this.name }),
|
|
26044
|
-
0
|
|
26045
|
-
];
|
|
26046
|
-
}
|
|
26047
|
-
});
|
|
26048
|
-
const ShapeTextbox = Node$1.create({
|
|
26049
|
-
name: "shapeTextbox",
|
|
26050
|
-
group: "block",
|
|
26051
|
-
content: "paragraph* block*",
|
|
26052
|
-
isolating: true,
|
|
26053
|
-
addOptions() {
|
|
26054
|
-
return {
|
|
26055
|
-
htmlAttributes: {
|
|
26056
|
-
class: "sd-editor-shape-textbox",
|
|
26057
|
-
"aria-label": "Shape textbox node"
|
|
26058
|
-
}
|
|
26059
|
-
};
|
|
26060
|
-
},
|
|
26061
|
-
addAttributes() {
|
|
26062
|
-
return {
|
|
26063
|
-
sdBlockId: {
|
|
26064
|
-
default: null,
|
|
26065
|
-
keepOnSplit: false,
|
|
26066
|
-
parseDOM: (elem) => elem.getAttribute("data-sd-block-id"),
|
|
26067
|
-
renderDOM: (attrs) => {
|
|
26068
|
-
return attrs.sdBlockId ? { "data-sd-block-id": attrs.sdBlockId } : {};
|
|
26069
|
-
}
|
|
26070
|
-
},
|
|
26071
|
-
attributes: {
|
|
26072
|
-
rendered: false
|
|
26073
|
-
}
|
|
26074
|
-
};
|
|
26075
|
-
},
|
|
26076
|
-
parseDOM() {
|
|
26077
|
-
return [
|
|
26078
|
-
{
|
|
26079
|
-
tag: `div[data-type="${this.name}"]`
|
|
26080
|
-
}
|
|
26081
|
-
];
|
|
26082
|
-
},
|
|
26083
|
-
renderDOM({ htmlAttributes }) {
|
|
26084
|
-
return [
|
|
26085
|
-
"div",
|
|
26086
|
-
Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes, { "data-type": this.name }),
|
|
26087
|
-
0
|
|
26088
|
-
];
|
|
26089
|
-
}
|
|
26090
|
-
});
|
|
26091
|
-
const ContentBlock = Node$1.create({
|
|
26092
|
-
name: "contentBlock",
|
|
26093
|
-
group: "inline",
|
|
26094
|
-
content: "",
|
|
26095
|
-
isolating: true,
|
|
26096
|
-
atom: true,
|
|
26097
|
-
inline: true,
|
|
26098
|
-
addOptions() {
|
|
26099
|
-
return {
|
|
26100
|
-
htmlAttributes: {
|
|
26101
|
-
contenteditable: false
|
|
26102
|
-
}
|
|
26103
|
-
};
|
|
26104
|
-
},
|
|
26105
|
-
addAttributes() {
|
|
26106
|
-
return {
|
|
26107
|
-
horizontalRule: {
|
|
26108
|
-
default: false,
|
|
26109
|
-
renderDOM: ({ horizontalRule }) => {
|
|
26110
|
-
if (!horizontalRule) return {};
|
|
26111
|
-
return { "data-horizontal-rule": "true" };
|
|
26112
|
-
}
|
|
26113
|
-
},
|
|
26114
|
-
size: {
|
|
26115
|
-
default: null,
|
|
26116
|
-
renderDOM: ({ size }) => {
|
|
26117
|
-
if (!size) return {};
|
|
26118
|
-
let style = "";
|
|
26119
|
-
if (size.top) style += `top: ${size.top}px; `;
|
|
26120
|
-
if (size.left) style += `left: ${size.left}px; `;
|
|
26121
|
-
if (size.width) style += `width: ${size.width.toString().endsWith("%") ? size.width : `${size.width}px`}; `;
|
|
26122
|
-
if (size.height)
|
|
26123
|
-
style += `height: ${size.height.toString().endsWith("%") ? size.height : `${size.height}px`}; `;
|
|
26124
|
-
return { style };
|
|
26125
|
-
}
|
|
26126
|
-
},
|
|
26127
|
-
background: {
|
|
26128
|
-
default: null,
|
|
26129
|
-
renderDOM: (attrs) => {
|
|
26130
|
-
if (!attrs.background) return {};
|
|
26131
|
-
return {
|
|
26132
|
-
style: `background-color: ${attrs.background}`
|
|
26133
|
-
};
|
|
26134
|
-
}
|
|
26135
|
-
},
|
|
26136
|
-
drawingContent: {
|
|
26137
|
-
rendered: false
|
|
26138
|
-
},
|
|
26139
|
-
attributes: {
|
|
26715
|
+
addAttributes() {
|
|
26716
|
+
return {
|
|
26717
|
+
marksAsAttrs: {
|
|
26718
|
+
default: null,
|
|
26140
26719
|
rendered: false
|
|
26141
26720
|
}
|
|
26142
26721
|
};
|
|
26143
26722
|
},
|
|
26723
|
+
addNodeView() {
|
|
26724
|
+
return ({ node, editor, getPos, decorations }) => {
|
|
26725
|
+
const htmlAttributes = this.options.htmlAttributes;
|
|
26726
|
+
return new AutoPageNumberNodeView(node, getPos, decorations, editor, htmlAttributes);
|
|
26727
|
+
};
|
|
26728
|
+
},
|
|
26144
26729
|
parseDOM() {
|
|
26145
|
-
return [
|
|
26146
|
-
{
|
|
26147
|
-
tag: `div[data-type="${this.name}"]`
|
|
26148
|
-
}
|
|
26149
|
-
];
|
|
26730
|
+
return [{ tag: 'span[data-id="auto-page-number"' }];
|
|
26150
26731
|
},
|
|
26151
26732
|
renderDOM({ htmlAttributes }) {
|
|
26152
|
-
return ["
|
|
26733
|
+
return ["span", Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes)];
|
|
26153
26734
|
},
|
|
26154
26735
|
addCommands() {
|
|
26155
26736
|
return {
|
|
26156
26737
|
/**
|
|
26157
|
-
* Insert
|
|
26158
|
-
* @category Command
|
|
26159
|
-
* @example
|
|
26160
|
-
* editor.commands.insertHorizontalRule()
|
|
26161
|
-
* @note Creates a visual separator between content sections
|
|
26162
|
-
*/
|
|
26163
|
-
insertHorizontalRule: () => ({ commands: commands2 }) => {
|
|
26164
|
-
return commands2.insertContent({
|
|
26165
|
-
type: this.name,
|
|
26166
|
-
attrs: {
|
|
26167
|
-
horizontalRule: true,
|
|
26168
|
-
size: { width: "100%", height: 2 },
|
|
26169
|
-
background: "#e5e7eb"
|
|
26170
|
-
}
|
|
26171
|
-
});
|
|
26172
|
-
},
|
|
26173
|
-
/**
|
|
26174
|
-
* Insert a content block
|
|
26738
|
+
* Insert an automatic page number
|
|
26175
26739
|
* @category Command
|
|
26176
|
-
* @
|
|
26177
|
-
* @example
|
|
26178
|
-
* // Insert a spacer block
|
|
26179
|
-
* editor.commands.insertContentBlock({ size: { height: 20 } })
|
|
26180
|
-
*
|
|
26740
|
+
* @returns {Function} Command function
|
|
26181
26741
|
* @example
|
|
26182
|
-
*
|
|
26183
|
-
*
|
|
26184
|
-
* size: { width: '50%', height: 3 },
|
|
26185
|
-
* background: '#3b82f6'
|
|
26186
|
-
* })
|
|
26187
|
-
* @note Used for spacing, dividers, and special inline content
|
|
26742
|
+
* editor.commands.addAutoPageNumber()
|
|
26743
|
+
* @note Only works in header/footer contexts
|
|
26188
26744
|
*/
|
|
26189
|
-
|
|
26190
|
-
|
|
26191
|
-
|
|
26192
|
-
|
|
26193
|
-
|
|
26745
|
+
addAutoPageNumber: () => ({ tr, dispatch, state, editor }) => {
|
|
26746
|
+
const { options } = editor;
|
|
26747
|
+
if (!options.isHeaderOrFooter) return false;
|
|
26748
|
+
const { schema } = state;
|
|
26749
|
+
const pageNumberType = schema?.nodes?.["page-number"];
|
|
26750
|
+
if (!pageNumberType) return false;
|
|
26751
|
+
const pageNumberNodeJSON = { type: "page-number" };
|
|
26752
|
+
const pageNumberNode = schema.nodeFromJSON(pageNumberNodeJSON);
|
|
26753
|
+
if (dispatch) {
|
|
26754
|
+
tr.replaceSelectionWith(pageNumberNode, false);
|
|
26755
|
+
tr.setMeta("forceUpdatePagination", true);
|
|
26756
|
+
}
|
|
26757
|
+
return true;
|
|
26194
26758
|
}
|
|
26195
26759
|
};
|
|
26760
|
+
},
|
|
26761
|
+
addShortcuts() {
|
|
26762
|
+
return {
|
|
26763
|
+
"Mod-Shift-alt-p": () => this.editor.commands.addAutoPageNumber()
|
|
26764
|
+
};
|
|
26196
26765
|
}
|
|
26197
26766
|
});
|
|
26198
|
-
|
|
26199
|
-
|
|
26200
|
-
|
|
26201
|
-
__publicField(this, "view");
|
|
26202
|
-
__publicField(this, "getPos");
|
|
26203
|
-
__publicField(this, "decorations");
|
|
26204
|
-
__publicField(this, "innerDecorations");
|
|
26205
|
-
__publicField(this, "editor");
|
|
26206
|
-
__publicField(this, "extension");
|
|
26207
|
-
__publicField(this, "htmlAttributes");
|
|
26208
|
-
__publicField(this, "root");
|
|
26209
|
-
__publicField(this, "isDragging", false);
|
|
26210
|
-
this.node = props.node;
|
|
26211
|
-
this.view = props.editor.view;
|
|
26212
|
-
this.getPos = props.getPos;
|
|
26213
|
-
this.decorations = props.decorations;
|
|
26214
|
-
this.innerDecorations = props.innerDecorations;
|
|
26215
|
-
this.editor = props.editor;
|
|
26216
|
-
this.extension = props.extension;
|
|
26217
|
-
this.htmlAttributes = props.htmlAttributes;
|
|
26218
|
-
this.mount(props);
|
|
26219
|
-
}
|
|
26220
|
-
mount() {
|
|
26221
|
-
return;
|
|
26222
|
-
}
|
|
26223
|
-
get dom() {
|
|
26224
|
-
return this.root;
|
|
26225
|
-
}
|
|
26226
|
-
get contentDOM() {
|
|
26227
|
-
return null;
|
|
26228
|
-
}
|
|
26229
|
-
update(node, decorations, innerDecorations) {
|
|
26230
|
-
if (node.type !== this.node.type) {
|
|
26231
|
-
return false;
|
|
26232
|
-
}
|
|
26233
|
-
this.node = node;
|
|
26234
|
-
this.decorations = decorations;
|
|
26235
|
-
this.innerDecorations = innerDecorations;
|
|
26236
|
-
this.updateHTMLAttributes();
|
|
26237
|
-
return true;
|
|
26238
|
-
}
|
|
26239
|
-
stopEvent(event) {
|
|
26240
|
-
if (!this.dom) return false;
|
|
26241
|
-
const target = event.target;
|
|
26242
|
-
const isInElement = this.dom.contains(target) && !this.contentDOM?.contains(target);
|
|
26243
|
-
if (!isInElement) return false;
|
|
26244
|
-
const isDragEvent = event.type.startsWith("drag");
|
|
26245
|
-
const isDropEvent = event.type === "drop";
|
|
26246
|
-
const isInput = ["INPUT", "BUTTON", "SELECT", "TEXTAREA"].includes(target.tagName) || target.isContentEditable;
|
|
26247
|
-
if (isInput && !isDropEvent && !isDragEvent) return true;
|
|
26248
|
-
const { isEditable } = this.editor;
|
|
26249
|
-
const { isDragging } = this;
|
|
26250
|
-
const isDraggable = !!this.node.type.spec.draggable;
|
|
26251
|
-
const isSelectable = NodeSelection.isSelectable(this.node);
|
|
26252
|
-
const isCopyEvent = event.type === "copy";
|
|
26253
|
-
const isPasteEvent = event.type === "paste";
|
|
26254
|
-
const isCutEvent = event.type === "cut";
|
|
26255
|
-
const isClickEvent = event.type === "mousedown";
|
|
26256
|
-
if (!isDraggable && isSelectable && isDragEvent && event.target === this.dom) {
|
|
26257
|
-
event.preventDefault();
|
|
26258
|
-
}
|
|
26259
|
-
if (isDraggable && isDragEvent && !isDragging && event.target === this.dom) {
|
|
26260
|
-
event.preventDefault();
|
|
26261
|
-
return false;
|
|
26262
|
-
}
|
|
26263
|
-
if (isDraggable && isEditable && !isDragging && isClickEvent) {
|
|
26264
|
-
const dragHandle = target.closest("[data-drag-handle]");
|
|
26265
|
-
const isValidDragHandle = dragHandle && (this.dom === dragHandle || this.dom.contains(dragHandle));
|
|
26266
|
-
if (isValidDragHandle) {
|
|
26267
|
-
this.isDragging = true;
|
|
26268
|
-
document.addEventListener(
|
|
26269
|
-
"dragend",
|
|
26270
|
-
() => {
|
|
26271
|
-
this.isDragging = false;
|
|
26272
|
-
},
|
|
26273
|
-
{ once: true }
|
|
26274
|
-
);
|
|
26275
|
-
document.addEventListener(
|
|
26276
|
-
"drop",
|
|
26277
|
-
() => {
|
|
26278
|
-
this.isDragging = false;
|
|
26279
|
-
},
|
|
26280
|
-
{ once: true }
|
|
26281
|
-
);
|
|
26282
|
-
document.addEventListener(
|
|
26283
|
-
"mouseup",
|
|
26284
|
-
() => {
|
|
26285
|
-
this.isDragging = false;
|
|
26286
|
-
},
|
|
26287
|
-
{ once: true }
|
|
26288
|
-
);
|
|
26289
|
-
}
|
|
26290
|
-
}
|
|
26291
|
-
if (isDragging || isDropEvent || isCopyEvent || isPasteEvent || isCutEvent || isClickEvent && isSelectable) {
|
|
26292
|
-
return false;
|
|
26293
|
-
}
|
|
26294
|
-
return true;
|
|
26295
|
-
}
|
|
26296
|
-
ignoreMutation(mutation) {
|
|
26297
|
-
if (!this.dom || !this.contentDOM) return true;
|
|
26298
|
-
if (this.node.isLeaf || this.node.isAtom) return true;
|
|
26299
|
-
if (mutation.type === "selection") return false;
|
|
26300
|
-
if (this.contentDOM === mutation.target && mutation.type === "attributes") return true;
|
|
26301
|
-
if (this.contentDOM.contains(mutation.target)) return false;
|
|
26302
|
-
return true;
|
|
26303
|
-
}
|
|
26304
|
-
destroy() {
|
|
26305
|
-
this.dom.remove();
|
|
26306
|
-
this.contentDOM?.remove();
|
|
26307
|
-
}
|
|
26308
|
-
updateAttributes(attrs) {
|
|
26309
|
-
const pos = this.getPos();
|
|
26310
|
-
if (typeof pos !== "number") {
|
|
26311
|
-
return;
|
|
26312
|
-
}
|
|
26313
|
-
return this.view.dispatch(
|
|
26314
|
-
this.view.state.tr.setNodeMarkup(pos, void 0, {
|
|
26315
|
-
...this.node.attrs,
|
|
26316
|
-
...attrs
|
|
26317
|
-
})
|
|
26318
|
-
);
|
|
26319
|
-
}
|
|
26320
|
-
updateHTMLAttributes() {
|
|
26321
|
-
const { extensionService } = this.editor;
|
|
26322
|
-
const { attributes } = extensionService;
|
|
26323
|
-
const extensionAttrs = attributes.filter((i) => i.type === this.node.type.name);
|
|
26324
|
-
this.htmlAttributes = Attribute.getAttributesToRender(this.node, extensionAttrs);
|
|
26325
|
-
}
|
|
26326
|
-
createDragHandle() {
|
|
26327
|
-
const dragHandle = document.createElement("span");
|
|
26328
|
-
dragHandle.classList.add("sd-structured-content-draggable");
|
|
26329
|
-
dragHandle.draggable = true;
|
|
26330
|
-
dragHandle.contentEditable = "false";
|
|
26331
|
-
dragHandle.dataset.dragHandle = "";
|
|
26332
|
-
const textElement = document.createElement("span");
|
|
26333
|
-
textElement.textContent = "Structured content";
|
|
26334
|
-
dragHandle.append(textElement);
|
|
26335
|
-
return dragHandle;
|
|
26336
|
-
}
|
|
26337
|
-
onDragStart(event) {
|
|
26338
|
-
const { view } = this.editor;
|
|
26339
|
-
const target = event.target;
|
|
26340
|
-
const dragHandle = target.nodeType === 3 ? target.parentElement?.closest("[data-drag-handle]") : target.closest("[data-drag-handle]");
|
|
26341
|
-
if (!this.dom || this.contentDOM?.contains(target) || !dragHandle) {
|
|
26342
|
-
return;
|
|
26343
|
-
}
|
|
26344
|
-
let x = 0;
|
|
26345
|
-
let y = 0;
|
|
26346
|
-
if (this.dom !== dragHandle) {
|
|
26347
|
-
const domBox = this.dom.getBoundingClientRect();
|
|
26348
|
-
const handleBox = dragHandle.getBoundingClientRect();
|
|
26349
|
-
const offsetX = event.offsetX ?? event.nativeEvent?.offsetX;
|
|
26350
|
-
const offsetY = event.offsetY ?? event.nativeEvent?.offsetY;
|
|
26351
|
-
x = handleBox.x - domBox.x + offsetX;
|
|
26352
|
-
y = handleBox.y - domBox.y + offsetY;
|
|
26353
|
-
}
|
|
26354
|
-
event.dataTransfer?.setDragImage(this.dom, x, y);
|
|
26355
|
-
const pos = this.getPos();
|
|
26356
|
-
if (typeof pos !== "number") {
|
|
26357
|
-
return;
|
|
26358
|
-
}
|
|
26359
|
-
const selection = NodeSelection.create(view.state.doc, pos);
|
|
26360
|
-
const transaction = view.state.tr.setSelection(selection);
|
|
26361
|
-
view.dispatch(transaction);
|
|
26362
|
-
}
|
|
26363
|
-
}
|
|
26364
|
-
class StructuredContentInlineView extends StructuredContentViewBase {
|
|
26365
|
-
constructor(props) {
|
|
26366
|
-
super(props);
|
|
26367
|
-
}
|
|
26368
|
-
mount() {
|
|
26369
|
-
this.buildView();
|
|
26370
|
-
}
|
|
26371
|
-
get contentDOM() {
|
|
26372
|
-
const contentElement = this.dom?.querySelector(`.${structuredContentInnerClass$1}`);
|
|
26373
|
-
return contentElement || null;
|
|
26374
|
-
}
|
|
26375
|
-
createElement() {
|
|
26376
|
-
const element = document.createElement("span");
|
|
26377
|
-
element.classList.add(structuredContentClass$1);
|
|
26378
|
-
element.setAttribute("data-structured-content", "");
|
|
26379
|
-
const contentElement = document.createElement("span");
|
|
26380
|
-
contentElement.classList.add(structuredContentInnerClass$1);
|
|
26381
|
-
element.append(contentElement);
|
|
26382
|
-
const domAttrs = Attribute.mergeAttributes(this.htmlAttributes);
|
|
26383
|
-
updateDOMAttributes(element, { ...domAttrs });
|
|
26384
|
-
return { element, contentElement };
|
|
26385
|
-
}
|
|
26386
|
-
buildView() {
|
|
26387
|
-
const { element } = this.createElement();
|
|
26388
|
-
const dragHandle = this.createDragHandle();
|
|
26389
|
-
element.prepend(dragHandle);
|
|
26390
|
-
element.addEventListener("dragstart", (e) => this.onDragStart(e));
|
|
26391
|
-
this.root = element;
|
|
26392
|
-
}
|
|
26393
|
-
updateView() {
|
|
26394
|
-
const domAttrs = Attribute.mergeAttributes(this.htmlAttributes);
|
|
26395
|
-
updateDOMAttributes(this.dom, { ...domAttrs });
|
|
26396
|
-
}
|
|
26397
|
-
update(node, decorations, innerDecorations) {
|
|
26398
|
-
const result = super.update(node, decorations, innerDecorations);
|
|
26399
|
-
if (!result) return false;
|
|
26400
|
-
this.updateView();
|
|
26401
|
-
return true;
|
|
26402
|
-
}
|
|
26403
|
-
}
|
|
26404
|
-
const structuredContentClass$1 = "sd-structured-content";
|
|
26405
|
-
const structuredContentInnerClass$1 = "sd-structured-content__content";
|
|
26406
|
-
const StructuredContent = Node$1.create({
|
|
26407
|
-
name: "structuredContent",
|
|
26408
|
-
group: "inline structuredContent",
|
|
26767
|
+
const TotalPageCount = Node$1.create({
|
|
26768
|
+
name: "total-page-number",
|
|
26769
|
+
group: "inline",
|
|
26409
26770
|
inline: true,
|
|
26410
|
-
|
|
26411
|
-
|
|
26412
|
-
|
|
26413
|
-
|
|
26414
|
-
draggable: true,
|
|
26771
|
+
atom: true,
|
|
26772
|
+
draggable: false,
|
|
26773
|
+
selectable: false,
|
|
26774
|
+
content: "text*",
|
|
26415
26775
|
addOptions() {
|
|
26416
26776
|
return {
|
|
26417
26777
|
htmlAttributes: {
|
|
26418
|
-
|
|
26419
|
-
"
|
|
26778
|
+
contenteditable: false,
|
|
26779
|
+
"data-id": "auto-total-pages",
|
|
26780
|
+
"aria-label": "Total page count node",
|
|
26781
|
+
class: "sd-editor-auto-total-pages"
|
|
26420
26782
|
}
|
|
26421
26783
|
};
|
|
26422
26784
|
},
|
|
26423
26785
|
addAttributes() {
|
|
26424
26786
|
return {
|
|
26425
|
-
|
|
26787
|
+
marksAsAttrs: {
|
|
26426
26788
|
default: null,
|
|
26427
|
-
parseDOM: (elem) => elem.getAttribute("data-id"),
|
|
26428
|
-
renderDOM: (attrs) => {
|
|
26429
|
-
if (!attrs.id) return {};
|
|
26430
|
-
return { "data-id": attrs.id };
|
|
26431
|
-
}
|
|
26432
|
-
},
|
|
26433
|
-
sdtPr: {
|
|
26434
26789
|
rendered: false
|
|
26435
26790
|
}
|
|
26436
26791
|
};
|
|
26437
26792
|
},
|
|
26793
|
+
addNodeView() {
|
|
26794
|
+
return ({ node, editor, getPos, decorations }) => {
|
|
26795
|
+
const htmlAttributes = this.options.htmlAttributes;
|
|
26796
|
+
return new AutoPageNumberNodeView(node, getPos, decorations, editor, htmlAttributes);
|
|
26797
|
+
};
|
|
26798
|
+
},
|
|
26438
26799
|
parseDOM() {
|
|
26439
|
-
return [{ tag:
|
|
26800
|
+
return [{ tag: 'span[data-id="auto-total-pages"' }];
|
|
26440
26801
|
},
|
|
26441
26802
|
renderDOM({ htmlAttributes }) {
|
|
26442
|
-
return [
|
|
26443
|
-
"span",
|
|
26444
|
-
Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes, {
|
|
26445
|
-
"data-structured-content": ""
|
|
26446
|
-
}),
|
|
26447
|
-
0
|
|
26448
|
-
];
|
|
26803
|
+
return ["span", Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes), 0];
|
|
26449
26804
|
},
|
|
26450
|
-
|
|
26451
|
-
return
|
|
26452
|
-
|
|
26805
|
+
addCommands() {
|
|
26806
|
+
return {
|
|
26807
|
+
/**
|
|
26808
|
+
* Insert total page count
|
|
26809
|
+
* @category Command
|
|
26810
|
+
* @returns {Function} Command function
|
|
26811
|
+
* @example
|
|
26812
|
+
* editor.commands.addTotalPageCount()
|
|
26813
|
+
* @note Only works in header/footer contexts
|
|
26814
|
+
*/
|
|
26815
|
+
addTotalPageCount: () => ({ tr, dispatch, state, editor }) => {
|
|
26816
|
+
const { options } = editor;
|
|
26817
|
+
if (!options.isHeaderOrFooter) return false;
|
|
26818
|
+
const { schema } = state;
|
|
26819
|
+
const pageNumberType = schema.nodes?.["total-page-number"];
|
|
26820
|
+
if (!pageNumberType) return false;
|
|
26821
|
+
const currentPages = editor?.options?.parentEditor?.currentTotalPages || 1;
|
|
26822
|
+
const pageNumberNode = {
|
|
26823
|
+
type: "total-page-number",
|
|
26824
|
+
content: [{ type: "text", text: String(currentPages) }]
|
|
26825
|
+
};
|
|
26826
|
+
const pageNode = schema.nodeFromJSON(pageNumberNode);
|
|
26827
|
+
if (dispatch) {
|
|
26828
|
+
tr.replaceSelectionWith(pageNode, false);
|
|
26829
|
+
}
|
|
26830
|
+
return true;
|
|
26831
|
+
}
|
|
26832
|
+
};
|
|
26833
|
+
},
|
|
26834
|
+
addShortcuts() {
|
|
26835
|
+
return {
|
|
26836
|
+
"Mod-Shift-alt-c": () => this.editor.commands.addTotalPageCount()
|
|
26453
26837
|
};
|
|
26454
26838
|
}
|
|
26455
26839
|
});
|
|
26456
|
-
|
|
26457
|
-
|
|
26458
|
-
|
|
26459
|
-
|
|
26460
|
-
|
|
26461
|
-
|
|
26462
|
-
|
|
26463
|
-
|
|
26464
|
-
|
|
26465
|
-
|
|
26466
|
-
|
|
26467
|
-
|
|
26468
|
-
|
|
26469
|
-
|
|
26470
|
-
|
|
26471
|
-
|
|
26472
|
-
|
|
26473
|
-
|
|
26474
|
-
const domAttrs = Attribute.mergeAttributes(this.htmlAttributes);
|
|
26475
|
-
updateDOMAttributes(element, { ...domAttrs });
|
|
26476
|
-
return { element, contentElement };
|
|
26477
|
-
}
|
|
26478
|
-
buildView() {
|
|
26479
|
-
const { element } = this.createElement();
|
|
26480
|
-
const dragHandle = this.createDragHandle();
|
|
26481
|
-
element.prepend(dragHandle);
|
|
26482
|
-
element.addEventListener("dragstart", (e) => this.onDragStart(e));
|
|
26483
|
-
this.root = element;
|
|
26840
|
+
const getNodeAttributes = (nodeName, editor) => {
|
|
26841
|
+
switch (nodeName) {
|
|
26842
|
+
case "page-number":
|
|
26843
|
+
return {
|
|
26844
|
+
text: editor.options.currentPageNumber || "1",
|
|
26845
|
+
className: "sd-editor-auto-page-number",
|
|
26846
|
+
dataId: "auto-page-number",
|
|
26847
|
+
ariaLabel: "Page number node"
|
|
26848
|
+
};
|
|
26849
|
+
case "total-page-number":
|
|
26850
|
+
return {
|
|
26851
|
+
text: editor.options.parentEditor?.currentTotalPages || "1",
|
|
26852
|
+
className: "sd-editor-auto-total-pages",
|
|
26853
|
+
dataId: "auto-total-pages",
|
|
26854
|
+
ariaLabel: "Total page count node"
|
|
26855
|
+
};
|
|
26856
|
+
default:
|
|
26857
|
+
return {};
|
|
26484
26858
|
}
|
|
26485
|
-
|
|
26486
|
-
|
|
26487
|
-
|
|
26859
|
+
};
|
|
26860
|
+
class AutoPageNumberNodeView {
|
|
26861
|
+
constructor(node, getPos, decorations, editor, htmlAttributes = {}) {
|
|
26862
|
+
__privateAdd(this, _AutoPageNumberNodeView_instances);
|
|
26863
|
+
this.node = node;
|
|
26864
|
+
this.editor = editor;
|
|
26865
|
+
this.view = editor.view;
|
|
26866
|
+
this.getPos = getPos;
|
|
26867
|
+
this.editor = editor;
|
|
26868
|
+
this.dom = __privateMethod(this, _AutoPageNumberNodeView_instances, renderDom_fn).call(this, node, htmlAttributes);
|
|
26488
26869
|
}
|
|
26489
|
-
update(node
|
|
26490
|
-
const
|
|
26491
|
-
|
|
26492
|
-
|
|
26870
|
+
update(node) {
|
|
26871
|
+
const incomingType = node?.type?.name;
|
|
26872
|
+
const currentType = this.node?.type?.name;
|
|
26873
|
+
if (!incomingType || incomingType !== currentType) return false;
|
|
26874
|
+
this.node = node;
|
|
26493
26875
|
return true;
|
|
26494
26876
|
}
|
|
26495
26877
|
}
|
|
26496
|
-
|
|
26497
|
-
|
|
26498
|
-
const
|
|
26499
|
-
|
|
26500
|
-
|
|
26501
|
-
|
|
26878
|
+
_AutoPageNumberNodeView_instances = new WeakSet();
|
|
26879
|
+
renderDom_fn = function(node, htmlAttributes) {
|
|
26880
|
+
const attrs = getNodeAttributes(this.node.type.name, this.editor);
|
|
26881
|
+
const content = document.createTextNode(String(attrs.text));
|
|
26882
|
+
const nodeContent = document.createElement("span");
|
|
26883
|
+
nodeContent.className = attrs.className;
|
|
26884
|
+
nodeContent.setAttribute("data-id", attrs.dataId);
|
|
26885
|
+
nodeContent.setAttribute("aria-label", attrs.ariaLabel);
|
|
26886
|
+
const currentPos = this.getPos();
|
|
26887
|
+
const { styles, marks } = getMarksFromNeighbors(currentPos, this.view);
|
|
26888
|
+
__privateMethod(this, _AutoPageNumberNodeView_instances, scheduleUpdateNodeStyle_fn).call(this, currentPos, marks);
|
|
26889
|
+
Object.assign(nodeContent.style, styles);
|
|
26890
|
+
nodeContent.appendChild(content);
|
|
26891
|
+
Object.entries(htmlAttributes).forEach(([key2, value]) => {
|
|
26892
|
+
if (value) nodeContent.setAttribute(key2, value);
|
|
26893
|
+
});
|
|
26894
|
+
return nodeContent;
|
|
26895
|
+
};
|
|
26896
|
+
scheduleUpdateNodeStyle_fn = function(pos, marks) {
|
|
26897
|
+
setTimeout(() => {
|
|
26898
|
+
const { state } = this.editor;
|
|
26899
|
+
const { dispatch } = this.view;
|
|
26900
|
+
const node = state.doc.nodeAt(pos);
|
|
26901
|
+
if (!node || node.isText) return;
|
|
26902
|
+
const currentMarks = node.attrs.marksAsAttrs || [];
|
|
26903
|
+
const newMarks = marks.map((m) => ({ type: m.type.name, attrs: m.attrs }));
|
|
26904
|
+
const isEqual = JSON.stringify(currentMarks) === JSON.stringify(newMarks);
|
|
26905
|
+
if (isEqual) return;
|
|
26906
|
+
const newAttrs = {
|
|
26907
|
+
...node.attrs,
|
|
26908
|
+
marksAsAttrs: newMarks
|
|
26909
|
+
};
|
|
26910
|
+
const tr = state.tr.setNodeMarkup(pos, void 0, newAttrs);
|
|
26911
|
+
dispatch(tr);
|
|
26912
|
+
}, 0);
|
|
26913
|
+
};
|
|
26914
|
+
const getMarksFromNeighbors = (currentPos, view) => {
|
|
26915
|
+
const $pos = view.state.doc.resolve(currentPos);
|
|
26916
|
+
const styles = {};
|
|
26917
|
+
const marks = [];
|
|
26918
|
+
const before = $pos.nodeBefore;
|
|
26919
|
+
if (before) {
|
|
26920
|
+
Object.assign(styles, processMarks(before.marks));
|
|
26921
|
+
marks.push(...before.marks);
|
|
26922
|
+
}
|
|
26923
|
+
const after = $pos.nodeAfter;
|
|
26924
|
+
if (after) {
|
|
26925
|
+
Object.assign(styles, { ...styles, ...processMarks(after.marks) });
|
|
26926
|
+
marks.push(...after.marks);
|
|
26927
|
+
}
|
|
26928
|
+
return {
|
|
26929
|
+
styles,
|
|
26930
|
+
marks
|
|
26931
|
+
};
|
|
26932
|
+
};
|
|
26933
|
+
const processMarks = (marks) => {
|
|
26934
|
+
const styles = {};
|
|
26935
|
+
marks.forEach((mark) => {
|
|
26936
|
+
const { type, attrs } = mark;
|
|
26937
|
+
switch (type.name) {
|
|
26938
|
+
case "textStyle":
|
|
26939
|
+
if (attrs.fontFamily) styles["font-family"] = attrs.fontFamily;
|
|
26940
|
+
if (attrs.fontSize) styles["font-size"] = attrs.fontSize;
|
|
26941
|
+
if (attrs.color) styles["color"] = attrs.color;
|
|
26942
|
+
if (attrs.backgroundColor) styles["background-color"] = attrs.backgroundColor;
|
|
26943
|
+
break;
|
|
26944
|
+
case "bold":
|
|
26945
|
+
styles["font-weight"] = "bold";
|
|
26946
|
+
break;
|
|
26947
|
+
case "italic":
|
|
26948
|
+
styles["font-style"] = "italic";
|
|
26949
|
+
break;
|
|
26950
|
+
case "underline":
|
|
26951
|
+
styles["text-decoration"] = (styles["text-decoration"] || "") + " underline";
|
|
26952
|
+
break;
|
|
26953
|
+
case "strike":
|
|
26954
|
+
styles["text-decoration"] = (styles["text-decoration"] || "") + " line-through";
|
|
26955
|
+
break;
|
|
26956
|
+
default:
|
|
26957
|
+
if (attrs?.style) {
|
|
26958
|
+
Object.entries(attrs.style).forEach(([key2, value]) => {
|
|
26959
|
+
styles[key2] = value;
|
|
26960
|
+
});
|
|
26961
|
+
}
|
|
26962
|
+
break;
|
|
26963
|
+
}
|
|
26964
|
+
});
|
|
26965
|
+
return styles;
|
|
26966
|
+
};
|
|
26967
|
+
const ShapeContainer = Node$1.create({
|
|
26968
|
+
name: "shapeContainer",
|
|
26969
|
+
group: "block",
|
|
26970
|
+
content: "block+",
|
|
26502
26971
|
isolating: true,
|
|
26503
|
-
atom: false,
|
|
26504
|
-
// false - has editable content.
|
|
26505
|
-
draggable: true,
|
|
26506
26972
|
addOptions() {
|
|
26507
26973
|
return {
|
|
26508
26974
|
htmlAttributes: {
|
|
26509
|
-
class:
|
|
26510
|
-
"aria-label": "
|
|
26975
|
+
class: "sd-editor-shape-container",
|
|
26976
|
+
"aria-label": "Shape container node"
|
|
26511
26977
|
}
|
|
26512
26978
|
};
|
|
26513
26979
|
},
|
|
26514
26980
|
addAttributes() {
|
|
26515
26981
|
return {
|
|
26516
|
-
|
|
26982
|
+
fillcolor: {
|
|
26983
|
+
renderDOM: (attrs) => {
|
|
26984
|
+
if (!attrs.fillcolor) return {};
|
|
26985
|
+
return {
|
|
26986
|
+
style: `background-color: ${attrs.fillcolor}`
|
|
26987
|
+
};
|
|
26988
|
+
}
|
|
26989
|
+
},
|
|
26990
|
+
sdBlockId: {
|
|
26517
26991
|
default: null,
|
|
26518
|
-
|
|
26992
|
+
keepOnSplit: false,
|
|
26993
|
+
parseDOM: (elem) => elem.getAttribute("data-sd-block-id"),
|
|
26519
26994
|
renderDOM: (attrs) => {
|
|
26520
|
-
|
|
26521
|
-
return { "data-id": attrs.id };
|
|
26995
|
+
return attrs.sdBlockId ? { "data-sd-block-id": attrs.sdBlockId } : {};
|
|
26522
26996
|
}
|
|
26523
26997
|
},
|
|
26524
|
-
|
|
26998
|
+
style: {
|
|
26999
|
+
renderDOM: (attrs) => {
|
|
27000
|
+
if (!attrs.style) return {};
|
|
27001
|
+
return {
|
|
27002
|
+
style: attrs.style
|
|
27003
|
+
};
|
|
27004
|
+
}
|
|
27005
|
+
},
|
|
27006
|
+
wrapAttributes: {
|
|
27007
|
+
rendered: false
|
|
27008
|
+
},
|
|
27009
|
+
attributes: {
|
|
26525
27010
|
rendered: false
|
|
26526
27011
|
}
|
|
26527
27012
|
};
|
|
26528
27013
|
},
|
|
26529
27014
|
parseDOM() {
|
|
26530
|
-
return [
|
|
27015
|
+
return [
|
|
27016
|
+
{
|
|
27017
|
+
tag: `div[data-type="${this.name}"]`
|
|
27018
|
+
}
|
|
27019
|
+
];
|
|
26531
27020
|
},
|
|
26532
27021
|
renderDOM({ htmlAttributes }) {
|
|
26533
27022
|
return [
|
|
26534
27023
|
"div",
|
|
26535
|
-
Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes, {
|
|
26536
|
-
"data-structured-content-block": ""
|
|
26537
|
-
}),
|
|
27024
|
+
Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes, { "data-type": this.name }),
|
|
26538
27025
|
0
|
|
26539
27026
|
];
|
|
26540
|
-
},
|
|
26541
|
-
addNodeView() {
|
|
26542
|
-
return (props) => {
|
|
26543
|
-
return new StructuredContentBlockView({ ...props });
|
|
26544
|
-
};
|
|
26545
27027
|
}
|
|
26546
27028
|
});
|
|
26547
|
-
|
|
26548
|
-
|
|
26549
|
-
__privateAdd(this, _DocumentSectionView_instances);
|
|
26550
|
-
this.node = node;
|
|
26551
|
-
this.editor = editor;
|
|
26552
|
-
this.decorations = decorations;
|
|
26553
|
-
this.view = editor.view;
|
|
26554
|
-
this.getPos = getPos;
|
|
26555
|
-
__privateMethod(this, _DocumentSectionView_instances, init_fn3).call(this);
|
|
26556
|
-
}
|
|
26557
|
-
}
|
|
26558
|
-
_DocumentSectionView_instances = new WeakSet();
|
|
26559
|
-
init_fn3 = function() {
|
|
26560
|
-
const { attrs } = this.node;
|
|
26561
|
-
const { id, title, description } = attrs;
|
|
26562
|
-
this.dom = document.createElement("div");
|
|
26563
|
-
this.dom.className = "sd-document-section-block";
|
|
26564
|
-
this.dom.setAttribute("data-id", id);
|
|
26565
|
-
this.dom.setAttribute("data-title", title);
|
|
26566
|
-
this.dom.setAttribute("data-description", description);
|
|
26567
|
-
this.dom.setAttribute("aria-label", "Document section");
|
|
26568
|
-
__privateMethod(this, _DocumentSectionView_instances, addToolTip_fn).call(this);
|
|
26569
|
-
this.contentDOM = document.createElement("div");
|
|
26570
|
-
this.contentDOM.className = "sd-document-section-block-content";
|
|
26571
|
-
this.contentDOM.setAttribute("contenteditable", "true");
|
|
26572
|
-
this.dom.appendChild(this.contentDOM);
|
|
26573
|
-
};
|
|
26574
|
-
addToolTip_fn = function() {
|
|
26575
|
-
const { title } = this.node.attrs;
|
|
26576
|
-
this.infoDiv = document.createElement("div");
|
|
26577
|
-
this.infoDiv.className = "sd-document-section-block-info";
|
|
26578
|
-
const textSpan = document.createElement("span");
|
|
26579
|
-
textSpan.textContent = title || "Document section";
|
|
26580
|
-
this.infoDiv.appendChild(textSpan);
|
|
26581
|
-
this.infoDiv.setAttribute("contenteditable", "false");
|
|
26582
|
-
this.dom.appendChild(this.infoDiv);
|
|
26583
|
-
};
|
|
26584
|
-
const getAllSections = (editor) => {
|
|
26585
|
-
if (!editor) return [];
|
|
26586
|
-
const type = editor.schema.nodes.documentSection;
|
|
26587
|
-
if (!type) return [];
|
|
26588
|
-
const sections = [];
|
|
26589
|
-
const { state } = editor;
|
|
26590
|
-
state.doc.descendants((node, pos) => {
|
|
26591
|
-
if (node.type.name === type.name) {
|
|
26592
|
-
sections.push({ node, pos });
|
|
26593
|
-
}
|
|
26594
|
-
});
|
|
26595
|
-
return sections;
|
|
26596
|
-
};
|
|
26597
|
-
const exportSectionsToHTML = (editor) => {
|
|
26598
|
-
const sections = getAllSections(editor);
|
|
26599
|
-
const processedSections = /* @__PURE__ */ new Set();
|
|
26600
|
-
const result = [];
|
|
26601
|
-
sections.forEach(({ node }) => {
|
|
26602
|
-
const { attrs } = node;
|
|
26603
|
-
const { id, title, description } = attrs;
|
|
26604
|
-
if (processedSections.has(id)) return;
|
|
26605
|
-
processedSections.add(id);
|
|
26606
|
-
const html = getHTMLFromNode(node, editor);
|
|
26607
|
-
result.push({
|
|
26608
|
-
id,
|
|
26609
|
-
title,
|
|
26610
|
-
description,
|
|
26611
|
-
html
|
|
26612
|
-
});
|
|
26613
|
-
});
|
|
26614
|
-
return result;
|
|
26615
|
-
};
|
|
26616
|
-
const getHTMLFromNode = (node, editor) => {
|
|
26617
|
-
const tempDocument = document.implementation.createHTMLDocument();
|
|
26618
|
-
const container = tempDocument.createElement("div");
|
|
26619
|
-
const fragment = DOMSerializer.fromSchema(editor.schema).serializeFragment(node.content);
|
|
26620
|
-
container.appendChild(fragment);
|
|
26621
|
-
let html = container.innerHTML;
|
|
26622
|
-
return html;
|
|
26623
|
-
};
|
|
26624
|
-
const exportSectionsToJSON = (editor) => {
|
|
26625
|
-
const sections = getAllSections(editor);
|
|
26626
|
-
const processedSections = /* @__PURE__ */ new Set();
|
|
26627
|
-
const result = [];
|
|
26628
|
-
sections.forEach(({ node }) => {
|
|
26629
|
-
const { attrs } = node;
|
|
26630
|
-
const { id, title, description } = attrs;
|
|
26631
|
-
if (processedSections.has(id)) return;
|
|
26632
|
-
processedSections.add(id);
|
|
26633
|
-
result.push({
|
|
26634
|
-
id,
|
|
26635
|
-
title,
|
|
26636
|
-
description,
|
|
26637
|
-
content: node.toJSON()
|
|
26638
|
-
});
|
|
26639
|
-
});
|
|
26640
|
-
return result;
|
|
26641
|
-
};
|
|
26642
|
-
const getLinkedSectionEditor = (id, options, editor) => {
|
|
26643
|
-
const sections = getAllSections(editor);
|
|
26644
|
-
const section = sections.find((s) => s.node.attrs.id === id);
|
|
26645
|
-
if (!section) return null;
|
|
26646
|
-
const child = editor.createChildEditor({
|
|
26647
|
-
...options,
|
|
26648
|
-
onUpdate: ({ editor: childEditor, transaction }) => {
|
|
26649
|
-
const isFromtLinkedParent = transaction.getMeta("fromLinkedParent");
|
|
26650
|
-
if (isFromtLinkedParent) return;
|
|
26651
|
-
const updatedContent = childEditor.state.doc.content;
|
|
26652
|
-
const sectionNode = getAllSections(editor)?.find((s) => s.node.attrs.id === id);
|
|
26653
|
-
if (!sectionNode) return;
|
|
26654
|
-
const { pos, node } = sectionNode;
|
|
26655
|
-
const newNode = node.type.create(node.attrs, updatedContent, node.marks);
|
|
26656
|
-
const tr = editor.state.tr.replaceWith(pos, pos + node.nodeSize, newNode);
|
|
26657
|
-
tr.setMeta("fromLinkedChild", true);
|
|
26658
|
-
editor.view.dispatch(tr);
|
|
26659
|
-
}
|
|
26660
|
-
});
|
|
26661
|
-
editor.on("update", ({ transaction }) => {
|
|
26662
|
-
const isFromLinkedChild = transaction.getMeta("fromLinkedChild");
|
|
26663
|
-
if (isFromLinkedChild) return;
|
|
26664
|
-
const sectionNode = getAllSections(editor)?.find((s) => s.node.attrs.id === id);
|
|
26665
|
-
if (!sectionNode) return;
|
|
26666
|
-
const sectionContent = sectionNode.node.content;
|
|
26667
|
-
const json = {
|
|
26668
|
-
type: "doc",
|
|
26669
|
-
content: sectionContent.content.map((node) => node.toJSON())
|
|
26670
|
-
};
|
|
26671
|
-
const childTr = child.state.tr;
|
|
26672
|
-
childTr.setMeta("fromLinkedParent", true);
|
|
26673
|
-
childTr.replaceWith(0, child.state.doc.content.size, child.schema.nodeFromJSON(json));
|
|
26674
|
-
child.view.dispatch(childTr);
|
|
26675
|
-
});
|
|
26676
|
-
return child;
|
|
26677
|
-
};
|
|
26678
|
-
const SectionHelpers = {
|
|
26679
|
-
getAllSections,
|
|
26680
|
-
exportSectionsToHTML,
|
|
26681
|
-
exportSectionsToJSON,
|
|
26682
|
-
getLinkedSectionEditor
|
|
26683
|
-
};
|
|
26684
|
-
const DocumentSection = Node$1.create({
|
|
26685
|
-
name: "documentSection",
|
|
27029
|
+
const ShapeTextbox = Node$1.create({
|
|
27030
|
+
name: "shapeTextbox",
|
|
26686
27031
|
group: "block",
|
|
26687
|
-
content: "block*",
|
|
26688
|
-
atom: true,
|
|
27032
|
+
content: "paragraph* block*",
|
|
26689
27033
|
isolating: true,
|
|
26690
27034
|
addOptions() {
|
|
26691
27035
|
return {
|
|
26692
27036
|
htmlAttributes: {
|
|
26693
|
-
class: "sd-
|
|
26694
|
-
"aria-label": "
|
|
27037
|
+
class: "sd-editor-shape-textbox",
|
|
27038
|
+
"aria-label": "Shape textbox node"
|
|
26695
27039
|
}
|
|
26696
27040
|
};
|
|
26697
27041
|
},
|
|
26698
|
-
parseDOM() {
|
|
26699
|
-
return [
|
|
26700
|
-
{
|
|
26701
|
-
tag: "div.sd-document-section-block",
|
|
26702
|
-
priority: 60
|
|
26703
|
-
}
|
|
26704
|
-
];
|
|
26705
|
-
},
|
|
26706
|
-
renderDOM({ htmlAttributes }) {
|
|
26707
|
-
return ["div", Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes), 0];
|
|
26708
|
-
},
|
|
26709
27042
|
addAttributes() {
|
|
26710
27043
|
return {
|
|
26711
|
-
id: {},
|
|
26712
27044
|
sdBlockId: {
|
|
26713
27045
|
default: null,
|
|
26714
27046
|
keepOnSplit: false,
|
|
@@ -26717,212 +27049,131 @@ const DocumentSection = Node$1.create({
|
|
|
26717
27049
|
return attrs.sdBlockId ? { "data-sd-block-id": attrs.sdBlockId } : {};
|
|
26718
27050
|
}
|
|
26719
27051
|
},
|
|
26720
|
-
|
|
26721
|
-
|
|
26722
|
-
|
|
26723
|
-
isLocked: { default: false }
|
|
27052
|
+
attributes: {
|
|
27053
|
+
rendered: false
|
|
27054
|
+
}
|
|
26724
27055
|
};
|
|
26725
27056
|
},
|
|
26726
|
-
|
|
26727
|
-
return
|
|
26728
|
-
|
|
27057
|
+
parseDOM() {
|
|
27058
|
+
return [
|
|
27059
|
+
{
|
|
27060
|
+
tag: `div[data-type="${this.name}"]`
|
|
27061
|
+
}
|
|
27062
|
+
];
|
|
27063
|
+
},
|
|
27064
|
+
renderDOM({ htmlAttributes }) {
|
|
27065
|
+
return [
|
|
27066
|
+
"div",
|
|
27067
|
+
Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes, { "data-type": this.name }),
|
|
27068
|
+
0
|
|
27069
|
+
];
|
|
27070
|
+
}
|
|
27071
|
+
});
|
|
27072
|
+
const ContentBlock = Node$1.create({
|
|
27073
|
+
name: "contentBlock",
|
|
27074
|
+
group: "inline",
|
|
27075
|
+
content: "",
|
|
27076
|
+
isolating: true,
|
|
27077
|
+
atom: true,
|
|
27078
|
+
inline: true,
|
|
27079
|
+
addOptions() {
|
|
27080
|
+
return {
|
|
27081
|
+
htmlAttributes: {
|
|
27082
|
+
contenteditable: false
|
|
27083
|
+
}
|
|
26729
27084
|
};
|
|
26730
27085
|
},
|
|
26731
|
-
|
|
27086
|
+
addAttributes() {
|
|
26732
27087
|
return {
|
|
26733
|
-
|
|
26734
|
-
|
|
26735
|
-
|
|
26736
|
-
|
|
26737
|
-
|
|
26738
|
-
* editor.commands.createDocumentSection({
|
|
26739
|
-
* id: 1,
|
|
26740
|
-
* title: 'Terms & Conditions',
|
|
26741
|
-
* isLocked: true,
|
|
26742
|
-
* html: '<p>Legal content...</p>'
|
|
26743
|
-
* })
|
|
26744
|
-
*/
|
|
26745
|
-
createDocumentSection: (options = {}) => ({ tr, state, dispatch, editor }) => {
|
|
26746
|
-
const { selection } = state;
|
|
26747
|
-
let { from: from2, to } = selection;
|
|
26748
|
-
let content = selection.content().content;
|
|
26749
|
-
const { html: optionsHTML, json: optionsJSON } = options;
|
|
26750
|
-
if (optionsHTML) {
|
|
26751
|
-
const html = htmlHandler(optionsHTML, this.editor);
|
|
26752
|
-
const doc2 = DOMParser$1.fromSchema(this.editor.schema).parse(html);
|
|
26753
|
-
content = doc2.content;
|
|
26754
|
-
}
|
|
26755
|
-
if (optionsJSON) {
|
|
26756
|
-
content = this.editor.schema.nodeFromJSON(optionsJSON);
|
|
26757
|
-
}
|
|
26758
|
-
if (!content?.content?.length) {
|
|
26759
|
-
content = this.editor.schema.nodeFromJSON({ type: "paragraph", content: [] });
|
|
26760
|
-
}
|
|
26761
|
-
if (!options.id) {
|
|
26762
|
-
const allSections = SectionHelpers.getAllSections(editor);
|
|
26763
|
-
options.id = allSections.length + 1;
|
|
26764
|
-
}
|
|
26765
|
-
if (!options.title) {
|
|
26766
|
-
options.title = "Document section";
|
|
26767
|
-
}
|
|
26768
|
-
const node = this.type.createAndFill(options, content);
|
|
26769
|
-
if (!node) return false;
|
|
26770
|
-
const isAlreadyInSdtBlock = findParentNode((node2) => node2.type.name === "documentSection")(selection);
|
|
26771
|
-
if (isAlreadyInSdtBlock && isAlreadyInSdtBlock.node) {
|
|
26772
|
-
const insertPos2 = isAlreadyInSdtBlock.pos + isAlreadyInSdtBlock.node.nodeSize;
|
|
26773
|
-
from2 = insertPos2;
|
|
26774
|
-
to = insertPos2;
|
|
26775
|
-
}
|
|
26776
|
-
tr.replaceRangeWith(from2, to, node);
|
|
26777
|
-
const nodeEnd = from2 + node.nodeSize;
|
|
26778
|
-
let shouldInsertParagraph = true;
|
|
26779
|
-
let insertPos = nodeEnd;
|
|
26780
|
-
if (nodeEnd >= tr.doc.content.size) {
|
|
26781
|
-
insertPos = tr.doc.content.size;
|
|
26782
|
-
if (insertPos > 0) {
|
|
26783
|
-
const $endPos = tr.doc.resolve(insertPos);
|
|
26784
|
-
if ($endPos.nodeBefore && $endPos.nodeBefore.type.name === "paragraph") {
|
|
26785
|
-
shouldInsertParagraph = false;
|
|
26786
|
-
}
|
|
26787
|
-
}
|
|
26788
|
-
}
|
|
26789
|
-
if (shouldInsertParagraph) {
|
|
26790
|
-
const emptyParagraph = tr.doc.type.schema.nodes.paragraph.create();
|
|
26791
|
-
tr.insert(insertPos, emptyParagraph);
|
|
26792
|
-
}
|
|
26793
|
-
if (dispatch) {
|
|
26794
|
-
tr.setMeta("documentSection", { action: "create" });
|
|
26795
|
-
dispatch(tr);
|
|
26796
|
-
setTimeout(() => {
|
|
26797
|
-
try {
|
|
26798
|
-
const currentState = editor.state;
|
|
26799
|
-
const docSize = currentState.doc.content.size;
|
|
26800
|
-
let targetPos = from2 + node.nodeSize;
|
|
26801
|
-
if (shouldInsertParagraph) {
|
|
26802
|
-
targetPos += 1;
|
|
26803
|
-
}
|
|
26804
|
-
targetPos = Math.min(targetPos, docSize);
|
|
26805
|
-
if (targetPos < docSize && targetPos > 0) {
|
|
26806
|
-
const newSelection = Selection.near(currentState.doc.resolve(targetPos));
|
|
26807
|
-
const newTr = currentState.tr.setSelection(newSelection);
|
|
26808
|
-
editor.view.dispatch(newTr);
|
|
26809
|
-
}
|
|
26810
|
-
} catch (e) {
|
|
26811
|
-
console.warn("Could not set delayed selection:", e);
|
|
26812
|
-
}
|
|
26813
|
-
}, 0);
|
|
27088
|
+
horizontalRule: {
|
|
27089
|
+
default: false,
|
|
27090
|
+
renderDOM: ({ horizontalRule }) => {
|
|
27091
|
+
if (!horizontalRule) return {};
|
|
27092
|
+
return { "data-horizontal-rule": "true" };
|
|
26814
27093
|
}
|
|
26815
|
-
return true;
|
|
26816
27094
|
},
|
|
26817
|
-
|
|
26818
|
-
|
|
26819
|
-
|
|
26820
|
-
|
|
26821
|
-
|
|
26822
|
-
|
|
26823
|
-
|
|
26824
|
-
|
|
26825
|
-
|
|
26826
|
-
|
|
26827
|
-
|
|
26828
|
-
const nodeStart = pos;
|
|
26829
|
-
const nodeEnd = nodeStart + node.nodeSize;
|
|
26830
|
-
const contentToPreserve = node.content;
|
|
26831
|
-
tr.delete(nodeStart, nodeEnd);
|
|
26832
|
-
if (contentToPreserve.size > 0) {
|
|
26833
|
-
tr.insert(nodeStart, contentToPreserve);
|
|
26834
|
-
}
|
|
26835
|
-
const newPos = Math.min(nodeStart, tr.doc.content.size);
|
|
26836
|
-
tr.setSelection(Selection.near(tr.doc.resolve(newPos)));
|
|
26837
|
-
if (dispatch) {
|
|
26838
|
-
tr.setMeta("documentSection", { action: "delete" });
|
|
26839
|
-
dispatch(tr);
|
|
27095
|
+
size: {
|
|
27096
|
+
default: null,
|
|
27097
|
+
renderDOM: ({ size }) => {
|
|
27098
|
+
if (!size) return {};
|
|
27099
|
+
let style = "";
|
|
27100
|
+
if (size.top) style += `top: ${size.top}px; `;
|
|
27101
|
+
if (size.left) style += `left: ${size.left}px; `;
|
|
27102
|
+
if (size.width) style += `width: ${size.width.toString().endsWith("%") ? size.width : `${size.width}px`}; `;
|
|
27103
|
+
if (size.height)
|
|
27104
|
+
style += `height: ${size.height.toString().endsWith("%") ? size.height : `${size.height}px`}; `;
|
|
27105
|
+
return { style };
|
|
26840
27106
|
}
|
|
26841
|
-
return true;
|
|
26842
27107
|
},
|
|
26843
|
-
|
|
26844
|
-
|
|
26845
|
-
|
|
26846
|
-
|
|
26847
|
-
|
|
26848
|
-
|
|
26849
|
-
|
|
26850
|
-
removeSectionById: (id) => ({ tr, dispatch }) => {
|
|
26851
|
-
const sections = SectionHelpers.getAllSections(this.editor);
|
|
26852
|
-
const sectionToRemove = sections.find(({ node: node2 }) => node2.attrs.id === id);
|
|
26853
|
-
if (!sectionToRemove) return false;
|
|
26854
|
-
const { pos, node } = sectionToRemove;
|
|
26855
|
-
const nodeStart = pos;
|
|
26856
|
-
const nodeEnd = nodeStart + node.nodeSize;
|
|
26857
|
-
tr.delete(nodeStart, nodeEnd);
|
|
26858
|
-
if (dispatch) {
|
|
26859
|
-
tr.setMeta("documentSection", { action: "delete", id });
|
|
26860
|
-
dispatch(tr);
|
|
27108
|
+
background: {
|
|
27109
|
+
default: null,
|
|
27110
|
+
renderDOM: (attrs) => {
|
|
27111
|
+
if (!attrs.background) return {};
|
|
27112
|
+
return {
|
|
27113
|
+
style: `background-color: ${attrs.background}`
|
|
27114
|
+
};
|
|
26861
27115
|
}
|
|
26862
|
-
return true;
|
|
26863
27116
|
},
|
|
27117
|
+
drawingContent: {
|
|
27118
|
+
rendered: false
|
|
27119
|
+
},
|
|
27120
|
+
attributes: {
|
|
27121
|
+
rendered: false
|
|
27122
|
+
}
|
|
27123
|
+
};
|
|
27124
|
+
},
|
|
27125
|
+
parseDOM() {
|
|
27126
|
+
return [
|
|
27127
|
+
{
|
|
27128
|
+
tag: `div[data-type="${this.name}"]`
|
|
27129
|
+
}
|
|
27130
|
+
];
|
|
27131
|
+
},
|
|
27132
|
+
renderDOM({ htmlAttributes }) {
|
|
27133
|
+
return ["div", Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes, { "data-type": this.name })];
|
|
27134
|
+
},
|
|
27135
|
+
addCommands() {
|
|
27136
|
+
return {
|
|
26864
27137
|
/**
|
|
26865
|
-
*
|
|
27138
|
+
* Insert a horizontal rule
|
|
26866
27139
|
* @category Command
|
|
26867
|
-
* @param {number} id - Section to lock
|
|
26868
27140
|
* @example
|
|
26869
|
-
* editor.commands.
|
|
27141
|
+
* editor.commands.insertHorizontalRule()
|
|
27142
|
+
* @note Creates a visual separator between content sections
|
|
26870
27143
|
*/
|
|
26871
|
-
|
|
26872
|
-
|
|
26873
|
-
|
|
26874
|
-
|
|
26875
|
-
|
|
26876
|
-
|
|
26877
|
-
|
|
26878
|
-
|
|
26879
|
-
}
|
|
26880
|
-
return true;
|
|
27144
|
+
insertHorizontalRule: () => ({ commands: commands2 }) => {
|
|
27145
|
+
return commands2.insertContent({
|
|
27146
|
+
type: this.name,
|
|
27147
|
+
attrs: {
|
|
27148
|
+
horizontalRule: true,
|
|
27149
|
+
size: { width: "100%", height: 2 },
|
|
27150
|
+
background: "#e5e7eb"
|
|
27151
|
+
}
|
|
27152
|
+
});
|
|
26881
27153
|
},
|
|
26882
27154
|
/**
|
|
26883
|
-
*
|
|
27155
|
+
* Insert a content block
|
|
26884
27156
|
* @category Command
|
|
26885
|
-
* @param {
|
|
27157
|
+
* @param {ContentBlockConfig} config - Block configuration
|
|
26886
27158
|
* @example
|
|
26887
|
-
*
|
|
26888
|
-
* editor.commands.
|
|
26889
|
-
*
|
|
26890
|
-
*
|
|
26891
|
-
*
|
|
26892
|
-
*
|
|
27159
|
+
* // Insert a spacer block
|
|
27160
|
+
* editor.commands.insertContentBlock({ size: { height: 20 } })
|
|
27161
|
+
*
|
|
27162
|
+
* @example
|
|
27163
|
+
* // Insert a colored divider
|
|
27164
|
+
* editor.commands.insertContentBlock({
|
|
27165
|
+
* size: { width: '50%', height: 3 },
|
|
27166
|
+
* background: '#3b82f6'
|
|
26893
27167
|
* })
|
|
27168
|
+
* @note Used for spacing, dividers, and special inline content
|
|
26894
27169
|
*/
|
|
26895
|
-
|
|
26896
|
-
|
|
26897
|
-
|
|
26898
|
-
|
|
26899
|
-
|
|
26900
|
-
let newContent = null;
|
|
26901
|
-
if (html) {
|
|
26902
|
-
const htmlDoc = htmlHandler(html, editor || this.editor);
|
|
26903
|
-
const doc2 = DOMParser$1.fromSchema((editor || this.editor).schema).parse(htmlDoc);
|
|
26904
|
-
newContent = doc2.content;
|
|
26905
|
-
}
|
|
26906
|
-
if (json) {
|
|
26907
|
-
newContent = (editor || this.editor).schema.nodeFromJSON(json);
|
|
26908
|
-
}
|
|
26909
|
-
if (!newContent) {
|
|
26910
|
-
newContent = node.content;
|
|
26911
|
-
}
|
|
26912
|
-
const updatedNode = node.type.create({ ...node.attrs, ...attrs }, newContent, node.marks);
|
|
26913
|
-
tr.replaceWith(pos, pos + node.nodeSize, updatedNode);
|
|
26914
|
-
if (dispatch) {
|
|
26915
|
-
tr.setMeta("documentSection", { action: "update", id, attrs });
|
|
26916
|
-
dispatch(tr);
|
|
26917
|
-
}
|
|
26918
|
-
return true;
|
|
27170
|
+
insertContentBlock: (config) => ({ commands: commands2 }) => {
|
|
27171
|
+
return commands2.insertContent({
|
|
27172
|
+
type: this.name,
|
|
27173
|
+
attrs: config
|
|
27174
|
+
});
|
|
26919
27175
|
}
|
|
26920
27176
|
};
|
|
26921
|
-
},
|
|
26922
|
-
addHelpers() {
|
|
26923
|
-
return {
|
|
26924
|
-
...SectionHelpers
|
|
26925
|
-
};
|
|
26926
27177
|
}
|
|
26927
27178
|
});
|
|
26928
27179
|
const { findChildren } = helpers;
|
|
@@ -33772,6 +34023,7 @@ const getStarterExtensions = () => {
|
|
|
33772
34023
|
Search,
|
|
33773
34024
|
StructuredContent,
|
|
33774
34025
|
StructuredContentBlock,
|
|
34026
|
+
StructuredContentCommands,
|
|
33775
34027
|
DocumentSection,
|
|
33776
34028
|
NodeResizer,
|
|
33777
34029
|
CustomSelection,
|