@cyberyozh/text-editor 0.1.7 → 0.1.9

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 (36) hide show
  1. package/dist/editor.css +12 -2
  2. package/dist/editor.css.map +1 -1
  3. package/dist/editor.d.mts +1 -0
  4. package/dist/editor.d.ts +1 -0
  5. package/dist/editor.js +202 -139
  6. package/dist/editor.js.map +1 -1
  7. package/dist/editor.mjs +200 -137
  8. package/dist/editor.mjs.map +1 -1
  9. package/dist/render.js +76 -11
  10. package/dist/render.js.map +1 -1
  11. package/dist/render.mjs +76 -11
  12. package/dist/render.mjs.map +1 -1
  13. package/dist/styles/index.css +12 -2
  14. package/package.json +2 -4
  15. package/src/editor/controls/bubble-menu-content.tsx +4 -8
  16. package/src/editor/controls/callout-menu.tsx +2 -0
  17. package/src/editor/controls/drag-handle.tsx +6 -1
  18. package/src/editor/dialogs/add-link-dialog/add-link-dialog.css +12 -4
  19. package/src/editor/dialogs/add-link-dialog/add-link-dialog.tsx +65 -28
  20. package/src/editor/dialogs/image-dialog/image-dialog.tsx +1 -1
  21. package/src/editor/editor.tsx +19 -12
  22. package/src/editor/handlers/dialog-handlers.ts +87 -156
  23. package/src/editor/handlers/index.ts +1 -2
  24. package/src/extensions/base/compatibility.ts +52 -0
  25. package/src/extensions/base/figure.ts +7 -0
  26. package/src/extensions/base/link.ts +3 -3
  27. package/src/extensions/views/components/table.tsx +23 -4
  28. package/src/extensions/views/node-views/figure.tsx +1 -1
  29. package/src/render/static-renderer-config.tsx +1 -17
  30. package/src/styles/editor/base.css +1 -1
  31. package/src/styles/extensions/callout.css +1 -1
  32. package/src/translations/en.json +5 -1
  33. package/src/translations/ru.json +5 -1
  34. package/src/types/image-handler.ts +2 -0
  35. package/src/types/link.ts +9 -0
  36. package/src/editor/handlers/create-image-upload-handler.ts +0 -24
package/dist/editor.mjs CHANGED
@@ -780,12 +780,8 @@ var BubbleMenuContent = ({ editor, onLinkClick }) => {
780
780
  editor.state.selection.$from.pos,
781
781
  editor.state.selection.$to.pos
782
782
  );
783
- let linkUrl;
784
- if (isLink) {
785
- const link = editor.getAttributes("link");
786
- linkUrl = link.href;
787
- }
788
- onLinkClick?.(selectedText, linkUrl);
783
+ const linkAttrs = editor.getAttributes("link");
784
+ onLinkClick?.({ title: selectedText, ...linkAttrs });
789
785
  openDialogCommand("link");
790
786
  };
791
787
  return /* @__PURE__ */ jsxs10(
@@ -1243,7 +1239,7 @@ var CalloutMenu = ({ isOpen, onClose, onColorSelect, editor, nodePos }) => {
1243
1239
  const b = parseInt(bgColor.slice(5, 7), 16);
1244
1240
  const brightness = (r * 299 + g * 587 + b * 114) / 1e3;
1245
1241
  const textColor = brightness > 128 ? "#000000" : "#FFFFFF";
1246
- editor.chain().setTextSelection({ from, to }).setColor(textColor).setNodeSelection(nodePos).updateAttributes("callout", { bgColor }).run();
1242
+ editor.chain().setTextSelection({ from, to }).setColor(textColor).setNodeSelection(nodePos).updateAttributes("callout", { bgColor }).updateAttributes("calloutTip", { bgColor }).updateAttributes("calloutAlert", { bgColor }).run();
1247
1243
  }
1248
1244
  }
1249
1245
  },
