@harbour-enterprises/superdoc 0.22.0-next.9 → 0.23.0-next.1

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.
Files changed (64) hide show
  1. package/dist/chunks/{PdfViewer-DyWe33pN.cjs → PdfViewer-C9SGNZr6.cjs} +1 -1
  2. package/dist/chunks/{PdfViewer-HN-tp5RN.es.js → PdfViewer-D9atA783.es.js} +1 -1
  3. package/dist/chunks/{index-ir6efMuz.es.js → index-C8q6lenv.es.js} +3 -3
  4. package/dist/chunks/{index-BeVpZc19.cjs → index-CIbe1VMu.cjs} +3 -3
  5. package/dist/chunks/{super-editor.es-BwqYS285.es.js → super-editor.es-Dj6Sxtr7.es.js} +2891 -2008
  6. package/dist/chunks/{super-editor.es-CKfdmK-8.cjs → super-editor.es-DxScE0ep.cjs} +2891 -2008
  7. package/dist/core/types/index.d.ts.map +1 -1
  8. package/dist/style.css +4 -0
  9. package/dist/super-editor/ai-writer.es.js +2 -2
  10. package/dist/super-editor/chunks/{converter-BgedUNCW.js → converter-C08GQjNi.js} +1536 -1056
  11. package/dist/super-editor/chunks/{docx-zipper-ByLK3trM.js → docx-zipper-C3-uf2tI.js} +1 -1
  12. package/dist/super-editor/chunks/{editor-CFqh_xBx.js → editor-C2IwVkIp.js} +1251 -846
  13. package/dist/super-editor/chunks/{toolbar-DdfyWgZF.js → toolbar-De8G_9NV.js} +2 -2
  14. package/dist/super-editor/converter.es.js +1 -1
  15. package/dist/super-editor/docx-zipper.es.js +2 -2
  16. package/dist/super-editor/editor.es.js +3 -3
  17. package/dist/super-editor/file-zipper.es.js +1 -1
  18. package/dist/super-editor/src/core/helpers/generateDocxRandomId.d.ts +5 -0
  19. package/dist/super-editor/src/core/super-converter/exporter.d.ts +4 -4
  20. package/dist/super-editor/src/core/super-converter/field-references/fld-preprocessors/hyperlink-preprocessor.d.ts +9 -0
  21. package/dist/super-editor/src/core/super-converter/field-references/fld-preprocessors/index.d.ts +2 -0
  22. package/dist/super-editor/src/core/super-converter/field-references/fld-preprocessors/num-pages-preprocessor.d.ts +9 -0
  23. package/dist/super-editor/src/core/super-converter/field-references/fld-preprocessors/page-preprocessor.d.ts +9 -0
  24. package/dist/super-editor/src/core/super-converter/field-references/fld-preprocessors/page-ref-preprocessor.d.ts +9 -0
  25. package/dist/super-editor/src/core/super-converter/field-references/fld-preprocessors/toc-preprocessor.d.ts +8 -0
  26. package/dist/super-editor/src/core/super-converter/field-references/index.d.ts +1 -0
  27. package/dist/super-editor/src/core/super-converter/field-references/preProcessNodesForFldChar.d.ts +21 -0
  28. package/dist/super-editor/src/core/super-converter/v2/exporter/helpers/translateChildNodes.d.ts +3 -3
  29. package/dist/super-editor/src/core/super-converter/v2/importer/pageReferenceImporter.d.ts +4 -0
  30. package/dist/super-editor/src/core/super-converter/v2/importer/tableOfContentsImporter.d.ts +4 -0
  31. package/dist/super-editor/src/core/super-converter/v2/types/index.d.ts +7 -1
  32. package/dist/super-editor/src/core/super-converter/v3/handlers/sd/pageReference/index.d.ts +1 -0
  33. package/dist/super-editor/src/core/super-converter/v3/handlers/sd/pageReference/pageReference-translator.d.ts +7 -0
  34. package/dist/super-editor/src/core/super-converter/v3/handlers/sd/tableOfContents/index.d.ts +1 -0
  35. package/dist/super-editor/src/core/super-converter/v3/handlers/sd/tableOfContents/tableOfContents-translator.d.ts +10 -0
  36. package/dist/super-editor/src/core/super-converter/v3/handlers/w/caps/caps-translator.d.ts +7 -0
  37. package/dist/super-editor/src/core/super-converter/v3/handlers/w/p/helpers/w-p-helpers.d.ts +0 -2
  38. package/dist/super-editor/src/core/super-converter/v3/handlers/w/sdt/helpers/handle-doc-part-obj.d.ts +9 -1
  39. package/dist/super-editor/src/core/super-converter/v3/handlers/w/sdt/helpers/translate-document-part-obj.d.ts +6 -0
  40. package/dist/super-editor/src/core/super-converter/v3/node-translator/node-translator.d.ts +2 -2
  41. package/dist/super-editor/src/extensions/index.d.ts +2 -1
  42. package/dist/super-editor/src/extensions/page-reference/index.d.ts +1 -0
  43. package/dist/super-editor/src/extensions/page-reference/page-reference.d.ts +2 -0
  44. package/dist/super-editor/src/extensions/structured-content/document-part-object.d.ts +2 -0
  45. package/dist/super-editor/src/extensions/structured-content/index.d.ts +2 -0
  46. package/dist/super-editor/src/extensions/structured-content/structured-content-commands.d.ts +67 -0
  47. package/dist/super-editor/src/extensions/structured-content/structuredContentHelpers/getStructuredContentBlockTags.d.ts +6 -0
  48. package/dist/super-editor/src/extensions/structured-content/structuredContentHelpers/getStructuredContentInlineTags.d.ts +6 -0
  49. package/dist/super-editor/src/extensions/structured-content/structuredContentHelpers/getStructuredContentTags.d.ts +6 -0
  50. package/dist/super-editor/src/extensions/structured-content/structuredContentHelpers/getStructuredContentTagsById.d.ts +7 -0
  51. package/dist/super-editor/src/extensions/structured-content/structuredContentHelpers/index.d.ts +4 -0
  52. package/dist/super-editor/src/extensions/tab/helpers/tabDecorations.d.ts +2 -2
  53. package/dist/super-editor/src/extensions/table-of-contents/index.d.ts +1 -0
  54. package/dist/super-editor/src/extensions/table-of-contents/table-of-contents.d.ts +2 -0
  55. package/dist/super-editor/style.css +4 -0
  56. package/dist/super-editor/super-editor.es.js +10 -8
  57. package/dist/super-editor/toolbar.es.js +2 -2
  58. package/dist/super-editor.cjs +1 -1
  59. package/dist/super-editor.es.js +1 -1
  60. package/dist/superdoc.cjs +2 -2
  61. package/dist/superdoc.es.js +2 -2
  62. package/dist/superdoc.umd.js +2892 -2009
  63. package/dist/superdoc.umd.js.map +1 -1
  64. 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, _ListItemNodeView_instances, init_fn2, _FieldAnnotationView_instances, createAnnotation_fn, _AutoPageNumberNodeView_instances, renderDom_fn, scheduleUpdateNodeStyle_fn, _DocumentSectionView_instances, init_fn3, addToolTip_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 InputRule, ah as kebabCase, ai as findParentNodeClosestToPos, aj as getListItemStyleDefinitions, ak as docxNumberigHelpers, al as parseIndentElement, am as combineIndents, an as SelectionRange, ao as Transform, ap as isInTable$1, aq as generateDocxRandomId, ar as insertNewRelationship, as as updateDOMAttributes, at as htmlHandler } from "./converter-BgedUNCW.js";
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-C08GQjNi.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-ByLK3trM.js";
17
+ import { D as DocxZipper } from "./docx-zipper-C3-uf2tI.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 = ({ state, nodes, mark, marks, trackedChangeType, isDeletionInsertion }) => {
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
  });
