@mdaemon/html-editor 1.0.6 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -12430,7 +12430,6 @@ function isMarkInSet(marks, type, attributes = {}) {
12430
12430
  return !!findMarkInSet(marks, type, attributes);
12431
12431
  }
12432
12432
  function getMarkRange($pos, type, attributes) {
12433
- var _a;
12434
12433
  if (!$pos || !type) {
12435
12434
  return;
12436
12435
  }
@@ -12441,7 +12440,12 @@ function getMarkRange($pos, type, attributes) {
12441
12440
  if (!start.node || !start.node.marks.some((mark2) => mark2.type === type)) {
12442
12441
  return;
12443
12442
  }
12444
- attributes = attributes || ((_a = start.node.marks[0]) == null ? void 0 : _a.attrs);
12443
+ if (!attributes) {
12444
+ const firstMark = start.node.marks.find((mark2) => mark2.type === type);
12445
+ if (firstMark) {
12446
+ attributes = firstMark.attrs;
12447
+ }
12448
+ }
12445
12449
  const mark = findMarkInSet([...start.node.marks], type, attributes);
12446
12450
  if (!mark) {
12447
12451
  return;
@@ -12472,7 +12476,7 @@ function getMarkType(nameOrType, schema) {
12472
12476
  }
12473
12477
  return nameOrType;
12474
12478
  }
12475
- var extendMarkRange = (typeOrName, attributes = {}) => ({ tr: tr2, state, dispatch }) => {
12479
+ var extendMarkRange = (typeOrName, attributes) => ({ tr: tr2, state, dispatch }) => {
12476
12480
  const type = getMarkType(typeOrName, state.schema);
12477
12481
  const { doc: doc2, selection } = tr2;
12478
12482
  const { $from, from: from2, to } = selection;
@@ -12783,7 +12787,7 @@ var insertContentAt = (position, value, options) => ({ tr: tr2, dispatch, editor
12783
12787
  const fromSelectionAtStart = $from.parentOffset === 0;
12784
12788
  const isTextSelection2 = $fromNode.isText || $fromNode.isTextblock;
12785
12789
  const hasContent = $fromNode.content.size > 0;
12786
- if (fromSelectionAtStart && isTextSelection2 && hasContent) {
12790
+ if (fromSelectionAtStart && isTextSelection2 && hasContent && isOnlyBlockContent) {
12787
12791
  from2 = Math.max(0, from2 - 1);
12788
12792
  }
12789
12793
  tr2.replaceWith(from2, to, newContent);
@@ -13226,6 +13230,9 @@ function getAttributesFromExtensions(extensions) {
13226
13230
  keepOnSplit: true,
13227
13231
  isRequired: false
13228
13232
  };
13233
+ const nodeExtensionTypes = nodeExtensions.filter((ext) => ext.name !== "text").map((ext) => ext.name);
13234
+ const markExtensionTypes = markExtensions.map((ext) => ext.name);
13235
+ const allExtensionTypes = [...nodeExtensionTypes, ...markExtensionTypes];
13229
13236
  extensions.forEach((extension) => {
13230
13237
  const context = {
13231
13238
  name: extension.name,
@@ -13243,7 +13250,19 @@ function getAttributesFromExtensions(extensions) {
13243
13250
  }
13244
13251
  const globalAttributes = addGlobalAttributes();
13245
13252
  globalAttributes.forEach((globalAttribute) => {
13246
- globalAttribute.types.forEach((type) => {
13253
+ let resolvedTypes;
13254
+ if (Array.isArray(globalAttribute.types)) {
13255
+ resolvedTypes = globalAttribute.types;
13256
+ } else if (globalAttribute.types === "*") {
13257
+ resolvedTypes = allExtensionTypes;
13258
+ } else if (globalAttribute.types === "nodes") {
13259
+ resolvedTypes = nodeExtensionTypes;
13260
+ } else if (globalAttribute.types === "marks") {
13261
+ resolvedTypes = markExtensionTypes;
13262
+ } else {
13263
+ resolvedTypes = [];
13264
+ }
13265
+ resolvedTypes.forEach((type) => {
13247
13266
  Object.entries(globalAttribute.attributes).forEach(([name, attribute]) => {
13248
13267
  extensionAttributes.push({
13249
13268
  type,
@@ -13292,6 +13311,67 @@ function getAttributesFromExtensions(extensions) {
13292
13311
  });
13293
13312
  return extensionAttributes;
13294
13313
  }
13314
+ function splitStyleDeclarations(styles) {
13315
+ const result = [];
13316
+ let current = "";
13317
+ let inSingleQuote = false;
13318
+ let inDoubleQuote = false;
13319
+ let parenDepth = 0;
13320
+ const length = styles.length;
13321
+ for (let i = 0; i < length; i += 1) {
13322
+ const char = styles[i];
13323
+ if (char === "'" && !inDoubleQuote) {
13324
+ inSingleQuote = !inSingleQuote;
13325
+ current += char;
13326
+ continue;
13327
+ }
13328
+ if (char === '"' && !inSingleQuote) {
13329
+ inDoubleQuote = !inDoubleQuote;
13330
+ current += char;
13331
+ continue;
13332
+ }
13333
+ if (!inSingleQuote && !inDoubleQuote) {
13334
+ if (char === "(") {
13335
+ parenDepth += 1;
13336
+ current += char;
13337
+ continue;
13338
+ }
13339
+ if (char === ")" && parenDepth > 0) {
13340
+ parenDepth -= 1;
13341
+ current += char;
13342
+ continue;
13343
+ }
13344
+ if (char === ";" && parenDepth === 0) {
13345
+ result.push(current);
13346
+ current = "";
13347
+ continue;
13348
+ }
13349
+ }
13350
+ current += char;
13351
+ }
13352
+ if (current) {
13353
+ result.push(current);
13354
+ }
13355
+ return result;
13356
+ }
13357
+ function parseStyleEntries(styles) {
13358
+ const pairs = [];
13359
+ const declarations = splitStyleDeclarations(styles || "");
13360
+ const numDeclarations = declarations.length;
13361
+ for (let i = 0; i < numDeclarations; i += 1) {
13362
+ const declaration = declarations[i];
13363
+ const firstColonIndex = declaration.indexOf(":");
13364
+ if (firstColonIndex === -1) {
13365
+ continue;
13366
+ }
13367
+ const property = declaration.slice(0, firstColonIndex).trim();
13368
+ const value = declaration.slice(firstColonIndex + 1).trim();
13369
+ if (property && value) {
13370
+ pairs.push([property, value]);
13371
+ }
13372
+ }
13373
+ return pairs;
13374
+ }
13295
13375
  function mergeAttributes(...objects) {
13296
13376
  return objects.filter((item) => !!item).reduce((items, item) => {
13297
13377
  const mergedAttributes = { ...items };
@@ -13307,17 +13387,7 @@ function mergeAttributes(...objects) {
13307
13387
  const insertClasses = valueClasses.filter((valueClass) => !existingClasses.includes(valueClass));
13308
13388
  mergedAttributes[key] = [...existingClasses, ...insertClasses].join(" ");
13309
13389
  } else if (key === "style") {
13310
- const newStyles = value ? value.split(";").map((style2) => style2.trim()).filter(Boolean) : [];
13311
- const existingStyles = mergedAttributes[key] ? mergedAttributes[key].split(";").map((style2) => style2.trim()).filter(Boolean) : [];
13312
- const styleMap = /* @__PURE__ */ new Map();
13313
- existingStyles.forEach((style2) => {
13314
- const [property, val] = style2.split(":").map((part) => part.trim());
13315
- styleMap.set(property, val);
13316
- });
13317
- newStyles.forEach((style2) => {
13318
- const [property, val] = style2.split(":").map((part) => part.trim());
13319
- styleMap.set(property, val);
13320
- });
13390
+ const styleMap = new Map([...parseStyleEntries(mergedAttributes[key]), ...parseStyleEntries(value)]);
13321
13391
  mergedAttributes[key] = Array.from(styleMap.entries()).map(([property, val]) => `${property}: ${val}`).join("; ");
13322
13392
  } else {
13323
13393
  mergedAttributes[key] = value;
@@ -13741,6 +13811,9 @@ function isMarkActive(state, typeOrName, attributes = {}) {
13741
13811
  const from2 = $from.pos;
13742
13812
  const to = $to.pos;
13743
13813
  state.doc.nodesBetween(from2, to, (node, pos) => {
13814
+ if (type && node.inlineContent && !node.type.allowsMarkType(type)) {
13815
+ return false;
13816
+ }
13744
13817
  if (!node.isText && !node.marks.length) {
13745
13818
  return;
13746
13819
  }
@@ -13849,7 +13922,7 @@ function isNodeEmpty(node, {
13849
13922
  return true;
13850
13923
  }
13851
13924
  if (node.isText) {
13852
- return /^\s*$/m.test((_a = node.text) != null ? _a : "");
13925
+ return !/\S/.test((_a = node.text) != null ? _a : "");
13853
13926
  }
13854
13927
  }
13855
13928
  if (node.isText) {
@@ -14237,6 +14310,16 @@ var joinListForwards = (tr2, listType) => {
14237
14310
  tr2.join(after);
14238
14311
  return true;
14239
14312
  };
14313
+ function createInnerSelectionForWholeDocList(tr2) {
14314
+ const doc2 = tr2.doc;
14315
+ const list = doc2.firstChild;
14316
+ if (!list) {
14317
+ return null;
14318
+ }
14319
+ const from2 = 1;
14320
+ const to = list.nodeSize - 1;
14321
+ return TextSelection.create(doc2, from2, to);
14322
+ }
14240
14323
  var toggleList = (listTypeOrName, itemTypeOrName, keepMarks, attributes = {}) => ({ editor, tr: tr2, state, dispatch, chain, commands, can }) => {
14241
14324
  const { extensions, splittableMarks } = editor.extensionManager;
14242
14325
  const listType = getNodeType(listTypeOrName, state.schema);
@@ -14249,13 +14332,36 @@ var toggleList = (listTypeOrName, itemTypeOrName, keepMarks, attributes = {}) =>
14249
14332
  return false;
14250
14333
  }
14251
14334
  const parentList = findParentNode((node) => isList(node.type.name, extensions))(selection);
14252
- if (range.depth >= 1 && parentList && range.depth - parentList.depth <= 1) {
14253
- if (parentList.node.type === listType) {
14335
+ const isAllSelection = selection.from === 0 && selection.to === state.doc.content.size;
14336
+ const topLevelNodes = state.doc.content.content;
14337
+ const soleTopLevelNode = topLevelNodes.length === 1 ? topLevelNodes[0] : null;
14338
+ const allSelectionList = isAllSelection && soleTopLevelNode && isList(soleTopLevelNode.type.name, extensions) ? {
14339
+ node: soleTopLevelNode,
14340
+ pos: 0
14341
+ } : null;
14342
+ const currentList = parentList != null ? parentList : allSelectionList;
14343
+ const isInsideExistingList = !!parentList && range.depth >= 1 && range.depth - parentList.depth <= 1;
14344
+ const hasWholeDocSelectedList = !!allSelectionList;
14345
+ if ((isInsideExistingList || hasWholeDocSelectedList) && currentList) {
14346
+ if (currentList.node.type === listType) {
14347
+ if (isAllSelection && hasWholeDocSelectedList) {
14348
+ return chain().command(({ tr: trx, dispatch: disp }) => {
14349
+ const nextSelection = createInnerSelectionForWholeDocList(trx);
14350
+ if (!nextSelection) {
14351
+ return false;
14352
+ }
14353
+ trx.setSelection(nextSelection);
14354
+ if (disp) {
14355
+ disp(trx);
14356
+ }
14357
+ return true;
14358
+ }).liftListItem(itemType).run();
14359
+ }
14254
14360
  return commands.liftListItem(itemType);
14255
14361
  }
14256
- if (isList(parentList.node.type.name, extensions) && listType.validContent(parentList.node.content) && dispatch) {
14362
+ if (isList(currentList.node.type.name, extensions) && listType.validContent(currentList.node.content)) {
14257
14363
  return chain().command(() => {
14258
- tr2.setNodeMarkup(parentList.pos, listType);
14364
+ tr2.setNodeMarkup(currentList.pos, listType);
14259
14365
  return true;
14260
14366
  }).command(() => joinListBackwards(tr2, listType)).command(() => joinListForwards(tr2, listType)).run();
14261
14367
  }
@@ -15249,6 +15355,39 @@ var ExtensionManager = class {
15249
15355
  };
15250
15356
  }, baseDispatch);
15251
15357
  }
15358
+ /**
15359
+ * Get the composed transformPastedHTML function from all extensions.
15360
+ * @param baseTransform The base transform function (e.g. from the editor props)
15361
+ * @returns A composed transform function that chains all extension transforms
15362
+ */
15363
+ transformPastedHTML(baseTransform) {
15364
+ const { editor } = this;
15365
+ const extensions = sortExtensions([...this.extensions]);
15366
+ return extensions.reduce(
15367
+ (transform, extension) => {
15368
+ const context = {
15369
+ name: extension.name,
15370
+ options: extension.options,
15371
+ storage: this.editor.extensionStorage[extension.name],
15372
+ editor,
15373
+ type: getSchemaTypeByName(extension.name, this.schema)
15374
+ };
15375
+ const extensionTransform = getExtensionField(
15376
+ extension,
15377
+ "transformPastedHTML",
15378
+ context
15379
+ );
15380
+ if (!extensionTransform) {
15381
+ return transform;
15382
+ }
15383
+ return (html, view) => {
15384
+ const transformedHtml = transform(html, view);
15385
+ return extensionTransform.call(context, transformedHtml);
15386
+ };
15387
+ },
15388
+ baseTransform || ((html) => html)
15389
+ );
15390
+ }
15252
15391
  get markViews() {
15253
15392
  const { editor } = this;
15254
15393
  const { markExtensions } = splitExtensions(this.extensions);
@@ -15467,7 +15606,7 @@ var Delete = Extension.create({
15467
15606
  const newEnd = mapping.slice(index).map(step.to);
15468
15607
  const oldStart = mapping.invert().map(newStart, -1);
15469
15608
  const oldEnd = mapping.invert().map(newEnd);
15470
- const foundBeforeMark = (_a3 = nextTransaction.doc.nodeAt(newStart - 1)) == null ? void 0 : _a3.marks.some((mark) => mark.eq(step.mark));
15609
+ const foundBeforeMark = newStart > 0 ? (_a3 = nextTransaction.doc.nodeAt(newStart - 1)) == null ? void 0 : _a3.marks.some((mark) => mark.eq(step.mark)) : false;
15471
15610
  const foundAfterMark = (_b3 = nextTransaction.doc.nodeAt(newEnd)) == null ? void 0 : _b3.marks.some((mark) => mark.eq(step.mark));
15472
15611
  this.editor.emit("delete", {
15473
15612
  type: "mark",
@@ -16219,7 +16358,7 @@ var Editor = class extends EventEmitter {
16219
16358
  return this.options.editable && this.view && this.view.editable;
16220
16359
  }
16221
16360
  /**
16222
- * Returns the editor state.
16361
+ * Returns the editor view.
16223
16362
  */
16224
16363
  get view() {
16225
16364
  if (this.editorView) {
@@ -16387,6 +16526,8 @@ var Editor = class extends EventEmitter {
16387
16526
  const { editorProps, enableExtensionDispatchTransaction } = this.options;
16388
16527
  const baseDispatch = editorProps.dispatchTransaction || this.dispatchTransaction.bind(this);
16389
16528
  const dispatch = enableExtensionDispatchTransaction ? this.extensionManager.dispatchTransaction(baseDispatch) : baseDispatch;
16529
+ const baseTransformPastedHTML = editorProps.transformPastedHTML;
16530
+ const transformPastedHTML = this.extensionManager.transformPastedHTML(baseTransformPastedHTML);
16390
16531
  this.editorView = new EditorView(element, {
16391
16532
  ...editorProps,
16392
16533
  attributes: {
@@ -16395,6 +16536,7 @@ var Editor = class extends EventEmitter {
16395
16536
  ...editorProps == null ? void 0 : editorProps.attributes
16396
16537
  },
16397
16538
  dispatchTransaction: dispatch,
16539
+ transformPastedHTML,
16398
16540
  state: this.editorState,
16399
16541
  markViews: this.extensionManager.markViews,
16400
16542
  nodeViews: this.extensionManager.nodeViews
@@ -16902,7 +17044,7 @@ var ResizableNodeView = class {
16902
17044
  const element = document.createElement("div");
16903
17045
  element.dataset.resizeContainer = "";
16904
17046
  element.dataset.node = this.node.type.name;
16905
- element.style.display = "flex";
17047
+ element.style.display = this.node.type.isInline ? "inline-flex" : "flex";
16906
17048
  if (this.classNames.container) {
16907
17049
  element.className = this.classNames.container;
16908
17050
  }
@@ -17704,17 +17846,21 @@ function renderNestedMarkdownContent(node, h2, prefixOrGenerator, ctx) {
17704
17846
  const prefix = typeof prefixOrGenerator === "function" ? prefixOrGenerator(ctx) : prefixOrGenerator;
17705
17847
  const [content, ...children] = node.content;
17706
17848
  const mainContent = h2.renderChildren([content]);
17707
- const output = [`${prefix}${mainContent}`];
17849
+ let output = `${prefix}${mainContent}`;
17708
17850
  if (children && children.length > 0) {
17709
- children.forEach((child) => {
17710
- const childContent = h2.renderChildren([child]);
17711
- if (childContent) {
17712
- const indentedChild = childContent.split("\n").map((line) => line ? h2.indent(line) : "").join("\n");
17713
- output.push(indentedChild);
17851
+ children.forEach((child, index) => {
17852
+ var _a, _b;
17853
+ const childContent = (_b = (_a = h2.renderChild) == null ? void 0 : _a.call(h2, child, index + 1)) != null ? _b : h2.renderChildren([child]);
17854
+ if (childContent !== void 0 && childContent !== null) {
17855
+ const indentedChild = childContent.split("\n").map((line) => line ? h2.indent(line) : h2.indent("")).join("\n");
17856
+ output += child.type === "paragraph" ? `
17857
+
17858
+ ${indentedChild}` : `
17859
+ ${indentedChild}`;
17714
17860
  }
17715
17861
  });
17716
17862
  }
17717
- return output.join("\n");
17863
+ return output;
17718
17864
  }
17719
17865
  function updateMarkViewAttributes(checkMark, editor, attrs = {}) {
17720
17866
  const { state } = editor;
@@ -17804,7 +17950,10 @@ function markPasteRule(config) {
17804
17950
  }
17805
17951
  markEnd = range.from + startSpaces + captureGroup.length;
17806
17952
  tr2.addMark(range.from + startSpaces, markEnd, config.type.create(attributes || {}));
17807
- tr2.removeStoredMark(config.type);
17953
+ const isMatchAtEndOfText = match.index !== void 0 && match.input !== void 0 && match.index + match[0].length >= match.input.length;
17954
+ if (!isMatchAtEndOfText) {
17955
+ tr2.removeStoredMark(config.type);
17956
+ }
17808
17957
  }
17809
17958
  }
17810
17959
  });
@@ -17840,7 +17989,9 @@ var Blockquote = Node3.create({
17840
17989
  return /* @__PURE__ */ h("blockquote", { ...mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), children: /* @__PURE__ */ h("slot", {}) });
17841
17990
  },
17842
17991
  parseMarkdown: (token, helpers) => {
17843
- return helpers.createNode("blockquote", void 0, helpers.parseChildren(token.tokens || []));
17992
+ var _a;
17993
+ const parseBlockChildren = (_a = helpers.parseBlockChildren) != null ? _a : helpers.parseChildren;
17994
+ return helpers.createNode("blockquote", void 0, parseBlockChildren(token.tokens || []));
17844
17995
  },
17845
17996
  renderMarkdown: (node, h2) => {
17846
17997
  if (!node.content) {
@@ -17848,8 +17999,9 @@ var Blockquote = Node3.create({
17848
17999
  }
17849
18000
  const prefix = ">";
17850
18001
  const result = [];
17851
- node.content.forEach((child) => {
17852
- const childContent = h2.renderChildren([child]);
18002
+ node.content.forEach((child, index) => {
18003
+ var _a, _b;
18004
+ const childContent = (_b = (_a = h2.renderChild) == null ? void 0 : _a.call(h2, child, index)) != null ? _b : h2.renderChildren([child]);
17853
18005
  const lines = childContent.split("\n");
17854
18006
  const linesWithPrefix = lines.map((line) => {
17855
18007
  if (line.trim() === "") {
@@ -17927,6 +18079,12 @@ var Bold = Mark2.create({
17927
18079
  parseMarkdown: (token, helpers) => {
17928
18080
  return helpers.applyMark("bold", helpers.parseInline(token.tokens || []));
17929
18081
  },
18082
+ markdownOptions: {
18083
+ htmlReopen: {
18084
+ open: "<strong>",
18085
+ close: "</strong>"
18086
+ }
18087
+ },
17930
18088
  renderMarkdown: (node, h2) => {
17931
18089
  return `**${h2.renderChildren(node)}**`;
17932
18090
  },
@@ -18103,8 +18261,8 @@ var CodeBlock = Node3.create({
18103
18261
  },
18104
18262
  markdownTokenName: "code",
18105
18263
  parseMarkdown: (token, helpers) => {
18106
- var _a;
18107
- if (((_a = token.raw) == null ? void 0 : _a.startsWith("```")) === false && token.codeBlockStyle !== "indented") {
18264
+ var _a, _b;
18265
+ if (((_a = token.raw) == null ? void 0 : _a.startsWith("```")) === false && ((_b = token.raw) == null ? void 0 : _b.startsWith("~~~")) === false && token.codeBlockStyle !== "indented") {
18108
18266
  return [];
18109
18267
  }
18110
18268
  return helpers.createNode(
@@ -18346,7 +18504,6 @@ var CodeBlock = Node3.create({
18346
18504
  ];
18347
18505
  }
18348
18506
  });
18349
- var index_default = CodeBlock;
18350
18507
  var Document = Node3.create({
18351
18508
  name: "doc",
18352
18509
  topNode: true,
@@ -18623,6 +18780,12 @@ var Italic = Mark2.create({
18623
18780
  parseMarkdown: (token, helpers) => {
18624
18781
  return helpers.applyMark("italic", helpers.parseInline(token.tokens || []));
18625
18782
  },
18783
+ markdownOptions: {
18784
+ htmlReopen: {
18785
+ open: "<em>",
18786
+ close: "</em>"
18787
+ }
18788
+ },
18626
18789
  renderMarkdown: (node, h2) => {
18627
18790
  return `*${h2.renderChildren(node)}*`;
18628
18791
  },
@@ -20321,14 +20484,16 @@ var ListItem = Node3.create({
20321
20484
  },
20322
20485
  markdownTokenName: "list_item",
20323
20486
  parseMarkdown: (token, helpers) => {
20487
+ var _a;
20324
20488
  if (token.type !== "list_item") {
20325
20489
  return [];
20326
20490
  }
20491
+ const parseBlockChildren = (_a = helpers.parseBlockChildren) != null ? _a : helpers.parseChildren;
20327
20492
  let content = [];
20328
20493
  if (token.tokens && token.tokens.length > 0) {
20329
20494
  const hasParagraphTokens = token.tokens.some((t) => t.type === "paragraph");
20330
20495
  if (hasParagraphTokens) {
20331
- content = helpers.parseChildren(token.tokens);
20496
+ content = parseBlockChildren(token.tokens);
20332
20497
  } else {
20333
20498
  const firstToken = token.tokens[0];
20334
20499
  if (firstToken && firstToken.type === "text" && firstToken.tokens && firstToken.tokens.length > 0) {
@@ -20341,11 +20506,11 @@ var ListItem = Node3.create({
20341
20506
  ];
20342
20507
  if (token.tokens.length > 1) {
20343
20508
  const remainingTokens = token.tokens.slice(1);
20344
- const additionalContent = helpers.parseChildren(remainingTokens);
20509
+ const additionalContent = parseBlockChildren(remainingTokens);
20345
20510
  content.push(...additionalContent);
20346
20511
  }
20347
20512
  } else {
20348
- content = helpers.parseChildren(token.tokens);
20513
+ content = parseBlockChildren(token.tokens);
20349
20514
  }
20350
20515
  }
20351
20516
  }
@@ -21263,18 +21428,22 @@ var Paragraph = Node3.create({
21263
21428
  return helpers.parseChildren([tokens[0]]);
21264
21429
  }
21265
21430
  const content = helpers.parseInline(tokens);
21266
- if (content.length === 1 && content[0].type === "text" && (content[0].text === EMPTY_PARAGRAPH_MARKDOWN || content[0].text === NBSP_CHAR)) {
21431
+ const hasExplicitEmptyParagraphMarker = tokens.length === 1 && tokens[0].type === "text" && (tokens[0].raw === EMPTY_PARAGRAPH_MARKDOWN || tokens[0].text === EMPTY_PARAGRAPH_MARKDOWN || tokens[0].raw === NBSP_CHAR || tokens[0].text === NBSP_CHAR);
21432
+ if (hasExplicitEmptyParagraphMarker && content.length === 1 && content[0].type === "text" && (content[0].text === EMPTY_PARAGRAPH_MARKDOWN || content[0].text === NBSP_CHAR)) {
21267
21433
  return helpers.createNode("paragraph", void 0, []);
21268
21434
  }
21269
21435
  return helpers.createNode("paragraph", void 0, content);
21270
21436
  },
21271
- renderMarkdown: (node, h2) => {
21437
+ renderMarkdown: (node, h2, ctx) => {
21438
+ var _a, _b;
21272
21439
  if (!node) {
21273
21440
  return "";
21274
21441
  }
21275
21442
  const content = Array.isArray(node.content) ? node.content : [];
21276
21443
  if (content.length === 0) {
21277
- return EMPTY_PARAGRAPH_MARKDOWN;
21444
+ const previousContent = Array.isArray((_a = ctx == null ? void 0 : ctx.previousNode) == null ? void 0 : _a.content) ? ctx.previousNode.content : [];
21445
+ const previousNodeIsEmptyParagraph = ((_b = ctx == null ? void 0 : ctx.previousNode) == null ? void 0 : _b.type) === "paragraph" && previousContent.length === 0;
21446
+ return previousNodeIsEmptyParagraph ? EMPTY_PARAGRAPH_MARKDOWN : "";
21278
21447
  }
21279
21448
  return h2.renderChildren(content);
21280
21449
  },
@@ -22533,6 +22702,9 @@ var Placeholder = Extension.create({
22533
22702
  doc2.descendants((node, pos) => {
22534
22703
  const hasAnchor = anchor >= pos && anchor <= pos + node.nodeSize;
22535
22704
  const isEmpty2 = !node.isLeaf && isNodeEmpty(node);
22705
+ if (!node.type.isTextblock) {
22706
+ return this.options.includeChildren;
22707
+ }
22536
22708
  if ((hasAnchor || !this.options.showOnlyCurrent) && isEmpty2) {
22537
22709
  const classes = [this.options.emptyNodeClass];
22538
22710
  if (isEmptyDoc) {
@@ -22586,6 +22758,7 @@ Extension.create({
22586
22758
  ];
22587
22759
  }
22588
22760
  });
22761
+ var skipTrailingNodeMeta = "skipTrailingNode";
22589
22762
  function nodeEqualsType({ types, node }) {
22590
22763
  return node && Array.isArray(types) && types.includes(node.type) || (node == null ? void 0 : node.type) === types;
22591
22764
  }
@@ -22605,11 +22778,14 @@ var TrailingNode = Extension.create({
22605
22778
  return [
22606
22779
  new Plugin({
22607
22780
  key: plugin,
22608
- appendTransaction: (_, __, state) => {
22781
+ appendTransaction: (transactions, __, state) => {
22609
22782
  const { doc: doc2, tr: tr2, schema } = state;
22610
22783
  const shouldInsertNodeAtEnd = plugin.getState(state);
22611
22784
  const endPosition = doc2.content.size;
22612
22785
  const type = schema.nodes[defaultNode];
22786
+ if (transactions.some((transaction) => transaction.getMeta(skipTrailingNodeMeta))) {
22787
+ return;
22788
+ }
22613
22789
  if (!shouldInsertNodeAtEnd) {
22614
22790
  return;
22615
22791
  }
@@ -25107,6 +25283,35 @@ function tableEditing({ allowTableNodeSelection = false } = {}) {
25107
25283
  }
25108
25284
  });
25109
25285
  }
25286
+ function normalizeTableCellAlign(value) {
25287
+ if (value === "left" || value === "right" || value === "center") {
25288
+ return value;
25289
+ }
25290
+ return null;
25291
+ }
25292
+ function parseAlign(element) {
25293
+ const styleAlign = (element.style.textAlign || "").trim().toLowerCase();
25294
+ const attrAlign = (element.getAttribute("align") || "").trim().toLowerCase();
25295
+ const align = styleAlign || attrAlign;
25296
+ return normalizeTableCellAlign(align);
25297
+ }
25298
+ function normalizeTableCellAlignFromAttributes(attributes) {
25299
+ return normalizeTableCellAlign(attributes == null ? void 0 : attributes.align);
25300
+ }
25301
+ function createAlignAttribute() {
25302
+ return {
25303
+ default: null,
25304
+ parseHTML: (element) => parseAlign(element),
25305
+ renderHTML: (attributes) => {
25306
+ if (!attributes.align) {
25307
+ return {};
25308
+ }
25309
+ return {
25310
+ style: `text-align: ${attributes.align}`
25311
+ };
25312
+ }
25313
+ };
25314
+ }
25110
25315
  var TableCell = Node3.create({
25111
25316
  name: "tableCell",
25112
25317
  addOptions() {
@@ -25139,7 +25344,8 @@ var TableCell = Node3.create({
25139
25344
  }
25140
25345
  return value;
25141
25346
  }
25142
- }
25347
+ },
25348
+ align: createAlignAttribute()
25143
25349
  };
25144
25350
  },
25145
25351
  tableRole: "cell",
@@ -25174,7 +25380,8 @@ var TableHeader = Node3.create({
25174
25380
  const value = colwidth ? colwidth.split(",").map((width) => parseInt(width, 10)) : null;
25175
25381
  return value;
25176
25382
  }
25177
- }
25383
+ },
25384
+ align: createAlignAttribute()
25178
25385
  };
25179
25386
  },
25180
25387
  tableRole: "header_cell",
@@ -25402,7 +25609,8 @@ function renderTableToMarkdown(node, h2, options = {}) {
25402
25609
  }
25403
25610
  const text = collapseWhitespace(raw);
25404
25611
  const isHeader = cellNode.type === "tableHeader";
25405
- cells.push({ text, isHeader });
25612
+ const align = normalizeTableCellAlignFromAttributes(cellNode.attrs);
25613
+ cells.push({ text, isHeader, align });
25406
25614
  });
25407
25615
  }
25408
25616
  rows.push(cells);
@@ -25428,11 +25636,33 @@ function renderTableToMarkdown(node, h2, options = {}) {
25428
25636
  const pad = (s, width) => s + " ".repeat(Math.max(0, width - s.length));
25429
25637
  const headerRow = rows[0];
25430
25638
  const hasHeader = headerRow.some((c2) => c2.isHeader);
25639
+ const colAlignments = new Array(columnCount).fill(null);
25640
+ rows.forEach((r2) => {
25641
+ var _a2;
25642
+ for (let i = 0; i < columnCount; i += 1) {
25643
+ if (!colAlignments[i] && ((_a2 = r2[i]) == null ? void 0 : _a2.align)) {
25644
+ colAlignments[i] = r2[i].align;
25645
+ }
25646
+ }
25647
+ });
25431
25648
  let out = "\n";
25432
25649
  const headerTexts = new Array(columnCount).fill(0).map((_, i) => hasHeader ? headerRow[i] && headerRow[i].text || "" : "");
25433
25650
  out += `| ${headerTexts.map((t, i) => pad(t, colWidths[i])).join(" | ")} |
25434
25651
  `;
25435
- out += `| ${colWidths.map((w) => "-".repeat(Math.max(3, w))).join(" | ")} |
25652
+ out += `| ${colWidths.map((w, index) => {
25653
+ const dashCount = Math.max(3, w);
25654
+ const alignment = colAlignments[index];
25655
+ if (alignment === "left") {
25656
+ return `:${"-".repeat(dashCount)}`;
25657
+ }
25658
+ if (alignment === "right") {
25659
+ return `${"-".repeat(dashCount)}:`;
25660
+ }
25661
+ if (alignment === "center") {
25662
+ return `:${"-".repeat(dashCount)}:`;
25663
+ }
25664
+ return "-".repeat(dashCount);
25665
+ }).join(" | ")} |
25436
25666
  `;
25437
25667
  const body = hasHeader ? rows.slice(1) : rows;
25438
25668
  body.forEach((r2) => {
@@ -25486,18 +25716,27 @@ var Table = Node3.create({
25486
25716
  },
25487
25717
  parseMarkdown: (token, h2) => {
25488
25718
  const rows = [];
25719
+ const alignments = Array.isArray(token.align) ? token.align : [];
25489
25720
  if (token.header) {
25490
25721
  const headerCells = [];
25491
- token.header.forEach((cell) => {
25492
- headerCells.push(h2.createNode("tableHeader", {}, [{ type: "paragraph", content: h2.parseInline(cell.tokens) }]));
25722
+ token.header.forEach((cell, index) => {
25723
+ var _a;
25724
+ const align = normalizeTableCellAlign((_a = alignments[index]) != null ? _a : cell.align);
25725
+ const attrs = align ? { align } : {};
25726
+ headerCells.push(
25727
+ h2.createNode("tableHeader", attrs, [{ type: "paragraph", content: h2.parseInline(cell.tokens) }])
25728
+ );
25493
25729
  });
25494
25730
  rows.push(h2.createNode("tableRow", {}, headerCells));
25495
25731
  }
25496
25732
  if (token.rows) {
25497
25733
  token.rows.forEach((row) => {
25498
25734
  const bodyCells = [];
25499
- row.forEach((cell) => {
25500
- bodyCells.push(h2.createNode("tableCell", {}, [{ type: "paragraph", content: h2.parseInline(cell.tokens) }]));
25735
+ row.forEach((cell, index) => {
25736
+ var _a;
25737
+ const align = normalizeTableCellAlign((_a = alignments[index]) != null ? _a : cell.align);
25738
+ const attrs = align ? { align } : {};
25739
+ bodyCells.push(h2.createNode("tableCell", attrs, [{ type: "paragraph", content: h2.parseInline(cell.tokens) }]));
25501
25740
  });
25502
25741
  rows.push(h2.createNode("tableRow", {}, bodyCells));
25503
25742
  });
@@ -27298,7 +27537,7 @@ function LowlightPlugin({
27298
27537
  });
27299
27538
  return lowlightPlugin;
27300
27539
  }
27301
- var CodeBlockLowlight = index_default.extend({
27540
+ var CodeBlockLowlight = CodeBlock.extend({
27302
27541
  addOptions() {
27303
27542
  var _a;
27304
27543
  return {
@@ -42297,6 +42536,9 @@ class Toolbar {
42297
42536
  get trans() {
42298
42537
  return getTranslate();
42299
42538
  }
42539
+ icon(name) {
42540
+ return this.options.iconSet[name] ?? name;
42541
+ }
42300
42542
  render() {
42301
42543
  this.container.innerHTML = "";
42302
42544
  this.container.className = `md-toolbar md-toolbar-${this.options.mode}${this.options.sticky ? " md-toolbar-sticky" : ""}`;
@@ -42349,7 +42591,7 @@ class Toolbar {
42349
42591
  button.className = "md-toolbar-btn md-toolbar-toggle-btn";
42350
42592
  button.setAttribute("data-button", "togglemore");
42351
42593
  button.title = this.trans("More");
42352
- button.innerHTML = '<span class="md-toolbar-btn-icon">…</span>';
42594
+ button.innerHTML = `<span class="md-toolbar-btn-icon">${this.icon("togglemore")}</span>`;
42353
42595
  button.addEventListener("click", (e) => {
42354
42596
  e.preventDefault();
42355
42597
  this.toggleOverflow();
@@ -42372,43 +42614,43 @@ class Toolbar {
42372
42614
  }
42373
42615
  switch (name.toLowerCase()) {
42374
42616
  case "bold":
42375
- return this.createActionButton("bold", "B", this.trans("Bold"), () => {
42617
+ return this.createActionButton("bold", this.icon("bold"), this.trans("Bold"), () => {
42376
42618
  this.tiptap?.chain().focus().toggleBold().run();
42377
42619
  }, () => this.tiptap?.isActive("bold") ?? false);
42378
42620
  case "italic":
42379
- return this.createActionButton("italic", "I", this.trans("Italic"), () => {
42621
+ return this.createActionButton("italic", this.icon("italic"), this.trans("Italic"), () => {
42380
42622
  this.tiptap?.chain().focus().toggleItalic().run();
42381
42623
  }, () => this.tiptap?.isActive("italic") ?? false);
42382
42624
  case "underline":
42383
- return this.createActionButton("underline", "U", this.trans("Underline"), () => {
42625
+ return this.createActionButton("underline", this.icon("underline"), this.trans("Underline"), () => {
42384
42626
  this.tiptap?.chain().focus().toggleUnderline().run();
42385
42627
  }, () => this.tiptap?.isActive("underline") ?? false);
42386
42628
  case "strikethrough":
42387
- return this.createActionButton("strikethrough", "S", this.trans("Strikethrough"), () => {
42629
+ return this.createActionButton("strikethrough", this.icon("strikethrough"), this.trans("Strikethrough"), () => {
42388
42630
  this.tiptap?.chain().focus().toggleStrike().run();
42389
42631
  }, () => this.tiptap?.isActive("strike") ?? false);
42390
42632
  case "bullist":
42391
- return this.createActionButton("bullist", "", this.trans("Bullet list"), () => {
42633
+ return this.createActionButton("bullist", this.icon("bullist"), this.trans("Bullet list"), () => {
42392
42634
  this.tiptap?.chain().focus().toggleBulletList().run();
42393
42635
  }, () => this.tiptap?.isActive("bulletList") ?? false);
42394
42636
  case "numlist":
42395
- return this.createActionButton("numlist", "1.", this.trans("Numbered list"), () => {
42637
+ return this.createActionButton("numlist", this.icon("numlist"), this.trans("Numbered list"), () => {
42396
42638
  this.tiptap?.chain().focus().toggleOrderedList().run();
42397
42639
  }, () => this.tiptap?.isActive("orderedList") ?? false);
42398
42640
  case "outdent":
42399
- return this.createActionButton("outdent", "", this.trans("Decrease indent"), () => {
42641
+ return this.createActionButton("outdent", this.icon("outdent"), this.trans("Decrease indent"), () => {
42400
42642
  if (this.tiptap?.isActive("listItem")) {
42401
42643
  this.tiptap?.chain().focus().liftListItem("listItem").run();
42402
42644
  }
42403
42645
  });
42404
42646
  case "indent":
42405
- return this.createActionButton("indent", "", this.trans("Increase indent"), () => {
42647
+ return this.createActionButton("indent", this.icon("indent"), this.trans("Increase indent"), () => {
42406
42648
  if (this.tiptap?.isActive("listItem")) {
42407
42649
  this.tiptap?.chain().focus().sinkListItem("listItem").run();
42408
42650
  }
42409
42651
  });
42410
42652
  case "blockquote":
42411
- return this.createActionButton("blockquote", '"', this.trans("Blockquote"), () => {
42653
+ return this.createActionButton("blockquote", this.icon("blockquote"), this.trans("Blockquote"), () => {
42412
42654
  this.tiptap?.chain().focus().toggleBlockquote().run();
42413
42655
  }, () => this.tiptap?.isActive("blockquote") ?? false);
42414
42656
  case "fontfamily":
@@ -42418,19 +42660,19 @@ class Toolbar {
42418
42660
  case "lineheight":
42419
42661
  return this.createLineHeightDropdown();
42420
42662
  case "alignleft":
42421
- return this.createActionButton("alignleft", '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="15" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>', this.trans("Align left"), () => {
42663
+ return this.createActionButton("alignleft", this.icon("alignleft"), this.trans("Align left"), () => {
42422
42664
  this.tiptap?.chain().focus().setTextAlign("left").run();
42423
42665
  }, () => this.tiptap?.isActive({ textAlign: "left" }) ?? false);
42424
42666
  case "aligncenter":
42425
- return this.createActionButton("aligncenter", '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="3" y1="6" x2="21" y2="6"/><line x1="6" y1="12" x2="18" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>', this.trans("Align center"), () => {
42667
+ return this.createActionButton("aligncenter", this.icon("aligncenter"), this.trans("Align center"), () => {
42426
42668
  this.tiptap?.chain().focus().setTextAlign("center").run();
42427
42669
  }, () => this.tiptap?.isActive({ textAlign: "center" }) ?? false);
42428
42670
  case "alignright":
42429
- return this.createActionButton("alignright", '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="3" y1="6" x2="21" y2="6"/><line x1="9" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>', this.trans("Align right"), () => {
42671
+ return this.createActionButton("alignright", this.icon("alignright"), this.trans("Align right"), () => {
42430
42672
  this.tiptap?.chain().focus().setTextAlign("right").run();
42431
42673
  }, () => this.tiptap?.isActive({ textAlign: "right" }) ?? false);
42432
42674
  case "alignjustify":
42433
- return this.createActionButton("alignjustify", '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>', this.trans("Justify"), () => {
42675
+ return this.createActionButton("alignjustify", this.icon("alignjustify"), this.trans("Justify"), () => {
42434
42676
  this.tiptap?.chain().focus().setTextAlign("justify").run();
42435
42677
  }, () => this.tiptap?.isActive({ textAlign: "justify" }) ?? false);
42436
42678
  case "forecolor":
@@ -42442,71 +42684,71 @@ class Toolbar {
42442
42684
  this.tiptap?.chain().focus().setHighlight({ color }).run();
42443
42685
  });
42444
42686
  case "removeformat":
42445
- return this.createActionButton("removeformat", "", this.trans("Remove formatting"), () => {
42687
+ return this.createActionButton("removeformat", this.icon("removeformat"), this.trans("Remove formatting"), () => {
42446
42688
  this.tiptap?.chain().focus().unsetAllMarks().clearNodes().run();
42447
42689
  });
42448
42690
  case "copy":
42449
- return this.createActionButton("copy", "📋", this.trans("Copy"), () => {
42691
+ return this.createActionButton("copy", this.icon("copy"), this.trans("Copy"), () => {
42450
42692
  document.execCommand("copy");
42451
42693
  });
42452
42694
  case "cut":
42453
- return this.createActionButton("cut", "", this.trans("Cut"), () => {
42695
+ return this.createActionButton("cut", this.icon("cut"), this.trans("Cut"), () => {
42454
42696
  document.execCommand("cut");
42455
42697
  });
42456
42698
  case "paste":
42457
- return this.createActionButton("paste", "📄", this.trans("Paste"), () => {
42699
+ return this.createActionButton("paste", this.icon("paste"), this.trans("Paste"), () => {
42458
42700
  document.execCommand("paste");
42459
42701
  });
42460
42702
  case "undo":
42461
- return this.createActionButton("undo", "", this.trans("Undo"), () => {
42703
+ return this.createActionButton("undo", this.icon("undo"), this.trans("Undo"), () => {
42462
42704
  this.tiptap?.chain().focus().undo().run();
42463
42705
  });
42464
42706
  case "redo":
42465
- return this.createActionButton("redo", "", this.trans("Redo"), () => {
42707
+ return this.createActionButton("redo", this.icon("redo"), this.trans("Redo"), () => {
42466
42708
  this.tiptap?.chain().focus().redo().run();
42467
42709
  });
42468
42710
  case "image":
42469
- return this.createActionButton("image", '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>', this.trans("Insert image"), () => {
42711
+ return this.createActionButton("image", this.icon("image"), this.trans("Insert image"), () => {
42470
42712
  this.openImageDialog();
42471
42713
  });
42472
42714
  case "charmap":
42473
- return this.createActionButton("charmap", "Ω", this.trans("Special character"), () => {
42715
+ return this.createActionButton("charmap", this.icon("charmap"), this.trans("Special character"), () => {
42474
42716
  this.openCharMap();
42475
42717
  });
42476
42718
  case "emoticons":
42477
- return this.createActionButton("emoticons", "😀", this.trans("Emoticons"), () => {
42719
+ return this.createActionButton("emoticons", this.icon("emoticons"), this.trans("Emoticons"), () => {
42478
42720
  this.openEmojiPicker();
42479
42721
  });
42480
42722
  case "fullscreen":
42481
- return this.createActionButton("fullscreen", "", this.trans("Fullscreen"), () => {
42723
+ return this.createActionButton("fullscreen", this.icon("fullscreen"), this.trans("Fullscreen"), () => {
42482
42724
  this.toggleFullscreen();
42483
42725
  }, () => this.state.isFullscreen);
42484
42726
  case "preview":
42485
- return this.createActionButton("preview", "👁", this.trans("Preview"), () => {
42727
+ return this.createActionButton("preview", this.icon("preview"), this.trans("Preview"), () => {
42486
42728
  this.openPreview();
42487
42729
  });
42488
42730
  case "code":
42489
- return this.createActionButton("code", '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>', this.trans("Source code"), () => {
42731
+ return this.createActionButton("code", this.icon("code"), this.trans("Source code"), () => {
42490
42732
  this.openSourceCode();
42491
42733
  });
42492
42734
  case "link":
42493
- return this.createActionButton("link", "🔗", this.trans("Insert link"), () => {
42735
+ return this.createActionButton("link", this.icon("link"), this.trans("Insert link"), () => {
42494
42736
  this.openLinkDialog();
42495
42737
  }, () => this.tiptap?.isActive("link") ?? false);
42496
42738
  case "codesample":
42497
- return this.createActionButton("codesample", "{}", this.trans("Code sample"), () => {
42739
+ return this.createActionButton("codesample", this.icon("codesample"), this.trans("Code sample"), () => {
42498
42740
  this.tiptap?.chain().focus().toggleCodeBlock().run();
42499
42741
  }, () => this.tiptap?.isActive("codeBlock") ?? false);
42500
42742
  case "ltr":
42501
- return this.createActionButton("ltr", "", this.trans("Left to right"), () => {
42743
+ return this.createActionButton("ltr", this.icon("ltr"), this.trans("Left to right"), () => {
42502
42744
  this.tiptap?.chain().focus().setTextDirection("ltr").run();
42503
42745
  });
42504
42746
  case "rtl":
42505
- return this.createActionButton("rtl", "", this.trans("Right to left"), () => {
42747
+ return this.createActionButton("rtl", this.icon("rtl"), this.trans("Right to left"), () => {
42506
42748
  this.tiptap?.chain().focus().setTextDirection("rtl").run();
42507
42749
  });
42508
42750
  case "searchreplace":
42509
- return this.createActionButton("searchreplace", "🔍", this.trans("Find and replace"), () => {
42751
+ return this.createActionButton("searchreplace", this.icon("searchreplace"), this.trans("Find and replace"), () => {
42510
42752
  this.openSearchReplace();
42511
42753
  });
42512
42754
  case "template":
@@ -42982,6 +43224,78 @@ class Toolbar {
42982
43224
  this.container.innerHTML = "";
42983
43225
  }
42984
43226
  }
43227
+ const SVG_ALIGN_LEFT = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="15" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>';
43228
+ const SVG_ALIGN_CENTER = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="3" y1="6" x2="21" y2="6"/><line x1="6" y1="12" x2="18" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>';
43229
+ const SVG_ALIGN_RIGHT = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="3" y1="6" x2="21" y2="6"/><line x1="9" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>';
43230
+ const SVG_ALIGN_JUSTIFY = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>';
43231
+ const SVG_IMAGE = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>';
43232
+ const SVG_CODE = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>';
43233
+ const DEFAULT_ICONS = {
43234
+ bold: "B",
43235
+ italic: "I",
43236
+ underline: "U",
43237
+ strikethrough: "S",
43238
+ bullist: "•",
43239
+ numlist: "1.",
43240
+ outdent: "←",
43241
+ indent: "→",
43242
+ blockquote: '"',
43243
+ alignleft: SVG_ALIGN_LEFT,
43244
+ aligncenter: SVG_ALIGN_CENTER,
43245
+ alignright: SVG_ALIGN_RIGHT,
43246
+ alignjustify: SVG_ALIGN_JUSTIFY,
43247
+ removeformat: "✕",
43248
+ copy: "📋",
43249
+ cut: "✂",
43250
+ paste: "📄",
43251
+ undo: "↩",
43252
+ redo: "↪",
43253
+ image: SVG_IMAGE,
43254
+ charmap: "Ω",
43255
+ emoticons: "😀",
43256
+ fullscreen: "⛶",
43257
+ preview: "👁",
43258
+ code: SVG_CODE,
43259
+ link: "🔗",
43260
+ codesample: "{}",
43261
+ ltr: "⇐",
43262
+ rtl: "⇒",
43263
+ searchreplace: "🔍",
43264
+ togglemore: "…"
43265
+ };
43266
+ const CONFAB_ICONS = {
43267
+ bold: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"/><path d="M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"/></svg>',
43268
+ italic: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="19" y1="4" x2="10" y2="4"/><line x1="14" y1="20" x2="5" y2="20"/><line x1="15" y1="4" x2="9" y2="20"/></svg>',
43269
+ underline: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 3v7a6 6 0 0 0 6 6 6 6 0 0 0 6-6V3"/><line x1="4" y1="21" x2="20" y2="21"/></svg>',
43270
+ strikethrough: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 4c-1.5-1-3.2-1.5-5-1.5C7.7 2.5 5 4.6 5 7.5c0 1.5.7 2.7 1.8 3.5"/><path d="M8 20c1.5 1 3.2 1.5 5 1.5 3.3 0 6-2.1 6-5 0-1.5-.7-2.7-1.8-3.5"/><line x1="2" y1="12" x2="22" y2="12"/></svg>',
43271
+ bullist: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="9" y1="6" x2="20" y2="6"/><line x1="9" y1="12" x2="20" y2="12"/><line x1="9" y1="18" x2="20" y2="18"/><circle cx="5" cy="6" r="1" fill="currentColor" stroke="none"/><circle cx="5" cy="12" r="1" fill="currentColor" stroke="none"/><circle cx="5" cy="18" r="1" fill="currentColor" stroke="none"/></svg>',
43272
+ numlist: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><text x="3" y="8" font-size="7" fill="currentColor" stroke="none" font-family="sans-serif">1</text><text x="3" y="14" font-size="7" fill="currentColor" stroke="none" font-family="sans-serif">2</text><text x="3" y="20" font-size="7" fill="currentColor" stroke="none" font-family="sans-serif">3</text></svg>',
43273
+ outdent: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" y1="4" x2="21" y2="4"/><line x1="3" y1="20" x2="21" y2="20"/><line x1="11" y1="9" x2="21" y2="9"/><line x1="11" y1="15" x2="21" y2="15"/><polyline points="7 9 3 12 7 15"/></svg>',
43274
+ indent: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" y1="4" x2="21" y2="4"/><line x1="3" y1="20" x2="21" y2="20"/><line x1="11" y1="9" x2="21" y2="9"/><line x1="11" y1="15" x2="21" y2="15"/><polyline points="3 9 7 12 3 15"/></svg>',
43275
+ blockquote: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 21c3 0 7-1 7-8V5c0-1.25-.76-2.02-2-2H4c-1.25 0-2 .76-2 2v6c0 1.25.76 2 2 2h4.5c-1 2-3.5 3.5-5.5 3.5"/><path d="M15 21c3 0 7-1 7-8V5c0-1.25-.76-2.02-2-2h-4c-1.25 0-2 .76-2 2v6c0 1.25.76 2 2 2h4.5c-1 2-3.5 3.5-5.5 3.5"/></svg>',
43276
+ alignleft: SVG_ALIGN_LEFT,
43277
+ aligncenter: SVG_ALIGN_CENTER,
43278
+ alignright: SVG_ALIGN_RIGHT,
43279
+ alignjustify: SVG_ALIGN_JUSTIFY,
43280
+ removeformat: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h11l-3 14"/><line x1="4" y1="7" x2="9" y2="3"/><line x1="18" y1="4" x2="22" y2="8"/><line x1="18" y1="8" x2="22" y2="4"/></svg>',
43281
+ copy: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>',
43282
+ cut: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><line x1="20" y1="4" x2="8.1" y2="15.9"/><line x1="14.5" y1="9.5" x2="20" y2="4"/><line x1="8.1" y1="8.1" x2="20" y2="20"/></svg>',
43283
+ paste: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><rect x="8" y="2" width="8" height="4" rx="1"/></svg>',
43284
+ undo: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="1 4 1 10 7 10"/><path d="M3.5 14a9 9 0 1 0 2.2-5.8L1 10"/></svg>',
43285
+ redo: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"/><path d="M20.5 14a9 9 0 1 1-2.2-5.8L23 10"/></svg>',
43286
+ image: SVG_IMAGE,
43287
+ charmap: "Ω",
43288
+ emoticons: "😀",
43289
+ fullscreen: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>',
43290
+ preview: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>',
43291
+ code: SVG_CODE,
43292
+ link: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.5.5l3-3a5 5 0 0 0-7.1-7.1l-1.7 1.7"/><path d="M14 11a5 5 0 0 0-7.5-.5l-3 3a5 5 0 0 0 7.1 7.1l1.7-1.7"/></svg>',
43293
+ codesample: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5a2 2 0 0 0 2 2h1"/><path d="M16 3h1a2 2 0 0 1 2 2v5a2 2 0 0 0 2 2 2 2 0 0 0-2 2v5a2 2 0 0 1-2 2h-1"/></svg>',
43294
+ ltr: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="18" y1="5" x2="18" y2="19"/><path d="M8 5a4 4 0 0 0 0 8h4"/><polyline points="4 17 8 21 12 17"/></svg>',
43295
+ rtl: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="6" y1="5" x2="6" y2="19"/><path d="M16 5a4 4 0 0 1 0 8h-4"/><polyline points="20 17 16 21 12 17"/></svg>',
43296
+ searchreplace: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.6" y2="16.6"/></svg>',
43297
+ togglemore: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="1" fill="currentColor"/><circle cx="5" cy="12" r="1" fill="currentColor"/><circle cx="19" cy="12" r="1" fill="currentColor"/></svg>'
43298
+ };
42985
43299
  const FontSize = Extension.create({
42986
43300
  name: "fontSize",
42987
43301
  addOptions() {
@@ -43109,6 +43423,30 @@ const TextDirection = Extension.create({
43109
43423
  };
43110
43424
  }
43111
43425
  });
43426
+ const SignatureBlock = Node3.create({
43427
+ name: "signatureBlock",
43428
+ group: "block",
43429
+ content: "block+",
43430
+ defining: true,
43431
+ isolating: true,
43432
+ addAttributes() {
43433
+ return {
43434
+ id: {
43435
+ default: "signature"
43436
+ }
43437
+ };
43438
+ },
43439
+ parseHTML() {
43440
+ return [
43441
+ {
43442
+ tag: 'div[id="signature"]'
43443
+ }
43444
+ ];
43445
+ },
43446
+ renderHTML({ HTMLAttributes }) {
43447
+ return ["div", mergeAttributes(HTMLAttributes), 0];
43448
+ }
43449
+ });
43112
43450
  const en = {
43113
43451
  "Bold": "Bold",
43114
43452
  "Italic": "Italic",
@@ -45240,6 +45578,8 @@ class HTMLEditor {
45240
45578
  directionality: config.directionality ?? "ltr",
45241
45579
  language: config.language ?? "en",
45242
45580
  height: config.height ?? 300,
45581
+ min_height: config.min_height,
45582
+ max_height: config.max_height,
45243
45583
  auto_focus: config.auto_focus,
45244
45584
  setFocus: config.setFocus,
45245
45585
  skin: config.skin ?? "oxide",
@@ -45276,6 +45616,20 @@ class HTMLEditor {
45276
45616
  this.editorWrapper.style.height = this.config.height;
45277
45617
  }
45278
45618
  }
45619
+ if (this.config.min_height) {
45620
+ if (typeof this.config.min_height === "number") {
45621
+ this.editorWrapper.style.minHeight = `${this.config.min_height}px`;
45622
+ } else {
45623
+ this.editorWrapper.style.minHeight = this.config.min_height;
45624
+ }
45625
+ }
45626
+ if (this.config.max_height) {
45627
+ if (typeof this.config.max_height === "number") {
45628
+ this.editorWrapper.style.maxHeight = `${this.config.max_height}px`;
45629
+ } else {
45630
+ this.editorWrapper.style.maxHeight = this.config.max_height;
45631
+ }
45632
+ }
45279
45633
  const toolbarContainer = document.createElement("div");
45280
45634
  toolbarContainer.className = "md-editor-toolbar";
45281
45635
  this.editorWrapper.appendChild(toolbarContainer);
@@ -45314,13 +45668,15 @@ class HTMLEditor {
45314
45668
  }
45315
45669
  };
45316
45670
  this.tiptap = new Editor(editorOptions);
45671
+ const iconSet = this.config.skin?.startsWith("confab") ? CONFAB_ICONS : DEFAULT_ICONS;
45317
45672
  this.toolbar = new Toolbar(toolbarContainer, {
45318
45673
  editor: this,
45319
45674
  buttons: this.config.toolbar ?? BASIC_TOOLBAR,
45320
45675
  mode: this.config.toolbar_mode ?? "sliding",
45321
45676
  sticky: this.config.toolbar_sticky ?? true,
45322
45677
  customButtons: this.customButtons,
45323
- config: this.config
45678
+ config: this.config,
45679
+ iconSet
45324
45680
  });
45325
45681
  if (this.config.auto_focus) {
45326
45682
  setTimeout(() => this.focus(), 10);
@@ -45403,6 +45759,7 @@ class HTMLEditor {
45403
45759
  codeBlock: false
45404
45760
  // We use CodeBlockLowlight instead
45405
45761
  }),
45762
+ SignatureBlock,
45406
45763
  Underline,
45407
45764
  TextStyle,
45408
45765
  FontFamily,
@@ -45641,13 +45998,16 @@ class HTMLEditor {
45641
45998
  }
45642
45999
  }
45643
46000
  exports.CHAR_MAP = CHAR_MAP;
46001
+ exports.CONFAB_ICONS = CONFAB_ICONS;
45644
46002
  exports.CharacterMap = CharacterMap;
46003
+ exports.DEFAULT_ICONS = DEFAULT_ICONS;
45645
46004
  exports.EMOJI_CATEGORIES = EMOJI_CATEGORIES;
45646
46005
  exports.EmojiPicker = EmojiPicker;
45647
46006
  exports.FontSize = FontSize;
45648
46007
  exports.HTMLEditor = HTMLEditor;
45649
46008
  exports.LineHeight = LineHeight;
45650
46009
  exports.SearchReplace = SearchReplace;
46010
+ exports.SignatureBlock = SignatureBlock;
45651
46011
  exports.TRANSLATION_KEYS = TRANSLATION_KEYS;
45652
46012
  exports.TextDirection = TextDirection;
45653
46013
  exports.Toolbar = Toolbar;