@harbour-enterprises/superdoc 0.23.0-next.25 → 0.23.0-next.27

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 (34) hide show
  1. package/dist/chunks/{PdfViewer-D5j64OT4.es.js → PdfViewer-C8baB1bn.es.js} +1 -1
  2. package/dist/chunks/{PdfViewer-CYMwWMP6.cjs → PdfViewer-DJ7UGyBT.cjs} +1 -1
  3. package/dist/chunks/{index-CIz8zQ3h.cjs → index-BjwQD_um.cjs} +2 -2
  4. package/dist/chunks/{index-ePxDRT3A.es.js → index-DScOqhcx.es.js} +2 -2
  5. package/dist/chunks/{super-editor.es-BhyobyII.es.js → super-editor.es-D0-dqxm2.es.js} +328 -133
  6. package/dist/chunks/{super-editor.es-DZWnc89F.cjs → super-editor.es-DpCRbxmi.cjs} +328 -133
  7. package/dist/style.css +6 -1
  8. package/dist/super-editor/ai-writer.es.js +2 -2
  9. package/dist/super-editor/chunks/{converter-CL8NqbzP.js → converter-B2Y-pDXk.js} +120 -24
  10. package/dist/super-editor/chunks/{docx-zipper-Ab__pf6Y.js → docx-zipper-bhLh8OB6.js} +1 -1
  11. package/dist/super-editor/chunks/{editor-DDXA7n3I.js → editor-GN9xFFdh.js} +2 -2
  12. package/dist/super-editor/chunks/{toolbar-BkZURoPS.js → toolbar-Bq8miKER.js} +14 -12
  13. package/dist/super-editor/converter.es.js +1 -1
  14. package/dist/super-editor/docx-zipper.es.js +2 -2
  15. package/dist/super-editor/editor.es.js +3 -3
  16. package/dist/super-editor/file-zipper.es.js +1 -1
  17. package/dist/super-editor/style.css +6 -1
  18. package/dist/super-editor/super-editor/src/components/slash-menu/constants.d.ts +4 -0
  19. package/dist/super-editor/super-editor/src/components/slash-menu/menuItems.d.ts +4 -36
  20. package/dist/super-editor/super-editor/src/components/slash-menu/tests/testHelpers.d.ts +5 -12
  21. package/dist/super-editor/super-editor/src/core/super-converter/field-references/fld-preprocessors/num-pages-preprocessor.d.ts +1 -3
  22. package/dist/super-editor/super-editor/src/core/super-converter/field-references/fld-preprocessors/page-preprocessor.d.ts +1 -3
  23. package/dist/super-editor/super-editor/src/core/super-converter/field-references/fld-preprocessors/page-ref-preprocessor.d.ts +1 -2
  24. package/dist/super-editor/super-editor/src/core/super-converter/v3/handlers/w/pict/helpers/handle-shape-textbox-import.d.ts +1 -1
  25. package/dist/super-editor/super-editor/src/core/super-converter/v3/handlers/w/pict/helpers/handle-v-rect-import.d.ts +1 -1
  26. package/dist/super-editor/super-editor.es.js +212 -113
  27. package/dist/super-editor/toolbar.es.js +2 -2
  28. package/dist/super-editor.cjs +1 -1
  29. package/dist/super-editor.es.js +1 -1
  30. package/dist/superdoc.cjs +2 -2
  31. package/dist/superdoc.es.js +2 -2
  32. package/dist/superdoc.umd.js +328 -133
  33. package/dist/superdoc.umd.js.map +1 -1
  34. package/package.json +1 -1