@@ -14878,7 +14876,7 @@ const _Editor = class _Editor extends EventEmitter {
14878
14876
  * @returns {Object | void} Migration results
14879
14877
  */
14880
14878
  processCollaborationMigrations() {
14881
- console.debug("[checkVersionMigrations] Current editor version", "0.21.0");
14879
+ console.debug("[checkVersionMigrations] Current editor version", "0.22.0");
14882
14880
  if (!this.options.ydoc) return;
14883
14881
  const metaMap = this.options.ydoc.getMap("meta");
14884
14882
  let docVersion = metaMap.get("version");
@@ -16967,6 +16965,1043 @@ const SlashMenu = Extension.create({
16967
16965
  return this.editor.options.isHeadless ? [] : [slashMenuPlugin];
16968
16966
  }
16969
16967
  });
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
+ );
17059
+ }
17060
+ }
17061
+ if (isDragging || isDropEvent || isCopyEvent || isPasteEvent || isCutEvent || isClickEvent && isSelectable) {
17062
+ return false;
17063
+ }
17064
+ return true;
17065
+ }
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;
17073
+ }
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);
17131
+ view.dispatch(transaction);
17132
+ }
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",
17179
+ inline: true,
17180
+ content: "inline*",
17181
+ isolating: true,
17182
+ atom: false,
17183
+ // false - has editable content.
17184
+ draggable: true,
17185
+ addOptions() {
17186
+ return {
17187
+ htmlAttributes: {
17188
+ class: structuredContentClass$1,
17189
+ "aria-label": "Structured content node"
17190
+ }
17191
+ };
17192
+ },
17193
+ addAttributes() {
17194
+ return {
17195
+ id: {
17196
+ default: null,
17197
+ parseDOM: (elem) => elem.getAttribute("data-id"),
17198
+ renderDOM: (attrs) => {
17199
+ if (!attrs.id) return {};
17200
+ return { "data-id": attrs.id };
17201
+ }
17202
+ },
17203
+ tag: {
17204
+ default: null,
17205
+ parseDOM: (elem) => elem.getAttribute("data-tag"),
17206
+ renderDOM: (attrs) => {
17207
+ if (!attrs.tag) return {};
17208
+ return { "data-tag": attrs.tag };
17209
+ }
17210
+ },
17211
+ alias: {
17212
+ default: null,
17213
+ parseDOM: (elem) => elem.getAttribute("data-alias"),
17214
+ renderDOM: (attrs) => {
17215
+ if (!attrs.alias) return {};
17216
+ return { "data-alias": attrs.alias };
17217
+ }
17218
+ },
17219
+ sdtPr: {
17220
+ rendered: false
17221
+ }
17222
+ };
17223
+ },
17224
+ parseDOM() {
17225
+ return [{ tag: "span[data-structured-content]" }];
17226
+ },
17227
+ renderDOM({ htmlAttributes }) {
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
+ };
17240
+ }
17241
+ });
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,
17292
+ addOptions() {
17293
+ return {
17294
+ htmlAttributes: {
17295
+ class: structuredContentClass,
17296
+ "aria-label": "Structured content block node"
17297
+ }
17298
+ };
17299
+ },
17300
+ addAttributes() {
17301
+ return {
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
+ }
17309
+ },
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
+ }
17317
+ },
17318
+ alias: {
17319
+ default: null,
17320
+ parseDOM: (elem) => elem.getAttribute("data-alias"),
17321
+ renderDOM: (attrs) => {
17322
+ if (!attrs.alias) return {};
17323
+ return { "data-alias": attrs.alias };
17324
+ }
17325
+ },
17326
+ sdtPr: {
17327
+ rendered: false
17328
+ }
17329
+ };
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",
17384
+ addCommands() {
17385
+ return {
17386
+ /**
17387
+ * Inserts a structured content inline at selection.
17388
+ * @category Command
17389
+ * @param {StructuredContentInlineInsert} options
17390
+ */
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);
17399
+ }
17400
+ if (options.text) {
17401
+ content = schema.text(options.text);
17402
+ }
17403
+ if (options.json) {
17404
+ content = schema.nodeFromJSON(options.json);
17405
+ }
17406
+ if (!content) {
17407
+ content = schema.text(" ");
17408
+ }
17409
+ const attrs = {
17410
+ ...options.attrs,
17411
+ id: options.attrs?.id || generateRandomSigned32BitIntStrId(),
17412
+ tag: "inline_text_sdt",
17413
+ alias: options.attrs?.alias || "Structured content"
17414
+ };
17415
+ const node = schema.nodes.structuredContent.create(attrs, content, null);
17416
+ const parent = findParentNode((node2) => node2.type.name === "structuredContent")(state.selection);
17417
+ if (parent) {
17418
+ const insertPos = parent.pos + parent.node.nodeSize;
17419
+ from2 = to = insertPos;
17420
+ }
17421
+ tr.replaceWith(from2, to, node);
17422
+ }
17423
+ return true;
17424
+ },
17425
+ /**
17426
+ * Inserts a structured content block at selection.
17427
+ * @category Command
17428
+ * @param {StructuredContentBlockInsert} options
17429
+ */
17430
+ insertStructuredContentBlock: (options = {}) => ({ editor, dispatch, state, tr }) => {
17431
+ const { schema } = editor;
17432
+ let { from: from2, to } = state.selection;
17433
+ if (dispatch) {
17434
+ const selectionContent = state.selection.content();
17435
+ let content = null;
17436
+ if (selectionContent.size) {
17437
+ content = selectionContent.content;
17438
+ }
17439
+ if (options.html) {
17440
+ const html = htmlHandler(options.html, editor);
17441
+ const doc2 = DOMParser$1.fromSchema(schema).parse(html);
17442
+ content = doc2.content;
17443
+ }
17444
+ if (options.json) {
17445
+ content = schema.nodeFromJSON(options.json);
17446
+ }
17447
+ if (!content) {
17448
+ content = schema.nodeFromJSON({ type: "paragraph", content: [] });
17449
+ }
17450
+ const attrs = {
17451
+ ...options.attrs,
17452
+ id: options.attrs?.id || generateRandomSigned32BitIntStrId(),
17453
+ tag: "block_table_sdt",
17454
+ alias: options.attrs?.alias || "Structured content"
17455
+ };
17456
+ const node = schema.nodes.structuredContentBlock.create(attrs, content, null);
17457
+ const parent = findParentNode((node2) => node2.type.name === "structuredContentBlock")(state.selection);
17458
+ if (parent) {
17459
+ const insertPos = parent.pos + parent.node.nodeSize;
17460
+ from2 = to = insertPos;
17461
+ }
17462
+ tr.replaceRangeWith(from2, to, node);
17463
+ }
17464
+ return true;
17465
+ },
17466
+ /**
17467
+ * Updates a structured content attributes or content.
17468
+ * If the updated node does not match the schema, it will not be updated.
17469
+ * @category Command
17470
+ * @param {string} id
17471
+ * @param {StructuredContentUpdate} options
17472
+ */
17473
+ updateStructuredContentById: (id, options = {}) => ({ editor, dispatch, state, tr }) => {
17474
+ const structuredContentTags = getStructuredContentTagsById(id, state);
17475
+ if (!structuredContentTags.length) {
17476
+ return true;
17477
+ }
17478
+ const { schema } = editor;
17479
+ if (dispatch) {
17480
+ const structuredContent = structuredContentTags[0];
17481
+ const { pos, node } = structuredContent;
17482
+ const posFrom = pos;
17483
+ const posTo = pos + node.nodeSize;
17484
+ let content = null;
17485
+ if (options.text) {
17486
+ content = schema.text(options.text);
17487
+ }
17488
+ if (options.html) {
17489
+ const html = htmlHandler(options.html, editor);
17490
+ const doc2 = DOMParser$1.fromSchema(schema).parse(html);
17491
+ content = doc2.content;
17492
+ }
17493
+ if (options.json) {
17494
+ content = schema.nodeFromJSON(options.json);
17495
+ }
17496
+ if (!content) {
17497
+ content = node.content;
17498
+ }
17499
+ const updatedNode = node.type.create({ ...node.attrs, ...options.attrs }, content, node.marks);
17500
+ try {
17501
+ updatedNode.check();
17502
+ } catch {
17503
+ console.error("Updated node does not conform to the schema");
17504
+ return false;
17505
+ }
17506
+ tr.replaceWith(posFrom, posTo, updatedNode);
17507
+ }
17508
+ return true;
17509
+ },
17510
+ /**
17511
+ * Removes a structured content.
17512
+ * @category Command
17513
+ * @param {Array<{ node: Node, pos: number }>} structuredContentTags
17514
+ */
17515
+ deleteStructuredContent: (structuredContentTags) => ({ dispatch, tr }) => {
17516
+ if (!structuredContentTags.length) {
17517
+ return true;
17518
+ }
17519
+ if (dispatch) {
17520
+ structuredContentTags.forEach((structuredContent) => {
17521
+ const { pos, node } = structuredContent;
17522
+ const posFrom = tr.mapping.map(pos);
17523
+ const posTo = tr.mapping.map(pos + node.nodeSize);
17524
+ const currentNode = tr.doc.nodeAt(posFrom);
17525
+ if (currentNode && node.eq(currentNode)) {
17526
+ tr.delete(posFrom, posTo);
17527
+ }
17528
+ });
17529
+ }
17530
+ return true;
17531
+ },
17532
+ /**
17533
+ * Removes a structured content by ID.
17534
+ * @category Command
17535
+ * @param {string | string[]} idOrIds
17536
+ */
17537
+ deleteStructuredContentById: (idOrIds) => ({ dispatch, state, tr }) => {
17538
+ const structuredContentTags = getStructuredContentTagsById(idOrIds, state);
17539
+ if (!structuredContentTags.length) {
17540
+ return true;
17541
+ }
17542
+ if (dispatch) {
17543
+ structuredContentTags.forEach((structuredContent) => {
17544
+ const { pos, node } = structuredContent;
17545
+ const posFrom = tr.mapping.map(pos);
17546
+ const posTo = tr.mapping.map(pos + node.nodeSize);
17547
+ const currentNode = tr.doc.nodeAt(posFrom);
17548
+ if (currentNode && node.eq(currentNode)) {
17549
+ tr.delete(posFrom, posTo);
17550
+ }
17551
+ });
17552
+ }
17553
+ return true;
17554
+ },
17555
+ /**
17556
+ * Removes a structured content at cursor, preserving its content.
17557
+ * @category Command
17558
+ */
17559
+ deleteStructuredContentAtSelection: () => ({ dispatch, state, tr }) => {
17560
+ const predicate = (node) => STRUCTURED_CONTENT_NAMES.includes(node.type.name);
17561
+ const structuredContent = findParentNode(predicate)(state.selection);
17562
+ if (!structuredContent) {
17563
+ return true;
17564
+ }
17565
+ if (dispatch) {
17566
+ const { node, pos } = structuredContent;
17567
+ const posFrom = pos;
17568
+ const posTo = posFrom + node.nodeSize;
17569
+ const content = node.content;
17570
+ tr.replaceWith(posFrom, posTo, content);
17571
+ }
17572
+ return true;
17573
+ }
17574
+ };
17575
+ },
17576
+ addHelpers() {
17577
+ return {
17578
+ ...structuredContentHelpers
17579
+ };
17580
+ }
17581
+ });
17582
+ class DocumentSectionView {
17583
+ constructor(node, getPos, decorations, editor) {
17584
+ __privateAdd(this, _DocumentSectionView_instances);
17585
+ this.node = node;
17586
+ this.editor = editor;
17587
+ this.decorations = decorations;
17588
+ this.view = editor.view;
17589
+ this.getPos = getPos;
17590
+ __privateMethod(this, _DocumentSectionView_instances, init_fn2).call(this);
17591
+ }
17592
+ }
17593
+ _DocumentSectionView_instances = new WeakSet();
17594
+ init_fn2 = function() {
17595
+ const { attrs } = this.node;
17596
+ const { id, title, description } = attrs;
17597
+ this.dom = document.createElement("div");
17598
+ this.dom.className = "sd-document-section-block";
17599
+ this.dom.setAttribute("data-id", id);
17600
+ this.dom.setAttribute("data-title", title);
17601
+ this.dom.setAttribute("data-description", description);
17602
+ this.dom.setAttribute("aria-label", "Document section");
17603
+ __privateMethod(this, _DocumentSectionView_instances, addToolTip_fn).call(this);
17604
+ this.contentDOM = document.createElement("div");
17605
+ this.contentDOM.className = "sd-document-section-block-content";
17606
+ this.contentDOM.setAttribute("contenteditable", "true");
17607
+ this.dom.appendChild(this.contentDOM);
17608
+ };
17609
+ addToolTip_fn = function() {
17610
+ const { title } = this.node.attrs;
17611
+ this.infoDiv = document.createElement("div");
17612
+ this.infoDiv.className = "sd-document-section-block-info";
17613
+ const textSpan = document.createElement("span");
17614
+ textSpan.textContent = title || "Document section";
17615
+ this.infoDiv.appendChild(textSpan);
17616
+ this.infoDiv.setAttribute("contenteditable", "false");
17617
+ this.dom.appendChild(this.infoDiv);
17618
+ };
17619
+ const getAllSections = (editor) => {
17620
+ if (!editor) return [];
17621
+ const type = editor.schema.nodes.documentSection;
17622
+ if (!type) return [];
17623
+ const sections = [];
17624
+ const { state } = editor;
17625
+ state.doc.descendants((node, pos) => {
17626
+ if (node.type.name === type.name) {
17627
+ sections.push({ node, pos });
17628
+ }
17629
+ });
17630
+ return sections;
17631
+ };
17632
+ const exportSectionsToHTML = (editor) => {
17633
+ const sections = getAllSections(editor);
17634
+ const processedSections = /* @__PURE__ */ new Set();
17635
+ const result = [];
17636
+ sections.forEach(({ node }) => {
17637
+ const { attrs } = node;
17638
+ const { id, title, description } = attrs;
17639
+ if (processedSections.has(id)) return;
17640
+ processedSections.add(id);
17641
+ const html = getHTMLFromNode(node, editor);
17642
+ result.push({
17643
+ id,
17644
+ title,
17645
+ description,
17646
+ html
17647
+ });
17648
+ });
17649
+ return result;
17650
+ };
17651
+ const getHTMLFromNode = (node, editor) => {
17652
+ const tempDocument = document.implementation.createHTMLDocument();
17653
+ const container = tempDocument.createElement("div");
17654
+ const fragment = DOMSerializer.fromSchema(editor.schema).serializeFragment(node.content);
17655
+ container.appendChild(fragment);
17656
+ let html = container.innerHTML;
17657
+ return html;
17658
+ };
17659
+ const exportSectionsToJSON = (editor) => {
17660
+ const sections = getAllSections(editor);
17661
+ const processedSections = /* @__PURE__ */ new Set();
17662
+ const result = [];
17663
+ sections.forEach(({ node }) => {
17664
+ const { attrs } = node;
17665
+ const { id, title, description } = attrs;
17666
+ if (processedSections.has(id)) return;
17667
+ processedSections.add(id);
17668
+ result.push({
17669
+ id,
17670
+ title,
17671
+ description,
17672
+ content: node.toJSON()
17673
+ });
17674
+ });
17675
+ return result;
17676
+ };
17677
+ const getLinkedSectionEditor = (id, options, editor) => {
17678
+ const sections = getAllSections(editor);
17679
+ const section = sections.find((s) => s.node.attrs.id === id);
17680
+ if (!section) return null;
17681
+ const child = editor.createChildEditor({
17682
+ ...options,
17683
+ onUpdate: ({ editor: childEditor, transaction }) => {
17684
+ const isFromtLinkedParent = transaction.getMeta("fromLinkedParent");
17685
+ if (isFromtLinkedParent) return;
17686
+ const updatedContent = childEditor.state.doc.content;
17687
+ const sectionNode = getAllSections(editor)?.find((s) => s.node.attrs.id === id);
17688
+ if (!sectionNode) return;
17689
+ const { pos, node } = sectionNode;
17690
+ const newNode = node.type.create(node.attrs, updatedContent, node.marks);
17691
+ const tr = editor.state.tr.replaceWith(pos, pos + node.nodeSize, newNode);
17692
+ tr.setMeta("fromLinkedChild", true);
17693
+ editor.view.dispatch(tr);
17694
+ }
17695
+ });
17696
+ editor.on("update", ({ transaction }) => {
17697
+ const isFromLinkedChild = transaction.getMeta("fromLinkedChild");
17698
+ if (isFromLinkedChild) return;
17699
+ const sectionNode = getAllSections(editor)?.find((s) => s.node.attrs.id === id);
17700
+ if (!sectionNode) return;
17701
+ const sectionContent = sectionNode.node.content;
17702
+ const json = {
17703
+ type: "doc",
17704
+ content: sectionContent.content.map((node) => node.toJSON())
17705
+ };
17706
+ const childTr = child.state.tr;
17707
+ childTr.setMeta("fromLinkedParent", true);
17708
+ childTr.replaceWith(0, child.state.doc.content.size, child.schema.nodeFromJSON(json));
17709
+ child.view.dispatch(childTr);
17710
+ });
17711
+ return child;
17712
+ };
17713
+ const SectionHelpers = {
17714
+ getAllSections,
17715
+ exportSectionsToHTML,
17716
+ exportSectionsToJSON,
17717
+ getLinkedSectionEditor
17718
+ };
17719
+ const DocumentSection = Node$1.create({
17720
+ name: "documentSection",
17721
+ group: "block",
17722
+ content: "block*",
17723
+ atom: true,
17724
+ isolating: true,
17725
+ addOptions() {
17726
+ return {
17727
+ htmlAttributes: {
17728
+ class: "sd-document-section-block",
17729
+ "aria-label": "Structured content block"
17730
+ }
17731
+ };
17732
+ },
17733
+ parseDOM() {
17734
+ return [
17735
+ {
17736
+ tag: "div.sd-document-section-block",
17737
+ priority: 60
17738
+ }
17739
+ ];
17740
+ },
17741
+ renderDOM({ htmlAttributes }) {
17742
+ return ["div", Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes), 0];
17743
+ },
17744
+ addAttributes() {
17745
+ return {
17746
+ id: {},
17747
+ sdBlockId: {
17748
+ default: null,
17749
+ keepOnSplit: false,
17750
+ parseDOM: (elem) => elem.getAttribute("data-sd-block-id"),
17751
+ renderDOM: (attrs) => {
17752
+ return attrs.sdBlockId ? { "data-sd-block-id": attrs.sdBlockId } : {};
17753
+ }
17754
+ },
17755
+ title: {},
17756
+ description: {},
17757
+ sectionType: {},
17758
+ isLocked: { default: false }
17759
+ };
17760
+ },
17761
+ addNodeView() {
17762
+ return ({ node, editor, getPos, decorations }) => {
17763
+ return new DocumentSectionView(node, getPos, decorations, editor);
17764
+ };
17765
+ },
17766
+ addCommands() {
17767
+ return {
17768
+ /**
17769
+ * Create a lockable content section
17770
+ * @category Command
17771
+ * @param {SectionCreate} [options={}] - Section configuration
17772
+ * @example
17773
+ * editor.commands.createDocumentSection({
17774
+ * id: 1,
17775
+ * title: 'Terms & Conditions',
17776
+ * isLocked: true,
17777
+ * html: '<p>Legal content...</p>'
17778
+ * })
17779
+ */
17780
+ createDocumentSection: (options = {}) => ({ tr, state, dispatch, editor }) => {
17781
+ const { selection } = state;
17782
+ let { from: from2, to } = selection;
17783
+ let content = selection.content().content;
17784
+ const { html: optionsHTML, json: optionsJSON } = options;
17785
+ if (optionsHTML) {
17786
+ const html = htmlHandler(optionsHTML, this.editor);
17787
+ const doc2 = DOMParser$1.fromSchema(this.editor.schema).parse(html);
17788
+ content = doc2.content;
17789
+ }
17790
+ if (optionsJSON) {
17791
+ content = this.editor.schema.nodeFromJSON(optionsJSON);
17792
+ }
17793
+ if (!content?.content?.length) {
17794
+ content = this.editor.schema.nodeFromJSON({ type: "paragraph", content: [] });
17795
+ }
17796
+ if (!options.id) {
17797
+ const allSections = SectionHelpers.getAllSections(editor);
17798
+ options.id = allSections.length + 1;
17799
+ }
17800
+ if (!options.title) {
17801
+ options.title = "Document section";
17802
+ }
17803
+ const node = this.type.createAndFill(options, content);
17804
+ if (!node) return false;
17805
+ const isAlreadyInSdtBlock = findParentNode((node2) => node2.type.name === "documentSection")(selection);
17806
+ if (isAlreadyInSdtBlock && isAlreadyInSdtBlock.node) {
17807
+ const insertPos2 = isAlreadyInSdtBlock.pos + isAlreadyInSdtBlock.node.nodeSize;
17808
+ from2 = insertPos2;
17809
+ to = insertPos2;
17810
+ }
17811
+ tr.replaceRangeWith(from2, to, node);
17812
+ const nodeEnd = from2 + node.nodeSize;
17813
+ let shouldInsertParagraph = true;
17814
+ let insertPos = nodeEnd;
17815
+ if (nodeEnd >= tr.doc.content.size) {
17816
+ insertPos = tr.doc.content.size;
17817
+ if (insertPos > 0) {
17818
+ const $endPos = tr.doc.resolve(insertPos);
17819
+ if ($endPos.nodeBefore && $endPos.nodeBefore.type.name === "paragraph") {
17820
+ shouldInsertParagraph = false;
17821
+ }
17822
+ }
17823
+ }
17824
+ if (shouldInsertParagraph) {
17825
+ const emptyParagraph = tr.doc.type.schema.nodes.paragraph.create();
17826
+ tr.insert(insertPos, emptyParagraph);
17827
+ }
17828
+ if (dispatch) {
17829
+ tr.setMeta("documentSection", { action: "create" });
17830
+ dispatch(tr);
17831
+ setTimeout(() => {
17832
+ try {
17833
+ const currentState = editor.state;
17834
+ const docSize = currentState.doc.content.size;
17835
+ let targetPos = from2 + node.nodeSize;
17836
+ if (shouldInsertParagraph) {
17837
+ targetPos += 1;
17838
+ }
17839
+ targetPos = Math.min(targetPos, docSize);
17840
+ if (targetPos < docSize && targetPos > 0) {
17841
+ const newSelection = Selection.near(currentState.doc.resolve(targetPos));
17842
+ const newTr = currentState.tr.setSelection(newSelection);
17843
+ editor.view.dispatch(newTr);
17844
+ }
17845
+ } catch (e) {
17846
+ console.warn("Could not set delayed selection:", e);
17847
+ }
17848
+ }, 0);
17849
+ }
17850
+ return true;
17851
+ },
17852
+ /**
17853
+ * Remove section wrapper at cursor, preserving its content
17854
+ * @category Command
17855
+ * @example
17856
+ * editor.commands.removeSectionAtSelection()
17857
+ * @note Content stays in document, only section wrapper is removed
17858
+ */
17859
+ removeSectionAtSelection: () => ({ tr, dispatch }) => {
17860
+ const sdtNode = findParentNode((node2) => node2.type.name === "documentSection")(tr.selection);
17861
+ if (!sdtNode) return false;
17862
+ const { node, pos } = sdtNode;
17863
+ const nodeStart = pos;
17864
+ const nodeEnd = nodeStart + node.nodeSize;
17865
+ const contentToPreserve = node.content;
17866
+ tr.delete(nodeStart, nodeEnd);
17867
+ if (contentToPreserve.size > 0) {
17868
+ tr.insert(nodeStart, contentToPreserve);
17869
+ }
17870
+ const newPos = Math.min(nodeStart, tr.doc.content.size);
17871
+ tr.setSelection(Selection.near(tr.doc.resolve(newPos)));
17872
+ if (dispatch) {
17873
+ tr.setMeta("documentSection", { action: "delete" });
17874
+ dispatch(tr);
17875
+ }
17876
+ return true;
17877
+ },
17878
+ /**
17879
+ * Delete section and all its content
17880
+ * @category Command
17881
+ * @param {number} id - Section to delete
17882
+ * @example
17883
+ * editor.commands.removeSectionById(123)
17884
+ */
17885
+ removeSectionById: (id) => ({ tr, dispatch }) => {
17886
+ const sections = SectionHelpers.getAllSections(this.editor);
17887
+ const sectionToRemove = sections.find(({ node: node2 }) => node2.attrs.id === id);
17888
+ if (!sectionToRemove) return false;
17889
+ const { pos, node } = sectionToRemove;
17890
+ const nodeStart = pos;
17891
+ const nodeEnd = nodeStart + node.nodeSize;
17892
+ tr.delete(nodeStart, nodeEnd);
17893
+ if (dispatch) {
17894
+ tr.setMeta("documentSection", { action: "delete", id });
17895
+ dispatch(tr);
17896
+ }
17897
+ return true;
17898
+ },
17899
+ /**
17900
+ * Lock section against edits
17901
+ * @category Command
17902
+ * @param {number} id - Section to lock
17903
+ * @example
17904
+ * editor.commands.lockSectionById(123)
17905
+ */
17906
+ lockSectionById: (id) => ({ tr, dispatch }) => {
17907
+ const sections = SectionHelpers.getAllSections(this.editor);
17908
+ const sectionToLock = sections.find(({ node }) => node.attrs.id === id);
17909
+ if (!sectionToLock) return false;
17910
+ tr.setNodeMarkup(sectionToLock.pos, null, { ...sectionToLock.node.attrs, isLocked: true });
17911
+ if (dispatch) {
17912
+ tr.setMeta("documentSection", { action: "lock", id });
17913
+ dispatch(tr);
17914
+ }
17915
+ return true;
17916
+ },
17917
+ /**
17918
+ * Modify section attributes or content
17919
+ * @category Command
17920
+ * @param {SectionUpdate} options - Changes to apply
17921
+ * @example
17922
+ * editor.commands.updateSectionById({ id: 123, attrs: { isLocked: false } })
17923
+ * editor.commands.updateSectionById({ id: 123, html: '<p>New content</p>' })
17924
+ * editor.commands.updateSectionById({
17925
+ * id: 123,
17926
+ * html: '<p>Updated</p>',
17927
+ * attrs: { title: 'New Title' }
17928
+ * })
17929
+ */
17930
+ updateSectionById: ({ id, html, json, attrs }) => ({ tr, dispatch, editor }) => {
17931
+ const sections = SectionHelpers.getAllSections(editor || this.editor);
17932
+ const sectionToUpdate = sections.find(({ node: node2 }) => node2.attrs.id === id);
17933
+ if (!sectionToUpdate) return false;
17934
+ const { pos, node } = sectionToUpdate;
17935
+ let newContent = null;
17936
+ if (html) {
17937
+ const htmlDoc = htmlHandler(html, editor || this.editor);
17938
+ const doc2 = DOMParser$1.fromSchema((editor || this.editor).schema).parse(htmlDoc);
17939
+ newContent = doc2.content;
17940
+ }
17941
+ if (json) {
17942
+ newContent = (editor || this.editor).schema.nodeFromJSON(json);
17943
+ }
17944
+ if (!newContent) {
17945
+ newContent = node.content;
17946
+ }
17947
+ const updatedNode = node.type.create({ ...node.attrs, ...attrs }, newContent, node.marks);
17948
+ tr.replaceWith(pos, pos + node.nodeSize, updatedNode);
17949
+ if (dispatch) {
17950
+ tr.setMeta("documentSection", { action: "update", id, attrs });
17951
+ dispatch(tr);
17952
+ }
17953
+ return true;
17954
+ }
17955
+ };
17956
+ },
17957
+ addHelpers() {
17958
+ return {
17959
+ ...SectionHelpers
17960
+ };
17961
+ }
17962
+ });
17963
+ const DocumentPartObject = Node$1.create({
17964
+ name: "documentPartObject",
17965
+ group: "block",
17966
+ content: "block*",
17967
+ isolating: true,
17968
+ addOptions() {
17969
+ return {
17970
+ htmlAttributes: {
17971
+ class: "sd-document-part-object-block",
17972
+ "aria-label": "Structured document part block"
17973
+ }
17974
+ };
17975
+ },
17976
+ parseDOM() {
17977
+ return [
17978
+ {
17979
+ tag: "div.sd-document-part-object-block",
17980
+ priority: 60
17981
+ }
17982
+ ];
17983
+ },
17984
+ renderDOM({ htmlAttributes }) {
17985
+ return ["div", Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes), 0];
17986
+ },
17987
+ addAttributes() {
17988
+ return {
17989
+ sdBlockId: {
17990
+ default: null,
17991
+ keepOnSplit: false,
17992
+ parseDOM: (elem) => elem.getAttribute("data-sd-block-id"),
17993
+ renderDOM: (attrs) => {
17994
+ return attrs.sdBlockId ? { "data-sd-block-id": attrs.sdBlockId } : {};
17995
+ }
17996
+ },
17997
+ id: {},
17998
+ docPartGallery: {},
17999
+ docPartUnique: {
18000
+ default: true
18001
+ }
18002
+ };
18003
+ }
18004
+ });
16970
18005
  const Document = Node$1.create({
16971
18006
  name: "doc",
16972
18007
  topNode: true,
@@ -18103,7 +19138,12 @@ const generateDecorations = (state, styles) => {
18103
19138
  return { ...base2, ...linkedStyle.definition?.styles || {} };
18104
19139
  };
18105
19140
  const pMap = buildStyleMap(paragraphStyleId);
18106
- const tMap = buildStyleMap(inlineTextStyleId);
19141
+ let tMap;
19142
+ if (paragraphStyleId?.startsWith("TOC")) {
19143
+ tMap = {};
19144
+ } else {
19145
+ tMap = buildStyleMap(inlineTextStyleId);
19146
+ }
18107
19147
  const rMap = buildStyleMap(runStyleId);
18108
19148
  const finalStyles = { ...pMap, ...tMap, ...rMap };
18109
19149
  if (Object.keys(finalStyles).length === 0) return;
@@ -18549,7 +19589,7 @@ class ListItemNodeView {
18549
19589
  this.decorations = decorations;
18550
19590
  this.view = editor.view;
18551
19591
  this.getPos = getPos;
18552
- __privateMethod(this, _ListItemNodeView_instances, init_fn2).call(this);
19592
+ __privateMethod(this, _ListItemNodeView_instances, init_fn3).call(this);
18553
19593
  activeListItemNodeViews.add(this);
18554
19594
  }
18555
19595
  refreshIndentStyling() {
@@ -18610,7 +19650,7 @@ class ListItemNodeView {
18610
19650
  }
18611
19651
  }
18612
19652
  _ListItemNodeView_instances = new WeakSet();
18613
- init_fn2 = function() {
19653
+ init_fn3 = function() {
18614
19654
  const { attrs } = this.node;
18615
19655
  const { listLevel, listNumberingType, lvlText, numId, level, customFormat } = attrs;
18616
19656
  let orderMarker = "";
@@ -19400,7 +20440,7 @@ const CommentsMark = Mark.create({
19400
20440
  });
19401
20441
  const defaultTabDistance = 48;
19402
20442
  const defaultLineLength = 816;
19403
- const getTabDecorations = (doc2, view, from2 = 0, to = null) => {
20443
+ const getTabDecorations = (doc2, view, helpers2, from2 = 0, to = null) => {
19404
20444
  const decorations = [];
19405
20445
  const paragraphCache = /* @__PURE__ */ new Map();
19406
20446
  const end2 = to ?? doc2.content.size;
@@ -19408,7 +20448,7 @@ const getTabDecorations = (doc2, view, from2 = 0, to = null) => {
19408
20448
  if (node.type.name !== "tab") return;
19409
20449
  let extraStyles = "";
19410
20450
  const $pos = doc2.resolve(pos);
19411
- const paragraphContext = getParagraphContext($pos, paragraphCache);
20451
+ const paragraphContext = getParagraphContext($pos, paragraphCache, helpers2);
19412
20452
  if (!paragraphContext) return;
19413
20453
  try {
19414
20454
  const { tabStops, flattened, startPos } = paragraphContext;
@@ -19463,18 +20503,27 @@ const getTabDecorations = (doc2, view, from2 = 0, to = null) => {
19463
20503
  });
19464
20504
  return decorations;
19465
20505
  };
19466
- function getParagraphContext($pos, cache) {
20506
+ function getParagraphContext($pos, cache, helpers2) {
19467
20507
  for (let depth = $pos.depth; depth >= 0; depth--) {
19468
20508
  const node = $pos.node(depth);
19469
20509
  if (node?.type?.name === "paragraph") {
19470
20510
  const startPos = $pos.start(depth);
19471
20511
  if (!cache.has(startPos)) {
20512
+ let tabStops = [];
20513
+ if (Array.isArray(node.attrs?.tabStops)) {
20514
+ tabStops = node.attrs.tabStops;
20515
+ } else {
20516
+ const style = helpers2.linkedStyles.getStyleById(node.attrs?.styleId);
20517
+ if (Array.isArray(style?.definition?.styles?.tabStops)) {
20518
+ tabStops = style.definition.styles.tabStops;
20519
+ }
20520
+ }
19472
20521
  cache.set(startPos, {
19473
20522
  paragraph: node,
19474
20523
  paragraphDepth: depth,
19475
20524
  startPos,
19476
20525
  indent: node.attrs?.indent || {},
19477
- tabStops: Array.isArray(node.attrs?.tabStops) ? node.attrs.tabStops : [],
20526
+ tabStops,
19478
20527
  flattened: flattenParagraph(node, startPos),
19479
20528
  accumulatedTabWidth: 0
19480
20529
  });
@@ -19640,7 +20689,7 @@ const TabNode = Node$1.create({
19640
20689
  };
19641
20690
  },
19642
20691
  addPmPlugins() {
19643
- const { view } = this.editor;
20692
+ const { view, helpers: helpers2 } = this.editor;
19644
20693
  const tabPlugin = new Plugin({
19645
20694
  name: "tabPlugin",
19646
20695
  key: new PluginKey("tabPlugin"),
@@ -19650,7 +20699,7 @@ const TabNode = Node$1.create({
19650
20699
  },
19651
20700
  apply(tr, { decorations }, _oldState, newState) {
19652
20701
  if (!decorations) {
19653
- decorations = DecorationSet.create(newState.doc, getTabDecorations(newState.doc, view));
20702
+ decorations = DecorationSet.create(newState.doc, getTabDecorations(newState.doc, view, helpers2));
19654
20703
  }
19655
20704
  if (!tr.docChanged) {
19656
20705
  return { decorations };
@@ -19690,7 +20739,7 @@ const TabNode = Node$1.create({
19690
20739
  rangesToRecalculate.forEach(([start2, end2]) => {
19691
20740
  const oldDecorations = decorations.find(start2, end2);
19692
20741
  decorations = decorations.remove(oldDecorations);
19693
- const newDecorations = getTabDecorations(newState.doc, view, start2, end2);
20742
+ const newDecorations = getTabDecorations(newState.doc, view, helpers2, start2, end2);
19694
20743
  decorations = decorations.add(newState.doc, newDecorations);
19695
20744
  });
19696
20745
  return { decorations };
@@ -25971,83 +27020,66 @@ const processMarks = (marks) => {
25971
27020
  });
25972
27021
  return styles;
25973
27022
  };
25974
- const ShapeContainer = Node$1.create({
25975
- name: "shapeContainer",
25976
- group: "block",
25977
- content: "block+",
25978
- isolating: true,
27023
+ const PageReference = Node$1.create({
27024
+ name: "pageReference",
27025
+ group: "inline",
27026
+ inline: true,
27027
+ atom: true,
27028
+ draggable: false,
27029
+ selectable: false,
27030
+ content: "inline*",
25979
27031
  addOptions() {
25980
27032
  return {
25981
27033
  htmlAttributes: {
25982
- class: "sd-editor-shape-container",
25983
- "aria-label": "Shape container node"
27034
+ contenteditable: false,
27035
+ "data-id": "auto-page-reference",
27036
+ "aria-label": "Page reference node",
27037
+ class: "sd-editor-page-reference"
25984
27038
  }
25985
27039
  };
25986
27040
  },
25987
27041
  addAttributes() {
25988
27042
  return {
25989
- fillcolor: {
25990
- renderDOM: (attrs) => {
25991
- if (!attrs.fillcolor) return {};
25992
- return {
25993
- style: `background-color: ${attrs.fillcolor}`
25994
- };
25995
- }
25996
- },
25997
- sdBlockId: {
27043
+ marksAsAttrs: {
25998
27044
  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
27045
  rendered: false
26015
27046
  },
26016
- attributes: {
27047
+ instruction: {
27048
+ default: "",
26017
27049
  rendered: false
26018
27050
  }
26019
27051
  };
26020
27052
  },
26021
27053
  parseDOM() {
26022
- return [
26023
- {
26024
- tag: `div[data-type="${this.name}"]`
26025
- }
26026
- ];
27054
+ return [{ tag: 'span[data-id="auto-page-reference"]' }];
26027
27055
  },
26028
27056
  renderDOM({ htmlAttributes }) {
26029
- return [
26030
- "div",
26031
- Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes, { "data-type": this.name }),
26032
- 0
26033
- ];
27057
+ return ["span", Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes), 0];
26034
27058
  }
26035
27059
  });
26036
- const ShapeTextbox = Node$1.create({
26037
- name: "shapeTextbox",
27060
+ const ShapeContainer = Node$1.create({
27061
+ name: "shapeContainer",
26038
27062
  group: "block",
26039
- content: "paragraph* block*",
27063
+ content: "block+",
26040
27064
  isolating: true,
26041
27065
  addOptions() {
26042
27066
  return {
26043
27067
  htmlAttributes: {
26044
- class: "sd-editor-shape-textbox",
26045
- "aria-label": "Shape textbox node"
27068
+ class: "sd-editor-shape-container",
27069
+ "aria-label": "Shape container node"
26046
27070
  }
26047
27071
  };
26048
27072
  },
26049
27073
  addAttributes() {
26050
27074
  return {
27075
+ fillcolor: {
27076
+ renderDOM: (attrs) => {
27077
+ if (!attrs.fillcolor) return {};
27078
+ return {
27079
+ style: `background-color: ${attrs.fillcolor}`
27080
+ };
27081
+ }
27082
+ },
26051
27083
  sdBlockId: {
26052
27084
  default: null,
26053
27085
  keepOnSplit: false,
@@ -26056,72 +27088,15 @@ const ShapeTextbox = Node$1.create({
26056
27088
  return attrs.sdBlockId ? { "data-sd-block-id": attrs.sdBlockId } : {};
26057
27089
  }
26058
27090
  },
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,
27091
+ style: {
26117
27092
  renderDOM: (attrs) => {
26118
- if (!attrs.background) return {};
27093
+ if (!attrs.style) return {};
26119
27094
  return {
26120
- style: `background-color: ${attrs.background}`
27095
+ style: attrs.style
26121
27096
  };
26122
27097
  }
26123
27098
  },
26124
- drawingContent: {
27099
+ wrapAttributes: {
26125
27100
  rendered: false
26126
27101
  },
26127
27102
  attributes: {
@@ -26131,786 +27106,167 @@ const ContentBlock = Node$1.create({
26131
27106
  },
26132
27107
  parseDOM() {
26133
27108
  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;
27109
+ {
27110
+ tag: `div[data-type="${this.name}"]`
27111
+ }
27112
+ ];
27113
+ },
27114
+ renderDOM({ htmlAttributes }) {
27115
+ return [
27116
+ "div",
27117
+ Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes, { "data-type": this.name }),
27118
+ 0
27119
+ ];
26482
27120
  }
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*",
27121
+ });
27122
+ const ShapeTextbox = Node$1.create({
27123
+ name: "shapeTextbox",
27124
+ group: "block",
27125
+ content: "paragraph* block*",
26490
27126
  isolating: true,
26491
- atom: false,
26492
- // false - has editable content.
26493
- draggable: true,
26494
27127
  addOptions() {
26495
27128
  return {
26496
27129
  htmlAttributes: {
26497
- class: structuredContentClass,
26498
- "aria-label": "Structured content block node"
27130
+ class: "sd-editor-shape-textbox",
27131
+ "aria-label": "Shape textbox node"
26499
27132
  }
26500
27133
  };
26501
27134
  },
26502
27135
  addAttributes() {
26503
27136
  return {
26504
- id: {
27137
+ sdBlockId: {
26505
27138
  default: null,
26506
- parseDOM: (elem) => elem.getAttribute("data-id"),
27139
+ keepOnSplit: false,
27140
+ parseDOM: (elem) => elem.getAttribute("data-sd-block-id"),
26507
27141
  renderDOM: (attrs) => {
26508
- if (!attrs.id) return {};
26509
- return { "data-id": attrs.id };
27142
+ return attrs.sdBlockId ? { "data-sd-block-id": attrs.sdBlockId } : {};
26510
27143
  }
26511
27144
  },
26512
- sdtPr: {
27145
+ attributes: {
26513
27146
  rendered: false
26514
27147
  }
26515
27148
  };
26516
27149
  },
26517
27150
  parseDOM() {
26518
- return [{ tag: "div[data-structured-content-block]" }];
27151
+ return [
27152
+ {
27153
+ tag: `div[data-type="${this.name}"]`
27154
+ }
27155
+ ];
26519
27156
  },
26520
27157
  renderDOM({ htmlAttributes }) {
26521
27158
  return [
26522
27159
  "div",
26523
- Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes, {
26524
- "data-structured-content-block": ""
26525
- }),
27160
+ Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes, { "data-type": this.name }),
26526
27161
  0
26527
27162
  ];
26528
- },
26529
- addNodeView() {
26530
- return (props) => {
26531
- return new StructuredContentBlockView({ ...props });
26532
- };
26533
27163
  }
26534
27164
  });
26535
- class DocumentSectionView {
26536
- constructor(node, getPos, decorations, editor) {
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",
26674
- group: "block",
26675
- content: "block*",
26676
- atom: true,
27165
+ const ContentBlock = Node$1.create({
27166
+ name: "contentBlock",
27167
+ group: "inline",
27168
+ content: "",
26677
27169
  isolating: true,
27170
+ atom: true,
27171
+ inline: true,
26678
27172
  addOptions() {
26679
27173
  return {
26680
27174
  htmlAttributes: {
26681
- class: "sd-document-section-block",
26682
- "aria-label": "Structured content block"
27175
+ contenteditable: false
26683
27176
  }
26684
27177
  };
26685
27178
  },
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
27179
  addAttributes() {
26698
27180
  return {
26699
- id: {},
26700
- sdBlockId: {
27181
+ horizontalRule: {
27182
+ default: false,
27183
+ renderDOM: ({ horizontalRule }) => {
27184
+ if (!horizontalRule) return {};
27185
+ return { "data-horizontal-rule": "true" };
27186
+ }
27187
+ },
27188
+ size: {
27189
+ default: null,
27190
+ renderDOM: ({ size }) => {
27191
+ if (!size) return {};
27192
+ let style = "";
27193
+ if (size.top) style += `top: ${size.top}px; `;
27194
+ if (size.left) style += `left: ${size.left}px; `;
27195
+ if (size.width) style += `width: ${size.width.toString().endsWith("%") ? size.width : `${size.width}px`}; `;
27196
+ if (size.height)
27197
+ style += `height: ${size.height.toString().endsWith("%") ? size.height : `${size.height}px`}; `;
27198
+ return { style };
27199
+ }
27200
+ },
27201
+ background: {
26701
27202
  default: null,
26702
- keepOnSplit: false,
26703
- parseDOM: (elem) => elem.getAttribute("data-sd-block-id"),
26704
27203
  renderDOM: (attrs) => {
26705
- return attrs.sdBlockId ? { "data-sd-block-id": attrs.sdBlockId } : {};
27204
+ if (!attrs.background) return {};
27205
+ return {
27206
+ style: `background-color: ${attrs.background}`
27207
+ };
26706
27208
  }
26707
27209
  },
26708
- title: {},
26709
- description: {},
26710
- sectionType: {},
26711
- isLocked: { default: false }
27210
+ drawingContent: {
27211
+ rendered: false
27212
+ },
27213
+ attributes: {
27214
+ rendered: false
27215
+ }
26712
27216
  };
26713
27217
  },
26714
- addNodeView() {
26715
- return ({ node, editor, getPos, decorations }) => {
26716
- return new DocumentSectionView(node, getPos, decorations, editor);
26717
- };
27218
+ parseDOM() {
27219
+ return [
27220
+ {
27221
+ tag: `div[data-type="${this.name}"]`
27222
+ }
27223
+ ];
27224
+ },
27225
+ renderDOM({ htmlAttributes }) {
27226
+ return ["div", Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes, { "data-type": this.name })];
26718
27227
  },
26719
27228
  addCommands() {
26720
27229
  return {
26721
27230
  /**
26722
- * Create a lockable content section
27231
+ * Insert a horizontal rule
26723
27232
  * @category Command
26724
- * @param {SectionCreate} [options={}] - Section configuration
26725
27233
  * @example
26726
- * editor.commands.createDocumentSection({
26727
- * id: 1,
26728
- * title: 'Terms & Conditions',
26729
- * isLocked: true,
26730
- * html: '<p>Legal content...</p>'
26731
- * })
27234
+ * editor.commands.insertHorizontalRule()
27235
+ * @note Creates a visual separator between content sections
26732
27236
  */
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
- }
27237
+ insertHorizontalRule: () => ({ commands: commands2 }) => {
27238
+ return commands2.insertContent({
27239
+ type: this.name,
27240
+ attrs: {
27241
+ horizontalRule: true,
27242
+ size: { width: "100%", height: 2 },
27243
+ background: "#e5e7eb"
26775
27244
  }
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);
26802
- }
26803
- return true;
26804
- },
26805
- /**
26806
- * Remove section wrapper at cursor, preserving its content
26807
- * @category Command
26808
- * @example
26809
- * editor.commands.removeSectionAtSelection()
26810
- * @note Content stays in document, only section wrapper is removed
26811
- */
26812
- removeSectionAtSelection: () => ({ tr, dispatch }) => {
26813
- const sdtNode = findParentNode((node2) => node2.type.name === "documentSection")(tr.selection);
26814
- if (!sdtNode) return false;
26815
- const { node, pos } = sdtNode;
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);
26828
- }
26829
- return true;
26830
- },
26831
- /**
26832
- * Delete section and all its content
26833
- * @category Command
26834
- * @param {number} id - Section to delete
26835
- * @example
26836
- * editor.commands.removeSectionById(123)
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);
26849
- }
26850
- return true;
27245
+ });
26851
27246
  },
26852
27247
  /**
26853
- * Lock section against edits
27248
+ * Insert a content block
26854
27249
  * @category Command
26855
- * @param {number} id - Section to lock
27250
+ * @param {ContentBlockConfig} config - Block configuration
26856
27251
  * @example
26857
- * editor.commands.lockSectionById(123)
26858
- */
26859
- lockSectionById: (id) => ({ tr, dispatch }) => {
26860
- const sections = SectionHelpers.getAllSections(this.editor);
26861
- const sectionToLock = sections.find(({ node }) => node.attrs.id === id);
26862
- if (!sectionToLock) return false;
26863
- tr.setNodeMarkup(sectionToLock.pos, null, { ...sectionToLock.node.attrs, isLocked: true });
26864
- if (dispatch) {
26865
- tr.setMeta("documentSection", { action: "lock", id });
26866
- dispatch(tr);
26867
- }
26868
- return true;
26869
- },
26870
- /**
26871
- * Modify section attributes or content
26872
- * @category Command
26873
- * @param {SectionUpdate} options - Changes to apply
27252
+ * // Insert a spacer block
27253
+ * editor.commands.insertContentBlock({ size: { height: 20 } })
27254
+ *
26874
27255
  * @example
26875
- * editor.commands.updateSectionById({ id: 123, attrs: { isLocked: false } })
26876
- * editor.commands.updateSectionById({ id: 123, html: '<p>New content</p>' })
26877
- * editor.commands.updateSectionById({
26878
- * id: 123,
26879
- * html: '<p>Updated</p>',
26880
- * attrs: { title: 'New Title' }
27256
+ * // Insert a colored divider
27257
+ * editor.commands.insertContentBlock({
27258
+ * size: { width: '50%', height: 3 },
27259
+ * background: '#3b82f6'
26881
27260
  * })
27261
+ * @note Used for spacing, dividers, and special inline content
26882
27262
  */
26883
- updateSectionById: ({ id, html, json, attrs }) => ({ tr, dispatch, editor }) => {
26884
- const sections = SectionHelpers.getAllSections(editor || this.editor);
26885
- const sectionToUpdate = sections.find(({ node: node2 }) => node2.attrs.id === id);
26886
- if (!sectionToUpdate) return false;
26887
- const { pos, node } = sectionToUpdate;
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;
27263
+ insertContentBlock: (config) => ({ commands: commands2 }) => {
27264
+ return commands2.insertContent({
27265
+ type: this.name,
27266
+ attrs: config
27267
+ });
26907
27268
  }
26908
27269
  };
26909
- },
26910
- addHelpers() {
26911
- return {
26912
- ...SectionHelpers
26913
- };
26914
27270
  }
26915
27271
  });
26916
27272
  const { findChildren } = helpers;
@@ -27114,6 +27470,51 @@ const checkForNewBlockNodesInTrs = (transactions) => {
27114
27470
  });
27115
27471
  });
27116
27472
  };
27473
+ const TableOfContents = Node$1.create({
27474
+ name: "tableOfContents",
27475
+ group: "block",
27476
+ content: "paragraph+",
27477
+ inline: false,
27478
+ addOptions() {
27479
+ return {
27480
+ htmlAttributes: {
27481
+ "data-id": "table-of-contents",
27482
+ "aria-label": "Table of Contents"
27483
+ }
27484
+ };
27485
+ },
27486
+ parseDOM() {
27487
+ return [
27488
+ {
27489
+ tag: 'div[data-id="table-of-contents"]'
27490
+ }
27491
+ ];
27492
+ },
27493
+ renderDOM({ htmlAttributes }) {
27494
+ return ["div", Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes), 0];
27495
+ },
27496
+ addAttributes() {
27497
+ return {
27498
+ instruction: {
27499
+ default: null,
27500
+ rendered: false
27501
+ },
27502
+ /**
27503
+ * @private
27504
+ * @category Attribute
27505
+ * @param {string} [sdBlockId] - Internal block tracking ID (not user-configurable)
27506
+ */
27507
+ sdBlockId: {
27508
+ default: null,
27509
+ keepOnSplit: false,
27510
+ parseDOM: (elem) => elem.getAttribute("data-sd-block-id"),
27511
+ renderDOM: (attrs) => {
27512
+ return attrs.sdBlockId ? { "data-sd-block-id": attrs.sdBlockId } : {};
27513
+ }
27514
+ }
27515
+ };
27516
+ }
27517
+ });
27117
27518
  const TextStyle = Mark.create({
27118
27519
  name: "textStyle",
27119
27520
  addOptions() {
@@ -33720,6 +34121,7 @@ const getStarterExtensions = () => {
33720
34121
  SlashMenu,
33721
34122
  Strike,
33722
34123
  TabNode,
34124
+ TableOfContents,
33723
34125
  Text,
33724
34126
  TextAlign,
33725
34127
  TextIndent,
@@ -33754,13 +34156,16 @@ const getStarterExtensions = () => {
33754
34156
  AiLoaderNode,
33755
34157
  PageNumber,
33756
34158
  TotalPageCount,
34159
+ PageReference,
33757
34160
  ShapeContainer,
33758
34161
  ShapeTextbox,
33759
34162
  ContentBlock,
33760
34163
  Search,
33761
34164
  StructuredContent,
33762
34165
  StructuredContentBlock,
34166
+ StructuredContentCommands,
33763
34167
  DocumentSection,
34168
+ DocumentPartObject,
33764
34169
  NodeResizer,
33765
34170
  CustomSelection,
33766
34171
  TextTransform