@@ -1277,7 +1273,7 @@ var DragHandle = ({ editor }) => {
1277
1273
  currentNodePosRef.current = pos;
1278
1274
  try {
1279
1275
  const node = editor.view.state.doc.nodeAt(pos);
1280
- const isCallout = node?.type.name === "callout";
1276
+ const isCallout = node?.type.name === "callout" || node?.type.name === "calloutAlert" || node?.type.name === "calloutTip";
1281
1277
  setIsCalloutNode(isCallout);
1282
1278
  if (prevPos !== null && prevPos !== pos) {
1283
1279
  setShowCalloutMenu(false);
@@ -1305,7 +1301,7 @@ var DragHandle = ({ editor }) => {
1305
1301
  if (node) {
1306
1302
  const from = pos + 1;
1307
1303
  const to = pos + node.nodeSize - 1;
1308
- editor.chain().setTextSelection({ from, to }).setColor(textColor).setNodeSelection(pos).updateAttributes("callout", { bgColor }).run();
1304
+ editor.chain().setTextSelection({ from, to }).setColor(textColor).setNodeSelection(pos).updateAttributes("callout", { bgColor }).updateAttributes("calloutTip", { bgColor }).updateAttributes("calloutAlert", { bgColor }).run();
1309
1305
  }
1310
1306
  setShowCalloutMenu(false);
1311
1307
  }
@@ -1974,7 +1970,8 @@ var ImageDialog = ({
1974
1970
  title: formState.title,
1975
1971
  caption: formState.caption,
1976
1972
  width: formState.width,
1977
- height: formState.height
1973
+ height: formState.height,
1974
+ storageKey: result.storageKey
1978
1975
  });
1979
1976
  handleClose();
1980
1977
  } finally {
@@ -2226,24 +2223,32 @@ var AddLinkDialog = ({
2226
2223
  open,
2227
2224
  onClose,
2228
2225
  onLinkAdd,
2229
- initialTitle = "",
2230
- initialUrl = ""
2226
+ linkDialogContext
2231
2227
  }) => {
2232
2228
  const translations2 = useTiptapTranslations();
2233
- const [title, setTitle] = useState8(initialTitle);
2234
- const [url, setUrl] = useState8(initialUrl);
2229
+ const initialLinkTarget = linkDialogContext?.target ? linkDialogContext.target === "_blank" : true;
2230
+ const initialLinkRel = linkDialogContext?.rel ? linkDialogContext.rel?.includes("noopener") : true;
2231
+ const [title, setTitle] = useState8(linkDialogContext?.title);
2232
+ const [url, setUrl] = useState8(linkDialogContext?.href);
2233
+ const [openInNewTab, setOpenInNewTab] = useState8(initialLinkTarget);
2234
+ const [addNoopener, setAddNoopener] = useState8(initialLinkRel);
2235
2235
  const [error, setError] = useState8("");
2236
2236
  const titleInputRef = useRef8(null);
2237
+ const clearDialogState = () => {
2238
+ setTitle(linkDialogContext?.title);
2239
+ setUrl(linkDialogContext?.href);
2240
+ setOpenInNewTab(initialLinkTarget);
2241
+ setAddNoopener(initialLinkRel);
2242
+ setError("");
2243
+ };
2237
2244
  useEffect6(() => {
2238
2245
  if (open) {
2239
- setTitle(initialTitle);
2240
- setUrl(initialUrl);
2241
- setError("");
2246
+ clearDialogState();
2242
2247
  setTimeout(() => {
2243
2248
  titleInputRef.current?.focus();
2244
2249
  }, 0);
2245
2250
  }
2246
- }, [open, initialTitle, initialUrl]);
2251
+ }, [open, linkDialogContext]);
2247
2252
  const validateUrl = (urlStr) => {
2248
2253
  if (!urlStr.trim()) {
2249
2254
  setError(translations2.link.emptyUrl);
@@ -2269,22 +2274,22 @@ var AddLinkDialog = ({
2269
2274
  };
2270
2275
  const handleSubmit = () => {
2271
2276
  setError("");
2272
- if (!title.trim()) {
2277
+ if (!title?.trim()) {
2273
2278
  setError(translations2.link.titleError);
2274
2279
  return;
2275
2280
  }
2276
- if (!validateUrl(url)) {
2281
+ if (!validateUrl(url ?? "")) {
2277
2282
  return;
2278
2283
  }
2279
- const hasProtocol = url.includes("://") || url.startsWith("mailto:") || url.startsWith("tel:");
2284
+ const hasProtocol = url?.includes("://") || url?.startsWith("mailto:") || url?.startsWith("tel:");
2280
2285
  const finalUrl = hasProtocol ? url : `https://${url}`;
2281
- onLinkAdd(title, finalUrl);
2286
+ const target = openInNewTab ? "_blank" : "_self";
2287
+ const rel = addNoopener ? "noopener noreferrer nofollow" : null;
2288
+ onLinkAdd({ title, href: finalUrl ?? "", target, rel });
2282
2289
  handleClose();
2283
2290
  };
2284
2291
  const handleClose = () => {
2285
- setTitle(initialTitle);
2286
- setUrl(initialUrl);
2287
- setError("");
2292
+ clearDialogState();
2288
2293
  onClose();
2289
2294
  };
2290
2295
  const handleKeyDown = (e) => {
@@ -2299,7 +2304,7 @@ var AddLinkDialog = ({
2299
2304
  open,
2300
2305
  handleClose,
2301
2306
  children: [
2302
- /* @__PURE__ */ jsx69("p", { className: "link-dialog-title", children: initialUrl ? translations2.link.editLink : translations2.link.addLink }),
2307
+ /* @__PURE__ */ jsx69("p", { className: "link-dialog-title", children: linkDialogContext?.href ? translations2.link.editLink : translations2.link.addLink }),
2303
2308
  /* @__PURE__ */ jsx69("hr", { className: "link-dialog-divider" }),
2304
2309
  /* @__PURE__ */ jsxs20("div", { className: "link-dialog-content", children: [
2305
2310
  /* @__PURE__ */ jsxs20("div", { className: "link-dialog-form-group", children: [
@@ -2341,12 +2346,40 @@ var AddLinkDialog = ({
2341
2346
  type: "text",
2342
2347
  className: "link-dialog-input",
2343
2348
  placeholder: translations2.link.urlPlaceholder,
2344
- value: url,
2349
+ value: url ?? "",
2345
2350
  onChange: (e) => setUrl(e.target.value),
2346
2351
  onKeyDown: handleKeyDown
2347
2352
  }
2348
2353
  )
2349
2354
  ] }),
2355
+ /* @__PURE__ */ jsxs20("div", { className: "link-dialog-form-group", children: [
2356
+ /* @__PURE__ */ jsxs20("label", { className: "link-dialog-checkbox-label", children: [
2357
+ /* @__PURE__ */ jsx69(
2358
+ "input",
2359
+ {
2360
+ type: "checkbox",
2361
+ checked: openInNewTab,
2362
+ onChange: (e) => setOpenInNewTab(e.target.checked)
2363
+ }
2364
+ ),
2365
+ /* @__PURE__ */ jsx69("span", { children: translations2.link.openInNewTab })
2366
+ ] }),
2367
+ /* @__PURE__ */ jsx69("p", { className: "link-dialog-help-text", children: translations2.link.openInNewTabHelp })
2368
+ ] }),
2369
+ /* @__PURE__ */ jsxs20("div", { className: "link-dialog-form-group", children: [
2370
+ /* @__PURE__ */ jsxs20("label", { className: "link-dialog-checkbox-label", children: [
2371
+ /* @__PURE__ */ jsx69(
2372
+ "input",
2373
+ {
2374
+ type: "checkbox",
2375
+ checked: addNoopener,
2376
+ onChange: (e) => setAddNoopener(e.target.checked)
2377
+ }
2378
+ ),
2379
+ /* @__PURE__ */ jsx69("span", { children: translations2.link.addNofollow })
2380
+ ] }),
2381
+ /* @__PURE__ */ jsx69("p", { className: "link-dialog-help-text", children: translations2.link.addNofollowHelp })
2382
+ ] }),
2350
2383
  error && /* @__PURE__ */ jsx69("div", { className: "link-dialog-error", children: error })
2351
2384
  ] }),
2352
2385
  /* @__PURE__ */ jsxs20("div", { className: "link-dialog-actions", children: [
@@ -2365,7 +2398,7 @@ var AddLinkDialog = ({
2365
2398
  className: "link-dialog-button-submit",
2366
2399
  onClick: handleSubmit,
2367
2400
  type: "button",
2368
- children: initialUrl ? translations2.link.editLink : translations2.link.addLink
2401
+ children: linkDialogContext?.href ? translations2.link.editLink : translations2.link.addLink
2369
2402
  }
2370
2403
  )
2371
2404
  ] })
@@ -3212,6 +3245,13 @@ var BaseFigure = Image2.extend({
3212
3245
  caption: {
3213
3246
  default: null,
3214
3247
  parseHTML: (element) => element.querySelector("figcaption")?.textContent || null
3248
+ },
3249
+ storageKey: {
3250
+ default: null,
3251
+ parseHTML: (element) => element.getAttribute("data-storage-key"),
3252
+ renderHTML: (attributes) => ({
3253
+ "data-storage-key": attributes.storageKey
3254
+ })
3215
3255
  }
3216
3256
  };
3217
3257
  },
@@ -3302,6 +3342,32 @@ var BaseLegacyBookAlert = Node6.create({
3302
3342
  return {
3303
3343
  type: {
3304
3344
  default: "error"
3345
+ },
3346
+ bgColor: {
3347
+ default: null,
3348
+ parseHTML: (element) => {
3349
+ if (typeof element === "string") return null;
3350
+ return element.getAttribute("data-bg-color");
3351
+ },
3352
+ renderHTML: (attributes) => {
3353
+ if (!attributes.bgColor) return {};
3354
+ return {
3355
+ "data-bg-color": attributes.bgColor
3356
+ };
3357
+ }
3358
+ },
3359
+ emoji: {
3360
+ default: null,
3361
+ parseHTML: (element) => {
3362
+ if (typeof element === "string") return null;
3363
+ return element.getAttribute("data-emoji");
3364
+ },
3365
+ renderHTML: (attributes) => {
3366
+ if (!attributes.emoji) return {};
3367
+ return {
3368
+ "data-emoji": attributes.emoji
3369
+ };
3370
+ }
3305
3371
  }
3306
3372
  };
3307
3373
  },
@@ -3331,6 +3397,32 @@ var BaseLegacyBookTip = Node6.create({
3331
3397
  return {
3332
3398
  type: {
3333
3399
  default: "info"
3400
+ },
3401
+ bgColor: {
3402
+ default: null,
3403
+ parseHTML: (element) => {
3404
+ if (typeof element === "string") return null;
3405
+ return element.getAttribute("data-bg-color");
3406
+ },
3407
+ renderHTML: (attributes) => {
3408
+ if (!attributes.bgColor) return {};
3409
+ return {
3410
+ "data-bg-color": attributes.bgColor
3411
+ };
3412
+ }
3413
+ },
3414
+ emoji: {
3415
+ default: null,
3416
+ parseHTML: (element) => {
3417
+ if (typeof element === "string") return null;
3418
+ return element.getAttribute("data-emoji");
3419
+ },
3420
+ renderHTML: (attributes) => {
3421
+ if (!attributes.emoji) return {};
3422
+ return {
3423
+ "data-emoji": attributes.emoji
3424
+ };
3425
+ }
3334
3426
  }
3335
3427
  };
3336
3428
  },
@@ -4462,7 +4554,7 @@ var CustomQuoteSignView = (props) => {
4462
4554
  import { NodeViewWrapper as NodeViewWrapper4 } from "@tiptap/react";
4463
4555
  import { jsx as jsx89 } from "react/jsx-runtime";
4464
4556
  var FigureView = ({ node, getPos, editor }) => {
4465
- const { fileId, src, alt, title, caption, width, height } = node.attrs;
4557
+ const { fileId, src, alt, title, caption, width, height, storageKey } = node.attrs;
4466
4558
  const imageExtension = editor.extensionManager.extensions.find((ext) => ext.name === "image");
4467
4559
  const getImageById = imageExtension?.options.getImageById;
4468
4560
  const onFigureClick = imageExtension?.options.onFigureClick;
@@ -5129,31 +5221,24 @@ function getEditorExtensions(options) {
5129
5221
  }
5130
5222
 
5131
5223
  // src/editor/handlers/dialog-handlers.ts
5224
+ import { TextSelection as TextSelection5 } from "@tiptap/pm/state";
5132
5225
  var createHandleImageAdd = (editor, closeDialogCommand, savedPos) => {
5133
5226
  return (attrs) => {
5134
5227
  if (!editor) return;
5135
5228
  const { state } = editor;
5136
- const { $from } = state.selection;
5137
- const text = $from.parent.textContent;
5138
- if (text.lastIndexOf("/") !== -1) {
5139
- editor.chain().focus().command(({ tr }) => {
5140
- const node = editor.schema.nodes.image.create({ ...attrs });
5141
- tr.replaceWith($from.before(), $from.after(), node);
5142
- return true;
5143
- }).scrollIntoView().run();
5144
- } else {
5145
- const insertPos = savedPos ?? state.selection.from;
5146
- editor.chain().focus().command(({ tr, state: state2 }) => {
5147
- const $pos = state2.doc.resolve(insertPos);
5148
- const figureNode = state2.schema.nodes.figure.create({ ...attrs });
5149
- if ($pos.parent.type.name === "paragraph" && $pos.parent.textContent === "") {
5150
- tr.replaceWith($pos.before(), $pos.after(), figureNode);
5151
- } else {
5152
- tr.insert(insertPos, figureNode);
5153
- }
5154
- return true;
5155
- }).scrollIntoView().run();
5156
- }
5229
+ const insertPos = savedPos ?? state.selection.from;
5230
+ editor.chain().focus().command(({ tr, state: state2 }) => {
5231
+ const $pos = state2.doc.resolve(insertPos);
5232
+ const imageNode = state2.schema.nodes.image.create({ ...attrs });
5233
+ if ($pos.parent.type.name === "paragraph" && $pos.parent.textContent === "") {
5234
+ tr.replaceWith($pos.before(), $pos.after(), imageNode);
5235
+ tr.setSelection(TextSelection5.near(tr.doc.resolve($pos.before())));
5236
+ } else {
5237
+ tr.insert(insertPos, imageNode);
5238
+ tr.setSelection(TextSelection5.near(tr.doc.resolve(insertPos)));
5239
+ }
5240
+ return true;
5241
+ }).run();
5157
5242
  closeDialogCommand();
5158
5243
  };
5159
5244
  };
@@ -5168,69 +5253,47 @@ var createHandleVideoAdd = (editor, closeDialogCommand, savedPos) => {
5168
5253
  return (url) => {
5169
5254
  if (!editor) return;
5170
5255
  const { state } = editor;
5171
- const { $from } = state.selection;
5172
- const text = $from.parent.textContent;
5173
- if (text.lastIndexOf("/") !== -1) {
5174
- editor.chain().focus().command(({ tr }) => {
5175
- tr.replaceWith(
5176
- $from.before(),
5177
- $from.after(),
5178
- editor.schema.nodes.video.create({ src: url })
5179
- );
5180
- return true;
5181
- }).scrollIntoView().run();
5182
- } else {
5183
- const insertPos = savedPos ?? state.selection.from;
5184
- editor.chain().focus().command(({ tr, state: state2 }) => {
5185
- const $pos = state2.doc.resolve(insertPos);
5186
- const videoNode = state2.schema.nodes.video.create({ src: url });
5187
- if ($pos.parent.type.name === "paragraph" && $pos.parent.textContent === "") {
5188
- tr.replaceWith($pos.before(), $pos.after(), videoNode);
5189
- } else {
5190
- tr.insert(insertPos, videoNode);
5191
- }
5192
- return true;
5193
- }).scrollIntoView().run();
5194
- }
5195
- closeDialogCommand();
5196
- };
5197
- };
5198
- var createHandleLinkAdd = (editor, closeDialogCommand, savedPos) => {
5199
- return (title, url) => {
5200
- if (!editor) return;
5201
- const hasSelection = !editor.state.selection.empty;
5202
- if (hasSelection) {
5203
- editor.chain().focus().command(({ tr, state }) => {
5204
- const { from, to } = state.selection;
5205
- tr.insertText(title, from, to);
5206
- tr.addMark(from, from + title.length, editor.schema.marks.link.create({ href: url }));
5207
- return true;
5208
- }).run();
5209
- } else {
5210
- const { state } = editor;
5211
- const { $from } = state.selection;
5212
- const text = $from.parent.textContent;
5213
- const nodeStart = $from.start();
5214
- const beforeCursor = text.substring(0, $from.pos - nodeStart);
5215
- const slashIndex = beforeCursor.lastIndexOf("/");
5216
- if (slashIndex !== -1) {
5217
- editor.chain().focus().command(({ tr }) => {
5218
- tr.delete(nodeStart + slashIndex, $from.pos);
5219
- return true;
5220
- }).extendMarkRange("link").setLink({ href: url }).insertContent(title).scrollIntoView().run();
5256
+ const insertPos = savedPos ?? state.selection.from;
5257
+ editor.chain().focus().command(({ tr, state: state2 }) => {
5258
+ const $pos = state2.doc.resolve(insertPos);
5259
+ const videoNode = state2.schema.nodes.video.create({ src: url });
5260
+ if ($pos.parent.type.name === "paragraph" && $pos.parent.textContent === "") {
5261
+ tr.replaceWith($pos.before(), $pos.after(), videoNode);
5262
+ tr.setSelection(TextSelection5.near(tr.doc.resolve($pos.before())));
5221
5263
  } else {
5222
- const insertPos = savedPos ?? state.selection.from;
5223
- editor.chain().focus().command(({ tr }) => {
5224
- const linkMark = editor.schema.marks.link.create({ href: url });
5225
- const textNode = editor.schema.text(title, [linkMark]);
5226
- tr.insert(insertPos, textNode);
5227
- return true;
5228
- }).scrollIntoView().run();
5264
+ tr.insert(insertPos, videoNode);
5265
+ tr.setSelection(TextSelection5.near(tr.doc.resolve(insertPos)));
5229
5266
  }
5230
- }
5267
+ return true;
5268
+ }).run();
5231
5269
  closeDialogCommand();
5232
5270
  };
5233
5271
  };
5272
+ var createHandleLinkAdd = (editor, closeDialogCommand, linkParams, savedPos) => {
5273
+ if (!editor) return;
5274
+ const hasSelection = !editor.state.selection.empty;
5275
+ const titleLength = linkParams.title?.length ?? 0;
5276
+ if (hasSelection) {
5277
+ editor.chain().focus().command(({ tr, state }) => {
5278
+ const { from, to } = state.selection;
5279
+ tr.insertText(linkParams.title ?? "", from, to);
5280
+ tr.addMark(from, from + titleLength, editor.schema.marks.link.create({ ...linkParams }));
5281
+ return true;
5282
+ }).run();
5283
+ } else {
5284
+ const { state } = editor;
5285
+ const insertPos = savedPos ?? state.selection.from;
5286
+ const titleLength2 = linkParams.title?.length ?? 0;
5287
+ editor.chain().focus().command(({ tr }) => {
5288
+ const linkMark = editor.schema.marks.link.create({ ...linkParams });
5289
+ const textNode = editor.schema.text(linkParams.title ?? "", [linkMark]);
5290
+ tr.insert(insertPos, textNode);
5291
+ tr.setSelection(TextSelection5.create(tr.doc, insertPos, insertPos + titleLength2));
5292
+ return true;
5293
+ }).run();
5294
+ }
5295
+ closeDialogCommand();
5296
+ };
5234
5297
  var createHandleKatexAdd = (editor, closeDialogCommand, savedPos) => {
5235
5298
  return (latex, pos) => {
5236
5299
  if (!editor) return;
@@ -5238,27 +5301,13 @@ var createHandleKatexAdd = (editor, closeDialogCommand, savedPos) => {
5238
5301
  editor.chain().setNodeSelection(pos).updateInlineMath({ latex }).focus().run();
5239
5302
  } else {
5240
5303
  const { state } = editor;
5241
- const { $from } = state.selection;
5242
- const text = $from.parent.textContent;
5243
- const nodeStart = $from.start();
5244
- const beforeCursor = text.substring(0, $from.pos - nodeStart);
5245
- const slashIndex = beforeCursor.lastIndexOf("/");
5246
- if (slashIndex !== -1) {
5247
- const deleteFrom = nodeStart + slashIndex;
5248
- const deleteTo = $from.pos;
5249
- editor.chain().focus().command(({ tr, state: state2 }) => {
5250
- const inlineMathNode = state2.schema.nodes.inlineMath.create({ latex });
5251
- tr.replaceRangeWith(deleteFrom, deleteTo, inlineMathNode);
5252
- return true;
5253
- }).scrollIntoView().run();
5254
- } else {
5255
- const insertPos = savedPos ?? state.selection.from;
5256
- editor.chain().focus().command(({ tr, state: state2 }) => {
5257
- const inlineMathNode = state2.schema.nodes.inlineMath.create({ latex });
5258
- tr.insert(insertPos, inlineMathNode);
5259
- return true;
5260
- }).scrollIntoView().run();
5261
- }
5304
+ const insertPos = savedPos ?? state.selection.from;
5305
+ editor.chain().focus().command(({ tr, state: state2 }) => {
5306
+ const inlineMathNode = state2.schema.nodes.inlineMath.create({ latex });
5307
+ tr.insert(insertPos, inlineMathNode);
5308
+ tr.setSelection(TextSelection5.near(tr.doc.resolve(insertPos)));
5309
+ return true;
5310
+ }).run();
5262
5311
  }
5263
5312
  closeDialogCommand();
5264
5313
  };
@@ -5710,7 +5759,11 @@ var ru_default = {
5710
5759
  invalidUrl: "\u041D\u0435\u0432\u0435\u0440\u043D\u044B\u0439 URL",
5711
5760
  emptyUrl: "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 URL \u0441\u0441\u044B\u043B\u043A\u0438",
5712
5761
  addLinkTitle: "\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0441\u0441\u044B\u043B\u043A\u0443",
5713
- removeLinkTitle: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0441\u044B\u043B\u043A\u0443"
5762
+ removeLinkTitle: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0441\u044B\u043B\u043A\u0443",
5763
+ openInNewTab: "\u041E\u0442\u043A\u0440\u044B\u0442\u044C \u0432 \u043D\u043E\u0432\u043E\u0439 \u0432\u043A\u043B\u0430\u0434\u043A\u0435",
5764
+ openInNewTabHelp: "\u0421\u0441\u044B\u043B\u043A\u0430 \u043E\u0442\u043A\u0440\u043E\u0435\u0442\u0441\u044F \u0432 \u043D\u043E\u0432\u043E\u043C \u043E\u043A\u043D\u0435 \u0438\u043B\u0438 \u0432\u043A\u043B\u0430\u0434\u043A\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430",
5765
+ addNofollow: '\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C rel="nofollow"',
5766
+ addNofollowHelp: "\u0423\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u0442 \u043F\u043E\u0438\u0441\u043A\u043E\u0432\u044B\u043C \u0441\u0438\u0441\u0442\u0435\u043C\u0430\u043C \u043D\u0435 \u0443\u0447\u0438\u0442\u044B\u0432\u0430\u0442\u044C \u0441\u0441\u044B\u043B\u043A\u0443 \u043F\u0440\u0438 \u0440\u0430\u0441\u0447\u0435\u0442\u0435 \u0440\u0435\u0439\u0442\u0438\u043D\u0433\u0430 \u0438 \u0438\u043D\u0434\u0435\u043A\u0441\u0430\u0446\u0438\u0438 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B, \u043D\u0430 \u043A\u043E\u0442\u043E\u0440\u043E\u0439 \u043E\u043D\u0438 \u0440\u0430\u0437\u043C\u0435\u0449\u0435\u043D\u044B. \u0420\u0435\u043A\u043E\u043C\u0435\u043D\u0434\u0443\u0435\u0442\u0441\u044F \u043F\u0440\u0438\u043C\u0435\u043D\u044F\u0442\u044C \u043A\u043E \u0432\u0441\u0435\u043C \u0441\u0441\u044B\u043B\u043A\u0430\u043C \u043D\u0430 \u0441\u0442\u043E\u0440\u043E\u043D\u043D\u0438\u0435 \u0441\u0430\u0439\u0442\u044B."
5714
5767
  },
5715
5768
  lists: {
5716
5769
  bulletList: "\u041D\u0435\u043D\u0443\u043C\u0435\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0439 \u0441\u043F\u0438\u0441\u043E\u043A",
@@ -5870,7 +5923,11 @@ var en_default = {
5870
5923
  invalidUrl: "Invalid URL",
5871
5924
  emptyUrl: "Enter link URL",
5872
5925
  addLinkTitle: "Add link",
5873
- removeLinkTitle: "Remove link"
5926
+ removeLinkTitle: "Remove link",
5927
+ openInNewTab: "Open in new tab",
5928
+ openInNewTabHelp: "Link will open in a new browser window or tab",
5929
+ addNofollow: 'Add rel="nofollow"',
5930
+ addNofollowHelp: "Tells search engines not to count this link when calculating page rankings and indexing. Recommended for all external links."
5874
5931
  },
5875
5932
  lists: {
5876
5933
  bulletList: "Bullet list",
@@ -6066,6 +6123,7 @@ function TiptapContent({
6066
6123
  return false;
6067
6124
  }
6068
6125
  },
6126
+ onCreate: ({ editor: editor2 }) => handleChange?.(editor2.getJSON()),
6069
6127
  onBlur: ({ editor: editor2 }) => handleChange?.(editor2.getJSON())
6070
6128
  },
6071
6129
  [lang]
@@ -6083,10 +6141,16 @@ function TiptapContent({
6083
6141
  setSavedDialogCursorPos(void 0);
6084
6142
  closeDialogCommand();
6085
6143
  };
6086
- const handleImageAdd = createHandleImageAdd(editor, handleCloseDialog, savedDialogCursorPos);
6144
+ const handleImageAdd = (attrs) => {
6145
+ createHandleImageAdd(editor, handleCloseDialog, savedDialogCursorPos)(attrs);
6146
+ };
6087
6147
  const handleImageEdit = createHandleImageEdit(editor, handleCloseDialog, editFigureContext?.pos);
6088
- const handleVideoAdd = createHandleVideoAdd(editor, handleCloseDialog, savedDialogCursorPos);
6089
- const handleLinkAdd = createHandleLinkAdd(editor, handleCloseDialog, savedDialogCursorPos);
6148
+ const handleVideoAdd = (url) => {
6149
+ createHandleVideoAdd(editor, handleCloseDialog, savedDialogCursorPos)(url);
6150
+ };
6151
+ const handleLinkAdd = (params) => {
6152
+ createHandleLinkAdd(editor, handleCloseDialog, params, savedDialogCursorPos);
6153
+ };
6090
6154
  const handleKatexAdd = (latex) => {
6091
6155
  const katexHandler = createHandleKatexAdd(editor, handleCloseDialog, savedDialogCursorPos);
6092
6156
  katexHandler(latex, katexDialogContext?.pos);
@@ -6123,7 +6187,7 @@ function TiptapContent({
6123
6187
  BubbleMenuContent,
6124
6188
  {
6125
6189
  editor,
6126
- onLinkClick: (selectedText, url) => setLinkDialogContext({ selectedText, url })
6190
+ onLinkClick: (params) => setLinkDialogContext(params)
6127
6191
  }
6128
6192
  )
6129
6193
  }
@@ -6159,8 +6223,7 @@ function TiptapContent({
6159
6223
  open: true,
6160
6224
  onClose: handleCloseDialog,
6161
6225
  onLinkAdd: handleLinkAdd,
6162
- initialTitle: linkDialogContext?.selectedText || "",
6163
- initialUrl: linkDialogContext?.url || ""
6226
+ linkDialogContext
6164
6227
  }
6165
6228
  ),
6166
6229
  activeDialog === "video" && /* @__PURE__ */ jsx93(