@@ -28088,9 +28088,10 @@ function handleAnnotationNode(params2) {
28088
28088
  const tagValue = tag?.attributes["w:val"];
28089
28089
  const shouldProcessAsJson = tagValue?.startsWith("{") && tagValue?.endsWith("}");
28090
28090
  let attrs = {};
28091
+ const aliasLabel = getSafeString(alias?.attributes?.["w:val"]);
28091
28092
  if (shouldProcessAsJson) {
28092
28093
  const parsedAttrs = parseTagValueJSON(tagValue);
28093
- const attrsFromJSON = {
28094
+ attrs = {
28094
28095
  type: parsedAttrs.fieldTypeShort,
28095
28096
  fieldId: parsedAttrs.fieldId,
28096
28097
  displayLabel: parsedAttrs.displayLabel,
@@ -28104,10 +28105,27 @@ function handleAnnotationNode(params2) {
28104
28105
  textHighlight: parsedAttrs.fieldTextHighlight,
28105
28106
  hash: parsedAttrs.hash
28106
28107
  };
28107
- attrs = attrsFromJSON;
28108
28108
  } else {
28109
- const attrsFromElements = getAttrsFromElements({ sdtPr, tag, alias, sdtId });
28110
- attrs = attrsFromElements;
28109
+ attrs = getAttrsFromElements({ sdtPr, tag, alias, sdtId });
28110
+ }
28111
+ const initialDisplayLabel = getSafeString(attrs.displayLabel);
28112
+ const extractedContent = getTextFromSdtContent(sdtContent);
28113
+ if (!attrs.defaultDisplayLabel) {
28114
+ if (initialDisplayLabel) {
28115
+ attrs.defaultDisplayLabel = initialDisplayLabel;
28116
+ } else if (aliasLabel) {
28117
+ attrs.defaultDisplayLabel = aliasLabel;
28118
+ }
28119
+ }
28120
+ const placeholderLabel = getPlaceholderLabel(attrs, aliasLabel);
28121
+ const placeholderText = ensurePlaceholderFormat(placeholderLabel);
28122
+ const isAnnotationsEnabled = Boolean(params2.editor?.options?.annotations);
28123
+ const contentIsDistinct = shouldUseSdtContent(extractedContent, placeholderText);
28124
+ const shouldUseContent = !isAnnotationsEnabled && contentIsDistinct && (hasMoustache(extractedContent) || !placeholderText);
28125
+ if (contentIsDistinct) {
28126
+ attrs.displayLabel = extractedContent;
28127
+ } else if (!attrs.displayLabel && placeholderLabel) {
28128
+ attrs.displayLabel = placeholderLabel;
28111
28129
  }
28112
28130
  const { attrs: marksAsAttrs, marks } = parseAnnotationMarks(sdtContent);
28113
28131
  const allAttrs = { ...attrs, ...marksAsAttrs };
@@ -28115,13 +28133,14 @@ function handleAnnotationNode(params2) {
28115
28133
  if (!attrs.fieldId || !attrs.type) {
28116
28134
  return null;
28117
28135
  }
28136
+ const textContent2 = shouldUseContent ? extractedContent : placeholderText;
28118
28137
  let result = {
28119
28138
  type: "text",
28120
- text: `{{${attrs.displayLabel}}}`,
28139
+ text: textContent2,
28121
28140
  attrs: allAttrs,
28122
28141
  marks
28123
28142
  };
28124
- if (params2.editor.options.annotations) {
28143
+ if (isAnnotationsEnabled) {
28125
28144
  result = {
28126
28145
  type: "fieldAnnotation",
28127
28146
  attrs: allAttrs
@@ -28182,6 +28201,84 @@ function getAttrsFromElements({ sdtPr, tag, alias, sdtId }) {
28182
28201
  };
28183
28202
  return attrs;
28184
28203
  }
28204
+ function getTextFromSdtContent(sdtContent) {
28205
+ if (!sdtContent?.elements?.length) return "";
28206
+ const chunks = [];
28207
+ collectTextChunks(sdtContent.elements, chunks);
28208
+ if (chunks.length && chunks[chunks.length - 1] === "\n") {
28209
+ chunks.pop();
28210
+ }
28211
+ const text = chunks.join("");
28212
+ return text.replace(/\u00a0/g, " ");
28213
+ }
28214
+ function getPlaceholderLabel(attrs, aliasValue) {
28215
+ const displayLabel = trimSafeString(attrs.displayLabel);
28216
+ if (displayLabel) return displayLabel;
28217
+ const defaultLabel = trimSafeString(attrs.defaultDisplayLabel);
28218
+ if (defaultLabel) return defaultLabel;
28219
+ return trimSafeString(aliasValue);
28220
+ }
28221
+ function shouldUseSdtContent(extractedContent, placeholderText) {
28222
+ const normalizedContent = normalizePlaceholderText(extractedContent);
28223
+ if (!normalizedContent) return false;
28224
+ const normalizedPlaceholder = normalizePlaceholderText(placeholderText);
28225
+ return normalizedContent !== normalizedPlaceholder;
28226
+ }
28227
+ function ensurePlaceholderFormat(label) {
28228
+ const trimmed = trimSafeString(label);
28229
+ if (!trimmed) return "";
28230
+ if (trimmed.startsWith("{{") && trimmed.endsWith("}}")) {
28231
+ return trimmed;
28232
+ }
28233
+ return `{{${trimmed}}}`;
28234
+ }
28235
+ function normalizePlaceholderText(value = "") {
28236
+ const trimmed = trimSafeString(value);
28237
+ if (!trimmed) return "";
28238
+ return stripPlaceholderBraces(trimmed).toLowerCase();
28239
+ }
28240
+ function stripPlaceholderBraces(value = "") {
28241
+ if (value.startsWith("{{") && value.endsWith("}}")) {
28242
+ return trimSafeString(value.slice(2, -2));
28243
+ }
28244
+ return value;
28245
+ }
28246
+ function hasMoustache(value = "") {
28247
+ return /\{\{\s*.+?\s*\}\}/.test(getSafeString(value));
28248
+ }
28249
+ function collectTextChunks(elements, chunks) {
28250
+ if (!elements) return;
28251
+ elements.forEach((element) => {
28252
+ if (!element) return;
28253
+ if (element.type === "text") {
28254
+ chunks.push(element.text || "");
28255
+ return;
28256
+ }
28257
+ if (element.name === "w:tab") {
28258
+ chunks.push(" ");
28259
+ return;
28260
+ }
28261
+ if (element.name === "w:br") {
28262
+ chunks.push("\n");
28263
+ return;
28264
+ }
28265
+ const isParagraph = element.name === "w:p";
28266
+ const initialLength = chunks.length;
28267
+ if (element.elements?.length) {
28268
+ collectTextChunks(element.elements, chunks);
28269
+ }
28270
+ if (isParagraph && chunks.length > initialLength) {
28271
+ chunks.push("\n");
28272
+ }
28273
+ });
28274
+ }
28275
+ function getSafeString(value) {
28276
+ if (typeof value !== "string") return "";
28277
+ return value;
28278
+ }
28279
+ function trimSafeString(value) {
28280
+ return getSafeString(value).replace(/\u00a0/g, " ").trim();
28281
+ }
28185
28282
  function handleDocPartObj(params2) {
28186
28283
  const { nodes } = params2;
28187
28284
  if (nodes.length === 0 || nodes[0].name !== "w:sdt") {
@@ -30841,7 +30938,7 @@ const attrConfig = Object.freeze({
30841
30938
  });
30842
30939
  const XML_NODE_NAME$4 = "w:commentRange";
30843
30940
  const SD_NODE_NAME$4 = "commentRange";
30844
- const decode$4 = (params2, decodedAttrs) => {
30941
+ const decode$4 = (params2) => {
30845
30942
  const { node, comments, commentsExportType, exportedCommentDefs } = params2;
30846
30943
  if (!node) return;
30847
30944
  if (!comments) return;
@@ -30896,7 +30993,7 @@ const commentRangeStartTranslator = NodeTranslator.from(getConfig("Start"));
30896
30993
  const commentRangeEndTranslator = NodeTranslator.from(getConfig("End"));
30897
30994
  const XML_NODE_NAME$3 = "sd:pageReference";
30898
30995
  const SD_NODE_NAME$3 = "pageReference";
30899
- const encode$3 = (params2, _2) => {
30996
+ const encode$3 = (params2) => {
30900
30997
  const { nodes = [], nodeListHandler } = params2 || {};
30901
30998
  const node = nodes[0];
30902
30999
  const processedText = nodeListHandler.handler({
@@ -30913,7 +31010,7 @@ const encode$3 = (params2, _2) => {
30913
31010
  };
30914
31011
  return processedNode;
30915
31012
  };
30916
- const decode$3 = (params2, _2) => {
31013
+ const decode$3 = (params2) => {
30917
31014
  const { node } = params2;
30918
31015
  const outputMarks = processOutputMarks(node.attrs?.marksAsAttrs || []);
30919
31016
  const contentNodes = (node.content ?? []).flatMap((n) => exportSchemaToJson({ ...params2, node: n }));
@@ -30996,7 +31093,7 @@ const config$3 = {
30996
31093
  const translator$3 = NodeTranslator.from(config$3);
30997
31094
  const XML_NODE_NAME$2 = "sd:tableOfContents";
30998
31095
  const SD_NODE_NAME$2 = "tableOfContents";
30999
- const encode$2 = (params2, _2) => {
31096
+ const encode$2 = (params2) => {
31000
31097
  const { nodes = [], nodeListHandler } = params2 || {};
31001
31098
  const node = nodes[0];
31002
31099
  const processedContent = nodeListHandler.handler({
@@ -31012,7 +31109,7 @@ const encode$2 = (params2, _2) => {
31012
31109
  };
31013
31110
  return processedNode;
31014
31111
  };
31015
- const decode$2 = (params2, _2) => {
31112
+ const decode$2 = (params2) => {
31016
31113
  const { node } = params2;
31017
31114
  const contentNodes = node.content.map((n) => exportSchemaToJson({ ...params2, node: n }));
31018
31115
  const tocBeginElements = [
@@ -31075,7 +31172,7 @@ function parseInlineStyles(styleString) {
31075
31172
  return acc;
31076
31173
  }, {});
31077
31174
  }
31078
- function handleVRectImport({ params: params2, pNode, pict }) {
31175
+ function handleVRectImport({ pNode, pict }) {
31079
31176
  const rect = pict.elements?.find((el) => el.name === "v:rect");
31080
31177
  const schemaAttrs = {};
31081
31178
  const rectAttrs = rect.attributes || {};
@@ -32081,7 +32178,7 @@ const tabNodeEntityHandler = {
32081
32178
  handler: handleTabNode
32082
32179
  };
32083
32180
  const tableOfContentsHandlerEntity = generateV2HandlerEntity("tableOfContentsHandler", translator$2);
32084
- function preProcessPageInstruction(nodesToCombine, _2, __) {
32181
+ function preProcessPageInstruction(nodesToCombine) {
32085
32182
  const pageNumNode = {
32086
32183
  name: "sd:autoPageNumber",
32087
32184
  type: "element"
@@ -32092,7 +32189,7 @@ function preProcessPageInstruction(nodesToCombine, _2, __) {
32092
32189
  });
32093
32190
  return [pageNumNode];
32094
32191
  }
32095
- function preProcessNumPagesInstruction(nodesToCombine, _2, __) {
32192
+ function preProcessNumPagesInstruction(nodesToCombine) {
32096
32193
  const totalPageNumNode = {
32097
32194
  name: "sd:totalPageNumber",
32098
32195
  type: "element"
@@ -32103,7 +32200,7 @@ function preProcessNumPagesInstruction(nodesToCombine, _2, __) {
32103
32200
  });
32104
32201
  return [totalPageNumNode];
32105
32202
  }
32106
- function preProcessPageRefInstruction(nodesToCombine, instrText, _2) {
32203
+ function preProcessPageRefInstruction(nodesToCombine, instrText) {
32107
32204
  const pageRefNode = {
32108
32205
  name: "sd:pageReference",
32109
32206
  type: "element",
@@ -32139,15 +32236,14 @@ function preProcessHyperlinkInstruction(nodesToCombine, instruction, docx) {
32139
32236
  }
32140
32237
  } else {
32141
32238
  const availableSwitches = {
32142
- "w:anchor": `l "(?<value>[^"]+)"`,
32143
- new_window: `
32144
- `,
32145
- "w:tgtFrame": ` "(?<value>[^"]+)"`,
32146
- "w:tooltip": `o "(?<value>[^"]+)"`
32239
+ "w:anchor": /(?:\\)?l "(?<value>[^"]+)"/,
32240
+ new_window: /(?:\\n|\n)/,
32241
+ "w:tgtFrame": /(?:\\t|\t) "(?<value>[^"]+)"/,
32242
+ "w:tooltip": /(?:\\)?o "(?<value>[^"]+)"/
32147
32243
  };
32148
32244
  const parsedSwitches = {};
32149
- for (const [key2, regex] of Object.entries(availableSwitches)) {
32150
- const match = instruction.match(new RegExp(regex));
32245
+ for (const [key2, pattern] of Object.entries(availableSwitches)) {
32246
+ const match = instruction.match(pattern);
32151
32247
  if (match) {
32152
32248
  parsedSwitches[key2] = match.groups?.value || true;
32153
32249
  }
@@ -32311,7 +32407,7 @@ const createDocumentJson = (docx, converter, editor) => {
32311
32407
  } else {
32312
32408
  trackStructure(identifierResult);
32313
32409
  }
32314
- } catch (error) {
32410
+ } catch {
32315
32411
  trackStructure();
32316
32412
  }
32317
32413
  }
@@ -32789,7 +32885,7 @@ const isAlternatingHeadersOddEven = (docx) => {
32789
32885
  const evenOdd = elements.find((el) => el.name === "w:evenAndOddHeaders");
32790
32886
  return !!evenOdd;
32791
32887
  };
32792
- function handleShapeTextboxImport({ params: params2, pNode, pict }) {
32888
+ function handleShapeTextboxImport({ params: params2, pict }) {
32793
32889
  const shape = pict.elements?.find((el) => el.name === "v:shape");
32794
32890
  const schemaAttrs = {};
32795
32891
  const schemaTextboxAttrs = {};
@@ -71893,7 +71989,7 @@ const fileHalfDashedIconSvg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="
71893
71989
  const commentIconSvg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M512 240c0 114.9-114.6 208-256 208c-37.1 0-72.3-6.4-104.1-17.9c-11.9 8.7-31.3 20.6-54.3 30.6C73.6 471.1 44.7 480 16 480c-6.5 0-12.3-3.9-14.8-9.9c-2.5-6-1.1-12.8 3.4-17.4c0 0 0 0 0 0s0 0 0 0s0 0 0 0c0 0 0 0 0 0l.3-.3c.3-.3 .7-.7 1.3-1.4c1.1-1.2 2.8-3.1 4.9-5.7c4.1-5 9.6-12.4 15.2-21.6c10-16.6 19.5-38.4 21.4-62.9C17.7 326.8 0 285.1 0 240C0 125.1 114.6 32 256 32s256 93.1 256 208z"/></svg>';
71894
71990
  const circleIconSvg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"/></svg>';
71895
71991
  const checkIconSvg$1 = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M438.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L160 338.7 393.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"/></svg>';
71896
- const xmarkIconSvg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z"/></svg>';
71992
+ const xMarkIconSvg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z"/></svg>';
71897
71993
  const upRightFromSquareIconSvg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M352 0c-12.9 0-24.6 7.8-29.6 19.8s-2.2 25.7 6.9 34.9L370.7 96 201.4 265.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L416 141.3l41.4 41.4c9.2 9.2 22.9 11.9 34.9 6.9s19.8-16.6 19.8-29.6l0-128c0-17.7-14.3-32-32-32L352 0zM80 32C35.8 32 0 67.8 0 112L0 432c0 44.2 35.8 80 80 80l320 0c44.2 0 80-35.8 80-80l0-112c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 112c0 8.8-7.2 16-16 16L80 448c-8.8 0-16-7.2-16-16l0-320c0-8.8 7.2-16 16-16l112 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L80 32z"/></svg>';
71898
71994
  const ellipsisVerticalIconSvg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M64 360a56 56 0 1 0 0 112 56 56 0 1 0 0-112zm0-160a56 56 0 1 0 0 112 56 56 0 1 0 0-112zM120 96A56 56 0 1 0 8 96a56 56 0 1 0 112 0z"/></svg>';
71899
71995
  const caretUpIconSvg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M182.6 137.4c-12.5-12.5-32.8-12.5-45.3 0l-128 128c-9.2 9.2-11.9 22.9-6.9 34.9s16.6 19.8 29.6 19.8l256 0c12.9 0 24.6-7.8 29.6-19.8s2.2-25.7-6.9-34.9l-128-128z"/></svg>';
@@ -71948,7 +72044,7 @@ const toolbarIcons = {
71948
72044
  colorOption: circleIconSvg,
71949
72045
  colorOptionCheck: checkIconSvg$1,
71950
72046
  linkInput: linkIconSvg,
71951
- removeLink: xmarkIconSvg,
72047
+ removeLink: xMarkIconSvg,
71952
72048
  openLink: upRightFromSquareIconSvg,
71953
72049
  overflow: ellipsisVerticalIconSvg,
71954
72050
  dropdownCaretUp: caretUpIconSvg,
@@ -85787,7 +85883,9 @@ const ICONS = {
85787
85883
  copy: copyIconSvg,
85788
85884
  paste: pasteIconSvg,
85789
85885
  addDocumentSection: plusIconSvg,
85790
- removeDocumentSection: trashIconSvg
85886
+ removeDocumentSection: trashIconSvg,
85887
+ trackChangesAccept: checkIconSvg$1,
85888
+ trackChangesReject: xMarkIconSvg
85791
85889
  };
85792
85890
  const TEXTS = {
85793
85891
  addRowBefore: "Insert row above",
@@ -85810,7 +85908,9 @@ const TEXTS = {
85810
85908
  copy: "Copy",
85811
85909
  paste: "Paste",
85812
85910
  removeDocumentSection: "Remove section",
85813
- createDocumentSection: "Create section"
85911
+ createDocumentSection: "Create section",
85912
+ trackChangesAccept: "Accept change",
85913
+ trackChangesReject: "Reject change"
85814
85914
  };
85815
85915
  const tableActionsOptions = [
85816
85916
  {
@@ -86014,34 +86114,37 @@ async function getEditorContext(editor, event) {
86014
86114
  const isInSectionNode = structureFromResolvedPos?.isInSectionNode ?? selectionHasNodeOrMark(state2, "documentSection", { requireEnds: true });
86015
86115
  const currentNodeType = node?.type?.name || null;
86016
86116
  const activeMarks = [];
86117
+ let trackedChangeId = null;
86017
86118
  if (event && pos !== null) {
86018
86119
  const $pos = state2.doc.resolve(pos);
86019
- if ($pos.marks && typeof $pos.marks === "function") {
86020
- $pos.marks().forEach((mark) => activeMarks.push(mark.type.name));
86120
+ const processMark = (mark) => {
86121
+ if (!activeMarks.includes(mark.type.name)) {
86122
+ activeMarks.push(mark.type.name);
86123
+ }
86124
+ if (!trackedChangeId && (mark.type.name === "trackInsert" || mark.type.name === "trackDelete" || mark.type.name === "trackFormat")) {
86125
+ trackedChangeId = mark.attrs.id;
86126
+ }
86127
+ };
86128
+ for (let depth = 0; depth <= $pos.depth; depth++) {
86129
+ const nodeAtDepth = $pos.node(depth);
86130
+ if (nodeAtDepth && nodeAtDepth.marks) {
86131
+ nodeAtDepth.marks.forEach(processMark);
86132
+ }
86021
86133
  }
86022
- if (node && node.marks) {
86023
- node.marks.forEach((mark) => activeMarks.push(mark.type.name));
86134
+ if (state2.storedMarks) {
86135
+ state2.storedMarks.forEach(processMark);
86024
86136
  }
86025
86137
  } else {
86026
86138
  state2.storedMarks?.forEach((mark) => activeMarks.push(mark.type.name));
86027
86139
  state2.selection.$head.marks().forEach((mark) => activeMarks.push(mark.type.name));
86028
86140
  }
86029
- const isTrackedChange = activeMarks.includes("trackInsert") || activeMarks.includes("trackDelete");
86030
- let trackedChangeId = null;
86031
- if (isTrackedChange && event && pos !== null) {
86032
- const $pos = state2.doc.resolve(pos);
86033
- const marksAtPos = $pos.marks();
86034
- const trackedMark = marksAtPos.find((mark) => mark.type.name === "trackInsert" || mark.type.name === "trackDelete");
86035
- if (trackedMark) {
86036
- trackedChangeId = trackedMark.attrs.id;
86037
- }
86038
- }
86141
+ const isTrackedChange = activeMarks.includes("trackInsert") || activeMarks.includes("trackDelete") || activeMarks.includes("trackFormat");
86039
86142
  const cursorCoords = pos ? view.coordsAtPos(pos) : null;
86040
86143
  const cursorPosition = cursorCoords ? {
86041
86144
  x: cursorCoords.left,
86042
86145
  y: cursorCoords.top
86043
86146
  } : null;
86044
- return {
86147
+ const context = {
86045
86148
  // Selection info
86046
86149
  selectedText,
86047
86150
  hasSelection: !empty2,
@@ -86067,9 +86170,11 @@ async function getEditorContext(editor, event) {
86067
86170
  pos,
86068
86171
  node,
86069
86172
  event,
86173
+ trigger: event ? "click" : "slash",
86070
86174
  // Editor reference for advanced use cases
86071
86175
  editor
86072
86176
  };
86177
+ return context;
86073
86178
  }
86074
86179
  function computeCanUndo(editor, state2) {
86075
86180
  if (typeof editor?.can === "function") {
@@ -86150,160 +86255,209 @@ const isModuleEnabled = (editorOptions, moduleName) => {
86150
86255
  switch (moduleName) {
86151
86256
  case "ai":
86152
86257
  return !!editorOptions?.isAiEnabled;
86153
- // Example for future use cases
86154
- // case 'comments':
86155
- // return !!editorOptions?.isCommentsEnabled;
86156
86258
  default:
86157
86259
  return true;
86158
86260
  }
86159
86261
  };
86160
- function applyCustomMenuConfiguration(defaultSections, context) {
86161
- const { editor } = context;
86162
- const slashMenuConfig = editor.options?.slashMenuConfig;
86163
- if (!slashMenuConfig) {
86164
- return defaultSections;
86165
- }
86166
- let sections = [];
86167
- if (slashMenuConfig.includeDefaultItems !== false) {
86168
- sections = [...defaultSections];
86169
- }
86170
- if (slashMenuConfig.customItems && Array.isArray(slashMenuConfig.customItems)) {
86171
- sections = [...sections, ...slashMenuConfig.customItems];
86172
- }
86173
- if (typeof slashMenuConfig.menuProvider === "function") {
86262
+ const shouldShowItem = (item, context) => {
86263
+ if (typeof item.showWhen === "function") {
86174
86264
  try {
86175
- sections = slashMenuConfig.menuProvider(context, sections) || sections;
86265
+ return item.showWhen(context);
86176
86266
  } catch (error) {
86177
- console.warn("[SlashMenu] Error in custom menuProvider:", error);
86267
+ console.warn("[SlashMenu] showWhen error for item", item.id, ":", error);
86268
+ return false;
86178
86269
  }
86179
86270
  }
86180
- return sections;
86181
- }
86182
- function filterCustomItems(sections, context) {
86183
- return sections.map((section) => {
86184
- const filteredItems = section.items.filter((item) => {
86185
- if (typeof item.showWhen === "function") {
86186
- try {
86187
- return item.showWhen(context);
86188
- } catch (error) {
86189
- console.warn(`[SlashMenu] Error in showWhen for item ${item.id}:`, error);
86190
- return false;
86191
- }
86192
- }
86193
- return true;
86194
- });
86195
- return {
86196
- ...section,
86197
- items: filteredItems
86198
- };
86199
- }).filter((section) => section.items.length > 0);
86200
- }
86201
- function getItems(context) {
86202
- const { editor, selectedText, trigger: trigger2, clipboardContent } = context;
86203
- const clipboardHasContent = Boolean(
86204
- clipboardContent?.hasContent || clipboardContent?.html || clipboardContent?.text || typeof clipboardContent?.size === "number" && clipboardContent.size > 0 || clipboardContent && typeof clipboardContent?.content?.size === "number" && clipboardContent.content.size > 0 || clipboardContent?.raw && typeof clipboardContent.raw.size === "number" && clipboardContent.raw.size > 0 || clipboardContent?.raw && typeof clipboardContent.raw?.content?.size === "number" && clipboardContent.raw.content.size > 0
86205
- );
86206
- const isInTable2 = selectionHasNodeOrMark(editor.view.state, "table", { requireEnds: true });
86207
- const isInSectionNode = selectionHasNodeOrMark(editor.view.state, "documentSection", { requireEnds: true });
86208
- const sections = [
86271
+ };
86272
+ function getItems(context, customItems = [], includeDefaultItems = true) {
86273
+ const { selectedText, editor } = context;
86274
+ if (arguments.length === 1 && editor?.options?.slashMenuConfig) {
86275
+ customItems = editor.options.slashMenuConfig.items || editor.options.slashMenuConfig.customItems || [];
86276
+ includeDefaultItems = editor.options.slashMenuConfig.includeDefaultItems !== false;
86277
+ }
86278
+ const enhancedContext = {
86279
+ ...context,
86280
+ isInTable: context.isInTable ?? false,
86281
+ isInSectionNode: context.isInSectionNode ?? false,
86282
+ isTrackedChange: context.isTrackedChange ?? false,
86283
+ clipboardContent: context.clipboardContent ?? { hasContent: false },
86284
+ selectedText: context.selectedText ?? "",
86285
+ hasSelection: context.hasSelection ?? Boolean(context.selectedText)
86286
+ };
86287
+ const defaultSections = [
86209
86288
  {
86210
86289
  id: "ai-content",
86290
+ isDefault: true,
86211
86291
  items: [
86212
86292
  {
86213
86293
  id: "insert-text",
86214
86294
  label: selectedText ? TEXTS.replaceText : TEXTS.insertText,
86215
86295
  icon: ICONS.ai,
86216
86296
  component: AIWriter,
86297
+ isDefault: true,
86217
86298
  action: (editor2) => {
86218
86299
  if (editor2?.commands && typeof editor2.commands?.insertAiMark === "function") {
86219
86300
  editor2.commands.insertAiMark();
86220
86301
  }
86221
86302
  },
86222
- allowedTriggers: [TRIGGERS.slash, TRIGGERS.click],
86223
- requiresModule: "ai"
86303
+ showWhen: (context2) => {
86304
+ const { trigger: trigger2 } = context2;
86305
+ const allowedTriggers = [TRIGGERS.slash, TRIGGERS.click];
86306
+ return allowedTriggers.includes(trigger2) && isModuleEnabled(context2.editor?.options, "ai");
86307
+ }
86308
+ }
86309
+ ]
86310
+ },
86311
+ {
86312
+ id: "track-changes",
86313
+ isDefault: true,
86314
+ items: [
86315
+ {
86316
+ id: "track-changes-accept",
86317
+ icon: ICONS.trackChangesAccept,
86318
+ label: TEXTS.trackChangesAccept,
86319
+ isDefault: true,
86320
+ action: (editor2, context2) => {
86321
+ if (context2?.trackedChangeId) {
86322
+ editor2.commands.acceptTrackedChangeById(context2.trackedChangeId);
86323
+ } else {
86324
+ editor2.commands.acceptTrackedChangeBySelection();
86325
+ }
86326
+ },
86327
+ showWhen: (context2) => {
86328
+ const { trigger: trigger2, isTrackedChange } = context2;
86329
+ return trigger2 === TRIGGERS.click && isTrackedChange;
86330
+ }
86331
+ },
86332
+ {
86333
+ id: "track-changes-reject",
86334
+ label: TEXTS.trackChangesReject,
86335
+ icon: ICONS.trackChangesReject,
86336
+ isDefault: true,
86337
+ action: (editor2, context2) => {
86338
+ if (context2?.trackedChangeId) {
86339
+ editor2.commands.rejectTrackedChangeById(context2.trackedChangeId);
86340
+ } else {
86341
+ editor2.commands.rejectTrackedChangeOnSelection();
86342
+ }
86343
+ },
86344
+ showWhen: (context2) => {
86345
+ const { trigger: trigger2, isTrackedChange } = context2;
86346
+ return trigger2 === TRIGGERS.click && isTrackedChange;
86347
+ }
86224
86348
  }
86225
86349
  ]
86226
86350
  },
86227
86351
  {
86228
86352
  id: "document-sections",
86353
+ isDefault: true,
86229
86354
  items: [
86230
86355
  {
86231
86356
  id: "insert-document-section",
86232
86357
  label: TEXTS.createDocumentSection,
86233
86358
  icon: ICONS.addDocumentSection,
86359
+ isDefault: true,
86234
86360
  action: (editor2) => {
86235
86361
  editor2.commands.createDocumentSection();
86236
86362
  },
86237
- allowedTriggers: [TRIGGERS.click]
86363
+ showWhen: (context2) => {
86364
+ const { trigger: trigger2 } = context2;
86365
+ return trigger2 === TRIGGERS.click;
86366
+ }
86238
86367
  },
86239
86368
  {
86240
86369
  id: "remove-section",
86241
86370
  label: TEXTS.removeDocumentSection,
86242
86371
  icon: ICONS.removeDocumentSection,
86372
+ isDefault: true,
86243
86373
  action: (editor2) => {
86244
86374
  editor2.commands.removeSectionAtSelection();
86245
86375
  },
86246
- allowedTriggers: [TRIGGERS.click],
86247
- requiresSectionParent: true
86376
+ showWhen: (context2) => {
86377
+ const { trigger: trigger2, isInSectionNode } = context2;
86378
+ return trigger2 === TRIGGERS.click && isInSectionNode;
86379
+ }
86248
86380
  }
86249
86381
  ]
86250
86382
  },
86251
86383
  {
86252
86384
  id: "general",
86385
+ isDefault: true,
86253
86386
  items: [
86254
86387
  {
86255
86388
  id: "insert-link",
86256
86389
  label: TEXTS.insertLink,
86257
86390
  icon: ICONS.link,
86258
86391
  component: LinkInput,
86259
- allowedTriggers: [TRIGGERS.click]
86392
+ isDefault: true,
86393
+ showWhen: (context2) => {
86394
+ const { trigger: trigger2 } = context2;
86395
+ return trigger2 === TRIGGERS.click;
86396
+ }
86260
86397
  },
86261
86398
  {
86262
86399
  id: "insert-table",
86263
86400
  label: TEXTS.insertTable,
86264
86401
  icon: ICONS.table,
86265
86402
  component: TableGrid,
86266
- allowedTriggers: [TRIGGERS.slash, TRIGGERS.click]
86403
+ isDefault: true,
86404
+ showWhen: (context2) => {
86405
+ const { trigger: trigger2, isInTable: isInTable2 } = context2;
86406
+ const allowedTriggers = [TRIGGERS.slash, TRIGGERS.click];
86407
+ return allowedTriggers.includes(trigger2) && !isInTable2;
86408
+ }
86267
86409
  },
86268
86410
  {
86269
86411
  id: "edit-table",
86270
86412
  label: TEXTS.editTable,
86271
86413
  icon: ICONS.table,
86272
86414
  component: TableActions,
86273
- allowedTriggers: [TRIGGERS.slash, TRIGGERS.click],
86274
- requiresTableParent: true
86415
+ isDefault: true,
86416
+ showWhen: (context2) => {
86417
+ const { trigger: trigger2, isInTable: isInTable2 } = context2;
86418
+ const allowedTriggers = [TRIGGERS.slash, TRIGGERS.click];
86419
+ return allowedTriggers.includes(trigger2) && isInTable2;
86420
+ }
86275
86421
  }
86276
86422
  ]
86277
86423
  },
86278
86424
  {
86279
86425
  id: "clipboard",
86426
+ isDefault: true,
86280
86427
  items: [
86281
86428
  {
86282
86429
  id: "cut",
86283
86430
  label: TEXTS.cut,
86284
86431
  icon: ICONS.cut,
86432
+ isDefault: true,
86285
86433
  action: (editor2) => {
86286
86434
  editor2.view.focus();
86287
86435
  document.execCommand("cut");
86288
86436
  },
86289
- allowedTriggers: [TRIGGERS.click],
86290
- requiresSelection: true
86437
+ showWhen: (context2) => {
86438
+ const { trigger: trigger2, selectedText: selectedText2 } = context2;
86439
+ return trigger2 === TRIGGERS.click && selectedText2;
86440
+ }
86291
86441
  },
86292
86442
  {
86293
86443
  id: "copy",
86294
86444
  label: TEXTS.copy,
86295
86445
  icon: ICONS.copy,
86446
+ isDefault: true,
86296
86447
  action: (editor2) => {
86297
86448
  editor2.view.focus();
86298
86449
  document.execCommand("copy");
86299
86450
  },
86300
- allowedTriggers: [TRIGGERS.click],
86301
- requiresSelection: true
86451
+ showWhen: (context2) => {
86452
+ const { trigger: trigger2, selectedText: selectedText2 } = context2;
86453
+ return trigger2 === TRIGGERS.click && selectedText2;
86454
+ }
86302
86455
  },
86303
86456
  {
86304
86457
  id: "paste",
86305
86458
  label: TEXTS.paste,
86306
86459
  icon: ICONS.paste,
86460
+ isDefault: true,
86307
86461
  action: async (editor2) => {
86308
86462
  try {
86309
86463
  const clipboardItems = await navigator.clipboard.read();
@@ -86317,7 +86471,7 @@ function getItems(context) {
86317
86471
  text = await (await item.getType("text/plain")).text();
86318
86472
  }
86319
86473
  }
86320
- const handled = handleClipboardPaste({ editor: editor2, view: editor2.view }, html, text);
86474
+ const handled = handleClipboardPaste({ editor: editor2, view: editor2.view }, html);
86321
86475
  if (!handled) {
86322
86476
  const dataTransfer = new DataTransfer();
86323
86477
  if (html) dataTransfer.setData("text/html", html);
@@ -86333,30 +86487,52 @@ function getItems(context) {
86333
86487
  console.warn("Failed to paste:", error);
86334
86488
  }
86335
86489
  },
86336
- allowedTriggers: [TRIGGERS.click, TRIGGERS.slash],
86337
- requiresClipboard: true
86490
+ showWhen: (context2) => {
86491
+ const { trigger: trigger2, clipboardContent } = context2;
86492
+ const allowedTriggers = [TRIGGERS.click, TRIGGERS.slash];
86493
+ const hasContent = clipboardContent?.hasContent || clipboardContent?.size > 0 || clipboardContent?.content?.size > 0;
86494
+ return allowedTriggers.includes(trigger2) && hasContent;
86495
+ }
86338
86496
  }
86339
86497
  ]
86340
86498
  }
86341
86499
  ];
86342
- let allSections = applyCustomMenuConfiguration(sections, context);
86343
- const filteredSections = allSections.map((section) => {
86344
- const filteredItems = section.items.filter((item) => {
86345
- if (item.requiresModule && !isModuleEnabled(editor?.options, item.requiresModule)) return false;
86346
- if (item.requiresSelection && !selectedText) return false;
86347
- if (!item.allowedTriggers.includes(trigger2)) return false;
86348
- if (item.requiresClipboard && !clipboardHasContent) return false;
86349
- if (item.requiresTableParent && !isInTable2 || item.id === "insert-table" && isInTable2) return false;
86350
- if (item.requiresSectionParent && !isInSectionNode) return false;
86351
- return true;
86500
+ let allSections = [];
86501
+ if (includeDefaultItems) {
86502
+ allSections = [...defaultSections];
86503
+ }
86504
+ if (customItems.length > 0) {
86505
+ customItems.forEach((customSection) => {
86506
+ const existingSectionIndex = allSections.findIndex((section) => section.id === customSection.id);
86507
+ if (existingSectionIndex !== -1) {
86508
+ allSections[existingSectionIndex].items = [
86509
+ ...allSections[existingSectionIndex].items,
86510
+ ...customSection.items.map((item) => ({ ...item, isDefault: false }))
86511
+ ];
86512
+ } else {
86513
+ allSections.push({
86514
+ ...customSection,
86515
+ isDefault: false,
86516
+ items: customSection.items.map((item) => ({ ...item, isDefault: false }))
86517
+ });
86518
+ }
86352
86519
  });
86520
+ }
86521
+ if (editor?.options?.slashMenuConfig?.menuProvider) {
86522
+ try {
86523
+ allSections = editor.options.slashMenuConfig.menuProvider(enhancedContext, allSections) || allSections;
86524
+ } catch (error) {
86525
+ console.warn("[SlashMenu] menuProvider error:", error);
86526
+ }
86527
+ }
86528
+ const filteredSections = allSections.map((section) => {
86529
+ const filteredItems = section.items.filter((item) => shouldShowItem(item, enhancedContext));
86353
86530
  return {
86354
86531
  ...section,
86355
86532
  items: filteredItems
86356
86533
  };
86357
86534
  }).filter((section) => section.items.length > 0);
86358
- const finalSections = filterCustomItems(filteredSections, context);
86359
- return finalSections;
86535
+ return filteredSections;
86360
86536
  }
86361
86537
  const _hoisted_1$3 = { class: "slash-menu-items" };
86362
86538
  const _hoisted_2$1 = {
@@ -86439,13 +86615,28 @@ const _sfc_main$4 = {
86439
86615
  });
86440
86616
  const customItemRefs = /* @__PURE__ */ new Map();
86441
86617
  const setCustomItemRef = (el, item) => {
86442
- if (el && item.render) {
86618
+ if (el) {
86443
86619
  customItemRefs.set(item.id, { element: el, item });
86444
86620
  vue.nextTick(() => {
86445
86621
  renderCustomItem(item.id);
86446
86622
  });
86447
86623
  }
86448
86624
  };
86625
+ const defaultRender = (context) => {
86626
+ const item = context.item || context.currentItem;
86627
+ const container = document.createElement("div");
86628
+ container.className = "slash-menu-default-content";
86629
+ if (item.icon) {
86630
+ const iconSpan = document.createElement("span");
86631
+ iconSpan.className = "slash-menu-item-icon";
86632
+ iconSpan.innerHTML = item.icon;
86633
+ container.appendChild(iconSpan);
86634
+ }
86635
+ const labelSpan = document.createElement("span");
86636
+ labelSpan.textContent = item.label;
86637
+ container.appendChild(labelSpan);
86638
+ return container;
86639
+ };
86449
86640
  const renderCustomItem = async (itemId) => {
86450
86641
  const refData = customItemRefs.get(itemId);
86451
86642
  if (!refData || refData.element.hasCustomContent) return;
@@ -86454,8 +86645,9 @@ const _sfc_main$4 = {
86454
86645
  if (!currentContext.value) {
86455
86646
  currentContext.value = await getEditorContext(props.editor);
86456
86647
  }
86457
- const context = currentContext.value;
86458
- const customElement = item.render(context);
86648
+ const contextWithItem = { ...currentContext.value, currentItem: item };
86649
+ const renderFunction = item.render || defaultRender;
86650
+ const customElement = renderFunction(contextWithItem);
86459
86651
  if (customElement instanceof HTMLElement) {
86460
86652
  element.innerHTML = "";
86461
86653
  element.appendChild(customElement);
@@ -86463,7 +86655,9 @@ const _sfc_main$4 = {
86463
86655
  }
86464
86656
  } catch (error) {
86465
86657
  console.warn(`[SlashMenu] Error rendering custom item ${itemId}:`, error);
86466
- element.innerHTML = `<span>${item.label || "Custom Item"}</span>`;
86658
+ const fallbackElement = defaultRender({ ...currentContext.value || {}, currentItem: item });
86659
+ element.innerHTML = "";
86660
+ element.appendChild(fallbackElement);
86467
86661
  element.hasCustomContent = true;
86468
86662
  }
86469
86663
  };
@@ -86658,19 +86852,20 @@ const _sfc_main$4 = {
86658
86852
  class: vue.normalizeClass(["slash-menu-item", { "is-selected": item.id === selectedId.value }]),
86659
86853
  onClick: ($event) => executeCommand(item)
86660
86854
  }, [
86661
- item.render ? (vue.openBlock(), vue.createElementBlock("div", {
86662
- key: 0,
86855
+ vue.createBaseVNode("div", {
86663
86856
  ref_for: true,
86664
86857
  ref: (el) => setCustomItemRef(el, item),
86665
86858
  class: "slash-menu-custom-item"
86666
- }, null, 512)) : (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 1 }, [
86667
- item.icon ? (vue.openBlock(), vue.createElementBlock("span", {
86668
- key: 0,
86669
- class: "slash-menu-item-icon",
86670
- innerHTML: item.icon
86671
- }, null, 8, _hoisted_4)) : vue.createCommentVNode("", true),
86672
- vue.createBaseVNode("span", null, vue.toDisplayString(item.label), 1)
86673
- ], 64))
86859
+ }, [
86860
+ !item.render ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 0 }, [
86861
+ item.icon ? (vue.openBlock(), vue.createElementBlock("span", {
86862
+ key: 0,
86863
+ class: "slash-menu-item-icon",
86864
+ innerHTML: item.icon
86865
+ }, null, 8, _hoisted_4)) : vue.createCommentVNode("", true),
86866
+ vue.createBaseVNode("span", null, vue.toDisplayString(item.label), 1)
86867
+ ], 64)) : vue.createCommentVNode("", true)
86868
+ ], 512)
86674
86869
  ], 10, _hoisted_3$1);
86675
86870
  }), 128))
86676
86871
  ], 64);