@harbour-enterprises/superdoc 0.22.0-next.9 → 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-HN-tp5RN.es.js → PdfViewer-BNWaI4WI.es.js} +1 -1
- package/dist/chunks/{PdfViewer-DyWe33pN.cjs → PdfViewer-DpkgwUPi.cjs} +1 -1
- package/dist/chunks/{index-BeVpZc19.cjs → index-BbGPYtNy.cjs} +2 -2
- package/dist/chunks/{index-ir6efMuz.es.js → index-DWKEKmiB.es.js} +2 -2
- package/dist/chunks/{super-editor.es-BwqYS285.es.js → super-editor.es-BVxfhpAJ.es.js} +1581 -1274
- package/dist/chunks/{super-editor.es-CKfdmK-8.cjs → super-editor.es-BoUJEZaF.cjs} +1581 -1274
- package/dist/core/types/index.d.ts.map +1 -1
- package/dist/style.css +1 -0
- 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-CFqh_xBx.js → editor-BBnC1DzI.js} +1436 -1172
- package/dist/super-editor/chunks/{toolbar-DdfyWgZF.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 +1581 -1274
- 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,7 +12107,7 @@ 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) {
|
|
@@ -12149,10 +12149,8 @@ const createOrUpdateTrackedChangeComment = ({ event, marks, deletionNodes, nodes
|
|
|
12149
12149
|
if (hasMatchingId) nodesWithMark.push(node2);
|
|
12150
12150
|
});
|
|
12151
12151
|
const { deletionText, trackedChangeText } = getTrackedChangeText({
|
|
12152
|
-
state: newEditorState,
|
|
12153
12152
|
nodes: nodesWithMark.length ? nodesWithMark : [node],
|
|
12154
12153
|
mark: trackedMark,
|
|
12155
|
-
marks,
|
|
12156
12154
|
trackedChangeType,
|
|
12157
12155
|
isDeletionInsertion
|
|
12158
12156
|
});
|
|
@@ -16967,258 +16965,785 @@ const SlashMenu = Extension.create({
|
|
|
16967
16965
|
return this.editor.options.isHeadless ? [] : [slashMenuPlugin];
|
|
16968
16966
|
}
|
|
16969
16967
|
});
|
|
16970
|
-
|
|
16971
|
-
|
|
16972
|
-
|
|
16973
|
-
|
|
16974
|
-
|
|
16975
|
-
|
|
16976
|
-
|
|
16977
|
-
|
|
16978
|
-
|
|
16979
|
-
|
|
16980
|
-
|
|
16981
|
-
|
|
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
|
-
|
|
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
|
+
);
|
|
17019
17059
|
}
|
|
17020
|
-
}
|
|
17060
|
+
}
|
|
17061
|
+
if (isDragging || isDropEvent || isCopyEvent || isPasteEvent || isCutEvent || isClickEvent && isSelectable) {
|
|
17062
|
+
return false;
|
|
17063
|
+
}
|
|
17064
|
+
return true;
|
|
17021
17065
|
}
|
|
17022
|
-
|
|
17023
|
-
|
|
17024
|
-
|
|
17025
|
-
|
|
17026
|
-
|
|
17027
|
-
|
|
17028
|
-
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;
|
|
17029
17073
|
}
|
|
17030
|
-
|
|
17031
|
-
|
|
17032
|
-
|
|
17033
|
-
|
|
17034
|
-
|
|
17035
|
-
|
|
17036
|
-
|
|
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);
|
|
17037
17131
|
view.dispatch(transaction);
|
|
17038
|
-
});
|
|
17039
|
-
if (handled) {
|
|
17040
|
-
tr.setMeta("preventDispatch", true);
|
|
17041
17132
|
}
|
|
17042
|
-
|
|
17043
|
-
|
|
17044
|
-
|
|
17045
|
-
|
|
17046
|
-
|
|
17047
|
-
|
|
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",
|
|
17048
17179
|
inline: true,
|
|
17049
17180
|
content: "inline*",
|
|
17050
|
-
|
|
17051
|
-
|
|
17181
|
+
isolating: true,
|
|
17182
|
+
atom: false,
|
|
17183
|
+
// false - has editable content.
|
|
17184
|
+
draggable: true,
|
|
17052
17185
|
addOptions() {
|
|
17053
17186
|
return {
|
|
17054
17187
|
htmlAttributes: {
|
|
17055
|
-
|
|
17188
|
+
class: structuredContentClass$1,
|
|
17189
|
+
"aria-label": "Structured content node"
|
|
17056
17190
|
}
|
|
17057
17191
|
};
|
|
17058
17192
|
},
|
|
17059
17193
|
addAttributes() {
|
|
17060
17194
|
return {
|
|
17061
|
-
|
|
17195
|
+
id: {
|
|
17062
17196
|
default: null,
|
|
17063
|
-
|
|
17064
|
-
|
|
17197
|
+
parseDOM: (elem) => elem.getAttribute("data-id"),
|
|
17198
|
+
renderDOM: (attrs) => {
|
|
17199
|
+
if (!attrs.id) return {};
|
|
17200
|
+
return { "data-id": attrs.id };
|
|
17201
|
+
}
|
|
17065
17202
|
},
|
|
17066
|
-
|
|
17203
|
+
tag: {
|
|
17067
17204
|
default: null,
|
|
17068
|
-
|
|
17069
|
-
|
|
17205
|
+
parseDOM: (elem) => elem.getAttribute("data-tag"),
|
|
17206
|
+
renderDOM: (attrs) => {
|
|
17207
|
+
if (!attrs.tag) return {};
|
|
17208
|
+
return { "data-tag": attrs.tag };
|
|
17209
|
+
}
|
|
17070
17210
|
},
|
|
17071
|
-
|
|
17211
|
+
alias: {
|
|
17072
17212
|
default: null,
|
|
17073
|
-
|
|
17074
|
-
|
|
17213
|
+
parseDOM: (elem) => elem.getAttribute("data-alias"),
|
|
17214
|
+
renderDOM: (attrs) => {
|
|
17215
|
+
if (!attrs.alias) return {};
|
|
17216
|
+
return { "data-alias": attrs.alias };
|
|
17217
|
+
}
|
|
17075
17218
|
},
|
|
17076
|
-
|
|
17077
|
-
|
|
17078
|
-
rendered: false,
|
|
17079
|
-
keepOnSplit: true
|
|
17219
|
+
sdtPr: {
|
|
17220
|
+
rendered: false
|
|
17080
17221
|
}
|
|
17081
17222
|
};
|
|
17082
17223
|
},
|
|
17083
|
-
addCommands() {
|
|
17084
|
-
return {
|
|
17085
|
-
splitRun
|
|
17086
|
-
};
|
|
17087
|
-
},
|
|
17088
17224
|
parseDOM() {
|
|
17089
|
-
return [{ tag: "span[data-
|
|
17225
|
+
return [{ tag: "span[data-structured-content]" }];
|
|
17090
17226
|
},
|
|
17091
17227
|
renderDOM({ htmlAttributes }) {
|
|
17092
|
-
|
|
17093
|
-
|
|
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
|
+
};
|
|
17094
17240
|
}
|
|
17095
17241
|
});
|
|
17096
|
-
|
|
17097
|
-
|
|
17098
|
-
|
|
17099
|
-
|
|
17100
|
-
|
|
17101
|
-
|
|
17102
|
-
|
|
17103
|
-
|
|
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,
|
|
17104
17292
|
addOptions() {
|
|
17105
17293
|
return {
|
|
17106
|
-
itemTypeName: "listItem",
|
|
17107
17294
|
htmlAttributes: {
|
|
17108
|
-
|
|
17109
|
-
|
|
17110
|
-
|
|
17111
|
-
keepAttributes: false
|
|
17295
|
+
class: structuredContentClass,
|
|
17296
|
+
"aria-label": "Structured content block node"
|
|
17297
|
+
}
|
|
17112
17298
|
};
|
|
17113
17299
|
},
|
|
17114
|
-
parseDOM() {
|
|
17115
|
-
return [{ tag: "ul" }];
|
|
17116
|
-
},
|
|
17117
|
-
renderDOM({ htmlAttributes }) {
|
|
17118
|
-
const attributes = Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes);
|
|
17119
|
-
return ["ul", attributes, 0];
|
|
17120
|
-
},
|
|
17121
17300
|
addAttributes() {
|
|
17122
17301
|
return {
|
|
17123
|
-
|
|
17124
|
-
default:
|
|
17125
|
-
|
|
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
|
+
}
|
|
17126
17309
|
},
|
|
17127
|
-
|
|
17128
|
-
|
|
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
|
+
}
|
|
17129
17317
|
},
|
|
17130
|
-
|
|
17318
|
+
alias: {
|
|
17131
17319
|
default: null,
|
|
17132
|
-
|
|
17133
|
-
parseDOM: (elem) => elem.getAttribute("data-sd-block-id"),
|
|
17320
|
+
parseDOM: (elem) => elem.getAttribute("data-alias"),
|
|
17134
17321
|
renderDOM: (attrs) => {
|
|
17135
|
-
|
|
17322
|
+
if (!attrs.alias) return {};
|
|
17323
|
+
return { "data-alias": attrs.alias };
|
|
17136
17324
|
}
|
|
17137
17325
|
},
|
|
17138
|
-
|
|
17139
|
-
rendered: false
|
|
17140
|
-
keepOnSplit: true
|
|
17326
|
+
sdtPr: {
|
|
17327
|
+
rendered: false
|
|
17141
17328
|
}
|
|
17142
17329
|
};
|
|
17143
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",
|
|
17144
17384
|
addCommands() {
|
|
17145
17385
|
return {
|
|
17146
17386
|
/**
|
|
17147
|
-
*
|
|
17387
|
+
* Inserts a structured content inline at selection.
|
|
17148
17388
|
* @category Command
|
|
17149
|
-
* @
|
|
17150
|
-
* // Toggle bullet list on selected text
|
|
17151
|
-
* editor.commands.toggleBulletList()
|
|
17152
|
-
* @note Converts selected paragraphs to list items or removes list formatting
|
|
17389
|
+
* @param {StructuredContentInlineInsert} options
|
|
17153
17390
|
*/
|
|
17154
|
-
|
|
17155
|
-
|
|
17156
|
-
|
|
17157
|
-
|
|
17158
|
-
|
|
17159
|
-
|
|
17160
|
-
|
|
17161
|
-
|
|
17162
|
-
return this.editor.commands.toggleBulletList();
|
|
17163
|
-
}
|
|
17164
|
-
};
|
|
17165
|
-
},
|
|
17166
|
-
addInputRules() {
|
|
17167
|
-
return [
|
|
17168
|
-
new InputRule({
|
|
17169
|
-
match: inputRegex$1,
|
|
17170
|
-
handler: ({ state, range }) => {
|
|
17171
|
-
const $pos = state.selection.$from;
|
|
17172
|
-
const listItemType = state.schema.nodes.listItem;
|
|
17173
|
-
for (let depth = $pos.depth; depth >= 0; depth--) {
|
|
17174
|
-
if ($pos.node(depth).type === listItemType) {
|
|
17175
|
-
return null;
|
|
17176
|
-
}
|
|
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);
|
|
17177
17399
|
}
|
|
17178
|
-
|
|
17179
|
-
|
|
17180
|
-
|
|
17181
|
-
|
|
17182
|
-
|
|
17183
|
-
|
|
17184
|
-
|
|
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);
|
|
17185
17422
|
}
|
|
17186
|
-
|
|
17187
|
-
|
|
17188
|
-
|
|
17189
|
-
|
|
17190
|
-
|
|
17191
|
-
|
|
17192
|
-
|
|
17193
|
-
|
|
17194
|
-
|
|
17195
|
-
|
|
17196
|
-
|
|
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
|
+
};
|
|
17197
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,
|
|
17198
17725
|
addOptions() {
|
|
17199
17726
|
return {
|
|
17200
|
-
itemTypeName: "listItem",
|
|
17201
17727
|
htmlAttributes: {
|
|
17202
|
-
|
|
17203
|
-
|
|
17204
|
-
|
|
17205
|
-
keepAttributes: false,
|
|
17206
|
-
listStyleTypes: ["decimal", "lowerAlpha", "lowerRoman"]
|
|
17728
|
+
class: "sd-document-section-block",
|
|
17729
|
+
"aria-label": "Structured content block"
|
|
17730
|
+
}
|
|
17207
17731
|
};
|
|
17208
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
|
+
},
|
|
17209
17744
|
addAttributes() {
|
|
17210
17745
|
return {
|
|
17211
|
-
|
|
17212
|
-
default: 1,
|
|
17213
|
-
parseDOM: (element) => {
|
|
17214
|
-
return element.hasAttribute("start") ? parseInt(element.getAttribute("start") || "", 10) : 1;
|
|
17215
|
-
},
|
|
17216
|
-
renderDOM: (attrs) => {
|
|
17217
|
-
return {
|
|
17218
|
-
start: attrs.order
|
|
17219
|
-
};
|
|
17220
|
-
}
|
|
17221
|
-
},
|
|
17746
|
+
id: {},
|
|
17222
17747
|
sdBlockId: {
|
|
17223
17748
|
default: null,
|
|
17224
17749
|
keepOnSplit: false,
|
|
@@ -17227,121 +17752,589 @@ const OrderedList = Node$1.create({
|
|
|
17227
17752
|
return attrs.sdBlockId ? { "data-sd-block-id": attrs.sdBlockId } : {};
|
|
17228
17753
|
}
|
|
17229
17754
|
},
|
|
17230
|
-
|
|
17231
|
-
|
|
17232
|
-
|
|
17233
|
-
|
|
17234
|
-
if (!attrs.syncId) return {};
|
|
17235
|
-
return {
|
|
17236
|
-
"data-sync-id": attrs.syncId
|
|
17237
|
-
};
|
|
17238
|
-
}
|
|
17239
|
-
// rendered: false,
|
|
17240
|
-
},
|
|
17241
|
-
listId: {
|
|
17242
|
-
keepOnSplit: true,
|
|
17243
|
-
parseDOM: (elem) => elem.getAttribute("data-list-id"),
|
|
17244
|
-
renderDOM: (attrs) => {
|
|
17245
|
-
if (!attrs.listId) return {};
|
|
17246
|
-
return {
|
|
17247
|
-
"data-list-id": attrs.listId
|
|
17248
|
-
};
|
|
17249
|
-
}
|
|
17250
|
-
},
|
|
17251
|
-
"list-style-type": {
|
|
17252
|
-
default: "decimal",
|
|
17253
|
-
rendered: false
|
|
17254
|
-
},
|
|
17255
|
-
attributes: {
|
|
17256
|
-
rendered: false,
|
|
17257
|
-
keepOnSplit: true
|
|
17258
|
-
}
|
|
17755
|
+
title: {},
|
|
17756
|
+
description: {},
|
|
17757
|
+
sectionType: {},
|
|
17758
|
+
isLocked: { default: false }
|
|
17259
17759
|
};
|
|
17260
17760
|
},
|
|
17261
|
-
|
|
17262
|
-
return
|
|
17263
|
-
|
|
17264
|
-
|
|
17265
|
-
const { start: start2, ...restAttributes } = htmlAttributes;
|
|
17266
|
-
return start2 === 1 ? ["ol", Attribute.mergeAttributes(this.options.htmlAttributes, restAttributes), 0] : ["ol", Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes), 0];
|
|
17761
|
+
addNodeView() {
|
|
17762
|
+
return ({ node, editor, getPos, decorations }) => {
|
|
17763
|
+
return new DocumentSectionView(node, getPos, decorations, editor);
|
|
17764
|
+
};
|
|
17267
17765
|
},
|
|
17268
17766
|
addCommands() {
|
|
17269
17767
|
return {
|
|
17270
17768
|
/**
|
|
17271
|
-
*
|
|
17769
|
+
* Create a lockable content section
|
|
17272
17770
|
* @category Command
|
|
17771
|
+
* @param {SectionCreate} [options={}] - Section configuration
|
|
17273
17772
|
* @example
|
|
17274
|
-
* editor.commands.
|
|
17275
|
-
*
|
|
17773
|
+
* editor.commands.createDocumentSection({
|
|
17774
|
+
* id: 1,
|
|
17775
|
+
* title: 'Terms & Conditions',
|
|
17776
|
+
* isLocked: true,
|
|
17777
|
+
* html: '<p>Legal content...</p>'
|
|
17778
|
+
* })
|
|
17276
17779
|
*/
|
|
17277
|
-
|
|
17278
|
-
|
|
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;
|
|
17279
17851
|
},
|
|
17280
17852
|
/**
|
|
17281
|
-
*
|
|
17853
|
+
* Remove section wrapper at cursor, preserving its content
|
|
17282
17854
|
* @category Command
|
|
17283
|
-
* @param {Array} followingNodes - Nodes to restart
|
|
17284
|
-
* @param {number} pos - Starting position
|
|
17285
17855
|
* @example
|
|
17286
|
-
* editor.commands.
|
|
17287
|
-
* @note
|
|
17856
|
+
* editor.commands.removeSectionAtSelection()
|
|
17857
|
+
* @note Content stays in document, only section wrapper is removed
|
|
17288
17858
|
*/
|
|
17289
|
-
|
|
17290
|
-
|
|
17291
|
-
|
|
17292
|
-
|
|
17293
|
-
|
|
17294
|
-
|
|
17295
|
-
|
|
17296
|
-
|
|
17297
|
-
|
|
17298
|
-
|
|
17299
|
-
|
|
17300
|
-
|
|
17301
|
-
|
|
17302
|
-
|
|
17303
|
-
|
|
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
|
+
}
|
|
17304
17876
|
return true;
|
|
17305
17877
|
},
|
|
17306
17878
|
/**
|
|
17307
|
-
*
|
|
17879
|
+
* Delete section and all its content
|
|
17308
17880
|
* @category Command
|
|
17881
|
+
* @param {number} id - Section to delete
|
|
17309
17882
|
* @example
|
|
17310
|
-
* editor.commands.
|
|
17311
|
-
* @note Cycles through decimal -> lowerAlpha -> lowerRoman based on depth
|
|
17883
|
+
* editor.commands.removeSectionById(123)
|
|
17312
17884
|
*/
|
|
17313
|
-
|
|
17314
|
-
|
|
17315
|
-
|
|
17316
|
-
|
|
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);
|
|
17317
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);
|
|
17318
17949
|
if (dispatch) {
|
|
17319
|
-
|
|
17320
|
-
|
|
17321
|
-
let listStyle = listStyleTypes[listLevel % listStyleTypes.length];
|
|
17322
|
-
let currentListStyle = list.node.attrs["list-style-type"];
|
|
17323
|
-
let nodeAtPos = tr.doc.nodeAt(list.pos);
|
|
17324
|
-
if (currentListStyle !== listStyle && nodeAtPos.eq(list.node)) {
|
|
17325
|
-
tr.setNodeMarkup(list.pos, void 0, {
|
|
17326
|
-
...list.node.attrs,
|
|
17327
|
-
...{
|
|
17328
|
-
"list-style-type": listStyle
|
|
17329
|
-
}
|
|
17330
|
-
});
|
|
17331
|
-
}
|
|
17950
|
+
tr.setMeta("documentSection", { action: "update", id, attrs });
|
|
17951
|
+
dispatch(tr);
|
|
17332
17952
|
}
|
|
17333
17953
|
return true;
|
|
17334
17954
|
}
|
|
17335
17955
|
};
|
|
17336
17956
|
},
|
|
17337
|
-
|
|
17957
|
+
addHelpers() {
|
|
17338
17958
|
return {
|
|
17339
|
-
|
|
17340
|
-
return this.editor.commands.toggleOrderedList();
|
|
17341
|
-
}
|
|
17959
|
+
...SectionHelpers
|
|
17342
17960
|
};
|
|
17343
|
-
}
|
|
17344
|
-
|
|
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
|
+
})
|
|
18180
|
+
];
|
|
18181
|
+
}
|
|
18182
|
+
});
|
|
18183
|
+
const inputRegex = /^(\d+)\.\s$/;
|
|
18184
|
+
const OrderedList = Node$1.create({
|
|
18185
|
+
name: "orderedList",
|
|
18186
|
+
group: "block list",
|
|
18187
|
+
selectable: false,
|
|
18188
|
+
content() {
|
|
18189
|
+
return `${this.options.itemTypeName}+`;
|
|
18190
|
+
},
|
|
18191
|
+
addOptions() {
|
|
18192
|
+
return {
|
|
18193
|
+
itemTypeName: "listItem",
|
|
18194
|
+
htmlAttributes: {
|
|
18195
|
+
"aria-label": "Ordered list node"
|
|
18196
|
+
},
|
|
18197
|
+
keepMarks: true,
|
|
18198
|
+
keepAttributes: false,
|
|
18199
|
+
listStyleTypes: ["decimal", "lowerAlpha", "lowerRoman"]
|
|
18200
|
+
};
|
|
18201
|
+
},
|
|
18202
|
+
addAttributes() {
|
|
18203
|
+
return {
|
|
18204
|
+
order: {
|
|
18205
|
+
default: 1,
|
|
18206
|
+
parseDOM: (element) => {
|
|
18207
|
+
return element.hasAttribute("start") ? parseInt(element.getAttribute("start") || "", 10) : 1;
|
|
18208
|
+
},
|
|
18209
|
+
renderDOM: (attrs) => {
|
|
18210
|
+
return {
|
|
18211
|
+
start: attrs.order
|
|
18212
|
+
};
|
|
18213
|
+
}
|
|
18214
|
+
},
|
|
18215
|
+
sdBlockId: {
|
|
18216
|
+
default: null,
|
|
18217
|
+
keepOnSplit: false,
|
|
18218
|
+
parseDOM: (elem) => elem.getAttribute("data-sd-block-id"),
|
|
18219
|
+
renderDOM: (attrs) => {
|
|
18220
|
+
return attrs.sdBlockId ? { "data-sd-block-id": attrs.sdBlockId } : {};
|
|
18221
|
+
}
|
|
18222
|
+
},
|
|
18223
|
+
syncId: {
|
|
18224
|
+
default: null,
|
|
18225
|
+
parseDOM: (elem) => elem.getAttribute("data-sync-id"),
|
|
18226
|
+
renderDOM: (attrs) => {
|
|
18227
|
+
if (!attrs.syncId) return {};
|
|
18228
|
+
return {
|
|
18229
|
+
"data-sync-id": attrs.syncId
|
|
18230
|
+
};
|
|
18231
|
+
}
|
|
18232
|
+
// rendered: false,
|
|
18233
|
+
},
|
|
18234
|
+
listId: {
|
|
18235
|
+
keepOnSplit: true,
|
|
18236
|
+
parseDOM: (elem) => elem.getAttribute("data-list-id"),
|
|
18237
|
+
renderDOM: (attrs) => {
|
|
18238
|
+
if (!attrs.listId) return {};
|
|
18239
|
+
return {
|
|
18240
|
+
"data-list-id": attrs.listId
|
|
18241
|
+
};
|
|
18242
|
+
}
|
|
18243
|
+
},
|
|
18244
|
+
"list-style-type": {
|
|
18245
|
+
default: "decimal",
|
|
18246
|
+
rendered: false
|
|
18247
|
+
},
|
|
18248
|
+
attributes: {
|
|
18249
|
+
rendered: false,
|
|
18250
|
+
keepOnSplit: true
|
|
18251
|
+
}
|
|
18252
|
+
};
|
|
18253
|
+
},
|
|
18254
|
+
parseDOM() {
|
|
18255
|
+
return [{ tag: "ol" }];
|
|
18256
|
+
},
|
|
18257
|
+
renderDOM({ htmlAttributes }) {
|
|
18258
|
+
const { start: start2, ...restAttributes } = htmlAttributes;
|
|
18259
|
+
return start2 === 1 ? ["ol", Attribute.mergeAttributes(this.options.htmlAttributes, restAttributes), 0] : ["ol", Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes), 0];
|
|
18260
|
+
},
|
|
18261
|
+
addCommands() {
|
|
18262
|
+
return {
|
|
18263
|
+
/**
|
|
18264
|
+
* Toggle ordered list formatting
|
|
18265
|
+
* @category Command
|
|
18266
|
+
* @example
|
|
18267
|
+
* editor.commands.toggleOrderedList()
|
|
18268
|
+
* @note Converts selection to ordered list or back to paragraphs
|
|
18269
|
+
*/
|
|
18270
|
+
toggleOrderedList: () => (params2) => {
|
|
18271
|
+
return toggleList(this.type)(params2);
|
|
18272
|
+
},
|
|
18273
|
+
/**
|
|
18274
|
+
* Restart list node numbering
|
|
18275
|
+
* @category Command
|
|
18276
|
+
* @param {Array} followingNodes - Nodes to restart
|
|
18277
|
+
* @param {number} pos - Starting position
|
|
18278
|
+
* @example
|
|
18279
|
+
* editor.commands.restartListNodes(nodes, position)
|
|
18280
|
+
* @note Resets list numbering for specified nodes
|
|
18281
|
+
*/
|
|
18282
|
+
restartListNodes: (followingNodes, pos) => ({ tr }) => {
|
|
18283
|
+
let currentNodePos = pos;
|
|
18284
|
+
const nodes = followingNodes.map((node) => {
|
|
18285
|
+
const resultNode = {
|
|
18286
|
+
node,
|
|
18287
|
+
pos: currentNodePos
|
|
18288
|
+
};
|
|
18289
|
+
currentNodePos += node.nodeSize;
|
|
18290
|
+
return resultNode;
|
|
18291
|
+
});
|
|
18292
|
+
nodes.forEach((item) => {
|
|
18293
|
+
const { pos: pos2 } = item;
|
|
18294
|
+
const newPos = tr.mapping.map(pos2);
|
|
18295
|
+
tr.setNodeMarkup(newPos, void 0, {});
|
|
18296
|
+
});
|
|
18297
|
+
return true;
|
|
18298
|
+
},
|
|
18299
|
+
/**
|
|
18300
|
+
* Update ordered list style type based on nesting level
|
|
18301
|
+
* @category Command
|
|
18302
|
+
* @example
|
|
18303
|
+
* editor.commands.updateOrderedListStyleType()
|
|
18304
|
+
* @note Cycles through decimal -> lowerAlpha -> lowerRoman based on depth
|
|
18305
|
+
*/
|
|
18306
|
+
updateOrderedListStyleType: () => ({ dispatch, tr }) => {
|
|
18307
|
+
let list = findParentNode((node) => node.type.name === this.name)(tr.selection);
|
|
18308
|
+
if (!list) {
|
|
18309
|
+
return true;
|
|
18310
|
+
}
|
|
18311
|
+
if (dispatch) {
|
|
18312
|
+
let listLevel = (list.depth - 1) / 2;
|
|
18313
|
+
let listStyleTypes = this.options.listStyleTypes;
|
|
18314
|
+
let listStyle = listStyleTypes[listLevel % listStyleTypes.length];
|
|
18315
|
+
let currentListStyle = list.node.attrs["list-style-type"];
|
|
18316
|
+
let nodeAtPos = tr.doc.nodeAt(list.pos);
|
|
18317
|
+
if (currentListStyle !== listStyle && nodeAtPos.eq(list.node)) {
|
|
18318
|
+
tr.setNodeMarkup(list.pos, void 0, {
|
|
18319
|
+
...list.node.attrs,
|
|
18320
|
+
...{
|
|
18321
|
+
"list-style-type": listStyle
|
|
18322
|
+
}
|
|
18323
|
+
});
|
|
18324
|
+
}
|
|
18325
|
+
}
|
|
18326
|
+
return true;
|
|
18327
|
+
}
|
|
18328
|
+
};
|
|
18329
|
+
},
|
|
18330
|
+
addShortcuts() {
|
|
18331
|
+
return {
|
|
18332
|
+
"Mod-Shift-7": () => {
|
|
18333
|
+
return this.editor.commands.toggleOrderedList();
|
|
18334
|
+
}
|
|
18335
|
+
};
|
|
18336
|
+
},
|
|
18337
|
+
addInputRules() {
|
|
17345
18338
|
return [
|
|
17346
18339
|
new InputRule({
|
|
17347
18340
|
match: inputRegex,
|
|
@@ -18549,7 +19542,7 @@ class ListItemNodeView {
|
|
|
18549
19542
|
this.decorations = decorations;
|
|
18550
19543
|
this.view = editor.view;
|
|
18551
19544
|
this.getPos = getPos;
|
|
18552
|
-
__privateMethod(this, _ListItemNodeView_instances,
|
|
19545
|
+
__privateMethod(this, _ListItemNodeView_instances, init_fn3).call(this);
|
|
18553
19546
|
activeListItemNodeViews.add(this);
|
|
18554
19547
|
}
|
|
18555
19548
|
refreshIndentStyling() {
|
|
@@ -18610,7 +19603,7 @@ class ListItemNodeView {
|
|
|
18610
19603
|
}
|
|
18611
19604
|
}
|
|
18612
19605
|
_ListItemNodeView_instances = new WeakSet();
|
|
18613
|
-
|
|
19606
|
+
init_fn3 = function() {
|
|
18614
19607
|
const { attrs } = this.node;
|
|
18615
19608
|
const { listLevel, listNumberingType, lvlText, numId, level, customFormat } = attrs;
|
|
18616
19609
|
let orderMarker = "";
|
|
@@ -25958,745 +26951,96 @@ const processMarks = (marks) => {
|
|
|
25958
26951
|
styles["text-decoration"] = (styles["text-decoration"] || "") + " underline";
|
|
25959
26952
|
break;
|
|
25960
26953
|
case "strike":
|
|
25961
|
-
styles["text-decoration"] = (styles["text-decoration"] || "") + " line-through";
|
|
25962
|
-
break;
|
|
25963
|
-
default:
|
|
25964
|
-
if (attrs?.style) {
|
|
25965
|
-
Object.entries(attrs.style).forEach(([key2, value]) => {
|
|
25966
|
-
styles[key2] = value;
|
|
25967
|
-
});
|
|
25968
|
-
}
|
|
25969
|
-
break;
|
|
25970
|
-
}
|
|
25971
|
-
});
|
|
25972
|
-
return styles;
|
|
25973
|
-
};
|
|
25974
|
-
const ShapeContainer = Node$1.create({
|
|
25975
|
-
name: "shapeContainer",
|
|
25976
|
-
group: "block",
|
|
25977
|
-
content: "block+",
|
|
25978
|
-
isolating: true,
|
|
25979
|
-
addOptions() {
|
|
25980
|
-
return {
|
|
25981
|
-
htmlAttributes: {
|
|
25982
|
-
class: "sd-editor-shape-container",
|
|
25983
|
-
"aria-label": "Shape container node"
|
|
25984
|
-
}
|
|
25985
|
-
};
|
|
25986
|
-
},
|
|
25987
|
-
addAttributes() {
|
|
25988
|
-
return {
|
|
25989
|
-
fillcolor: {
|
|
25990
|
-
renderDOM: (attrs) => {
|
|
25991
|
-
if (!attrs.fillcolor) return {};
|
|
25992
|
-
return {
|
|
25993
|
-
style: `background-color: ${attrs.fillcolor}`
|
|
25994
|
-
};
|
|
25995
|
-
}
|
|
25996
|
-
},
|
|
25997
|
-
sdBlockId: {
|
|
25998
|
-
default: null,
|
|
25999
|
-
keepOnSplit: false,
|
|
26000
|
-
parseDOM: (elem) => elem.getAttribute("data-sd-block-id"),
|
|
26001
|
-
renderDOM: (attrs) => {
|
|
26002
|
-
return attrs.sdBlockId ? { "data-sd-block-id": attrs.sdBlockId } : {};
|
|
26003
|
-
}
|
|
26004
|
-
},
|
|
26005
|
-
style: {
|
|
26006
|
-
renderDOM: (attrs) => {
|
|
26007
|
-
if (!attrs.style) return {};
|
|
26008
|
-
return {
|
|
26009
|
-
style: attrs.style
|
|
26010
|
-
};
|
|
26011
|
-
}
|
|
26012
|
-
},
|
|
26013
|
-
wrapAttributes: {
|
|
26014
|
-
rendered: false
|
|
26015
|
-
},
|
|
26016
|
-
attributes: {
|
|
26017
|
-
rendered: false
|
|
26018
|
-
}
|
|
26019
|
-
};
|
|
26020
|
-
},
|
|
26021
|
-
parseDOM() {
|
|
26022
|
-
return [
|
|
26023
|
-
{
|
|
26024
|
-
tag: `div[data-type="${this.name}"]`
|
|
26025
|
-
}
|
|
26026
|
-
];
|
|
26027
|
-
},
|
|
26028
|
-
renderDOM({ htmlAttributes }) {
|
|
26029
|
-
return [
|
|
26030
|
-
"div",
|
|
26031
|
-
Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes, { "data-type": this.name }),
|
|
26032
|
-
0
|
|
26033
|
-
];
|
|
26034
|
-
}
|
|
26035
|
-
});
|
|
26036
|
-
const ShapeTextbox = Node$1.create({
|
|
26037
|
-
name: "shapeTextbox",
|
|
26038
|
-
group: "block",
|
|
26039
|
-
content: "paragraph* block*",
|
|
26040
|
-
isolating: true,
|
|
26041
|
-
addOptions() {
|
|
26042
|
-
return {
|
|
26043
|
-
htmlAttributes: {
|
|
26044
|
-
class: "sd-editor-shape-textbox",
|
|
26045
|
-
"aria-label": "Shape textbox node"
|
|
26046
|
-
}
|
|
26047
|
-
};
|
|
26048
|
-
},
|
|
26049
|
-
addAttributes() {
|
|
26050
|
-
return {
|
|
26051
|
-
sdBlockId: {
|
|
26052
|
-
default: null,
|
|
26053
|
-
keepOnSplit: false,
|
|
26054
|
-
parseDOM: (elem) => elem.getAttribute("data-sd-block-id"),
|
|
26055
|
-
renderDOM: (attrs) => {
|
|
26056
|
-
return attrs.sdBlockId ? { "data-sd-block-id": attrs.sdBlockId } : {};
|
|
26057
|
-
}
|
|
26058
|
-
},
|
|
26059
|
-
attributes: {
|
|
26060
|
-
rendered: false
|
|
26061
|
-
}
|
|
26062
|
-
};
|
|
26063
|
-
},
|
|
26064
|
-
parseDOM() {
|
|
26065
|
-
return [
|
|
26066
|
-
{
|
|
26067
|
-
tag: `div[data-type="${this.name}"]`
|
|
26068
|
-
}
|
|
26069
|
-
];
|
|
26070
|
-
},
|
|
26071
|
-
renderDOM({ htmlAttributes }) {
|
|
26072
|
-
return [
|
|
26073
|
-
"div",
|
|
26074
|
-
Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes, { "data-type": this.name }),
|
|
26075
|
-
0
|
|
26076
|
-
];
|
|
26077
|
-
}
|
|
26078
|
-
});
|
|
26079
|
-
const ContentBlock = Node$1.create({
|
|
26080
|
-
name: "contentBlock",
|
|
26081
|
-
group: "inline",
|
|
26082
|
-
content: "",
|
|
26083
|
-
isolating: true,
|
|
26084
|
-
atom: true,
|
|
26085
|
-
inline: true,
|
|
26086
|
-
addOptions() {
|
|
26087
|
-
return {
|
|
26088
|
-
htmlAttributes: {
|
|
26089
|
-
contenteditable: false
|
|
26090
|
-
}
|
|
26091
|
-
};
|
|
26092
|
-
},
|
|
26093
|
-
addAttributes() {
|
|
26094
|
-
return {
|
|
26095
|
-
horizontalRule: {
|
|
26096
|
-
default: false,
|
|
26097
|
-
renderDOM: ({ horizontalRule }) => {
|
|
26098
|
-
if (!horizontalRule) return {};
|
|
26099
|
-
return { "data-horizontal-rule": "true" };
|
|
26100
|
-
}
|
|
26101
|
-
},
|
|
26102
|
-
size: {
|
|
26103
|
-
default: null,
|
|
26104
|
-
renderDOM: ({ size }) => {
|
|
26105
|
-
if (!size) return {};
|
|
26106
|
-
let style = "";
|
|
26107
|
-
if (size.top) style += `top: ${size.top}px; `;
|
|
26108
|
-
if (size.left) style += `left: ${size.left}px; `;
|
|
26109
|
-
if (size.width) style += `width: ${size.width.toString().endsWith("%") ? size.width : `${size.width}px`}; `;
|
|
26110
|
-
if (size.height)
|
|
26111
|
-
style += `height: ${size.height.toString().endsWith("%") ? size.height : `${size.height}px`}; `;
|
|
26112
|
-
return { style };
|
|
26113
|
-
}
|
|
26114
|
-
},
|
|
26115
|
-
background: {
|
|
26116
|
-
default: null,
|
|
26117
|
-
renderDOM: (attrs) => {
|
|
26118
|
-
if (!attrs.background) return {};
|
|
26119
|
-
return {
|
|
26120
|
-
style: `background-color: ${attrs.background}`
|
|
26121
|
-
};
|
|
26122
|
-
}
|
|
26123
|
-
},
|
|
26124
|
-
drawingContent: {
|
|
26125
|
-
rendered: false
|
|
26126
|
-
},
|
|
26127
|
-
attributes: {
|
|
26128
|
-
rendered: false
|
|
26129
|
-
}
|
|
26130
|
-
};
|
|
26131
|
-
},
|
|
26132
|
-
parseDOM() {
|
|
26133
|
-
return [
|
|
26134
|
-
{
|
|
26135
|
-
tag: `div[data-type="${this.name}"]`
|
|
26136
|
-
}
|
|
26137
|
-
];
|
|
26138
|
-
},
|
|
26139
|
-
renderDOM({ htmlAttributes }) {
|
|
26140
|
-
return ["div", Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes, { "data-type": this.name })];
|
|
26141
|
-
},
|
|
26142
|
-
addCommands() {
|
|
26143
|
-
return {
|
|
26144
|
-
/**
|
|
26145
|
-
* Insert a horizontal rule
|
|
26146
|
-
* @category Command
|
|
26147
|
-
* @example
|
|
26148
|
-
* editor.commands.insertHorizontalRule()
|
|
26149
|
-
* @note Creates a visual separator between content sections
|
|
26150
|
-
*/
|
|
26151
|
-
insertHorizontalRule: () => ({ commands: commands2 }) => {
|
|
26152
|
-
return commands2.insertContent({
|
|
26153
|
-
type: this.name,
|
|
26154
|
-
attrs: {
|
|
26155
|
-
horizontalRule: true,
|
|
26156
|
-
size: { width: "100%", height: 2 },
|
|
26157
|
-
background: "#e5e7eb"
|
|
26158
|
-
}
|
|
26159
|
-
});
|
|
26160
|
-
},
|
|
26161
|
-
/**
|
|
26162
|
-
* Insert a content block
|
|
26163
|
-
* @category Command
|
|
26164
|
-
* @param {ContentBlockConfig} config - Block configuration
|
|
26165
|
-
* @example
|
|
26166
|
-
* // Insert a spacer block
|
|
26167
|
-
* editor.commands.insertContentBlock({ size: { height: 20 } })
|
|
26168
|
-
*
|
|
26169
|
-
* @example
|
|
26170
|
-
* // Insert a colored divider
|
|
26171
|
-
* editor.commands.insertContentBlock({
|
|
26172
|
-
* size: { width: '50%', height: 3 },
|
|
26173
|
-
* background: '#3b82f6'
|
|
26174
|
-
* })
|
|
26175
|
-
* @note Used for spacing, dividers, and special inline content
|
|
26176
|
-
*/
|
|
26177
|
-
insertContentBlock: (config) => ({ commands: commands2 }) => {
|
|
26178
|
-
return commands2.insertContent({
|
|
26179
|
-
type: this.name,
|
|
26180
|
-
attrs: config
|
|
26181
|
-
});
|
|
26182
|
-
}
|
|
26183
|
-
};
|
|
26184
|
-
}
|
|
26185
|
-
});
|
|
26186
|
-
class StructuredContentViewBase {
|
|
26187
|
-
constructor(props) {
|
|
26188
|
-
__publicField(this, "node");
|
|
26189
|
-
__publicField(this, "view");
|
|
26190
|
-
__publicField(this, "getPos");
|
|
26191
|
-
__publicField(this, "decorations");
|
|
26192
|
-
__publicField(this, "innerDecorations");
|
|
26193
|
-
__publicField(this, "editor");
|
|
26194
|
-
__publicField(this, "extension");
|
|
26195
|
-
__publicField(this, "htmlAttributes");
|
|
26196
|
-
__publicField(this, "root");
|
|
26197
|
-
__publicField(this, "isDragging", false);
|
|
26198
|
-
this.node = props.node;
|
|
26199
|
-
this.view = props.editor.view;
|
|
26200
|
-
this.getPos = props.getPos;
|
|
26201
|
-
this.decorations = props.decorations;
|
|
26202
|
-
this.innerDecorations = props.innerDecorations;
|
|
26203
|
-
this.editor = props.editor;
|
|
26204
|
-
this.extension = props.extension;
|
|
26205
|
-
this.htmlAttributes = props.htmlAttributes;
|
|
26206
|
-
this.mount(props);
|
|
26207
|
-
}
|
|
26208
|
-
mount() {
|
|
26209
|
-
return;
|
|
26210
|
-
}
|
|
26211
|
-
get dom() {
|
|
26212
|
-
return this.root;
|
|
26213
|
-
}
|
|
26214
|
-
get contentDOM() {
|
|
26215
|
-
return null;
|
|
26216
|
-
}
|
|
26217
|
-
update(node, decorations, innerDecorations) {
|
|
26218
|
-
if (node.type !== this.node.type) {
|
|
26219
|
-
return false;
|
|
26220
|
-
}
|
|
26221
|
-
this.node = node;
|
|
26222
|
-
this.decorations = decorations;
|
|
26223
|
-
this.innerDecorations = innerDecorations;
|
|
26224
|
-
this.updateHTMLAttributes();
|
|
26225
|
-
return true;
|
|
26226
|
-
}
|
|
26227
|
-
stopEvent(event) {
|
|
26228
|
-
if (!this.dom) return false;
|
|
26229
|
-
const target = event.target;
|
|
26230
|
-
const isInElement = this.dom.contains(target) && !this.contentDOM?.contains(target);
|
|
26231
|
-
if (!isInElement) return false;
|
|
26232
|
-
const isDragEvent = event.type.startsWith("drag");
|
|
26233
|
-
const isDropEvent = event.type === "drop";
|
|
26234
|
-
const isInput = ["INPUT", "BUTTON", "SELECT", "TEXTAREA"].includes(target.tagName) || target.isContentEditable;
|
|
26235
|
-
if (isInput && !isDropEvent && !isDragEvent) return true;
|
|
26236
|
-
const { isEditable } = this.editor;
|
|
26237
|
-
const { isDragging } = this;
|
|
26238
|
-
const isDraggable = !!this.node.type.spec.draggable;
|
|
26239
|
-
const isSelectable = NodeSelection.isSelectable(this.node);
|
|
26240
|
-
const isCopyEvent = event.type === "copy";
|
|
26241
|
-
const isPasteEvent = event.type === "paste";
|
|
26242
|
-
const isCutEvent = event.type === "cut";
|
|
26243
|
-
const isClickEvent = event.type === "mousedown";
|
|
26244
|
-
if (!isDraggable && isSelectable && isDragEvent && event.target === this.dom) {
|
|
26245
|
-
event.preventDefault();
|
|
26246
|
-
}
|
|
26247
|
-
if (isDraggable && isDragEvent && !isDragging && event.target === this.dom) {
|
|
26248
|
-
event.preventDefault();
|
|
26249
|
-
return false;
|
|
26250
|
-
}
|
|
26251
|
-
if (isDraggable && isEditable && !isDragging && isClickEvent) {
|
|
26252
|
-
const dragHandle = target.closest("[data-drag-handle]");
|
|
26253
|
-
const isValidDragHandle = dragHandle && (this.dom === dragHandle || this.dom.contains(dragHandle));
|
|
26254
|
-
if (isValidDragHandle) {
|
|
26255
|
-
this.isDragging = true;
|
|
26256
|
-
document.addEventListener(
|
|
26257
|
-
"dragend",
|
|
26258
|
-
() => {
|
|
26259
|
-
this.isDragging = false;
|
|
26260
|
-
},
|
|
26261
|
-
{ once: true }
|
|
26262
|
-
);
|
|
26263
|
-
document.addEventListener(
|
|
26264
|
-
"drop",
|
|
26265
|
-
() => {
|
|
26266
|
-
this.isDragging = false;
|
|
26267
|
-
},
|
|
26268
|
-
{ once: true }
|
|
26269
|
-
);
|
|
26270
|
-
document.addEventListener(
|
|
26271
|
-
"mouseup",
|
|
26272
|
-
() => {
|
|
26273
|
-
this.isDragging = false;
|
|
26274
|
-
},
|
|
26275
|
-
{ once: true }
|
|
26276
|
-
);
|
|
26277
|
-
}
|
|
26278
|
-
}
|
|
26279
|
-
if (isDragging || isDropEvent || isCopyEvent || isPasteEvent || isCutEvent || isClickEvent && isSelectable) {
|
|
26280
|
-
return false;
|
|
26281
|
-
}
|
|
26282
|
-
return true;
|
|
26283
|
-
}
|
|
26284
|
-
ignoreMutation(mutation) {
|
|
26285
|
-
if (!this.dom || !this.contentDOM) return true;
|
|
26286
|
-
if (this.node.isLeaf || this.node.isAtom) return true;
|
|
26287
|
-
if (mutation.type === "selection") return false;
|
|
26288
|
-
if (this.contentDOM === mutation.target && mutation.type === "attributes") return true;
|
|
26289
|
-
if (this.contentDOM.contains(mutation.target)) return false;
|
|
26290
|
-
return true;
|
|
26291
|
-
}
|
|
26292
|
-
destroy() {
|
|
26293
|
-
this.dom.remove();
|
|
26294
|
-
this.contentDOM?.remove();
|
|
26295
|
-
}
|
|
26296
|
-
updateAttributes(attrs) {
|
|
26297
|
-
const pos = this.getPos();
|
|
26298
|
-
if (typeof pos !== "number") {
|
|
26299
|
-
return;
|
|
26300
|
-
}
|
|
26301
|
-
return this.view.dispatch(
|
|
26302
|
-
this.view.state.tr.setNodeMarkup(pos, void 0, {
|
|
26303
|
-
...this.node.attrs,
|
|
26304
|
-
...attrs
|
|
26305
|
-
})
|
|
26306
|
-
);
|
|
26307
|
-
}
|
|
26308
|
-
updateHTMLAttributes() {
|
|
26309
|
-
const { extensionService } = this.editor;
|
|
26310
|
-
const { attributes } = extensionService;
|
|
26311
|
-
const extensionAttrs = attributes.filter((i) => i.type === this.node.type.name);
|
|
26312
|
-
this.htmlAttributes = Attribute.getAttributesToRender(this.node, extensionAttrs);
|
|
26313
|
-
}
|
|
26314
|
-
createDragHandle() {
|
|
26315
|
-
const dragHandle = document.createElement("span");
|
|
26316
|
-
dragHandle.classList.add("sd-structured-content-draggable");
|
|
26317
|
-
dragHandle.draggable = true;
|
|
26318
|
-
dragHandle.contentEditable = "false";
|
|
26319
|
-
dragHandle.dataset.dragHandle = "";
|
|
26320
|
-
const textElement = document.createElement("span");
|
|
26321
|
-
textElement.textContent = "Structured content";
|
|
26322
|
-
dragHandle.append(textElement);
|
|
26323
|
-
return dragHandle;
|
|
26324
|
-
}
|
|
26325
|
-
onDragStart(event) {
|
|
26326
|
-
const { view } = this.editor;
|
|
26327
|
-
const target = event.target;
|
|
26328
|
-
const dragHandle = target.nodeType === 3 ? target.parentElement?.closest("[data-drag-handle]") : target.closest("[data-drag-handle]");
|
|
26329
|
-
if (!this.dom || this.contentDOM?.contains(target) || !dragHandle) {
|
|
26330
|
-
return;
|
|
26331
|
-
}
|
|
26332
|
-
let x = 0;
|
|
26333
|
-
let y = 0;
|
|
26334
|
-
if (this.dom !== dragHandle) {
|
|
26335
|
-
const domBox = this.dom.getBoundingClientRect();
|
|
26336
|
-
const handleBox = dragHandle.getBoundingClientRect();
|
|
26337
|
-
const offsetX = event.offsetX ?? event.nativeEvent?.offsetX;
|
|
26338
|
-
const offsetY = event.offsetY ?? event.nativeEvent?.offsetY;
|
|
26339
|
-
x = handleBox.x - domBox.x + offsetX;
|
|
26340
|
-
y = handleBox.y - domBox.y + offsetY;
|
|
26341
|
-
}
|
|
26342
|
-
event.dataTransfer?.setDragImage(this.dom, x, y);
|
|
26343
|
-
const pos = this.getPos();
|
|
26344
|
-
if (typeof pos !== "number") {
|
|
26345
|
-
return;
|
|
26346
|
-
}
|
|
26347
|
-
const selection = NodeSelection.create(view.state.doc, pos);
|
|
26348
|
-
const transaction = view.state.tr.setSelection(selection);
|
|
26349
|
-
view.dispatch(transaction);
|
|
26350
|
-
}
|
|
26351
|
-
}
|
|
26352
|
-
class StructuredContentInlineView extends StructuredContentViewBase {
|
|
26353
|
-
constructor(props) {
|
|
26354
|
-
super(props);
|
|
26355
|
-
}
|
|
26356
|
-
mount() {
|
|
26357
|
-
this.buildView();
|
|
26358
|
-
}
|
|
26359
|
-
get contentDOM() {
|
|
26360
|
-
const contentElement = this.dom?.querySelector(`.${structuredContentInnerClass$1}`);
|
|
26361
|
-
return contentElement || null;
|
|
26362
|
-
}
|
|
26363
|
-
createElement() {
|
|
26364
|
-
const element = document.createElement("span");
|
|
26365
|
-
element.classList.add(structuredContentClass$1);
|
|
26366
|
-
element.setAttribute("data-structured-content", "");
|
|
26367
|
-
const contentElement = document.createElement("span");
|
|
26368
|
-
contentElement.classList.add(structuredContentInnerClass$1);
|
|
26369
|
-
element.append(contentElement);
|
|
26370
|
-
const domAttrs = Attribute.mergeAttributes(this.htmlAttributes);
|
|
26371
|
-
updateDOMAttributes(element, { ...domAttrs });
|
|
26372
|
-
return { element, contentElement };
|
|
26373
|
-
}
|
|
26374
|
-
buildView() {
|
|
26375
|
-
const { element } = this.createElement();
|
|
26376
|
-
const dragHandle = this.createDragHandle();
|
|
26377
|
-
element.prepend(dragHandle);
|
|
26378
|
-
element.addEventListener("dragstart", (e) => this.onDragStart(e));
|
|
26379
|
-
this.root = element;
|
|
26380
|
-
}
|
|
26381
|
-
updateView() {
|
|
26382
|
-
const domAttrs = Attribute.mergeAttributes(this.htmlAttributes);
|
|
26383
|
-
updateDOMAttributes(this.dom, { ...domAttrs });
|
|
26384
|
-
}
|
|
26385
|
-
update(node, decorations, innerDecorations) {
|
|
26386
|
-
const result = super.update(node, decorations, innerDecorations);
|
|
26387
|
-
if (!result) return false;
|
|
26388
|
-
this.updateView();
|
|
26389
|
-
return true;
|
|
26390
|
-
}
|
|
26391
|
-
}
|
|
26392
|
-
const structuredContentClass$1 = "sd-structured-content";
|
|
26393
|
-
const structuredContentInnerClass$1 = "sd-structured-content__content";
|
|
26394
|
-
const StructuredContent = Node$1.create({
|
|
26395
|
-
name: "structuredContent",
|
|
26396
|
-
group: "inline structuredContent",
|
|
26397
|
-
inline: true,
|
|
26398
|
-
content: "inline*",
|
|
26399
|
-
isolating: true,
|
|
26400
|
-
atom: false,
|
|
26401
|
-
// false - has editable content.
|
|
26402
|
-
draggable: true,
|
|
26403
|
-
addOptions() {
|
|
26404
|
-
return {
|
|
26405
|
-
htmlAttributes: {
|
|
26406
|
-
class: structuredContentClass$1,
|
|
26407
|
-
"aria-label": "Structured content node"
|
|
26408
|
-
}
|
|
26409
|
-
};
|
|
26410
|
-
},
|
|
26411
|
-
addAttributes() {
|
|
26412
|
-
return {
|
|
26413
|
-
id: {
|
|
26414
|
-
default: null,
|
|
26415
|
-
parseDOM: (elem) => elem.getAttribute("data-id"),
|
|
26416
|
-
renderDOM: (attrs) => {
|
|
26417
|
-
if (!attrs.id) return {};
|
|
26418
|
-
return { "data-id": attrs.id };
|
|
26419
|
-
}
|
|
26420
|
-
},
|
|
26421
|
-
sdtPr: {
|
|
26422
|
-
rendered: false
|
|
26423
|
-
}
|
|
26424
|
-
};
|
|
26425
|
-
},
|
|
26426
|
-
parseDOM() {
|
|
26427
|
-
return [{ tag: "span[data-structured-content]" }];
|
|
26428
|
-
},
|
|
26429
|
-
renderDOM({ htmlAttributes }) {
|
|
26430
|
-
return [
|
|
26431
|
-
"span",
|
|
26432
|
-
Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes, {
|
|
26433
|
-
"data-structured-content": ""
|
|
26434
|
-
}),
|
|
26435
|
-
0
|
|
26436
|
-
];
|
|
26437
|
-
},
|
|
26438
|
-
addNodeView() {
|
|
26439
|
-
return (props) => {
|
|
26440
|
-
return new StructuredContentInlineView({ ...props });
|
|
26441
|
-
};
|
|
26442
|
-
}
|
|
26443
|
-
});
|
|
26444
|
-
class StructuredContentBlockView extends StructuredContentViewBase {
|
|
26445
|
-
constructor(props) {
|
|
26446
|
-
super(props);
|
|
26447
|
-
}
|
|
26448
|
-
mount() {
|
|
26449
|
-
this.buildView();
|
|
26450
|
-
}
|
|
26451
|
-
get contentDOM() {
|
|
26452
|
-
const contentElement = this.dom?.querySelector(`.${structuredContentInnerClass}`);
|
|
26453
|
-
return contentElement || null;
|
|
26454
|
-
}
|
|
26455
|
-
createElement() {
|
|
26456
|
-
const element = document.createElement("div");
|
|
26457
|
-
element.classList.add(structuredContentClass);
|
|
26458
|
-
element.setAttribute("data-structured-content-block", "");
|
|
26459
|
-
const contentElement = document.createElement("div");
|
|
26460
|
-
contentElement.classList.add(structuredContentInnerClass);
|
|
26461
|
-
element.append(contentElement);
|
|
26462
|
-
const domAttrs = Attribute.mergeAttributes(this.htmlAttributes);
|
|
26463
|
-
updateDOMAttributes(element, { ...domAttrs });
|
|
26464
|
-
return { element, contentElement };
|
|
26465
|
-
}
|
|
26466
|
-
buildView() {
|
|
26467
|
-
const { element } = this.createElement();
|
|
26468
|
-
const dragHandle = this.createDragHandle();
|
|
26469
|
-
element.prepend(dragHandle);
|
|
26470
|
-
element.addEventListener("dragstart", (e) => this.onDragStart(e));
|
|
26471
|
-
this.root = element;
|
|
26472
|
-
}
|
|
26473
|
-
updateView() {
|
|
26474
|
-
const domAttrs = Attribute.mergeAttributes(this.htmlAttributes);
|
|
26475
|
-
updateDOMAttributes(this.dom, { ...domAttrs });
|
|
26476
|
-
}
|
|
26477
|
-
update(node, decorations, innerDecorations) {
|
|
26478
|
-
const result = super.update(node, decorations, innerDecorations);
|
|
26479
|
-
if (!result) return false;
|
|
26480
|
-
this.updateView();
|
|
26481
|
-
return true;
|
|
26482
|
-
}
|
|
26483
|
-
}
|
|
26484
|
-
const structuredContentClass = "sd-structured-content-block";
|
|
26485
|
-
const structuredContentInnerClass = "sd-structured-content-block__content";
|
|
26486
|
-
const StructuredContentBlock = Node$1.create({
|
|
26487
|
-
name: "structuredContentBlock",
|
|
26488
|
-
group: "block structuredContent",
|
|
26489
|
-
content: "block*",
|
|
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+",
|
|
26490
26971
|
isolating: true,
|
|
26491
|
-
atom: false,
|
|
26492
|
-
// false - has editable content.
|
|
26493
|
-
draggable: true,
|
|
26494
26972
|
addOptions() {
|
|
26495
26973
|
return {
|
|
26496
26974
|
htmlAttributes: {
|
|
26497
|
-
class:
|
|
26498
|
-
"aria-label": "
|
|
26975
|
+
class: "sd-editor-shape-container",
|
|
26976
|
+
"aria-label": "Shape container node"
|
|
26499
26977
|
}
|
|
26500
26978
|
};
|
|
26501
26979
|
},
|
|
26502
26980
|
addAttributes() {
|
|
26503
26981
|
return {
|
|
26504
|
-
|
|
26982
|
+
fillcolor: {
|
|
26983
|
+
renderDOM: (attrs) => {
|
|
26984
|
+
if (!attrs.fillcolor) return {};
|
|
26985
|
+
return {
|
|
26986
|
+
style: `background-color: ${attrs.fillcolor}`
|
|
26987
|
+
};
|
|
26988
|
+
}
|
|
26989
|
+
},
|
|
26990
|
+
sdBlockId: {
|
|
26505
26991
|
default: null,
|
|
26506
|
-
|
|
26992
|
+
keepOnSplit: false,
|
|
26993
|
+
parseDOM: (elem) => elem.getAttribute("data-sd-block-id"),
|
|
26507
26994
|
renderDOM: (attrs) => {
|
|
26508
|
-
|
|
26509
|
-
return { "data-id": attrs.id };
|
|
26995
|
+
return attrs.sdBlockId ? { "data-sd-block-id": attrs.sdBlockId } : {};
|
|
26510
26996
|
}
|
|
26511
26997
|
},
|
|
26512
|
-
|
|
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: {
|
|
26513
27010
|
rendered: false
|
|
26514
27011
|
}
|
|
26515
27012
|
};
|
|
26516
27013
|
},
|
|
26517
27014
|
parseDOM() {
|
|
26518
|
-
return [
|
|
27015
|
+
return [
|
|
27016
|
+
{
|
|
27017
|
+
tag: `div[data-type="${this.name}"]`
|
|
27018
|
+
}
|
|
27019
|
+
];
|
|
26519
27020
|
},
|
|
26520
27021
|
renderDOM({ htmlAttributes }) {
|
|
26521
27022
|
return [
|
|
26522
27023
|
"div",
|
|
26523
|
-
Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes, {
|
|
26524
|
-
"data-structured-content-block": ""
|
|
26525
|
-
}),
|
|
27024
|
+
Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes, { "data-type": this.name }),
|
|
26526
27025
|
0
|
|
26527
27026
|
];
|
|
26528
|
-
},
|
|
26529
|
-
addNodeView() {
|
|
26530
|
-
return (props) => {
|
|
26531
|
-
return new StructuredContentBlockView({ ...props });
|
|
26532
|
-
};
|
|
26533
27027
|
}
|
|
26534
27028
|
});
|
|
26535
|
-
|
|
26536
|
-
|
|
26537
|
-
__privateAdd(this, _DocumentSectionView_instances);
|
|
26538
|
-
this.node = node;
|
|
26539
|
-
this.editor = editor;
|
|
26540
|
-
this.decorations = decorations;
|
|
26541
|
-
this.view = editor.view;
|
|
26542
|
-
this.getPos = getPos;
|
|
26543
|
-
__privateMethod(this, _DocumentSectionView_instances, init_fn3).call(this);
|
|
26544
|
-
}
|
|
26545
|
-
}
|
|
26546
|
-
_DocumentSectionView_instances = new WeakSet();
|
|
26547
|
-
init_fn3 = function() {
|
|
26548
|
-
const { attrs } = this.node;
|
|
26549
|
-
const { id, title, description } = attrs;
|
|
26550
|
-
this.dom = document.createElement("div");
|
|
26551
|
-
this.dom.className = "sd-document-section-block";
|
|
26552
|
-
this.dom.setAttribute("data-id", id);
|
|
26553
|
-
this.dom.setAttribute("data-title", title);
|
|
26554
|
-
this.dom.setAttribute("data-description", description);
|
|
26555
|
-
this.dom.setAttribute("aria-label", "Document section");
|
|
26556
|
-
__privateMethod(this, _DocumentSectionView_instances, addToolTip_fn).call(this);
|
|
26557
|
-
this.contentDOM = document.createElement("div");
|
|
26558
|
-
this.contentDOM.className = "sd-document-section-block-content";
|
|
26559
|
-
this.contentDOM.setAttribute("contenteditable", "true");
|
|
26560
|
-
this.dom.appendChild(this.contentDOM);
|
|
26561
|
-
};
|
|
26562
|
-
addToolTip_fn = function() {
|
|
26563
|
-
const { title } = this.node.attrs;
|
|
26564
|
-
this.infoDiv = document.createElement("div");
|
|
26565
|
-
this.infoDiv.className = "sd-document-section-block-info";
|
|
26566
|
-
const textSpan = document.createElement("span");
|
|
26567
|
-
textSpan.textContent = title || "Document section";
|
|
26568
|
-
this.infoDiv.appendChild(textSpan);
|
|
26569
|
-
this.infoDiv.setAttribute("contenteditable", "false");
|
|
26570
|
-
this.dom.appendChild(this.infoDiv);
|
|
26571
|
-
};
|
|
26572
|
-
const getAllSections = (editor) => {
|
|
26573
|
-
if (!editor) return [];
|
|
26574
|
-
const type = editor.schema.nodes.documentSection;
|
|
26575
|
-
if (!type) return [];
|
|
26576
|
-
const sections = [];
|
|
26577
|
-
const { state } = editor;
|
|
26578
|
-
state.doc.descendants((node, pos) => {
|
|
26579
|
-
if (node.type.name === type.name) {
|
|
26580
|
-
sections.push({ node, pos });
|
|
26581
|
-
}
|
|
26582
|
-
});
|
|
26583
|
-
return sections;
|
|
26584
|
-
};
|
|
26585
|
-
const exportSectionsToHTML = (editor) => {
|
|
26586
|
-
const sections = getAllSections(editor);
|
|
26587
|
-
const processedSections = /* @__PURE__ */ new Set();
|
|
26588
|
-
const result = [];
|
|
26589
|
-
sections.forEach(({ node }) => {
|
|
26590
|
-
const { attrs } = node;
|
|
26591
|
-
const { id, title, description } = attrs;
|
|
26592
|
-
if (processedSections.has(id)) return;
|
|
26593
|
-
processedSections.add(id);
|
|
26594
|
-
const html = getHTMLFromNode(node, editor);
|
|
26595
|
-
result.push({
|
|
26596
|
-
id,
|
|
26597
|
-
title,
|
|
26598
|
-
description,
|
|
26599
|
-
html
|
|
26600
|
-
});
|
|
26601
|
-
});
|
|
26602
|
-
return result;
|
|
26603
|
-
};
|
|
26604
|
-
const getHTMLFromNode = (node, editor) => {
|
|
26605
|
-
const tempDocument = document.implementation.createHTMLDocument();
|
|
26606
|
-
const container = tempDocument.createElement("div");
|
|
26607
|
-
const fragment = DOMSerializer.fromSchema(editor.schema).serializeFragment(node.content);
|
|
26608
|
-
container.appendChild(fragment);
|
|
26609
|
-
let html = container.innerHTML;
|
|
26610
|
-
return html;
|
|
26611
|
-
};
|
|
26612
|
-
const exportSectionsToJSON = (editor) => {
|
|
26613
|
-
const sections = getAllSections(editor);
|
|
26614
|
-
const processedSections = /* @__PURE__ */ new Set();
|
|
26615
|
-
const result = [];
|
|
26616
|
-
sections.forEach(({ node }) => {
|
|
26617
|
-
const { attrs } = node;
|
|
26618
|
-
const { id, title, description } = attrs;
|
|
26619
|
-
if (processedSections.has(id)) return;
|
|
26620
|
-
processedSections.add(id);
|
|
26621
|
-
result.push({
|
|
26622
|
-
id,
|
|
26623
|
-
title,
|
|
26624
|
-
description,
|
|
26625
|
-
content: node.toJSON()
|
|
26626
|
-
});
|
|
26627
|
-
});
|
|
26628
|
-
return result;
|
|
26629
|
-
};
|
|
26630
|
-
const getLinkedSectionEditor = (id, options, editor) => {
|
|
26631
|
-
const sections = getAllSections(editor);
|
|
26632
|
-
const section = sections.find((s) => s.node.attrs.id === id);
|
|
26633
|
-
if (!section) return null;
|
|
26634
|
-
const child = editor.createChildEditor({
|
|
26635
|
-
...options,
|
|
26636
|
-
onUpdate: ({ editor: childEditor, transaction }) => {
|
|
26637
|
-
const isFromtLinkedParent = transaction.getMeta("fromLinkedParent");
|
|
26638
|
-
if (isFromtLinkedParent) return;
|
|
26639
|
-
const updatedContent = childEditor.state.doc.content;
|
|
26640
|
-
const sectionNode = getAllSections(editor)?.find((s) => s.node.attrs.id === id);
|
|
26641
|
-
if (!sectionNode) return;
|
|
26642
|
-
const { pos, node } = sectionNode;
|
|
26643
|
-
const newNode = node.type.create(node.attrs, updatedContent, node.marks);
|
|
26644
|
-
const tr = editor.state.tr.replaceWith(pos, pos + node.nodeSize, newNode);
|
|
26645
|
-
tr.setMeta("fromLinkedChild", true);
|
|
26646
|
-
editor.view.dispatch(tr);
|
|
26647
|
-
}
|
|
26648
|
-
});
|
|
26649
|
-
editor.on("update", ({ transaction }) => {
|
|
26650
|
-
const isFromLinkedChild = transaction.getMeta("fromLinkedChild");
|
|
26651
|
-
if (isFromLinkedChild) return;
|
|
26652
|
-
const sectionNode = getAllSections(editor)?.find((s) => s.node.attrs.id === id);
|
|
26653
|
-
if (!sectionNode) return;
|
|
26654
|
-
const sectionContent = sectionNode.node.content;
|
|
26655
|
-
const json = {
|
|
26656
|
-
type: "doc",
|
|
26657
|
-
content: sectionContent.content.map((node) => node.toJSON())
|
|
26658
|
-
};
|
|
26659
|
-
const childTr = child.state.tr;
|
|
26660
|
-
childTr.setMeta("fromLinkedParent", true);
|
|
26661
|
-
childTr.replaceWith(0, child.state.doc.content.size, child.schema.nodeFromJSON(json));
|
|
26662
|
-
child.view.dispatch(childTr);
|
|
26663
|
-
});
|
|
26664
|
-
return child;
|
|
26665
|
-
};
|
|
26666
|
-
const SectionHelpers = {
|
|
26667
|
-
getAllSections,
|
|
26668
|
-
exportSectionsToHTML,
|
|
26669
|
-
exportSectionsToJSON,
|
|
26670
|
-
getLinkedSectionEditor
|
|
26671
|
-
};
|
|
26672
|
-
const DocumentSection = Node$1.create({
|
|
26673
|
-
name: "documentSection",
|
|
27029
|
+
const ShapeTextbox = Node$1.create({
|
|
27030
|
+
name: "shapeTextbox",
|
|
26674
27031
|
group: "block",
|
|
26675
|
-
content: "block*",
|
|
26676
|
-
atom: true,
|
|
27032
|
+
content: "paragraph* block*",
|
|
26677
27033
|
isolating: true,
|
|
26678
27034
|
addOptions() {
|
|
26679
27035
|
return {
|
|
26680
27036
|
htmlAttributes: {
|
|
26681
|
-
class: "sd-
|
|
26682
|
-
"aria-label": "
|
|
27037
|
+
class: "sd-editor-shape-textbox",
|
|
27038
|
+
"aria-label": "Shape textbox node"
|
|
26683
27039
|
}
|
|
26684
27040
|
};
|
|
26685
27041
|
},
|
|
26686
|
-
parseDOM() {
|
|
26687
|
-
return [
|
|
26688
|
-
{
|
|
26689
|
-
tag: "div.sd-document-section-block",
|
|
26690
|
-
priority: 60
|
|
26691
|
-
}
|
|
26692
|
-
];
|
|
26693
|
-
},
|
|
26694
|
-
renderDOM({ htmlAttributes }) {
|
|
26695
|
-
return ["div", Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes), 0];
|
|
26696
|
-
},
|
|
26697
27042
|
addAttributes() {
|
|
26698
27043
|
return {
|
|
26699
|
-
id: {},
|
|
26700
27044
|
sdBlockId: {
|
|
26701
27045
|
default: null,
|
|
26702
27046
|
keepOnSplit: false,
|
|
@@ -26705,212 +27049,131 @@ const DocumentSection = Node$1.create({
|
|
|
26705
27049
|
return attrs.sdBlockId ? { "data-sd-block-id": attrs.sdBlockId } : {};
|
|
26706
27050
|
}
|
|
26707
27051
|
},
|
|
26708
|
-
|
|
26709
|
-
|
|
26710
|
-
|
|
26711
|
-
isLocked: { default: false }
|
|
27052
|
+
attributes: {
|
|
27053
|
+
rendered: false
|
|
27054
|
+
}
|
|
26712
27055
|
};
|
|
26713
27056
|
},
|
|
26714
|
-
|
|
26715
|
-
return
|
|
26716
|
-
|
|
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
|
+
}
|
|
26717
27084
|
};
|
|
26718
27085
|
},
|
|
26719
|
-
|
|
27086
|
+
addAttributes() {
|
|
26720
27087
|
return {
|
|
26721
|
-
|
|
26722
|
-
|
|
26723
|
-
|
|
26724
|
-
|
|
26725
|
-
|
|
26726
|
-
* editor.commands.createDocumentSection({
|
|
26727
|
-
* id: 1,
|
|
26728
|
-
* title: 'Terms & Conditions',
|
|
26729
|
-
* isLocked: true,
|
|
26730
|
-
* html: '<p>Legal content...</p>'
|
|
26731
|
-
* })
|
|
26732
|
-
*/
|
|
26733
|
-
createDocumentSection: (options = {}) => ({ tr, state, dispatch, editor }) => {
|
|
26734
|
-
const { selection } = state;
|
|
26735
|
-
let { from: from2, to } = selection;
|
|
26736
|
-
let content = selection.content().content;
|
|
26737
|
-
const { html: optionsHTML, json: optionsJSON } = options;
|
|
26738
|
-
if (optionsHTML) {
|
|
26739
|
-
const html = htmlHandler(optionsHTML, this.editor);
|
|
26740
|
-
const doc2 = DOMParser$1.fromSchema(this.editor.schema).parse(html);
|
|
26741
|
-
content = doc2.content;
|
|
26742
|
-
}
|
|
26743
|
-
if (optionsJSON) {
|
|
26744
|
-
content = this.editor.schema.nodeFromJSON(optionsJSON);
|
|
26745
|
-
}
|
|
26746
|
-
if (!content?.content?.length) {
|
|
26747
|
-
content = this.editor.schema.nodeFromJSON({ type: "paragraph", content: [] });
|
|
26748
|
-
}
|
|
26749
|
-
if (!options.id) {
|
|
26750
|
-
const allSections = SectionHelpers.getAllSections(editor);
|
|
26751
|
-
options.id = allSections.length + 1;
|
|
26752
|
-
}
|
|
26753
|
-
if (!options.title) {
|
|
26754
|
-
options.title = "Document section";
|
|
26755
|
-
}
|
|
26756
|
-
const node = this.type.createAndFill(options, content);
|
|
26757
|
-
if (!node) return false;
|
|
26758
|
-
const isAlreadyInSdtBlock = findParentNode((node2) => node2.type.name === "documentSection")(selection);
|
|
26759
|
-
if (isAlreadyInSdtBlock && isAlreadyInSdtBlock.node) {
|
|
26760
|
-
const insertPos2 = isAlreadyInSdtBlock.pos + isAlreadyInSdtBlock.node.nodeSize;
|
|
26761
|
-
from2 = insertPos2;
|
|
26762
|
-
to = insertPos2;
|
|
26763
|
-
}
|
|
26764
|
-
tr.replaceRangeWith(from2, to, node);
|
|
26765
|
-
const nodeEnd = from2 + node.nodeSize;
|
|
26766
|
-
let shouldInsertParagraph = true;
|
|
26767
|
-
let insertPos = nodeEnd;
|
|
26768
|
-
if (nodeEnd >= tr.doc.content.size) {
|
|
26769
|
-
insertPos = tr.doc.content.size;
|
|
26770
|
-
if (insertPos > 0) {
|
|
26771
|
-
const $endPos = tr.doc.resolve(insertPos);
|
|
26772
|
-
if ($endPos.nodeBefore && $endPos.nodeBefore.type.name === "paragraph") {
|
|
26773
|
-
shouldInsertParagraph = false;
|
|
26774
|
-
}
|
|
26775
|
-
}
|
|
26776
|
-
}
|
|
26777
|
-
if (shouldInsertParagraph) {
|
|
26778
|
-
const emptyParagraph = tr.doc.type.schema.nodes.paragraph.create();
|
|
26779
|
-
tr.insert(insertPos, emptyParagraph);
|
|
26780
|
-
}
|
|
26781
|
-
if (dispatch) {
|
|
26782
|
-
tr.setMeta("documentSection", { action: "create" });
|
|
26783
|
-
dispatch(tr);
|
|
26784
|
-
setTimeout(() => {
|
|
26785
|
-
try {
|
|
26786
|
-
const currentState = editor.state;
|
|
26787
|
-
const docSize = currentState.doc.content.size;
|
|
26788
|
-
let targetPos = from2 + node.nodeSize;
|
|
26789
|
-
if (shouldInsertParagraph) {
|
|
26790
|
-
targetPos += 1;
|
|
26791
|
-
}
|
|
26792
|
-
targetPos = Math.min(targetPos, docSize);
|
|
26793
|
-
if (targetPos < docSize && targetPos > 0) {
|
|
26794
|
-
const newSelection = Selection.near(currentState.doc.resolve(targetPos));
|
|
26795
|
-
const newTr = currentState.tr.setSelection(newSelection);
|
|
26796
|
-
editor.view.dispatch(newTr);
|
|
26797
|
-
}
|
|
26798
|
-
} catch (e) {
|
|
26799
|
-
console.warn("Could not set delayed selection:", e);
|
|
26800
|
-
}
|
|
26801
|
-
}, 0);
|
|
27088
|
+
horizontalRule: {
|
|
27089
|
+
default: false,
|
|
27090
|
+
renderDOM: ({ horizontalRule }) => {
|
|
27091
|
+
if (!horizontalRule) return {};
|
|
27092
|
+
return { "data-horizontal-rule": "true" };
|
|
26802
27093
|
}
|
|
26803
|
-
return true;
|
|
26804
27094
|
},
|
|
26805
|
-
|
|
26806
|
-
|
|
26807
|
-
|
|
26808
|
-
|
|
26809
|
-
|
|
26810
|
-
|
|
26811
|
-
|
|
26812
|
-
|
|
26813
|
-
|
|
26814
|
-
|
|
26815
|
-
|
|
26816
|
-
const nodeStart = pos;
|
|
26817
|
-
const nodeEnd = nodeStart + node.nodeSize;
|
|
26818
|
-
const contentToPreserve = node.content;
|
|
26819
|
-
tr.delete(nodeStart, nodeEnd);
|
|
26820
|
-
if (contentToPreserve.size > 0) {
|
|
26821
|
-
tr.insert(nodeStart, contentToPreserve);
|
|
26822
|
-
}
|
|
26823
|
-
const newPos = Math.min(nodeStart, tr.doc.content.size);
|
|
26824
|
-
tr.setSelection(Selection.near(tr.doc.resolve(newPos)));
|
|
26825
|
-
if (dispatch) {
|
|
26826
|
-
tr.setMeta("documentSection", { action: "delete" });
|
|
26827
|
-
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 };
|
|
26828
27106
|
}
|
|
26829
|
-
return true;
|
|
26830
27107
|
},
|
|
26831
|
-
|
|
26832
|
-
|
|
26833
|
-
|
|
26834
|
-
|
|
26835
|
-
|
|
26836
|
-
|
|
26837
|
-
|
|
26838
|
-
removeSectionById: (id) => ({ tr, dispatch }) => {
|
|
26839
|
-
const sections = SectionHelpers.getAllSections(this.editor);
|
|
26840
|
-
const sectionToRemove = sections.find(({ node: node2 }) => node2.attrs.id === id);
|
|
26841
|
-
if (!sectionToRemove) return false;
|
|
26842
|
-
const { pos, node } = sectionToRemove;
|
|
26843
|
-
const nodeStart = pos;
|
|
26844
|
-
const nodeEnd = nodeStart + node.nodeSize;
|
|
26845
|
-
tr.delete(nodeStart, nodeEnd);
|
|
26846
|
-
if (dispatch) {
|
|
26847
|
-
tr.setMeta("documentSection", { action: "delete", id });
|
|
26848
|
-
dispatch(tr);
|
|
27108
|
+
background: {
|
|
27109
|
+
default: null,
|
|
27110
|
+
renderDOM: (attrs) => {
|
|
27111
|
+
if (!attrs.background) return {};
|
|
27112
|
+
return {
|
|
27113
|
+
style: `background-color: ${attrs.background}`
|
|
27114
|
+
};
|
|
26849
27115
|
}
|
|
26850
|
-
return true;
|
|
26851
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 {
|
|
26852
27137
|
/**
|
|
26853
|
-
*
|
|
27138
|
+
* Insert a horizontal rule
|
|
26854
27139
|
* @category Command
|
|
26855
|
-
* @param {number} id - Section to lock
|
|
26856
27140
|
* @example
|
|
26857
|
-
* editor.commands.
|
|
27141
|
+
* editor.commands.insertHorizontalRule()
|
|
27142
|
+
* @note Creates a visual separator between content sections
|
|
26858
27143
|
*/
|
|
26859
|
-
|
|
26860
|
-
|
|
26861
|
-
|
|
26862
|
-
|
|
26863
|
-
|
|
26864
|
-
|
|
26865
|
-
|
|
26866
|
-
|
|
26867
|
-
}
|
|
26868
|
-
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
|
+
});
|
|
26869
27153
|
},
|
|
26870
27154
|
/**
|
|
26871
|
-
*
|
|
27155
|
+
* Insert a content block
|
|
26872
27156
|
* @category Command
|
|
26873
|
-
* @param {
|
|
27157
|
+
* @param {ContentBlockConfig} config - Block configuration
|
|
26874
27158
|
* @example
|
|
26875
|
-
*
|
|
26876
|
-
* editor.commands.
|
|
26877
|
-
*
|
|
26878
|
-
*
|
|
26879
|
-
*
|
|
26880
|
-
*
|
|
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'
|
|
26881
27167
|
* })
|
|
27168
|
+
* @note Used for spacing, dividers, and special inline content
|
|
26882
27169
|
*/
|
|
26883
|
-
|
|
26884
|
-
|
|
26885
|
-
|
|
26886
|
-
|
|
26887
|
-
|
|
26888
|
-
let newContent = null;
|
|
26889
|
-
if (html) {
|
|
26890
|
-
const htmlDoc = htmlHandler(html, editor || this.editor);
|
|
26891
|
-
const doc2 = DOMParser$1.fromSchema((editor || this.editor).schema).parse(htmlDoc);
|
|
26892
|
-
newContent = doc2.content;
|
|
26893
|
-
}
|
|
26894
|
-
if (json) {
|
|
26895
|
-
newContent = (editor || this.editor).schema.nodeFromJSON(json);
|
|
26896
|
-
}
|
|
26897
|
-
if (!newContent) {
|
|
26898
|
-
newContent = node.content;
|
|
26899
|
-
}
|
|
26900
|
-
const updatedNode = node.type.create({ ...node.attrs, ...attrs }, newContent, node.marks);
|
|
26901
|
-
tr.replaceWith(pos, pos + node.nodeSize, updatedNode);
|
|
26902
|
-
if (dispatch) {
|
|
26903
|
-
tr.setMeta("documentSection", { action: "update", id, attrs });
|
|
26904
|
-
dispatch(tr);
|
|
26905
|
-
}
|
|
26906
|
-
return true;
|
|
27170
|
+
insertContentBlock: (config) => ({ commands: commands2 }) => {
|
|
27171
|
+
return commands2.insertContent({
|
|
27172
|
+
type: this.name,
|
|
27173
|
+
attrs: config
|
|
27174
|
+
});
|
|
26907
27175
|
}
|
|
26908
27176
|
};
|
|
26909
|
-
},
|
|
26910
|
-
addHelpers() {
|
|
26911
|
-
return {
|
|
26912
|
-
...SectionHelpers
|
|
26913
|
-
};
|
|
26914
27177
|
}
|
|
26915
27178
|
});
|
|
26916
27179
|
const { findChildren } = helpers;
|
|
@@ -33760,6 +34023,7 @@ const getStarterExtensions = () => {
|
|
|
33760
34023
|
Search,
|
|
33761
34024
|
StructuredContent,
|
|
33762
34025
|
StructuredContentBlock,
|
|
34026
|
+
StructuredContentCommands,
|
|
33763
34027
|
DocumentSection,
|
|
33764
34028
|
NodeResizer,
|
|
33765
34029
|
CustomSelection,
|