@notum-cz/strapi-plugin-tiptap-editor 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +160 -0
  3. package/dist/_chunks/AccentCursive-CpAPpH9C.mjs +3383 -0
  4. package/dist/_chunks/AccentCursive-CpAPpH9C.mjs.map +1 -0
  5. package/dist/_chunks/AccentCursive-D6sTlhub.js +3384 -0
  6. package/dist/_chunks/AccentCursive-D6sTlhub.js.map +1 -0
  7. package/dist/_chunks/FormattedHeadingInput-DycgfIze.mjs +101 -0
  8. package/dist/_chunks/FormattedHeadingInput-DycgfIze.mjs.map +1 -0
  9. package/dist/_chunks/FormattedHeadingInput-FFjiRSEJ.js +101 -0
  10. package/dist/_chunks/FormattedHeadingInput-FFjiRSEJ.js.map +1 -0
  11. package/dist/_chunks/RichTextInput-BZQ2iVqa.mjs +4481 -0
  12. package/dist/_chunks/RichTextInput-BZQ2iVqa.mjs.map +1 -0
  13. package/dist/_chunks/RichTextInput-BbbQxPc-.js +4414 -0
  14. package/dist/_chunks/RichTextInput-BbbQxPc-.js.map +1 -0
  15. package/dist/_chunks/RichTextInput-BjLR2pi0.js +4416 -0
  16. package/dist/_chunks/RichTextInput-BjLR2pi0.js.map +1 -0
  17. package/dist/_chunks/RichTextInput-BlxoJMa2.js +4488 -0
  18. package/dist/_chunks/RichTextInput-BlxoJMa2.js.map +1 -0
  19. package/dist/_chunks/RichTextInput-Bm3X8fR2.mjs +4400 -0
  20. package/dist/_chunks/RichTextInput-Bm3X8fR2.mjs.map +1 -0
  21. package/dist/_chunks/RichTextInput-Bms-gSvK.js +4407 -0
  22. package/dist/_chunks/RichTextInput-Bms-gSvK.js.map +1 -0
  23. package/dist/_chunks/RichTextInput-BtNjPJRN.mjs +4400 -0
  24. package/dist/_chunks/RichTextInput-BtNjPJRN.mjs.map +1 -0
  25. package/dist/_chunks/RichTextInput-Bw3tcXfp.js +4407 -0
  26. package/dist/_chunks/RichTextInput-Bw3tcXfp.js.map +1 -0
  27. package/dist/_chunks/RichTextInput-CsgNpoxq.mjs +4409 -0
  28. package/dist/_chunks/RichTextInput-CsgNpoxq.mjs.map +1 -0
  29. package/dist/_chunks/RichTextInput-CwTvEMda.js +4407 -0
  30. package/dist/_chunks/RichTextInput-CwTvEMda.js.map +1 -0
  31. package/dist/_chunks/RichTextInput-DG-36krM.js +1181 -0
  32. package/dist/_chunks/RichTextInput-DG-36krM.js.map +1 -0
  33. package/dist/_chunks/RichTextInput-DLac-zNQ.mjs +4400 -0
  34. package/dist/_chunks/RichTextInput-DLac-zNQ.mjs.map +1 -0
  35. package/dist/_chunks/RichTextInput-DSXttrvi.js +4407 -0
  36. package/dist/_chunks/RichTextInput-DSXttrvi.js.map +1 -0
  37. package/dist/_chunks/RichTextInput-DeJ6Exto.mjs +4400 -0
  38. package/dist/_chunks/RichTextInput-DeJ6Exto.mjs.map +1 -0
  39. package/dist/_chunks/RichTextInput-DgT88AkO.mjs +1175 -0
  40. package/dist/_chunks/RichTextInput-DgT88AkO.mjs.map +1 -0
  41. package/dist/_chunks/RichTextInput-DlMaDJQF.mjs +4400 -0
  42. package/dist/_chunks/RichTextInput-DlMaDJQF.mjs.map +1 -0
  43. package/dist/_chunks/RichTextInput-DtaYdjCs.mjs +4400 -0
  44. package/dist/_chunks/RichTextInput-DtaYdjCs.mjs.map +1 -0
  45. package/dist/_chunks/RichTextInput-YTKXo5oq.js +4407 -0
  46. package/dist/_chunks/RichTextInput-YTKXo5oq.js.map +1 -0
  47. package/dist/_chunks/RichTextInput-tmg-oMJk.mjs +4407 -0
  48. package/dist/_chunks/RichTextInput-tmg-oMJk.mjs.map +1 -0
  49. package/dist/_chunks/RichTextInput-umhMsI5o.js +4407 -0
  50. package/dist/_chunks/RichTextInput-umhMsI5o.js.map +1 -0
  51. package/dist/_chunks/en-B4KWt_jN.js +5 -0
  52. package/dist/_chunks/en-B4KWt_jN.js.map +1 -0
  53. package/dist/_chunks/en-Byx4XI2L.mjs +5 -0
  54. package/dist/_chunks/en-Byx4XI2L.mjs.map +1 -0
  55. package/dist/admin/index.js +71 -0
  56. package/dist/admin/index.js.map +1 -0
  57. package/dist/admin/index.mjs +72 -0
  58. package/dist/admin/index.mjs.map +1 -0
  59. package/dist/admin/src/components/BaseTiptapInput.d.ts +12 -0
  60. package/dist/admin/src/components/FormattedHeadingInput.d.ts +4 -0
  61. package/dist/admin/src/components/Initializer.d.ts +5 -0
  62. package/dist/admin/src/components/LinkDialog.d.ts +14 -0
  63. package/dist/admin/src/components/RichTextInput.d.ts +4 -0
  64. package/dist/admin/src/components/Spacer.d.ts +3 -0
  65. package/dist/admin/src/components/TableSizeDialog.d.ts +10 -0
  66. package/dist/admin/src/components/TiptapInput.d.ts +7 -0
  67. package/dist/admin/src/components/TiptapInputStyles.d.ts +2 -0
  68. package/dist/admin/src/components/ToolbarButton.d.ts +11 -0
  69. package/dist/admin/src/extensions/AccentCursive.d.ts +18 -0
  70. package/dist/admin/src/extensions/Heading.d.ts +8 -0
  71. package/dist/admin/src/extensions/Link.d.ts +7 -0
  72. package/dist/admin/src/extensions/Script.d.ts +7 -0
  73. package/dist/admin/src/extensions/StarterKit.d.ts +13 -0
  74. package/dist/admin/src/extensions/Table.d.ts +11 -0
  75. package/dist/admin/src/extensions/TextAlign.d.ts +9 -0
  76. package/dist/admin/src/fields/formattedHeadingField.d.ts +20 -0
  77. package/dist/admin/src/fields/richTextField.d.ts +20 -0
  78. package/dist/admin/src/icons/TextAlignCenter.d.ts +2 -0
  79. package/dist/admin/src/icons/TextAlignJustify.d.ts +2 -0
  80. package/dist/admin/src/icons/TextAlignLeft.d.ts +2 -0
  81. package/dist/admin/src/icons/TextAlignRight.d.ts +2 -0
  82. package/dist/admin/src/index.d.ts +10 -0
  83. package/dist/admin/src/pluginId.d.ts +1 -0
  84. package/dist/admin/src/utils/getTranslation.d.ts +2 -0
  85. package/dist/admin/src/utils/tiptapUtils.d.ts +18 -0
  86. package/dist/server/index.js +44 -0
  87. package/dist/server/index.js.map +1 -0
  88. package/dist/server/index.mjs +45 -0
  89. package/dist/server/index.mjs.map +1 -0
  90. package/dist/server/src/bootstrap.d.ts +5 -0
  91. package/dist/server/src/config/index.d.ts +5 -0
  92. package/dist/server/src/content-types/index.d.ts +2 -0
  93. package/dist/server/src/controllers/index.d.ts +2 -0
  94. package/dist/server/src/destroy.d.ts +5 -0
  95. package/dist/server/src/fields/richTextField.d.ts +2 -0
  96. package/dist/server/src/index.d.ts +25 -0
  97. package/dist/server/src/middlewares/index.d.ts +2 -0
  98. package/dist/server/src/policies/index.d.ts +2 -0
  99. package/dist/server/src/register.d.ts +5 -0
  100. package/dist/server/src/routes/index.d.ts +2 -0
  101. package/dist/server/src/services/index.d.ts +2 -0
  102. package/dist/shared/fields.d.ts +1 -0
  103. package/dist/shared/pluginId.d.ts +1 -0
  104. package/package.json +80 -0
@@ -0,0 +1,4488 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const designSystem = require("@strapi/design-system");
5
+ const react = require("@tiptap/react");
6
+ const styled = require("styled-components");
7
+ const React = require("react");
8
+ const admin = require("@strapi/strapi/admin");
9
+ const StarterKit = require("@tiptap/starter-kit");
10
+ const icons = require("@strapi/icons");
11
+ const transform = require("@tiptap/pm/transform");
12
+ const commands = require("@tiptap/pm/commands");
13
+ const state = require("@tiptap/pm/state");
14
+ const model = require("@tiptap/pm/model");
15
+ const schemaList = require("@tiptap/pm/schema-list");
16
+ const view = require("@tiptap/pm/view");
17
+ require("@tiptap/pm/keymap");
18
+ const Superscript = require("@tiptap/extension-superscript");
19
+ const Subscript = require("@tiptap/extension-subscript");
20
+ const extensionTable = require("@tiptap/extension-table");
21
+ const dropcursor = require("@tiptap/pm/dropcursor");
22
+ const gapcursor = require("@tiptap/pm/gapcursor");
23
+ const history = require("@tiptap/pm/history");
24
+ const TextAlign = require("@tiptap/extension-text-align");
25
+ const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
26
+ const styled__default = /* @__PURE__ */ _interopDefault(styled);
27
+ const React__default = /* @__PURE__ */ _interopDefault(React);
28
+ const StarterKit__default = /* @__PURE__ */ _interopDefault(StarterKit);
29
+ const Superscript__default = /* @__PURE__ */ _interopDefault(Superscript);
30
+ const Subscript__default = /* @__PURE__ */ _interopDefault(Subscript);
31
+ const TextAlign__default = /* @__PURE__ */ _interopDefault(TextAlign);
32
+ const TiptapInputStyles = styled__default.default.div`
33
+ .editor-toolbar {
34
+ margin-bottom: 0.25rem;
35
+ padding-bottom: 0.25rem;
36
+ }
37
+
38
+ .ProseMirror {
39
+ font-size: 1.4rem; /* Increase editor font size to match Strapi default */
40
+ outline: none;
41
+ max-height: 60vh;
42
+ min-height: 15vh;
43
+ overflow-y: auto;
44
+ padding: 1rem;
45
+ }
46
+
47
+ /* Remove unnecessary margin at the top of the editor */
48
+ .ProseMirror *:first-child {
49
+ margin-top: 0;
50
+ }
51
+
52
+ /* --- Basic text styles --- */
53
+
54
+ .ProseMirror p {
55
+ margin: 0 0 12px;
56
+ }
57
+
58
+ .ProseMirror p:last-child {
59
+ margin-bottom: 0;
60
+ }
61
+
62
+ .ProseMirror h1,
63
+ .ProseMirror h2,
64
+ .ProseMirror h3,
65
+ .ProseMirror h4 {
66
+ font-weight: 600;
67
+ line-height: 1.25;
68
+ margin: 1em 0 0.5em;
69
+ }
70
+
71
+ .ProseMirror h1 {
72
+ font-size: 4rem;
73
+ }
74
+
75
+ .ProseMirror h2 {
76
+ font-size: 3.2rem;
77
+ }
78
+
79
+ .ProseMirror h3 {
80
+ font-size: 2.5rem;
81
+ }
82
+
83
+ .ProseMirror h4 {
84
+ font-size: 2rem;
85
+ }
86
+
87
+ .ProseMirror ul,
88
+ .ProseMirror ol {
89
+ margin: 0.75em 0 1em;
90
+ padding-left: 1.5rem;
91
+ }
92
+
93
+ .ProseMirror ul {
94
+ list-style: disc;
95
+ }
96
+
97
+ .ProseMirror ol {
98
+ list-style: decimal;
99
+ }
100
+
101
+ .ProseMirror li {
102
+ margin: 0.25em 0;
103
+ }
104
+
105
+ .ProseMirror blockquote {
106
+ border-left: 3px solid #222;
107
+ margin: 1em 0;
108
+ padding: 0.25em 1rem;
109
+ font-style: italic;
110
+ background: #fafafa;
111
+ }
112
+
113
+ .ProseMirror code {
114
+ background: #f3f3f3;
115
+ padding: 2px 4px;
116
+ border-radius: 4px;
117
+ font-family:
118
+ ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', monospace;
119
+ font-size: 0.9em;
120
+ }
121
+
122
+ .ProseMirror a {
123
+ color: #0c75af;
124
+ text-decoration: underline;
125
+ }
126
+
127
+ .ProseMirror strong {
128
+ font-weight: 600;
129
+ }
130
+
131
+ .ProseMirror em {
132
+ font-style: italic;
133
+ }
134
+
135
+ .ProseMirror u {
136
+ text-decoration: underline;
137
+ }
138
+
139
+ .ProseMirror s {
140
+ text-decoration: line-through;
141
+ }
142
+
143
+ // Source: https://tiptap.dev/docs/editor/extensions/nodes/table
144
+
145
+ .ProseMirror {
146
+ table {
147
+ border-collapse: collapse;
148
+ margin: 0;
149
+ overflow: hidden;
150
+ table-layout: fixed;
151
+ width: 100%;
152
+
153
+ td,
154
+ th {
155
+ border: 1px solid #ddd;
156
+ box-sizing: border-box;
157
+ min-width: 1em;
158
+ padding: 6px 8px;
159
+ position: relative;
160
+ vertical-align: top;
161
+
162
+ > * {
163
+ margin-bottom: 0;
164
+ }
165
+ }
166
+
167
+ /* It is not possible to distinguish header vs body cells when rendering
168
+ content in React. So we render all as td and the user should use bold text
169
+ in cells. */
170
+ th {
171
+ background-color: inherit;
172
+ font-weight: normal;
173
+ text-align: left;
174
+ }
175
+
176
+ .selectedCell:after {
177
+ background: rgba(0, 37, 159, 0.32);
178
+ content: '';
179
+ left: 0;
180
+ right: 0;
181
+ top: 0;
182
+ bottom: 0;
183
+ pointer-events: none;
184
+ position: absolute;
185
+ z-index: 2;
186
+ }
187
+
188
+ .column-resize-handle {
189
+ background-color: purple;
190
+ bottom: -2px;
191
+ pointer-events: none;
192
+ position: absolute;
193
+ right: -2px;
194
+ top: 0;
195
+ width: 4px;
196
+ }
197
+ }
198
+
199
+ .tableWrapper {
200
+ margin: 1.5rem 0;
201
+ overflow-x: auto;
202
+ }
203
+
204
+ &.resize-cursor {
205
+ cursor: ew-resize;
206
+ cursor: col-resize;
207
+ }
208
+ }
209
+
210
+ /* --- Only Cursive --- */
211
+ /* How the only cursive text looks like in editor */
212
+
213
+ .only-cursive {
214
+ font-style: italic;
215
+ font-weight: bold;
216
+ }
217
+ `;
218
+ const BaseTiptapInput = React.forwardRef(
219
+ ({ hint, disabled = false, labelAction, label, name, required = false, editor, field, children }, forwardedRef) => {
220
+ const borderColor = field.error ? "danger600" : "neutral200";
221
+ const background = disabled ? "neutral200" : "neutral100";
222
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { name, id: name, hint, error: field.error, required, children: [
223
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { action: labelAction, children: label }),
224
+ /* @__PURE__ */ jsxRuntime.jsx(TiptapInputStyles, { children: /* @__PURE__ */ jsxRuntime.jsxs(
225
+ designSystem.Box,
226
+ {
227
+ className: `tiptap-editor-wrapper ${field.error ? "has-error" : ""} ${disabled ? "is-disabled" : ""}`,
228
+ hasRadius: true,
229
+ borderColor,
230
+ background,
231
+ paddingTop: 1,
232
+ paddingBottom: 0,
233
+ paddingLeft: 0,
234
+ paddingRight: 0,
235
+ children: [
236
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { className: "editor-toolbar", paddingLeft: 2, paddingRight: 2, paddingBottom: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, wrap: "wrap", children }) }),
237
+ /* @__PURE__ */ jsxRuntime.jsx(
238
+ designSystem.Box,
239
+ {
240
+ className: "editor-content",
241
+ background: "neutral0",
242
+ paddingTop: 2,
243
+ paddingBottom: 2,
244
+ paddingLeft: 2,
245
+ paddingRight: 2,
246
+ children: /* @__PURE__ */ jsxRuntime.jsx(react.EditorContent, { editor, disabled, ref: forwardedRef })
247
+ }
248
+ )
249
+ ]
250
+ }
251
+ ) }),
252
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {}),
253
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {})
254
+ ] });
255
+ }
256
+ );
257
+ function tiptapContent(text) {
258
+ return {
259
+ type: "doc",
260
+ content: [
261
+ {
262
+ type: "paragraph",
263
+ content: [
264
+ {
265
+ type: "text",
266
+ text
267
+ }
268
+ ]
269
+ }
270
+ ]
271
+ };
272
+ }
273
+ function parseJSONContent(value, defaultValue) {
274
+ if (!value) {
275
+ return tiptapContent(defaultValue);
276
+ }
277
+ try {
278
+ return typeof value === "string" ? JSON.parse(value) : value;
279
+ } catch (e) {
280
+ console.error("Failed to parse JSON content:", e);
281
+ return tiptapContent(`
282
+ This component's content is malformed. Please change it or remove this component.
283
+ Original content: ${JSON.stringify(value)}
284
+ `);
285
+ }
286
+ }
287
+ function useTiptapEditor(name, defaultValue = "", extensions2 = []) {
288
+ const field = admin.useField(name);
289
+ const editor = react.useEditor({
290
+ extensions: extensions2,
291
+ content: parseJSONContent(field.value, defaultValue),
292
+ onUpdate: ({ editor: editor2 }) => {
293
+ const json = editor2.getJSON();
294
+ field.onChange(name, JSON.stringify(json));
295
+ }
296
+ });
297
+ return { editor, field };
298
+ }
299
+ function Spacer({ width }) {
300
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: width + "px" } });
301
+ }
302
+ function ToolbarButton({
303
+ key,
304
+ onClick,
305
+ icon,
306
+ active,
307
+ disabled,
308
+ tooltip,
309
+ marginLeft,
310
+ hidden
311
+ }) {
312
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { description: tooltip, children: /* @__PURE__ */ jsxRuntime.jsx(
313
+ designSystem.Button,
314
+ {
315
+ onClick,
316
+ variant: "tertiary",
317
+ size: "S",
318
+ paddingLeft: 2,
319
+ paddingRight: 2,
320
+ marginLeft: marginLeft ?? 1,
321
+ disabled,
322
+ style: {
323
+ color: active ? "black" : void 0,
324
+ backgroundColor: active ? "#d9d8ff" : void 0,
325
+ display: hidden ? "none" : void 0
326
+ },
327
+ children: icon
328
+ }
329
+ ) }, key);
330
+ }
331
+ function useStarterKit(editor, props = { disabled: false }) {
332
+ const editorState = react.useEditorState({
333
+ editor,
334
+ selector: (ctx) => {
335
+ return {
336
+ isBold: ctx.editor.isActive("bold") ?? false,
337
+ canBold: ctx.editor.can().chain().toggleBold().run() ?? false,
338
+ isItalic: ctx.editor.isActive("italic") ?? false,
339
+ canItalic: ctx.editor.can().chain().toggleItalic().run() ?? false,
340
+ isUnderline: ctx.editor.isActive("underline") ?? false,
341
+ canUnderline: ctx.editor.can().chain().toggleUnderline().run() ?? false,
342
+ isStrike: ctx.editor.isActive("strike") ?? false,
343
+ canStrike: ctx.editor.can().chain().toggleStrike().run() ?? false,
344
+ isCode: ctx.editor.isActive("code") ?? false,
345
+ canCode: ctx.editor.can().chain().toggleCode().run() ?? false,
346
+ isBulletList: ctx.editor.isActive("bulletList") ?? false,
347
+ canToggleBulletList: ctx.editor.can().chain().toggleBulletList().run() ?? false,
348
+ isOrderedList: ctx.editor.isActive("orderedList") ?? false,
349
+ canToggleOrderedList: ctx.editor.can().chain().toggleOrderedList().run() ?? false,
350
+ isBlockquote: ctx.editor.isActive("blockquote") ?? false,
351
+ canToggleBlockquote: ctx.editor.can().chain().toggleBlockquote().run() ?? false
352
+ };
353
+ }
354
+ });
355
+ const toggleBold = () => editor?.chain().focus().toggleBold().run();
356
+ const toggleItalic = () => editor?.chain().focus().toggleItalic().run();
357
+ const toggleUnderline = () => editor?.chain().focus().toggleUnderline().run();
358
+ const toggleStrike = () => editor?.chain().focus().toggleStrike().run();
359
+ const toggleCode = () => editor?.chain().focus().toggleCode().run();
360
+ const toggleBulletList = () => editor?.chain().focus().toggleBulletList().run();
361
+ const toggleOrderedList = () => editor?.chain().focus().toggleOrderedList().run();
362
+ const toggleBlockquote = () => editor?.chain().focus().toggleBlockquote().run();
363
+ return {
364
+ boldButton: /* @__PURE__ */ jsxRuntime.jsx(
365
+ ToolbarButton,
366
+ {
367
+ onClick: toggleBold,
368
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Bold, {}),
369
+ active: editorState.isBold,
370
+ disabled: props.disabled || !editor || !editorState.canBold,
371
+ tooltip: "Bold"
372
+ },
373
+ "bold"
374
+ ),
375
+ italicButton: /* @__PURE__ */ jsxRuntime.jsx(
376
+ ToolbarButton,
377
+ {
378
+ onClick: toggleItalic,
379
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Italic, {}),
380
+ active: editorState.isItalic,
381
+ disabled: props.disabled || !editor || !editorState.canItalic,
382
+ tooltip: "Italic"
383
+ },
384
+ "italic"
385
+ ),
386
+ underlineButton: /* @__PURE__ */ jsxRuntime.jsx(
387
+ ToolbarButton,
388
+ {
389
+ onClick: toggleUnderline,
390
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Underline, {}),
391
+ active: editorState.isUnderline,
392
+ disabled: props.disabled || !editor || !editorState.canUnderline,
393
+ tooltip: "Underline"
394
+ },
395
+ "underline"
396
+ ),
397
+ strikeButton: /* @__PURE__ */ jsxRuntime.jsx(
398
+ ToolbarButton,
399
+ {
400
+ onClick: toggleStrike,
401
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.StrikeThrough, {}),
402
+ active: editorState.isStrike,
403
+ disabled: props.disabled || !editor || !editorState.canStrike,
404
+ tooltip: "Strikethrough"
405
+ },
406
+ "strike"
407
+ ),
408
+ bulletButton: /* @__PURE__ */ jsxRuntime.jsx(
409
+ ToolbarButton,
410
+ {
411
+ onClick: toggleBulletList,
412
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.BulletList, {}),
413
+ active: editorState.isBulletList,
414
+ disabled: props.disabled || !editor || !editorState.canToggleBulletList,
415
+ tooltip: "Bullet list"
416
+ },
417
+ "bullet"
418
+ ),
419
+ orderedButton: /* @__PURE__ */ jsxRuntime.jsx(
420
+ ToolbarButton,
421
+ {
422
+ onClick: toggleOrderedList,
423
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.NumberList, {}),
424
+ active: editorState.isOrderedList,
425
+ disabled: props.disabled || !editor || !editorState.canToggleOrderedList,
426
+ tooltip: "Numbered list"
427
+ },
428
+ "ordered"
429
+ ),
430
+ codeButton: /* @__PURE__ */ jsxRuntime.jsx(
431
+ ToolbarButton,
432
+ {
433
+ onClick: toggleCode,
434
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Code, {}),
435
+ active: editorState.isCode,
436
+ disabled: props.disabled || !editor || !editorState.canCode,
437
+ tooltip: "Inline code"
438
+ },
439
+ "code"
440
+ ),
441
+ blockquoteButton: /* @__PURE__ */ jsxRuntime.jsx(
442
+ ToolbarButton,
443
+ {
444
+ onClick: toggleBlockquote,
445
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Quotes, {}),
446
+ active: editorState.isBlockquote,
447
+ disabled: props.disabled || !editor || !editorState.canToggleBlockquote,
448
+ tooltip: "Quote"
449
+ },
450
+ "blockquote"
451
+ )
452
+ };
453
+ }
454
+ const LinkDialog = ({
455
+ open,
456
+ url,
457
+ mode,
458
+ onClose,
459
+ onSave,
460
+ onRemove
461
+ }) => {
462
+ const [value, setValue] = React__default.default.useState(url || "");
463
+ React__default.default.useEffect(() => {
464
+ if (open) {
465
+ setValue(url || "");
466
+ }
467
+ }, [open, url, mode]);
468
+ const handleSave = () => {
469
+ onSave({ url: value.trim() });
470
+ };
471
+ const isSaveDisabled = mode === "add" ? value.trim() === "" : false;
472
+ return /* @__PURE__ */ jsxRuntime.jsx(
473
+ designSystem.Dialog.Root,
474
+ {
475
+ open,
476
+ onOpenChange: (v) => {
477
+ if (!v) onClose();
478
+ },
479
+ children: open && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
480
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: mode === "add" ? "Add link" : "Edit link" }),
481
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { width: "100%", children: [
482
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "URL" }),
483
+ /* @__PURE__ */ jsxRuntime.jsx(
484
+ designSystem.TextInput,
485
+ {
486
+ name: "link-url",
487
+ placeholder: "https://example.com",
488
+ value,
489
+ onChange: (e) => setValue(e.target.value)
490
+ }
491
+ )
492
+ ] }) }),
493
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
494
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, onClick: onClose, children: "Cancel" }) }),
495
+ mode === "edit" && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "danger-light", fullWidth: true, onClick: onRemove, children: "Remove link" }),
496
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Action, { children: /* @__PURE__ */ jsxRuntime.jsx(
497
+ designSystem.Button,
498
+ {
499
+ fullWidth: true,
500
+ variant: "success-light",
501
+ onClick: handleSave,
502
+ disabled: isSaveDisabled,
503
+ children: "Save"
504
+ }
505
+ ) })
506
+ ] })
507
+ ] })
508
+ }
509
+ );
510
+ };
511
+ function useLink(editor, props = { disabled: false }) {
512
+ const editorState = react.useEditorState({
513
+ editor,
514
+ selector: (ctx) => {
515
+ return {
516
+ isLink: ctx.editor.isActive("link") ?? false,
517
+ canSetLink: ctx.editor.can().setLink?.({ href: "https://example.com" }) ?? true
518
+ };
519
+ }
520
+ });
521
+ const [showLinkDialog, setShowLinkDialog] = React.useState(false);
522
+ const [currentLinkUrl, setCurrentLinkUrl] = React.useState("");
523
+ const [linkDialogMode, setLinkDialogMode] = React.useState("add");
524
+ const selectionRef = React.useRef(null);
525
+ const openAddLinkDialog = () => {
526
+ if (!editor) return;
527
+ const { from, to } = editor.state.selection;
528
+ selectionRef.current = { from, to };
529
+ setCurrentLinkUrl("");
530
+ setLinkDialogMode("add");
531
+ setShowLinkDialog(true);
532
+ };
533
+ const openEditLinkDialog = () => {
534
+ if (!editor) return;
535
+ const { from, to } = editor.state.selection;
536
+ selectionRef.current = { from, to };
537
+ const currentHref = editor.getAttributes("link").href || "";
538
+ setCurrentLinkUrl(currentHref);
539
+ setLinkDialogMode("edit");
540
+ setShowLinkDialog(true);
541
+ };
542
+ const toggleLink = () => {
543
+ if (!editor) return;
544
+ if (editorState.isLink) {
545
+ openEditLinkDialog();
546
+ } else {
547
+ openAddLinkDialog();
548
+ }
549
+ };
550
+ const restoreSelection = () => {
551
+ if (!editor) return;
552
+ const sel = selectionRef.current;
553
+ if (sel) {
554
+ editor.chain().setTextSelection({ from: sel.from, to: sel.to }).run();
555
+ }
556
+ };
557
+ const handleSaveEditedLink = ({ url }) => {
558
+ if (!editor) return;
559
+ restoreSelection();
560
+ const chain = editor.chain().focus().extendMarkRange("link");
561
+ if (url === "") {
562
+ chain.unsetLink().run();
563
+ } else {
564
+ chain.updateAttributes("link", { href: url }).run();
565
+ }
566
+ setShowLinkDialog(false);
567
+ };
568
+ const handleRemoveLink = () => {
569
+ if (!editor) return;
570
+ restoreSelection();
571
+ editor.chain().focus().extendMarkRange("link").unsetLink().run();
572
+ setShowLinkDialog(false);
573
+ };
574
+ const handleSaveNewLink = ({ url }) => {
575
+ if (!editor) return;
576
+ restoreSelection();
577
+ editor.chain().focus().setLink({ href: url }).run();
578
+ setShowLinkDialog(false);
579
+ };
580
+ return {
581
+ linkButton: /* @__PURE__ */ jsxRuntime.jsx(
582
+ ToolbarButton,
583
+ {
584
+ onClick: toggleLink,
585
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Link, {}),
586
+ active: editorState.isLink,
587
+ disabled: props.disabled || !editor || !editorState.canSetLink,
588
+ tooltip: editorState.isLink ? "Edit or remove link" : "Add link"
589
+ },
590
+ "link"
591
+ ),
592
+ linkDialog: /* @__PURE__ */ jsxRuntime.jsx(
593
+ LinkDialog,
594
+ {
595
+ open: showLinkDialog,
596
+ url: currentLinkUrl,
597
+ mode: linkDialogMode,
598
+ onClose: () => setShowLinkDialog(false),
599
+ onSave: linkDialogMode === "add" ? handleSaveNewLink : handleSaveEditedLink,
600
+ onRemove: handleRemoveLink
601
+ }
602
+ )
603
+ };
604
+ }
605
+ var __defProp = Object.defineProperty;
606
+ var __export = (target, all) => {
607
+ for (var name in all)
608
+ __defProp(target, name, { get: all[name], enumerable: true });
609
+ };
610
+ function createChainableState(config) {
611
+ const { state: state2, transaction } = config;
612
+ let { selection } = transaction;
613
+ let { doc } = transaction;
614
+ let { storedMarks } = transaction;
615
+ return {
616
+ ...state2,
617
+ apply: state2.apply.bind(state2),
618
+ applyTransaction: state2.applyTransaction.bind(state2),
619
+ plugins: state2.plugins,
620
+ schema: state2.schema,
621
+ reconfigure: state2.reconfigure.bind(state2),
622
+ toJSON: state2.toJSON.bind(state2),
623
+ get storedMarks() {
624
+ return storedMarks;
625
+ },
626
+ get selection() {
627
+ return selection;
628
+ },
629
+ get doc() {
630
+ return doc;
631
+ },
632
+ get tr() {
633
+ selection = transaction.selection;
634
+ doc = transaction.doc;
635
+ storedMarks = transaction.storedMarks;
636
+ return transaction;
637
+ }
638
+ };
639
+ }
640
+ var CommandManager = class {
641
+ constructor(props) {
642
+ this.editor = props.editor;
643
+ this.rawCommands = this.editor.extensionManager.commands;
644
+ this.customState = props.state;
645
+ }
646
+ get hasCustomState() {
647
+ return !!this.customState;
648
+ }
649
+ get state() {
650
+ return this.customState || this.editor.state;
651
+ }
652
+ get commands() {
653
+ const { rawCommands, editor, state: state2 } = this;
654
+ const { view: view2 } = editor;
655
+ const { tr } = state2;
656
+ const props = this.buildProps(tr);
657
+ return Object.fromEntries(
658
+ Object.entries(rawCommands).map(([name, command2]) => {
659
+ const method = (...args) => {
660
+ const callback = command2(...args)(props);
661
+ if (!tr.getMeta("preventDispatch") && !this.hasCustomState) {
662
+ view2.dispatch(tr);
663
+ }
664
+ return callback;
665
+ };
666
+ return [name, method];
667
+ })
668
+ );
669
+ }
670
+ get chain() {
671
+ return () => this.createChain();
672
+ }
673
+ get can() {
674
+ return () => this.createCan();
675
+ }
676
+ createChain(startTr, shouldDispatch = true) {
677
+ const { rawCommands, editor, state: state2 } = this;
678
+ const { view: view2 } = editor;
679
+ const callbacks = [];
680
+ const hasStartTransaction = !!startTr;
681
+ const tr = startTr || state2.tr;
682
+ const run3 = () => {
683
+ if (!hasStartTransaction && shouldDispatch && !tr.getMeta("preventDispatch") && !this.hasCustomState) {
684
+ view2.dispatch(tr);
685
+ }
686
+ return callbacks.every((callback) => callback === true);
687
+ };
688
+ const chain = {
689
+ ...Object.fromEntries(
690
+ Object.entries(rawCommands).map(([name, command2]) => {
691
+ const chainedCommand = (...args) => {
692
+ const props = this.buildProps(tr, shouldDispatch);
693
+ const callback = command2(...args)(props);
694
+ callbacks.push(callback);
695
+ return chain;
696
+ };
697
+ return [name, chainedCommand];
698
+ })
699
+ ),
700
+ run: run3
701
+ };
702
+ return chain;
703
+ }
704
+ createCan(startTr) {
705
+ const { rawCommands, state: state2 } = this;
706
+ const dispatch = false;
707
+ const tr = startTr || state2.tr;
708
+ const props = this.buildProps(tr, dispatch);
709
+ const formattedCommands = Object.fromEntries(
710
+ Object.entries(rawCommands).map(([name, command2]) => {
711
+ return [name, (...args) => command2(...args)({ ...props, dispatch: void 0 })];
712
+ })
713
+ );
714
+ return {
715
+ ...formattedCommands,
716
+ chain: () => this.createChain(tr, dispatch)
717
+ };
718
+ }
719
+ buildProps(tr, shouldDispatch = true) {
720
+ const { rawCommands, editor, state: state2 } = this;
721
+ const { view: view2 } = editor;
722
+ const props = {
723
+ tr,
724
+ editor,
725
+ view: view2,
726
+ state: createChainableState({
727
+ state: state2,
728
+ transaction: tr
729
+ }),
730
+ dispatch: shouldDispatch ? () => void 0 : void 0,
731
+ chain: () => this.createChain(tr, shouldDispatch),
732
+ can: () => this.createCan(tr),
733
+ get commands() {
734
+ return Object.fromEntries(
735
+ Object.entries(rawCommands).map(([name, command2]) => {
736
+ return [name, (...args) => command2(...args)(props)];
737
+ })
738
+ );
739
+ }
740
+ };
741
+ return props;
742
+ }
743
+ };
744
+ var commands_exports = {};
745
+ __export(commands_exports, {
746
+ blur: () => blur,
747
+ clearContent: () => clearContent,
748
+ clearNodes: () => clearNodes,
749
+ command: () => command,
750
+ createParagraphNear: () => createParagraphNear,
751
+ cut: () => cut,
752
+ deleteCurrentNode: () => deleteCurrentNode,
753
+ deleteNode: () => deleteNode,
754
+ deleteRange: () => deleteRange,
755
+ deleteSelection: () => deleteSelection,
756
+ enter: () => enter,
757
+ exitCode: () => exitCode,
758
+ extendMarkRange: () => extendMarkRange,
759
+ first: () => first,
760
+ focus: () => focus,
761
+ forEach: () => forEach,
762
+ insertContent: () => insertContent,
763
+ insertContentAt: () => insertContentAt,
764
+ joinBackward: () => joinBackward,
765
+ joinDown: () => joinDown,
766
+ joinForward: () => joinForward,
767
+ joinItemBackward: () => joinItemBackward,
768
+ joinItemForward: () => joinItemForward,
769
+ joinTextblockBackward: () => joinTextblockBackward,
770
+ joinTextblockForward: () => joinTextblockForward,
771
+ joinUp: () => joinUp,
772
+ keyboardShortcut: () => keyboardShortcut,
773
+ lift: () => lift,
774
+ liftEmptyBlock: () => liftEmptyBlock,
775
+ liftListItem: () => liftListItem,
776
+ newlineInCode: () => newlineInCode,
777
+ resetAttributes: () => resetAttributes,
778
+ scrollIntoView: () => scrollIntoView,
779
+ selectAll: () => selectAll,
780
+ selectNodeBackward: () => selectNodeBackward,
781
+ selectNodeForward: () => selectNodeForward,
782
+ selectParentNode: () => selectParentNode,
783
+ selectTextblockEnd: () => selectTextblockEnd,
784
+ selectTextblockStart: () => selectTextblockStart,
785
+ setContent: () => setContent,
786
+ setMark: () => setMark,
787
+ setMeta: () => setMeta,
788
+ setNode: () => setNode,
789
+ setNodeSelection: () => setNodeSelection,
790
+ setTextDirection: () => setTextDirection,
791
+ setTextSelection: () => setTextSelection,
792
+ sinkListItem: () => sinkListItem,
793
+ splitBlock: () => splitBlock,
794
+ splitListItem: () => splitListItem,
795
+ toggleList: () => toggleList,
796
+ toggleMark: () => toggleMark,
797
+ toggleNode: () => toggleNode,
798
+ toggleWrap: () => toggleWrap,
799
+ undoInputRule: () => undoInputRule,
800
+ unsetAllMarks: () => unsetAllMarks,
801
+ unsetMark: () => unsetMark,
802
+ unsetTextDirection: () => unsetTextDirection,
803
+ updateAttributes: () => updateAttributes,
804
+ wrapIn: () => wrapIn,
805
+ wrapInList: () => wrapInList
806
+ });
807
+ var blur = () => ({ editor, view: view2 }) => {
808
+ requestAnimationFrame(() => {
809
+ var _a;
810
+ if (!editor.isDestroyed) {
811
+ view2.dom.blur();
812
+ (_a = window == null ? void 0 : window.getSelection()) == null ? void 0 : _a.removeAllRanges();
813
+ }
814
+ });
815
+ return true;
816
+ };
817
+ var clearContent = (emitUpdate = true) => ({ commands: commands2 }) => {
818
+ return commands2.setContent("", { emitUpdate });
819
+ };
820
+ var clearNodes = () => ({ state: state2, tr, dispatch }) => {
821
+ const { selection } = tr;
822
+ const { ranges } = selection;
823
+ if (!dispatch) {
824
+ return true;
825
+ }
826
+ ranges.forEach(({ $from, $to }) => {
827
+ state2.doc.nodesBetween($from.pos, $to.pos, (node, pos) => {
828
+ if (node.type.isText) {
829
+ return;
830
+ }
831
+ const { doc, mapping } = tr;
832
+ const $mappedFrom = doc.resolve(mapping.map(pos));
833
+ const $mappedTo = doc.resolve(mapping.map(pos + node.nodeSize));
834
+ const nodeRange = $mappedFrom.blockRange($mappedTo);
835
+ if (!nodeRange) {
836
+ return;
837
+ }
838
+ const targetLiftDepth = transform.liftTarget(nodeRange);
839
+ if (node.type.isTextblock) {
840
+ const { defaultType } = $mappedFrom.parent.contentMatchAt($mappedFrom.index());
841
+ tr.setNodeMarkup(nodeRange.start, defaultType);
842
+ }
843
+ if (targetLiftDepth || targetLiftDepth === 0) {
844
+ tr.lift(nodeRange, targetLiftDepth);
845
+ }
846
+ });
847
+ });
848
+ return true;
849
+ };
850
+ var command = (fn) => (props) => {
851
+ return fn(props);
852
+ };
853
+ var createParagraphNear = () => ({ state: state2, dispatch }) => {
854
+ return commands.createParagraphNear(state2, dispatch);
855
+ };
856
+ var cut = (originRange, targetPos) => ({ editor, tr }) => {
857
+ const { state: state$1 } = editor;
858
+ const contentSlice = state$1.doc.slice(originRange.from, originRange.to);
859
+ tr.deleteRange(originRange.from, originRange.to);
860
+ const newPos = tr.mapping.map(targetPos);
861
+ tr.insert(newPos, contentSlice.content);
862
+ tr.setSelection(new state.TextSelection(tr.doc.resolve(Math.max(newPos - 1, 0))));
863
+ return true;
864
+ };
865
+ var deleteCurrentNode = () => ({ tr, dispatch }) => {
866
+ const { selection } = tr;
867
+ const currentNode = selection.$anchor.node();
868
+ if (currentNode.content.size > 0) {
869
+ return false;
870
+ }
871
+ const $pos = tr.selection.$anchor;
872
+ for (let depth = $pos.depth; depth > 0; depth -= 1) {
873
+ const node = $pos.node(depth);
874
+ if (node.type === currentNode.type) {
875
+ if (dispatch) {
876
+ const from = $pos.before(depth);
877
+ const to = $pos.after(depth);
878
+ tr.delete(from, to).scrollIntoView();
879
+ }
880
+ return true;
881
+ }
882
+ }
883
+ return false;
884
+ };
885
+ function getNodeType(nameOrType, schema) {
886
+ if (typeof nameOrType === "string") {
887
+ if (!schema.nodes[nameOrType]) {
888
+ throw Error(`There is no node type named '${nameOrType}'. Maybe you forgot to add the extension?`);
889
+ }
890
+ return schema.nodes[nameOrType];
891
+ }
892
+ return nameOrType;
893
+ }
894
+ var deleteNode = (typeOrName) => ({ tr, state: state2, dispatch }) => {
895
+ const type = getNodeType(typeOrName, state2.schema);
896
+ const $pos = tr.selection.$anchor;
897
+ for (let depth = $pos.depth; depth > 0; depth -= 1) {
898
+ const node = $pos.node(depth);
899
+ if (node.type === type) {
900
+ if (dispatch) {
901
+ const from = $pos.before(depth);
902
+ const to = $pos.after(depth);
903
+ tr.delete(from, to).scrollIntoView();
904
+ }
905
+ return true;
906
+ }
907
+ }
908
+ return false;
909
+ };
910
+ var deleteRange = (range) => ({ tr, dispatch }) => {
911
+ const { from, to } = range;
912
+ if (dispatch) {
913
+ tr.delete(from, to);
914
+ }
915
+ return true;
916
+ };
917
+ var deleteSelection = () => ({ state: state2, dispatch }) => {
918
+ return commands.deleteSelection(state2, dispatch);
919
+ };
920
+ var enter = () => ({ commands: commands2 }) => {
921
+ return commands2.keyboardShortcut("Enter");
922
+ };
923
+ var exitCode = () => ({ state: state2, dispatch }) => {
924
+ return commands.exitCode(state2, dispatch);
925
+ };
926
+ function isRegExp(value) {
927
+ return Object.prototype.toString.call(value) === "[object RegExp]";
928
+ }
929
+ function objectIncludes(object1, object2, options = { strict: true }) {
930
+ const keys = Object.keys(object2);
931
+ if (!keys.length) {
932
+ return true;
933
+ }
934
+ return keys.every((key) => {
935
+ if (options.strict) {
936
+ return object2[key] === object1[key];
937
+ }
938
+ if (isRegExp(object2[key])) {
939
+ return object2[key].test(object1[key]);
940
+ }
941
+ return object2[key] === object1[key];
942
+ });
943
+ }
944
+ function findMarkInSet(marks, type, attributes = {}) {
945
+ return marks.find((item) => {
946
+ return item.type === type && objectIncludes(
947
+ // Only check equality for the attributes that are provided
948
+ Object.fromEntries(Object.keys(attributes).map((k) => [k, item.attrs[k]])),
949
+ attributes
950
+ );
951
+ });
952
+ }
953
+ function isMarkInSet(marks, type, attributes = {}) {
954
+ return !!findMarkInSet(marks, type, attributes);
955
+ }
956
+ function getMarkRange($pos, type, attributes) {
957
+ var _a;
958
+ if (!$pos || !type) {
959
+ return;
960
+ }
961
+ let start = $pos.parent.childAfter($pos.parentOffset);
962
+ if (!start.node || !start.node.marks.some((mark2) => mark2.type === type)) {
963
+ start = $pos.parent.childBefore($pos.parentOffset);
964
+ }
965
+ if (!start.node || !start.node.marks.some((mark2) => mark2.type === type)) {
966
+ return;
967
+ }
968
+ attributes = attributes || ((_a = start.node.marks[0]) == null ? void 0 : _a.attrs);
969
+ const mark = findMarkInSet([...start.node.marks], type, attributes);
970
+ if (!mark) {
971
+ return;
972
+ }
973
+ let startIndex = start.index;
974
+ let startPos = $pos.start() + start.offset;
975
+ let endIndex = startIndex + 1;
976
+ let endPos = startPos + start.node.nodeSize;
977
+ while (startIndex > 0 && isMarkInSet([...$pos.parent.child(startIndex - 1).marks], type, attributes)) {
978
+ startIndex -= 1;
979
+ startPos -= $pos.parent.child(startIndex).nodeSize;
980
+ }
981
+ while (endIndex < $pos.parent.childCount && isMarkInSet([...$pos.parent.child(endIndex).marks], type, attributes)) {
982
+ endPos += $pos.parent.child(endIndex).nodeSize;
983
+ endIndex += 1;
984
+ }
985
+ return {
986
+ from: startPos,
987
+ to: endPos
988
+ };
989
+ }
990
+ function getMarkType(nameOrType, schema) {
991
+ if (typeof nameOrType === "string") {
992
+ if (!schema.marks[nameOrType]) {
993
+ throw Error(`There is no mark type named '${nameOrType}'. Maybe you forgot to add the extension?`);
994
+ }
995
+ return schema.marks[nameOrType];
996
+ }
997
+ return nameOrType;
998
+ }
999
+ var extendMarkRange = (typeOrName, attributes = {}) => ({ tr, state: state$1, dispatch }) => {
1000
+ const type = getMarkType(typeOrName, state$1.schema);
1001
+ const { doc, selection } = tr;
1002
+ const { $from, from, to } = selection;
1003
+ if (dispatch) {
1004
+ const range = getMarkRange($from, type, attributes);
1005
+ if (range && range.from <= from && range.to >= to) {
1006
+ const newSelection = state.TextSelection.create(doc, range.from, range.to);
1007
+ tr.setSelection(newSelection);
1008
+ }
1009
+ }
1010
+ return true;
1011
+ };
1012
+ var first = (commands2) => (props) => {
1013
+ const items = typeof commands2 === "function" ? commands2(props) : commands2;
1014
+ for (let i = 0; i < items.length; i += 1) {
1015
+ if (items[i](props)) {
1016
+ return true;
1017
+ }
1018
+ }
1019
+ return false;
1020
+ };
1021
+ function isTextSelection(value) {
1022
+ return value instanceof state.TextSelection;
1023
+ }
1024
+ function minMax(value = 0, min = 0, max = 0) {
1025
+ return Math.min(Math.max(value, min), max);
1026
+ }
1027
+ function resolveFocusPosition(doc, position = null) {
1028
+ if (!position) {
1029
+ return null;
1030
+ }
1031
+ const selectionAtStart = state.Selection.atStart(doc);
1032
+ const selectionAtEnd = state.Selection.atEnd(doc);
1033
+ if (position === "start" || position === true) {
1034
+ return selectionAtStart;
1035
+ }
1036
+ if (position === "end") {
1037
+ return selectionAtEnd;
1038
+ }
1039
+ const minPos = selectionAtStart.from;
1040
+ const maxPos = selectionAtEnd.to;
1041
+ if (position === "all") {
1042
+ return state.TextSelection.create(doc, minMax(0, minPos, maxPos), minMax(doc.content.size, minPos, maxPos));
1043
+ }
1044
+ return state.TextSelection.create(doc, minMax(position, minPos, maxPos), minMax(position, minPos, maxPos));
1045
+ }
1046
+ function isAndroid() {
1047
+ return navigator.platform === "Android" || /android/i.test(navigator.userAgent);
1048
+ }
1049
+ function isiOS() {
1050
+ return ["iPad Simulator", "iPhone Simulator", "iPod Simulator", "iPad", "iPhone", "iPod"].includes(navigator.platform) || // iPad on iOS 13 detection
1051
+ navigator.userAgent.includes("Mac") && "ontouchend" in document;
1052
+ }
1053
+ function isSafari() {
1054
+ return typeof navigator !== "undefined" ? /^((?!chrome|android).)*safari/i.test(navigator.userAgent) : false;
1055
+ }
1056
+ var focus = (position = null, options = {}) => ({ editor, view: view2, tr, dispatch }) => {
1057
+ options = {
1058
+ scrollIntoView: true,
1059
+ ...options
1060
+ };
1061
+ const delayedFocus = () => {
1062
+ if (isiOS() || isAndroid()) {
1063
+ view2.dom.focus();
1064
+ }
1065
+ if (isSafari() && !isiOS() && !isAndroid()) {
1066
+ view2.dom.focus({ preventScroll: true });
1067
+ }
1068
+ requestAnimationFrame(() => {
1069
+ if (!editor.isDestroyed) {
1070
+ view2.focus();
1071
+ if (options == null ? void 0 : options.scrollIntoView) {
1072
+ editor.commands.scrollIntoView();
1073
+ }
1074
+ }
1075
+ });
1076
+ };
1077
+ try {
1078
+ if (view2.hasFocus() && position === null || position === false) {
1079
+ return true;
1080
+ }
1081
+ } catch {
1082
+ return false;
1083
+ }
1084
+ if (dispatch && position === null && !isTextSelection(editor.state.selection)) {
1085
+ delayedFocus();
1086
+ return true;
1087
+ }
1088
+ const selection = resolveFocusPosition(tr.doc, position) || editor.state.selection;
1089
+ const isSameSelection = editor.state.selection.eq(selection);
1090
+ if (dispatch) {
1091
+ if (!isSameSelection) {
1092
+ tr.setSelection(selection);
1093
+ }
1094
+ if (isSameSelection && tr.storedMarks) {
1095
+ tr.setStoredMarks(tr.storedMarks);
1096
+ }
1097
+ delayedFocus();
1098
+ }
1099
+ return true;
1100
+ };
1101
+ var forEach = (items, fn) => (props) => {
1102
+ return items.every((item, index) => fn(item, { ...props, index }));
1103
+ };
1104
+ var insertContent = (value, options) => ({ tr, commands: commands2 }) => {
1105
+ return commands2.insertContentAt({ from: tr.selection.from, to: tr.selection.to }, value, options);
1106
+ };
1107
+ var removeWhitespaces = (node) => {
1108
+ const children = node.childNodes;
1109
+ for (let i = children.length - 1; i >= 0; i -= 1) {
1110
+ const child = children[i];
1111
+ if (child.nodeType === 3 && child.nodeValue && /^(\n\s\s|\n)$/.test(child.nodeValue)) {
1112
+ node.removeChild(child);
1113
+ } else if (child.nodeType === 1) {
1114
+ removeWhitespaces(child);
1115
+ }
1116
+ }
1117
+ return node;
1118
+ };
1119
+ function elementFromString(value) {
1120
+ if (typeof window === "undefined") {
1121
+ throw new Error("[tiptap error]: there is no window object available, so this function cannot be used");
1122
+ }
1123
+ const wrappedValue = `<body>${value}</body>`;
1124
+ const html = new window.DOMParser().parseFromString(wrappedValue, "text/html").body;
1125
+ return removeWhitespaces(html);
1126
+ }
1127
+ function createNodeFromContent(content, schema, options) {
1128
+ if (content instanceof model.Node || content instanceof model.Fragment) {
1129
+ return content;
1130
+ }
1131
+ options = {
1132
+ slice: true,
1133
+ parseOptions: {},
1134
+ ...options
1135
+ };
1136
+ const isJSONContent = typeof content === "object" && content !== null;
1137
+ const isTextContent = typeof content === "string";
1138
+ if (isJSONContent) {
1139
+ try {
1140
+ const isArrayContent = Array.isArray(content) && content.length > 0;
1141
+ if (isArrayContent) {
1142
+ return model.Fragment.fromArray(content.map((item) => schema.nodeFromJSON(item)));
1143
+ }
1144
+ const node = schema.nodeFromJSON(content);
1145
+ if (options.errorOnInvalidContent) {
1146
+ node.check();
1147
+ }
1148
+ return node;
1149
+ } catch (error) {
1150
+ if (options.errorOnInvalidContent) {
1151
+ throw new Error("[tiptap error]: Invalid JSON content", { cause: error });
1152
+ }
1153
+ console.warn("[tiptap warn]: Invalid content.", "Passed value:", content, "Error:", error);
1154
+ return createNodeFromContent("", schema, options);
1155
+ }
1156
+ }
1157
+ if (isTextContent) {
1158
+ if (options.errorOnInvalidContent) {
1159
+ let hasInvalidContent = false;
1160
+ let invalidContent = "";
1161
+ const contentCheckSchema = new model.Schema({
1162
+ topNode: schema.spec.topNode,
1163
+ marks: schema.spec.marks,
1164
+ // Prosemirror's schemas are executed such that: the last to execute, matches last
1165
+ // This means that we can add a catch-all node at the end of the schema to catch any content that we don't know how to handle
1166
+ nodes: schema.spec.nodes.append({
1167
+ __tiptap__private__unknown__catch__all__node: {
1168
+ content: "inline*",
1169
+ group: "block",
1170
+ parseDOM: [
1171
+ {
1172
+ tag: "*",
1173
+ getAttrs: (e) => {
1174
+ hasInvalidContent = true;
1175
+ invalidContent = typeof e === "string" ? e : e.outerHTML;
1176
+ return null;
1177
+ }
1178
+ }
1179
+ ]
1180
+ }
1181
+ })
1182
+ });
1183
+ if (options.slice) {
1184
+ model.DOMParser.fromSchema(contentCheckSchema).parseSlice(elementFromString(content), options.parseOptions);
1185
+ } else {
1186
+ model.DOMParser.fromSchema(contentCheckSchema).parse(elementFromString(content), options.parseOptions);
1187
+ }
1188
+ if (options.errorOnInvalidContent && hasInvalidContent) {
1189
+ throw new Error("[tiptap error]: Invalid HTML content", {
1190
+ cause: new Error(`Invalid element found: ${invalidContent}`)
1191
+ });
1192
+ }
1193
+ }
1194
+ const parser = model.DOMParser.fromSchema(schema);
1195
+ if (options.slice) {
1196
+ return parser.parseSlice(elementFromString(content), options.parseOptions).content;
1197
+ }
1198
+ return parser.parse(elementFromString(content), options.parseOptions);
1199
+ }
1200
+ return createNodeFromContent("", schema, options);
1201
+ }
1202
+ function selectionToInsertionEnd(tr, startLen, bias) {
1203
+ const last = tr.steps.length - 1;
1204
+ if (last < startLen) {
1205
+ return;
1206
+ }
1207
+ const step = tr.steps[last];
1208
+ if (!(step instanceof transform.ReplaceStep || step instanceof transform.ReplaceAroundStep)) {
1209
+ return;
1210
+ }
1211
+ const map = tr.mapping.maps[last];
1212
+ let end = 0;
1213
+ map.forEach((_from, _to, _newFrom, newTo) => {
1214
+ if (end === 0) {
1215
+ end = newTo;
1216
+ }
1217
+ });
1218
+ tr.setSelection(state.Selection.near(tr.doc.resolve(end), bias));
1219
+ }
1220
+ var isFragment = (nodeOrFragment) => {
1221
+ return !("type" in nodeOrFragment);
1222
+ };
1223
+ var insertContentAt = (position, value, options) => ({ tr, dispatch, editor }) => {
1224
+ var _a;
1225
+ if (dispatch) {
1226
+ options = {
1227
+ parseOptions: editor.options.parseOptions,
1228
+ updateSelection: true,
1229
+ applyInputRules: false,
1230
+ applyPasteRules: false,
1231
+ ...options
1232
+ };
1233
+ let content;
1234
+ const emitContentError = (error) => {
1235
+ editor.emit("contentError", {
1236
+ editor,
1237
+ error,
1238
+ disableCollaboration: () => {
1239
+ if ("collaboration" in editor.storage && typeof editor.storage.collaboration === "object" && editor.storage.collaboration) {
1240
+ editor.storage.collaboration.isDisabled = true;
1241
+ }
1242
+ }
1243
+ });
1244
+ };
1245
+ const parseOptions = {
1246
+ preserveWhitespace: "full",
1247
+ ...options.parseOptions
1248
+ };
1249
+ if (!options.errorOnInvalidContent && !editor.options.enableContentCheck && editor.options.emitContentError) {
1250
+ try {
1251
+ createNodeFromContent(value, editor.schema, {
1252
+ parseOptions,
1253
+ errorOnInvalidContent: true
1254
+ });
1255
+ } catch (e) {
1256
+ emitContentError(e);
1257
+ }
1258
+ }
1259
+ try {
1260
+ content = createNodeFromContent(value, editor.schema, {
1261
+ parseOptions,
1262
+ errorOnInvalidContent: (_a = options.errorOnInvalidContent) != null ? _a : editor.options.enableContentCheck
1263
+ });
1264
+ } catch (e) {
1265
+ emitContentError(e);
1266
+ return false;
1267
+ }
1268
+ let { from, to } = typeof position === "number" ? { from: position, to: position } : { from: position.from, to: position.to };
1269
+ let isOnlyTextContent = true;
1270
+ let isOnlyBlockContent = true;
1271
+ const nodes = isFragment(content) ? content : [content];
1272
+ nodes.forEach((node) => {
1273
+ node.check();
1274
+ isOnlyTextContent = isOnlyTextContent ? node.isText && node.marks.length === 0 : false;
1275
+ isOnlyBlockContent = isOnlyBlockContent ? node.isBlock : false;
1276
+ });
1277
+ if (from === to && isOnlyBlockContent) {
1278
+ const { parent } = tr.doc.resolve(from);
1279
+ const isEmptyTextBlock = parent.isTextblock && !parent.type.spec.code && !parent.childCount;
1280
+ if (isEmptyTextBlock) {
1281
+ from -= 1;
1282
+ to += 1;
1283
+ }
1284
+ }
1285
+ let newContent;
1286
+ if (isOnlyTextContent) {
1287
+ if (Array.isArray(value)) {
1288
+ newContent = value.map((v) => v.text || "").join("");
1289
+ } else if (value instanceof model.Fragment) {
1290
+ let text = "";
1291
+ value.forEach((node) => {
1292
+ if (node.text) {
1293
+ text += node.text;
1294
+ }
1295
+ });
1296
+ newContent = text;
1297
+ } else if (typeof value === "object" && !!value && !!value.text) {
1298
+ newContent = value.text;
1299
+ } else {
1300
+ newContent = value;
1301
+ }
1302
+ tr.insertText(newContent, from, to);
1303
+ } else {
1304
+ newContent = content;
1305
+ const $from = tr.doc.resolve(from);
1306
+ const $fromNode = $from.node();
1307
+ const fromSelectionAtStart = $from.parentOffset === 0;
1308
+ const isTextSelection2 = $fromNode.isText || $fromNode.isTextblock;
1309
+ const hasContent = $fromNode.content.size > 0;
1310
+ if (fromSelectionAtStart && isTextSelection2 && hasContent) {
1311
+ from = Math.max(0, from - 1);
1312
+ }
1313
+ tr.replaceWith(from, to, newContent);
1314
+ }
1315
+ if (options.updateSelection) {
1316
+ selectionToInsertionEnd(tr, tr.steps.length - 1, -1);
1317
+ }
1318
+ if (options.applyInputRules) {
1319
+ tr.setMeta("applyInputRules", { from, text: newContent });
1320
+ }
1321
+ if (options.applyPasteRules) {
1322
+ tr.setMeta("applyPasteRules", { from, text: newContent });
1323
+ }
1324
+ }
1325
+ return true;
1326
+ };
1327
+ var joinUp = () => ({ state: state2, dispatch }) => {
1328
+ return commands.joinUp(state2, dispatch);
1329
+ };
1330
+ var joinDown = () => ({ state: state2, dispatch }) => {
1331
+ return commands.joinDown(state2, dispatch);
1332
+ };
1333
+ var joinBackward = () => ({ state: state2, dispatch }) => {
1334
+ return commands.joinBackward(state2, dispatch);
1335
+ };
1336
+ var joinForward = () => ({ state: state2, dispatch }) => {
1337
+ return commands.joinForward(state2, dispatch);
1338
+ };
1339
+ var joinItemBackward = () => ({ state: state2, dispatch, tr }) => {
1340
+ try {
1341
+ const point = transform.joinPoint(state2.doc, state2.selection.$from.pos, -1);
1342
+ if (point === null || point === void 0) {
1343
+ return false;
1344
+ }
1345
+ tr.join(point, 2);
1346
+ if (dispatch) {
1347
+ dispatch(tr);
1348
+ }
1349
+ return true;
1350
+ } catch {
1351
+ return false;
1352
+ }
1353
+ };
1354
+ var joinItemForward = () => ({ state: state2, dispatch, tr }) => {
1355
+ try {
1356
+ const point = transform.joinPoint(state2.doc, state2.selection.$from.pos, 1);
1357
+ if (point === null || point === void 0) {
1358
+ return false;
1359
+ }
1360
+ tr.join(point, 2);
1361
+ if (dispatch) {
1362
+ dispatch(tr);
1363
+ }
1364
+ return true;
1365
+ } catch {
1366
+ return false;
1367
+ }
1368
+ };
1369
+ var joinTextblockBackward = () => ({ state: state2, dispatch }) => {
1370
+ return commands.joinTextblockBackward(state2, dispatch);
1371
+ };
1372
+ var joinTextblockForward = () => ({ state: state2, dispatch }) => {
1373
+ return commands.joinTextblockForward(state2, dispatch);
1374
+ };
1375
+ function isMacOS() {
1376
+ return typeof navigator !== "undefined" ? /Mac/.test(navigator.platform) : false;
1377
+ }
1378
+ function normalizeKeyName(name) {
1379
+ const parts = name.split(/-(?!$)/);
1380
+ let result = parts[parts.length - 1];
1381
+ if (result === "Space") {
1382
+ result = " ";
1383
+ }
1384
+ let alt;
1385
+ let ctrl;
1386
+ let shift;
1387
+ let meta;
1388
+ for (let i = 0; i < parts.length - 1; i += 1) {
1389
+ const mod = parts[i];
1390
+ if (/^(cmd|meta|m)$/i.test(mod)) {
1391
+ meta = true;
1392
+ } else if (/^a(lt)?$/i.test(mod)) {
1393
+ alt = true;
1394
+ } else if (/^(c|ctrl|control)$/i.test(mod)) {
1395
+ ctrl = true;
1396
+ } else if (/^s(hift)?$/i.test(mod)) {
1397
+ shift = true;
1398
+ } else if (/^mod$/i.test(mod)) {
1399
+ if (isiOS() || isMacOS()) {
1400
+ meta = true;
1401
+ } else {
1402
+ ctrl = true;
1403
+ }
1404
+ } else {
1405
+ throw new Error(`Unrecognized modifier name: ${mod}`);
1406
+ }
1407
+ }
1408
+ if (alt) {
1409
+ result = `Alt-${result}`;
1410
+ }
1411
+ if (ctrl) {
1412
+ result = `Ctrl-${result}`;
1413
+ }
1414
+ if (meta) {
1415
+ result = `Meta-${result}`;
1416
+ }
1417
+ if (shift) {
1418
+ result = `Shift-${result}`;
1419
+ }
1420
+ return result;
1421
+ }
1422
+ var keyboardShortcut = (name) => ({ editor, view: view2, tr, dispatch }) => {
1423
+ const keys = normalizeKeyName(name).split(/-(?!$)/);
1424
+ const key = keys.find((item) => !["Alt", "Ctrl", "Meta", "Shift"].includes(item));
1425
+ const event = new KeyboardEvent("keydown", {
1426
+ key: key === "Space" ? " " : key,
1427
+ altKey: keys.includes("Alt"),
1428
+ ctrlKey: keys.includes("Ctrl"),
1429
+ metaKey: keys.includes("Meta"),
1430
+ shiftKey: keys.includes("Shift"),
1431
+ bubbles: true,
1432
+ cancelable: true
1433
+ });
1434
+ const capturedTransaction = editor.captureTransaction(() => {
1435
+ view2.someProp("handleKeyDown", (f) => f(view2, event));
1436
+ });
1437
+ capturedTransaction == null ? void 0 : capturedTransaction.steps.forEach((step) => {
1438
+ const newStep = step.map(tr.mapping);
1439
+ if (newStep && dispatch) {
1440
+ tr.maybeStep(newStep);
1441
+ }
1442
+ });
1443
+ return true;
1444
+ };
1445
+ function isNodeActive(state2, typeOrName, attributes = {}) {
1446
+ const { from, to, empty } = state2.selection;
1447
+ const type = typeOrName ? getNodeType(typeOrName, state2.schema) : null;
1448
+ const nodeRanges = [];
1449
+ state2.doc.nodesBetween(from, to, (node, pos) => {
1450
+ if (node.isText) {
1451
+ return;
1452
+ }
1453
+ const relativeFrom = Math.max(from, pos);
1454
+ const relativeTo = Math.min(to, pos + node.nodeSize);
1455
+ nodeRanges.push({
1456
+ node,
1457
+ from: relativeFrom,
1458
+ to: relativeTo
1459
+ });
1460
+ });
1461
+ const selectionRange = to - from;
1462
+ const matchedNodeRanges = nodeRanges.filter((nodeRange) => {
1463
+ if (!type) {
1464
+ return true;
1465
+ }
1466
+ return type.name === nodeRange.node.type.name;
1467
+ }).filter((nodeRange) => objectIncludes(nodeRange.node.attrs, attributes, { strict: false }));
1468
+ if (empty) {
1469
+ return !!matchedNodeRanges.length;
1470
+ }
1471
+ const range = matchedNodeRanges.reduce((sum, nodeRange) => sum + nodeRange.to - nodeRange.from, 0);
1472
+ return range >= selectionRange;
1473
+ }
1474
+ var lift = (typeOrName, attributes = {}) => ({ state: state2, dispatch }) => {
1475
+ const type = getNodeType(typeOrName, state2.schema);
1476
+ const isActive2 = isNodeActive(state2, type, attributes);
1477
+ if (!isActive2) {
1478
+ return false;
1479
+ }
1480
+ return commands.lift(state2, dispatch);
1481
+ };
1482
+ var liftEmptyBlock = () => ({ state: state2, dispatch }) => {
1483
+ return commands.liftEmptyBlock(state2, dispatch);
1484
+ };
1485
+ var liftListItem = (typeOrName) => ({ state: state2, dispatch }) => {
1486
+ const type = getNodeType(typeOrName, state2.schema);
1487
+ return schemaList.liftListItem(type)(state2, dispatch);
1488
+ };
1489
+ var newlineInCode = () => ({ state: state2, dispatch }) => {
1490
+ return commands.newlineInCode(state2, dispatch);
1491
+ };
1492
+ function getSchemaTypeNameByName(name, schema) {
1493
+ if (schema.nodes[name]) {
1494
+ return "node";
1495
+ }
1496
+ if (schema.marks[name]) {
1497
+ return "mark";
1498
+ }
1499
+ return null;
1500
+ }
1501
+ function deleteProps(obj, propOrProps) {
1502
+ const props = typeof propOrProps === "string" ? [propOrProps] : propOrProps;
1503
+ return Object.keys(obj).reduce((newObj, prop) => {
1504
+ if (!props.includes(prop)) {
1505
+ newObj[prop] = obj[prop];
1506
+ }
1507
+ return newObj;
1508
+ }, {});
1509
+ }
1510
+ var resetAttributes = (typeOrName, attributes) => ({ tr, state: state2, dispatch }) => {
1511
+ let nodeType = null;
1512
+ let markType = null;
1513
+ const schemaType = getSchemaTypeNameByName(
1514
+ typeof typeOrName === "string" ? typeOrName : typeOrName.name,
1515
+ state2.schema
1516
+ );
1517
+ if (!schemaType) {
1518
+ return false;
1519
+ }
1520
+ if (schemaType === "node") {
1521
+ nodeType = getNodeType(typeOrName, state2.schema);
1522
+ }
1523
+ if (schemaType === "mark") {
1524
+ markType = getMarkType(typeOrName, state2.schema);
1525
+ }
1526
+ let canReset = false;
1527
+ tr.selection.ranges.forEach((range) => {
1528
+ state2.doc.nodesBetween(range.$from.pos, range.$to.pos, (node, pos) => {
1529
+ if (nodeType && nodeType === node.type) {
1530
+ canReset = true;
1531
+ if (dispatch) {
1532
+ tr.setNodeMarkup(pos, void 0, deleteProps(node.attrs, attributes));
1533
+ }
1534
+ }
1535
+ if (markType && node.marks.length) {
1536
+ node.marks.forEach((mark) => {
1537
+ if (markType === mark.type) {
1538
+ canReset = true;
1539
+ if (dispatch) {
1540
+ tr.addMark(pos, pos + node.nodeSize, markType.create(deleteProps(mark.attrs, attributes)));
1541
+ }
1542
+ }
1543
+ });
1544
+ }
1545
+ });
1546
+ });
1547
+ return canReset;
1548
+ };
1549
+ var scrollIntoView = () => ({ tr, dispatch }) => {
1550
+ if (dispatch) {
1551
+ tr.scrollIntoView();
1552
+ }
1553
+ return true;
1554
+ };
1555
+ var selectAll = () => ({ tr, dispatch }) => {
1556
+ if (dispatch) {
1557
+ const selection = new state.AllSelection(tr.doc);
1558
+ tr.setSelection(selection);
1559
+ }
1560
+ return true;
1561
+ };
1562
+ var selectNodeBackward = () => ({ state: state2, dispatch }) => {
1563
+ return commands.selectNodeBackward(state2, dispatch);
1564
+ };
1565
+ var selectNodeForward = () => ({ state: state2, dispatch }) => {
1566
+ return commands.selectNodeForward(state2, dispatch);
1567
+ };
1568
+ var selectParentNode = () => ({ state: state2, dispatch }) => {
1569
+ return commands.selectParentNode(state2, dispatch);
1570
+ };
1571
+ var selectTextblockEnd = () => ({ state: state2, dispatch }) => {
1572
+ return commands.selectTextblockEnd(state2, dispatch);
1573
+ };
1574
+ var selectTextblockStart = () => ({ state: state2, dispatch }) => {
1575
+ return commands.selectTextblockStart(state2, dispatch);
1576
+ };
1577
+ function createDocument(content, schema, parseOptions = {}, options = {}) {
1578
+ return createNodeFromContent(content, schema, {
1579
+ slice: false,
1580
+ parseOptions,
1581
+ errorOnInvalidContent: options.errorOnInvalidContent
1582
+ });
1583
+ }
1584
+ var setContent = (content, { errorOnInvalidContent, emitUpdate = true, parseOptions = {} } = {}) => ({ editor, tr, dispatch, commands: commands2 }) => {
1585
+ const { doc } = tr;
1586
+ if (parseOptions.preserveWhitespace !== "full") {
1587
+ const document2 = createDocument(content, editor.schema, parseOptions, {
1588
+ errorOnInvalidContent: errorOnInvalidContent != null ? errorOnInvalidContent : editor.options.enableContentCheck
1589
+ });
1590
+ if (dispatch) {
1591
+ tr.replaceWith(0, doc.content.size, document2).setMeta("preventUpdate", !emitUpdate);
1592
+ }
1593
+ return true;
1594
+ }
1595
+ if (dispatch) {
1596
+ tr.setMeta("preventUpdate", !emitUpdate);
1597
+ }
1598
+ return commands2.insertContentAt({ from: 0, to: doc.content.size }, content, {
1599
+ parseOptions,
1600
+ errorOnInvalidContent: errorOnInvalidContent != null ? errorOnInvalidContent : editor.options.enableContentCheck
1601
+ });
1602
+ };
1603
+ function getMarkAttributes(state2, typeOrName) {
1604
+ const type = getMarkType(typeOrName, state2.schema);
1605
+ const { from, to, empty } = state2.selection;
1606
+ const marks = [];
1607
+ if (empty) {
1608
+ if (state2.storedMarks) {
1609
+ marks.push(...state2.storedMarks);
1610
+ }
1611
+ marks.push(...state2.selection.$head.marks());
1612
+ } else {
1613
+ state2.doc.nodesBetween(from, to, (node) => {
1614
+ marks.push(...node.marks);
1615
+ });
1616
+ }
1617
+ const mark = marks.find((markItem) => markItem.type.name === type.name);
1618
+ if (!mark) {
1619
+ return {};
1620
+ }
1621
+ return { ...mark.attrs };
1622
+ }
1623
+ function combineTransactionSteps(oldDoc, transactions) {
1624
+ const transform$1 = new transform.Transform(oldDoc);
1625
+ transactions.forEach((transaction) => {
1626
+ transaction.steps.forEach((step) => {
1627
+ transform$1.step(step);
1628
+ });
1629
+ });
1630
+ return transform$1;
1631
+ }
1632
+ function defaultBlockAt(match) {
1633
+ for (let i = 0; i < match.edgeCount; i += 1) {
1634
+ const { type } = match.edge(i);
1635
+ if (type.isTextblock && !type.hasRequiredAttrs()) {
1636
+ return type;
1637
+ }
1638
+ }
1639
+ return null;
1640
+ }
1641
+ function findParentNodeClosestToPos($pos, predicate) {
1642
+ for (let i = $pos.depth; i > 0; i -= 1) {
1643
+ const node = $pos.node(i);
1644
+ if (predicate(node)) {
1645
+ return {
1646
+ pos: i > 0 ? $pos.before(i) : 0,
1647
+ start: $pos.start(i),
1648
+ depth: i,
1649
+ node
1650
+ };
1651
+ }
1652
+ }
1653
+ }
1654
+ function findParentNode(predicate) {
1655
+ return (selection) => findParentNodeClosestToPos(selection.$from, predicate);
1656
+ }
1657
+ function getExtensionField(extension, field, context) {
1658
+ if (extension.config[field] === void 0 && extension.parent) {
1659
+ return getExtensionField(extension.parent, field, context);
1660
+ }
1661
+ if (typeof extension.config[field] === "function") {
1662
+ const value = extension.config[field].bind({
1663
+ ...context,
1664
+ parent: extension.parent ? getExtensionField(extension.parent, field, context) : null
1665
+ });
1666
+ return value;
1667
+ }
1668
+ return extension.config[field];
1669
+ }
1670
+ function isFunction(value) {
1671
+ return typeof value === "function";
1672
+ }
1673
+ function callOrReturn(value, context = void 0, ...props) {
1674
+ if (isFunction(value)) {
1675
+ if (context) {
1676
+ return value.bind(context)(...props);
1677
+ }
1678
+ return value(...props);
1679
+ }
1680
+ return value;
1681
+ }
1682
+ function splitExtensions(extensions2) {
1683
+ const baseExtensions = extensions2.filter((extension) => extension.type === "extension");
1684
+ const nodeExtensions = extensions2.filter((extension) => extension.type === "node");
1685
+ const markExtensions = extensions2.filter((extension) => extension.type === "mark");
1686
+ return {
1687
+ baseExtensions,
1688
+ nodeExtensions,
1689
+ markExtensions
1690
+ };
1691
+ }
1692
+ function mergeAttributes(...objects) {
1693
+ return objects.filter((item) => !!item).reduce((items, item) => {
1694
+ const mergedAttributes = { ...items };
1695
+ Object.entries(item).forEach(([key, value]) => {
1696
+ const exists = mergedAttributes[key];
1697
+ if (!exists) {
1698
+ mergedAttributes[key] = value;
1699
+ return;
1700
+ }
1701
+ if (key === "class") {
1702
+ const valueClasses = value ? String(value).split(" ") : [];
1703
+ const existingClasses = mergedAttributes[key] ? mergedAttributes[key].split(" ") : [];
1704
+ const insertClasses = valueClasses.filter((valueClass) => !existingClasses.includes(valueClass));
1705
+ mergedAttributes[key] = [...existingClasses, ...insertClasses].join(" ");
1706
+ } else if (key === "style") {
1707
+ const newStyles = value ? value.split(";").map((style2) => style2.trim()).filter(Boolean) : [];
1708
+ const existingStyles = mergedAttributes[key] ? mergedAttributes[key].split(";").map((style2) => style2.trim()).filter(Boolean) : [];
1709
+ const styleMap = /* @__PURE__ */ new Map();
1710
+ existingStyles.forEach((style2) => {
1711
+ const [property, val] = style2.split(":").map((part) => part.trim());
1712
+ styleMap.set(property, val);
1713
+ });
1714
+ newStyles.forEach((style2) => {
1715
+ const [property, val] = style2.split(":").map((part) => part.trim());
1716
+ styleMap.set(property, val);
1717
+ });
1718
+ mergedAttributes[key] = Array.from(styleMap.entries()).map(([property, val]) => `${property}: ${val}`).join("; ");
1719
+ } else {
1720
+ mergedAttributes[key] = value;
1721
+ }
1722
+ });
1723
+ return mergedAttributes;
1724
+ }, {});
1725
+ }
1726
+ function getTextBetween(startNode, range, options) {
1727
+ const { from, to } = range;
1728
+ const { blockSeparator = "\n\n", textSerializers = {} } = options || {};
1729
+ let text = "";
1730
+ startNode.nodesBetween(from, to, (node, pos, parent, index) => {
1731
+ var _a;
1732
+ if (node.isBlock && pos > from) {
1733
+ text += blockSeparator;
1734
+ }
1735
+ const textSerializer = textSerializers == null ? void 0 : textSerializers[node.type.name];
1736
+ if (textSerializer) {
1737
+ if (parent) {
1738
+ text += textSerializer({
1739
+ node,
1740
+ pos,
1741
+ parent,
1742
+ index,
1743
+ range
1744
+ });
1745
+ }
1746
+ return false;
1747
+ }
1748
+ if (node.isText) {
1749
+ text += (_a = node == null ? void 0 : node.text) == null ? void 0 : _a.slice(Math.max(from, pos) - pos, to - pos);
1750
+ }
1751
+ });
1752
+ return text;
1753
+ }
1754
+ function getTextSerializersFromSchema(schema) {
1755
+ return Object.fromEntries(
1756
+ Object.entries(schema.nodes).filter(([, node]) => node.spec.toText).map(([name, node]) => [name, node.spec.toText])
1757
+ );
1758
+ }
1759
+ function removeDuplicates(array, by = JSON.stringify) {
1760
+ const seen = {};
1761
+ return array.filter((item) => {
1762
+ const key = by(item);
1763
+ return Object.prototype.hasOwnProperty.call(seen, key) ? false : seen[key] = true;
1764
+ });
1765
+ }
1766
+ function simplifyChangedRanges(changes) {
1767
+ const uniqueChanges = removeDuplicates(changes);
1768
+ return uniqueChanges.length === 1 ? uniqueChanges : uniqueChanges.filter((change, index) => {
1769
+ const rest = uniqueChanges.filter((_, i) => i !== index);
1770
+ return !rest.some((otherChange) => {
1771
+ return change.oldRange.from >= otherChange.oldRange.from && change.oldRange.to <= otherChange.oldRange.to && change.newRange.from >= otherChange.newRange.from && change.newRange.to <= otherChange.newRange.to;
1772
+ });
1773
+ });
1774
+ }
1775
+ function getChangedRanges(transform2) {
1776
+ const { mapping, steps } = transform2;
1777
+ const changes = [];
1778
+ mapping.maps.forEach((stepMap, index) => {
1779
+ const ranges = [];
1780
+ if (!stepMap.ranges.length) {
1781
+ const { from, to } = steps[index];
1782
+ if (from === void 0 || to === void 0) {
1783
+ return;
1784
+ }
1785
+ ranges.push({ from, to });
1786
+ } else {
1787
+ stepMap.forEach((from, to) => {
1788
+ ranges.push({ from, to });
1789
+ });
1790
+ }
1791
+ ranges.forEach(({ from, to }) => {
1792
+ const newStart = mapping.slice(index).map(from, -1);
1793
+ const newEnd = mapping.slice(index).map(to);
1794
+ const oldStart = mapping.invert().map(newStart, -1);
1795
+ const oldEnd = mapping.invert().map(newEnd);
1796
+ changes.push({
1797
+ oldRange: {
1798
+ from: oldStart,
1799
+ to: oldEnd
1800
+ },
1801
+ newRange: {
1802
+ from: newStart,
1803
+ to: newEnd
1804
+ }
1805
+ });
1806
+ });
1807
+ });
1808
+ return simplifyChangedRanges(changes);
1809
+ }
1810
+ function getSplittedAttributes(extensionAttributes, typeName, attributes) {
1811
+ return Object.fromEntries(
1812
+ Object.entries(attributes).filter(([name]) => {
1813
+ const extensionAttribute = extensionAttributes.find((item) => {
1814
+ return item.type === typeName && item.name === name;
1815
+ });
1816
+ if (!extensionAttribute) {
1817
+ return false;
1818
+ }
1819
+ return extensionAttribute.attribute.keepOnSplit;
1820
+ })
1821
+ );
1822
+ }
1823
+ function isMarkActive(state2, typeOrName, attributes = {}) {
1824
+ const { empty, ranges } = state2.selection;
1825
+ const type = typeOrName ? getMarkType(typeOrName, state2.schema) : null;
1826
+ if (empty) {
1827
+ return !!(state2.storedMarks || state2.selection.$from.marks()).filter((mark) => {
1828
+ if (!type) {
1829
+ return true;
1830
+ }
1831
+ return type.name === mark.type.name;
1832
+ }).find((mark) => objectIncludes(mark.attrs, attributes, { strict: false }));
1833
+ }
1834
+ let selectionRange = 0;
1835
+ const markRanges = [];
1836
+ ranges.forEach(({ $from, $to }) => {
1837
+ const from = $from.pos;
1838
+ const to = $to.pos;
1839
+ state2.doc.nodesBetween(from, to, (node, pos) => {
1840
+ if (!node.isText && !node.marks.length) {
1841
+ return;
1842
+ }
1843
+ const relativeFrom = Math.max(from, pos);
1844
+ const relativeTo = Math.min(to, pos + node.nodeSize);
1845
+ const range2 = relativeTo - relativeFrom;
1846
+ selectionRange += range2;
1847
+ markRanges.push(
1848
+ ...node.marks.map((mark) => ({
1849
+ mark,
1850
+ from: relativeFrom,
1851
+ to: relativeTo
1852
+ }))
1853
+ );
1854
+ });
1855
+ });
1856
+ if (selectionRange === 0) {
1857
+ return false;
1858
+ }
1859
+ const matchedRange = markRanges.filter((markRange) => {
1860
+ if (!type) {
1861
+ return true;
1862
+ }
1863
+ return type.name === markRange.mark.type.name;
1864
+ }).filter((markRange) => objectIncludes(markRange.mark.attrs, attributes, { strict: false })).reduce((sum, markRange) => sum + markRange.to - markRange.from, 0);
1865
+ const excludedRange = markRanges.filter((markRange) => {
1866
+ if (!type) {
1867
+ return true;
1868
+ }
1869
+ return markRange.mark.type !== type && markRange.mark.type.excludes(type);
1870
+ }).reduce((sum, markRange) => sum + markRange.to - markRange.from, 0);
1871
+ const range = matchedRange > 0 ? matchedRange + excludedRange : matchedRange;
1872
+ return range >= selectionRange;
1873
+ }
1874
+ function isList(name, extensions2) {
1875
+ const { nodeExtensions } = splitExtensions(extensions2);
1876
+ const extension = nodeExtensions.find((item) => item.name === name);
1877
+ if (!extension) {
1878
+ return false;
1879
+ }
1880
+ const context = {
1881
+ name: extension.name,
1882
+ options: extension.options,
1883
+ storage: extension.storage
1884
+ };
1885
+ const group = callOrReturn(getExtensionField(extension, "group", context));
1886
+ if (typeof group !== "string") {
1887
+ return false;
1888
+ }
1889
+ return group.split(" ").includes("list");
1890
+ }
1891
+ function isNodeEmpty(node, {
1892
+ checkChildren = true,
1893
+ ignoreWhitespace = false
1894
+ } = {}) {
1895
+ var _a;
1896
+ if (ignoreWhitespace) {
1897
+ if (node.type.name === "hardBreak") {
1898
+ return true;
1899
+ }
1900
+ if (node.isText) {
1901
+ return /^\s*$/m.test((_a = node.text) != null ? _a : "");
1902
+ }
1903
+ }
1904
+ if (node.isText) {
1905
+ return !node.text;
1906
+ }
1907
+ if (node.isAtom || node.isLeaf) {
1908
+ return false;
1909
+ }
1910
+ if (node.content.childCount === 0) {
1911
+ return true;
1912
+ }
1913
+ if (checkChildren) {
1914
+ let isContentEmpty = true;
1915
+ node.content.forEach((childNode) => {
1916
+ if (isContentEmpty === false) {
1917
+ return;
1918
+ }
1919
+ if (!isNodeEmpty(childNode, { ignoreWhitespace, checkChildren })) {
1920
+ isContentEmpty = false;
1921
+ }
1922
+ });
1923
+ return isContentEmpty;
1924
+ }
1925
+ return false;
1926
+ }
1927
+ function isNodeSelection(value) {
1928
+ return value instanceof state.NodeSelection;
1929
+ }
1930
+ function canSetMark(state2, tr, newMarkType) {
1931
+ var _a;
1932
+ const { selection } = tr;
1933
+ let cursor = null;
1934
+ if (isTextSelection(selection)) {
1935
+ cursor = selection.$cursor;
1936
+ }
1937
+ if (cursor) {
1938
+ const currentMarks = (_a = state2.storedMarks) != null ? _a : cursor.marks();
1939
+ const parentAllowsMarkType = cursor.parent.type.allowsMarkType(newMarkType);
1940
+ return parentAllowsMarkType && (!!newMarkType.isInSet(currentMarks) || !currentMarks.some((mark) => mark.type.excludes(newMarkType)));
1941
+ }
1942
+ const { ranges } = selection;
1943
+ return ranges.some(({ $from, $to }) => {
1944
+ let someNodeSupportsMark = $from.depth === 0 ? state2.doc.inlineContent && state2.doc.type.allowsMarkType(newMarkType) : false;
1945
+ state2.doc.nodesBetween($from.pos, $to.pos, (node, _pos, parent) => {
1946
+ if (someNodeSupportsMark) {
1947
+ return false;
1948
+ }
1949
+ if (node.isInline) {
1950
+ const parentAllowsMarkType = !parent || parent.type.allowsMarkType(newMarkType);
1951
+ const currentMarksAllowMarkType = !!newMarkType.isInSet(node.marks) || !node.marks.some((otherMark) => otherMark.type.excludes(newMarkType));
1952
+ someNodeSupportsMark = parentAllowsMarkType && currentMarksAllowMarkType;
1953
+ }
1954
+ return !someNodeSupportsMark;
1955
+ });
1956
+ return someNodeSupportsMark;
1957
+ });
1958
+ }
1959
+ var setMark = (typeOrName, attributes = {}) => ({ tr, state: state2, dispatch }) => {
1960
+ const { selection } = tr;
1961
+ const { empty, ranges } = selection;
1962
+ const type = getMarkType(typeOrName, state2.schema);
1963
+ if (dispatch) {
1964
+ if (empty) {
1965
+ const oldAttributes = getMarkAttributes(state2, type);
1966
+ tr.addStoredMark(
1967
+ type.create({
1968
+ ...oldAttributes,
1969
+ ...attributes
1970
+ })
1971
+ );
1972
+ } else {
1973
+ ranges.forEach((range) => {
1974
+ const from = range.$from.pos;
1975
+ const to = range.$to.pos;
1976
+ state2.doc.nodesBetween(from, to, (node, pos) => {
1977
+ const trimmedFrom = Math.max(pos, from);
1978
+ const trimmedTo = Math.min(pos + node.nodeSize, to);
1979
+ const someHasMark = node.marks.find((mark) => mark.type === type);
1980
+ if (someHasMark) {
1981
+ node.marks.forEach((mark) => {
1982
+ if (type === mark.type) {
1983
+ tr.addMark(
1984
+ trimmedFrom,
1985
+ trimmedTo,
1986
+ type.create({
1987
+ ...mark.attrs,
1988
+ ...attributes
1989
+ })
1990
+ );
1991
+ }
1992
+ });
1993
+ } else {
1994
+ tr.addMark(trimmedFrom, trimmedTo, type.create(attributes));
1995
+ }
1996
+ });
1997
+ });
1998
+ }
1999
+ }
2000
+ return canSetMark(state2, tr, type);
2001
+ };
2002
+ var setMeta = (key, value) => ({ tr }) => {
2003
+ tr.setMeta(key, value);
2004
+ return true;
2005
+ };
2006
+ var setNode = (typeOrName, attributes = {}) => ({ state: state2, dispatch, chain }) => {
2007
+ const type = getNodeType(typeOrName, state2.schema);
2008
+ let attributesToCopy;
2009
+ if (state2.selection.$anchor.sameParent(state2.selection.$head)) {
2010
+ attributesToCopy = state2.selection.$anchor.parent.attrs;
2011
+ }
2012
+ if (!type.isTextblock) {
2013
+ console.warn('[tiptap warn]: Currently "setNode()" only supports text block nodes.');
2014
+ return false;
2015
+ }
2016
+ return chain().command(({ commands: commands$1 }) => {
2017
+ const canSetBlock = commands.setBlockType(type, { ...attributesToCopy, ...attributes })(state2);
2018
+ if (canSetBlock) {
2019
+ return true;
2020
+ }
2021
+ return commands$1.clearNodes();
2022
+ }).command(({ state: updatedState }) => {
2023
+ return commands.setBlockType(type, { ...attributesToCopy, ...attributes })(updatedState, dispatch);
2024
+ }).run();
2025
+ };
2026
+ var setNodeSelection = (position) => ({ tr, dispatch }) => {
2027
+ if (dispatch) {
2028
+ const { doc } = tr;
2029
+ const from = minMax(position, 0, doc.content.size);
2030
+ const selection = state.NodeSelection.create(doc, from);
2031
+ tr.setSelection(selection);
2032
+ }
2033
+ return true;
2034
+ };
2035
+ var setTextDirection = (direction, position) => ({ tr, state: state2, dispatch }) => {
2036
+ const { selection } = state2;
2037
+ let from;
2038
+ let to;
2039
+ if (typeof position === "number") {
2040
+ from = position;
2041
+ to = position;
2042
+ } else if (position && "from" in position && "to" in position) {
2043
+ from = position.from;
2044
+ to = position.to;
2045
+ } else {
2046
+ from = selection.from;
2047
+ to = selection.to;
2048
+ }
2049
+ if (dispatch) {
2050
+ tr.doc.nodesBetween(from, to, (node, pos) => {
2051
+ if (node.isText) {
2052
+ return;
2053
+ }
2054
+ tr.setNodeMarkup(pos, void 0, {
2055
+ ...node.attrs,
2056
+ dir: direction
2057
+ });
2058
+ });
2059
+ }
2060
+ return true;
2061
+ };
2062
+ var setTextSelection = (position) => ({ tr, dispatch }) => {
2063
+ if (dispatch) {
2064
+ const { doc } = tr;
2065
+ const { from, to } = typeof position === "number" ? { from: position, to: position } : position;
2066
+ const minPos = state.TextSelection.atStart(doc).from;
2067
+ const maxPos = state.TextSelection.atEnd(doc).to;
2068
+ const resolvedFrom = minMax(from, minPos, maxPos);
2069
+ const resolvedEnd = minMax(to, minPos, maxPos);
2070
+ const selection = state.TextSelection.create(doc, resolvedFrom, resolvedEnd);
2071
+ tr.setSelection(selection);
2072
+ }
2073
+ return true;
2074
+ };
2075
+ var sinkListItem = (typeOrName) => ({ state: state2, dispatch }) => {
2076
+ const type = getNodeType(typeOrName, state2.schema);
2077
+ return schemaList.sinkListItem(type)(state2, dispatch);
2078
+ };
2079
+ function ensureMarks(state2, splittableMarks) {
2080
+ const marks = state2.storedMarks || state2.selection.$to.parentOffset && state2.selection.$from.marks();
2081
+ if (marks) {
2082
+ const filteredMarks = marks.filter((mark) => splittableMarks == null ? void 0 : splittableMarks.includes(mark.type.name));
2083
+ state2.tr.ensureMarks(filteredMarks);
2084
+ }
2085
+ }
2086
+ var splitBlock = ({ keepMarks = true } = {}) => ({ tr, state: state$1, dispatch, editor }) => {
2087
+ const { selection, doc } = tr;
2088
+ const { $from, $to } = selection;
2089
+ const extensionAttributes = editor.extensionManager.attributes;
2090
+ const newAttributes = getSplittedAttributes(extensionAttributes, $from.node().type.name, $from.node().attrs);
2091
+ if (selection instanceof state.NodeSelection && selection.node.isBlock) {
2092
+ if (!$from.parentOffset || !transform.canSplit(doc, $from.pos)) {
2093
+ return false;
2094
+ }
2095
+ if (dispatch) {
2096
+ if (keepMarks) {
2097
+ ensureMarks(state$1, editor.extensionManager.splittableMarks);
2098
+ }
2099
+ tr.split($from.pos).scrollIntoView();
2100
+ }
2101
+ return true;
2102
+ }
2103
+ if (!$from.parent.isBlock) {
2104
+ return false;
2105
+ }
2106
+ const atEnd = $to.parentOffset === $to.parent.content.size;
2107
+ const deflt = $from.depth === 0 ? void 0 : defaultBlockAt($from.node(-1).contentMatchAt($from.indexAfter(-1)));
2108
+ let types = atEnd && deflt ? [
2109
+ {
2110
+ type: deflt,
2111
+ attrs: newAttributes
2112
+ }
2113
+ ] : void 0;
2114
+ let can = transform.canSplit(tr.doc, tr.mapping.map($from.pos), 1, types);
2115
+ if (!types && !can && transform.canSplit(tr.doc, tr.mapping.map($from.pos), 1, deflt ? [{ type: deflt }] : void 0)) {
2116
+ can = true;
2117
+ types = deflt ? [
2118
+ {
2119
+ type: deflt,
2120
+ attrs: newAttributes
2121
+ }
2122
+ ] : void 0;
2123
+ }
2124
+ if (dispatch) {
2125
+ if (can) {
2126
+ if (selection instanceof state.TextSelection) {
2127
+ tr.deleteSelection();
2128
+ }
2129
+ tr.split(tr.mapping.map($from.pos), 1, types);
2130
+ if (deflt && !atEnd && !$from.parentOffset && $from.parent.type !== deflt) {
2131
+ const first2 = tr.mapping.map($from.before());
2132
+ const $first = tr.doc.resolve(first2);
2133
+ if ($from.node(-1).canReplaceWith($first.index(), $first.index() + 1, deflt)) {
2134
+ tr.setNodeMarkup(tr.mapping.map($from.before()), deflt);
2135
+ }
2136
+ }
2137
+ }
2138
+ if (keepMarks) {
2139
+ ensureMarks(state$1, editor.extensionManager.splittableMarks);
2140
+ }
2141
+ tr.scrollIntoView();
2142
+ }
2143
+ return can;
2144
+ };
2145
+ var splitListItem = (typeOrName, overrideAttrs = {}) => ({ tr, state: state$1, dispatch, editor }) => {
2146
+ var _a;
2147
+ const type = getNodeType(typeOrName, state$1.schema);
2148
+ const { $from, $to } = state$1.selection;
2149
+ const node = state$1.selection.node;
2150
+ if (node && node.isBlock || $from.depth < 2 || !$from.sameParent($to)) {
2151
+ return false;
2152
+ }
2153
+ const grandParent = $from.node(-1);
2154
+ if (grandParent.type !== type) {
2155
+ return false;
2156
+ }
2157
+ const extensionAttributes = editor.extensionManager.attributes;
2158
+ if ($from.parent.content.size === 0 && $from.node(-1).childCount === $from.indexAfter(-1)) {
2159
+ if ($from.depth === 2 || $from.node(-3).type !== type || $from.index(-2) !== $from.node(-2).childCount - 1) {
2160
+ return false;
2161
+ }
2162
+ if (dispatch) {
2163
+ let wrap = model.Fragment.empty;
2164
+ const depthBefore = $from.index(-1) ? 1 : $from.index(-2) ? 2 : 3;
2165
+ for (let d = $from.depth - depthBefore; d >= $from.depth - 3; d -= 1) {
2166
+ wrap = model.Fragment.from($from.node(d).copy(wrap));
2167
+ }
2168
+ const depthAfter = (
2169
+ // eslint-disable-next-line no-nested-ternary
2170
+ $from.indexAfter(-1) < $from.node(-2).childCount ? 1 : $from.indexAfter(-2) < $from.node(-3).childCount ? 2 : 3
2171
+ );
2172
+ const newNextTypeAttributes2 = {
2173
+ ...getSplittedAttributes(extensionAttributes, $from.node().type.name, $from.node().attrs),
2174
+ ...overrideAttrs
2175
+ };
2176
+ const nextType2 = ((_a = type.contentMatch.defaultType) == null ? void 0 : _a.createAndFill(newNextTypeAttributes2)) || void 0;
2177
+ wrap = wrap.append(model.Fragment.from(type.createAndFill(null, nextType2) || void 0));
2178
+ const start = $from.before($from.depth - (depthBefore - 1));
2179
+ tr.replace(start, $from.after(-depthAfter), new model.Slice(wrap, 4 - depthBefore, 0));
2180
+ let sel = -1;
2181
+ tr.doc.nodesBetween(start, tr.doc.content.size, (n, pos) => {
2182
+ if (sel > -1) {
2183
+ return false;
2184
+ }
2185
+ if (n.isTextblock && n.content.size === 0) {
2186
+ sel = pos + 1;
2187
+ }
2188
+ });
2189
+ if (sel > -1) {
2190
+ tr.setSelection(state.TextSelection.near(tr.doc.resolve(sel)));
2191
+ }
2192
+ tr.scrollIntoView();
2193
+ }
2194
+ return true;
2195
+ }
2196
+ const nextType = $to.pos === $from.end() ? grandParent.contentMatchAt(0).defaultType : null;
2197
+ const newTypeAttributes = {
2198
+ ...getSplittedAttributes(extensionAttributes, grandParent.type.name, grandParent.attrs),
2199
+ ...overrideAttrs
2200
+ };
2201
+ const newNextTypeAttributes = {
2202
+ ...getSplittedAttributes(extensionAttributes, $from.node().type.name, $from.node().attrs),
2203
+ ...overrideAttrs
2204
+ };
2205
+ tr.delete($from.pos, $to.pos);
2206
+ const types = nextType ? [
2207
+ { type, attrs: newTypeAttributes },
2208
+ { type: nextType, attrs: newNextTypeAttributes }
2209
+ ] : [{ type, attrs: newTypeAttributes }];
2210
+ if (!transform.canSplit(tr.doc, $from.pos, 2)) {
2211
+ return false;
2212
+ }
2213
+ if (dispatch) {
2214
+ const { selection, storedMarks } = state$1;
2215
+ const { splittableMarks } = editor.extensionManager;
2216
+ const marks = storedMarks || selection.$to.parentOffset && selection.$from.marks();
2217
+ tr.split($from.pos, 2, types).scrollIntoView();
2218
+ if (!marks || !dispatch) {
2219
+ return true;
2220
+ }
2221
+ const filteredMarks = marks.filter((mark) => splittableMarks.includes(mark.type.name));
2222
+ tr.ensureMarks(filteredMarks);
2223
+ }
2224
+ return true;
2225
+ };
2226
+ var joinListBackwards = (tr, listType) => {
2227
+ const list = findParentNode((node) => node.type === listType)(tr.selection);
2228
+ if (!list) {
2229
+ return true;
2230
+ }
2231
+ const before = tr.doc.resolve(Math.max(0, list.pos - 1)).before(list.depth);
2232
+ if (before === void 0) {
2233
+ return true;
2234
+ }
2235
+ const nodeBefore = tr.doc.nodeAt(before);
2236
+ const canJoinBackwards = list.node.type === (nodeBefore == null ? void 0 : nodeBefore.type) && transform.canJoin(tr.doc, list.pos);
2237
+ if (!canJoinBackwards) {
2238
+ return true;
2239
+ }
2240
+ tr.join(list.pos);
2241
+ return true;
2242
+ };
2243
+ var joinListForwards = (tr, listType) => {
2244
+ const list = findParentNode((node) => node.type === listType)(tr.selection);
2245
+ if (!list) {
2246
+ return true;
2247
+ }
2248
+ const after = tr.doc.resolve(list.start).after(list.depth);
2249
+ if (after === void 0) {
2250
+ return true;
2251
+ }
2252
+ const nodeAfter = tr.doc.nodeAt(after);
2253
+ const canJoinForwards = list.node.type === (nodeAfter == null ? void 0 : nodeAfter.type) && transform.canJoin(tr.doc, after);
2254
+ if (!canJoinForwards) {
2255
+ return true;
2256
+ }
2257
+ tr.join(after);
2258
+ return true;
2259
+ };
2260
+ var toggleList = (listTypeOrName, itemTypeOrName, keepMarks, attributes = {}) => ({ editor, tr, state: state2, dispatch, chain, commands: commands2, can }) => {
2261
+ const { extensions: extensions2, splittableMarks } = editor.extensionManager;
2262
+ const listType = getNodeType(listTypeOrName, state2.schema);
2263
+ const itemType = getNodeType(itemTypeOrName, state2.schema);
2264
+ const { selection, storedMarks } = state2;
2265
+ const { $from, $to } = selection;
2266
+ const range = $from.blockRange($to);
2267
+ const marks = storedMarks || selection.$to.parentOffset && selection.$from.marks();
2268
+ if (!range) {
2269
+ return false;
2270
+ }
2271
+ const parentList = findParentNode((node) => isList(node.type.name, extensions2))(selection);
2272
+ if (range.depth >= 1 && parentList && range.depth - parentList.depth <= 1) {
2273
+ if (parentList.node.type === listType) {
2274
+ return commands2.liftListItem(itemType);
2275
+ }
2276
+ if (isList(parentList.node.type.name, extensions2) && listType.validContent(parentList.node.content) && dispatch) {
2277
+ return chain().command(() => {
2278
+ tr.setNodeMarkup(parentList.pos, listType);
2279
+ return true;
2280
+ }).command(() => joinListBackwards(tr, listType)).command(() => joinListForwards(tr, listType)).run();
2281
+ }
2282
+ }
2283
+ if (!keepMarks || !marks || !dispatch) {
2284
+ return chain().command(() => {
2285
+ const canWrapInList = can().wrapInList(listType, attributes);
2286
+ if (canWrapInList) {
2287
+ return true;
2288
+ }
2289
+ return commands2.clearNodes();
2290
+ }).wrapInList(listType, attributes).command(() => joinListBackwards(tr, listType)).command(() => joinListForwards(tr, listType)).run();
2291
+ }
2292
+ return chain().command(() => {
2293
+ const canWrapInList = can().wrapInList(listType, attributes);
2294
+ const filteredMarks = marks.filter((mark) => splittableMarks.includes(mark.type.name));
2295
+ tr.ensureMarks(filteredMarks);
2296
+ if (canWrapInList) {
2297
+ return true;
2298
+ }
2299
+ return commands2.clearNodes();
2300
+ }).wrapInList(listType, attributes).command(() => joinListBackwards(tr, listType)).command(() => joinListForwards(tr, listType)).run();
2301
+ };
2302
+ var toggleMark = (typeOrName, attributes = {}, options = {}) => ({ state: state2, commands: commands2 }) => {
2303
+ const { extendEmptyMarkRange = false } = options;
2304
+ const type = getMarkType(typeOrName, state2.schema);
2305
+ const isActive2 = isMarkActive(state2, type, attributes);
2306
+ if (isActive2) {
2307
+ return commands2.unsetMark(type, { extendEmptyMarkRange });
2308
+ }
2309
+ return commands2.setMark(type, attributes);
2310
+ };
2311
+ var toggleNode = (typeOrName, toggleTypeOrName, attributes = {}) => ({ state: state2, commands: commands2 }) => {
2312
+ const type = getNodeType(typeOrName, state2.schema);
2313
+ const toggleType = getNodeType(toggleTypeOrName, state2.schema);
2314
+ const isActive2 = isNodeActive(state2, type, attributes);
2315
+ let attributesToCopy;
2316
+ if (state2.selection.$anchor.sameParent(state2.selection.$head)) {
2317
+ attributesToCopy = state2.selection.$anchor.parent.attrs;
2318
+ }
2319
+ if (isActive2) {
2320
+ return commands2.setNode(toggleType, attributesToCopy);
2321
+ }
2322
+ return commands2.setNode(type, { ...attributesToCopy, ...attributes });
2323
+ };
2324
+ var toggleWrap = (typeOrName, attributes = {}) => ({ state: state2, commands: commands2 }) => {
2325
+ const type = getNodeType(typeOrName, state2.schema);
2326
+ const isActive2 = isNodeActive(state2, type, attributes);
2327
+ if (isActive2) {
2328
+ return commands2.lift(type);
2329
+ }
2330
+ return commands2.wrapIn(type, attributes);
2331
+ };
2332
+ var undoInputRule = () => ({ state: state2, dispatch }) => {
2333
+ const plugins = state2.plugins;
2334
+ for (let i = 0; i < plugins.length; i += 1) {
2335
+ const plugin = plugins[i];
2336
+ let undoable;
2337
+ if (plugin.spec.isInputRules && (undoable = plugin.getState(state2))) {
2338
+ if (dispatch) {
2339
+ const tr = state2.tr;
2340
+ const toUndo = undoable.transform;
2341
+ for (let j = toUndo.steps.length - 1; j >= 0; j -= 1) {
2342
+ tr.step(toUndo.steps[j].invert(toUndo.docs[j]));
2343
+ }
2344
+ if (undoable.text) {
2345
+ const marks = tr.doc.resolve(undoable.from).marks();
2346
+ tr.replaceWith(undoable.from, undoable.to, state2.schema.text(undoable.text, marks));
2347
+ } else {
2348
+ tr.delete(undoable.from, undoable.to);
2349
+ }
2350
+ }
2351
+ return true;
2352
+ }
2353
+ }
2354
+ return false;
2355
+ };
2356
+ var unsetAllMarks = () => ({ tr, dispatch }) => {
2357
+ const { selection } = tr;
2358
+ const { empty, ranges } = selection;
2359
+ if (empty) {
2360
+ return true;
2361
+ }
2362
+ if (dispatch) {
2363
+ ranges.forEach((range) => {
2364
+ tr.removeMark(range.$from.pos, range.$to.pos);
2365
+ });
2366
+ }
2367
+ return true;
2368
+ };
2369
+ var unsetMark = (typeOrName, options = {}) => ({ tr, state: state2, dispatch }) => {
2370
+ var _a;
2371
+ const { extendEmptyMarkRange = false } = options;
2372
+ const { selection } = tr;
2373
+ const type = getMarkType(typeOrName, state2.schema);
2374
+ const { $from, empty, ranges } = selection;
2375
+ if (!dispatch) {
2376
+ return true;
2377
+ }
2378
+ if (empty && extendEmptyMarkRange) {
2379
+ let { from, to } = selection;
2380
+ const attrs = (_a = $from.marks().find((mark) => mark.type === type)) == null ? void 0 : _a.attrs;
2381
+ const range = getMarkRange($from, type, attrs);
2382
+ if (range) {
2383
+ from = range.from;
2384
+ to = range.to;
2385
+ }
2386
+ tr.removeMark(from, to, type);
2387
+ } else {
2388
+ ranges.forEach((range) => {
2389
+ tr.removeMark(range.$from.pos, range.$to.pos, type);
2390
+ });
2391
+ }
2392
+ tr.removeStoredMark(type);
2393
+ return true;
2394
+ };
2395
+ var unsetTextDirection = (position) => ({ tr, state: state2, dispatch }) => {
2396
+ const { selection } = state2;
2397
+ let from;
2398
+ let to;
2399
+ if (typeof position === "number") {
2400
+ from = position;
2401
+ to = position;
2402
+ } else if (position && "from" in position && "to" in position) {
2403
+ from = position.from;
2404
+ to = position.to;
2405
+ } else {
2406
+ from = selection.from;
2407
+ to = selection.to;
2408
+ }
2409
+ if (dispatch) {
2410
+ tr.doc.nodesBetween(from, to, (node, pos) => {
2411
+ if (node.isText) {
2412
+ return;
2413
+ }
2414
+ const newAttrs = { ...node.attrs };
2415
+ delete newAttrs.dir;
2416
+ tr.setNodeMarkup(pos, void 0, newAttrs);
2417
+ });
2418
+ }
2419
+ return true;
2420
+ };
2421
+ var updateAttributes = (typeOrName, attributes = {}) => ({ tr, state: state2, dispatch }) => {
2422
+ let nodeType = null;
2423
+ let markType = null;
2424
+ const schemaType = getSchemaTypeNameByName(
2425
+ typeof typeOrName === "string" ? typeOrName : typeOrName.name,
2426
+ state2.schema
2427
+ );
2428
+ if (!schemaType) {
2429
+ return false;
2430
+ }
2431
+ if (schemaType === "node") {
2432
+ nodeType = getNodeType(typeOrName, state2.schema);
2433
+ }
2434
+ if (schemaType === "mark") {
2435
+ markType = getMarkType(typeOrName, state2.schema);
2436
+ }
2437
+ let canUpdate = false;
2438
+ tr.selection.ranges.forEach((range) => {
2439
+ const from = range.$from.pos;
2440
+ const to = range.$to.pos;
2441
+ let lastPos;
2442
+ let lastNode;
2443
+ let trimmedFrom;
2444
+ let trimmedTo;
2445
+ if (tr.selection.empty) {
2446
+ state2.doc.nodesBetween(from, to, (node, pos) => {
2447
+ if (nodeType && nodeType === node.type) {
2448
+ canUpdate = true;
2449
+ trimmedFrom = Math.max(pos, from);
2450
+ trimmedTo = Math.min(pos + node.nodeSize, to);
2451
+ lastPos = pos;
2452
+ lastNode = node;
2453
+ }
2454
+ });
2455
+ } else {
2456
+ state2.doc.nodesBetween(from, to, (node, pos) => {
2457
+ if (pos < from && nodeType && nodeType === node.type) {
2458
+ canUpdate = true;
2459
+ trimmedFrom = Math.max(pos, from);
2460
+ trimmedTo = Math.min(pos + node.nodeSize, to);
2461
+ lastPos = pos;
2462
+ lastNode = node;
2463
+ }
2464
+ if (pos >= from && pos <= to) {
2465
+ if (nodeType && nodeType === node.type) {
2466
+ canUpdate = true;
2467
+ if (dispatch) {
2468
+ tr.setNodeMarkup(pos, void 0, {
2469
+ ...node.attrs,
2470
+ ...attributes
2471
+ });
2472
+ }
2473
+ }
2474
+ if (markType && node.marks.length) {
2475
+ node.marks.forEach((mark) => {
2476
+ if (markType === mark.type) {
2477
+ canUpdate = true;
2478
+ if (dispatch) {
2479
+ const trimmedFrom2 = Math.max(pos, from);
2480
+ const trimmedTo2 = Math.min(pos + node.nodeSize, to);
2481
+ tr.addMark(
2482
+ trimmedFrom2,
2483
+ trimmedTo2,
2484
+ markType.create({
2485
+ ...mark.attrs,
2486
+ ...attributes
2487
+ })
2488
+ );
2489
+ }
2490
+ }
2491
+ });
2492
+ }
2493
+ }
2494
+ });
2495
+ }
2496
+ if (lastNode) {
2497
+ if (lastPos !== void 0 && dispatch) {
2498
+ tr.setNodeMarkup(lastPos, void 0, {
2499
+ ...lastNode.attrs,
2500
+ ...attributes
2501
+ });
2502
+ }
2503
+ if (markType && lastNode.marks.length) {
2504
+ lastNode.marks.forEach((mark) => {
2505
+ if (markType === mark.type && dispatch) {
2506
+ tr.addMark(
2507
+ trimmedFrom,
2508
+ trimmedTo,
2509
+ markType.create({
2510
+ ...mark.attrs,
2511
+ ...attributes
2512
+ })
2513
+ );
2514
+ }
2515
+ });
2516
+ }
2517
+ }
2518
+ });
2519
+ return canUpdate;
2520
+ };
2521
+ var wrapIn = (typeOrName, attributes = {}) => ({ state: state2, dispatch }) => {
2522
+ const type = getNodeType(typeOrName, state2.schema);
2523
+ return commands.wrapIn(type, attributes)(state2, dispatch);
2524
+ };
2525
+ var wrapInList = (typeOrName, attributes = {}) => ({ state: state2, dispatch }) => {
2526
+ const type = getNodeType(typeOrName, state2.schema);
2527
+ return schemaList.wrapInList(type, attributes)(state2, dispatch);
2528
+ };
2529
+ var InputRule = class {
2530
+ constructor(config) {
2531
+ var _a;
2532
+ this.find = config.find;
2533
+ this.handler = config.handler;
2534
+ this.undoable = (_a = config.undoable) != null ? _a : true;
2535
+ }
2536
+ };
2537
+ function getType(value) {
2538
+ return Object.prototype.toString.call(value).slice(8, -1);
2539
+ }
2540
+ function isPlainObject(value) {
2541
+ if (getType(value) !== "Object") {
2542
+ return false;
2543
+ }
2544
+ return value.constructor === Object && Object.getPrototypeOf(value) === Object.prototype;
2545
+ }
2546
+ function mergeDeep(target, source) {
2547
+ const output = { ...target };
2548
+ if (isPlainObject(target) && isPlainObject(source)) {
2549
+ Object.keys(source).forEach((key) => {
2550
+ if (isPlainObject(source[key]) && isPlainObject(target[key])) {
2551
+ output[key] = mergeDeep(target[key], source[key]);
2552
+ } else {
2553
+ output[key] = source[key];
2554
+ }
2555
+ });
2556
+ }
2557
+ return output;
2558
+ }
2559
+ var Extendable = class {
2560
+ constructor(config = {}) {
2561
+ this.type = "extendable";
2562
+ this.parent = null;
2563
+ this.child = null;
2564
+ this.name = "";
2565
+ this.config = {
2566
+ name: this.name
2567
+ };
2568
+ this.config = {
2569
+ ...this.config,
2570
+ ...config
2571
+ };
2572
+ this.name = this.config.name;
2573
+ }
2574
+ get options() {
2575
+ return {
2576
+ ...callOrReturn(
2577
+ getExtensionField(this, "addOptions", {
2578
+ name: this.name
2579
+ })
2580
+ ) || {}
2581
+ };
2582
+ }
2583
+ get storage() {
2584
+ return {
2585
+ ...callOrReturn(
2586
+ getExtensionField(this, "addStorage", {
2587
+ name: this.name,
2588
+ options: this.options
2589
+ })
2590
+ ) || {}
2591
+ };
2592
+ }
2593
+ configure(options = {}) {
2594
+ const extension = this.extend({
2595
+ ...this.config,
2596
+ addOptions: () => {
2597
+ return mergeDeep(this.options, options);
2598
+ }
2599
+ });
2600
+ extension.name = this.name;
2601
+ extension.parent = this.parent;
2602
+ return extension;
2603
+ }
2604
+ extend(extendedConfig = {}) {
2605
+ const extension = new this.constructor({ ...this.config, ...extendedConfig });
2606
+ extension.parent = this;
2607
+ this.child = extension;
2608
+ extension.name = "name" in extendedConfig ? extendedConfig.name : extension.parent.name;
2609
+ return extension;
2610
+ }
2611
+ };
2612
+ var extensions_exports = {};
2613
+ __export(extensions_exports, {
2614
+ ClipboardTextSerializer: () => ClipboardTextSerializer,
2615
+ Commands: () => Commands,
2616
+ Delete: () => Delete,
2617
+ Drop: () => Drop,
2618
+ Editable: () => Editable,
2619
+ FocusEvents: () => FocusEvents,
2620
+ Keymap: () => Keymap,
2621
+ Paste: () => Paste,
2622
+ Tabindex: () => Tabindex,
2623
+ TextDirection: () => TextDirection,
2624
+ focusEventsPluginKey: () => focusEventsPluginKey
2625
+ });
2626
+ var Extension = class _Extension extends Extendable {
2627
+ constructor() {
2628
+ super(...arguments);
2629
+ this.type = "extension";
2630
+ }
2631
+ /**
2632
+ * Create a new Extension instance
2633
+ * @param config - Extension configuration object or a function that returns a configuration object
2634
+ */
2635
+ static create(config = {}) {
2636
+ const resolvedConfig = typeof config === "function" ? config() : config;
2637
+ return new _Extension(resolvedConfig);
2638
+ }
2639
+ configure(options) {
2640
+ return super.configure(options);
2641
+ }
2642
+ extend(extendedConfig) {
2643
+ const resolvedConfig = typeof extendedConfig === "function" ? extendedConfig() : extendedConfig;
2644
+ return super.extend(resolvedConfig);
2645
+ }
2646
+ };
2647
+ var ClipboardTextSerializer = Extension.create({
2648
+ name: "clipboardTextSerializer",
2649
+ addOptions() {
2650
+ return {
2651
+ blockSeparator: void 0
2652
+ };
2653
+ },
2654
+ addProseMirrorPlugins() {
2655
+ return [
2656
+ new state.Plugin({
2657
+ key: new state.PluginKey("clipboardTextSerializer"),
2658
+ props: {
2659
+ clipboardTextSerializer: () => {
2660
+ const { editor } = this;
2661
+ const { state: state2, schema } = editor;
2662
+ const { doc, selection } = state2;
2663
+ const { ranges } = selection;
2664
+ const from = Math.min(...ranges.map((range2) => range2.$from.pos));
2665
+ const to = Math.max(...ranges.map((range2) => range2.$to.pos));
2666
+ const textSerializers = getTextSerializersFromSchema(schema);
2667
+ const range = { from, to };
2668
+ return getTextBetween(doc, range, {
2669
+ ...this.options.blockSeparator !== void 0 ? { blockSeparator: this.options.blockSeparator } : {},
2670
+ textSerializers
2671
+ });
2672
+ }
2673
+ }
2674
+ })
2675
+ ];
2676
+ }
2677
+ });
2678
+ var Commands = Extension.create({
2679
+ name: "commands",
2680
+ addCommands() {
2681
+ return {
2682
+ ...commands_exports
2683
+ };
2684
+ }
2685
+ });
2686
+ var Delete = Extension.create({
2687
+ name: "delete",
2688
+ onUpdate({ transaction, appendedTransactions }) {
2689
+ var _a, _b, _c;
2690
+ const callback = () => {
2691
+ var _a2, _b2, _c2, _d;
2692
+ if ((_d = (_c2 = (_b2 = (_a2 = this.editor.options.coreExtensionOptions) == null ? void 0 : _a2.delete) == null ? void 0 : _b2.filterTransaction) == null ? void 0 : _c2.call(_b2, transaction)) != null ? _d : transaction.getMeta("y-sync$")) {
2693
+ return;
2694
+ }
2695
+ const nextTransaction = combineTransactionSteps(transaction.before, [transaction, ...appendedTransactions]);
2696
+ const changes = getChangedRanges(nextTransaction);
2697
+ changes.forEach((change) => {
2698
+ if (nextTransaction.mapping.mapResult(change.oldRange.from).deletedAfter && nextTransaction.mapping.mapResult(change.oldRange.to).deletedBefore) {
2699
+ nextTransaction.before.nodesBetween(change.oldRange.from, change.oldRange.to, (node, from) => {
2700
+ const to = from + node.nodeSize - 2;
2701
+ const isFullyWithinRange = change.oldRange.from <= from && to <= change.oldRange.to;
2702
+ this.editor.emit("delete", {
2703
+ type: "node",
2704
+ node,
2705
+ from,
2706
+ to,
2707
+ newFrom: nextTransaction.mapping.map(from),
2708
+ newTo: nextTransaction.mapping.map(to),
2709
+ deletedRange: change.oldRange,
2710
+ newRange: change.newRange,
2711
+ partial: !isFullyWithinRange,
2712
+ editor: this.editor,
2713
+ transaction,
2714
+ combinedTransform: nextTransaction
2715
+ });
2716
+ });
2717
+ }
2718
+ });
2719
+ const mapping = nextTransaction.mapping;
2720
+ nextTransaction.steps.forEach((step, index) => {
2721
+ var _a3, _b3;
2722
+ if (step instanceof transform.RemoveMarkStep) {
2723
+ const newStart = mapping.slice(index).map(step.from, -1);
2724
+ const newEnd = mapping.slice(index).map(step.to);
2725
+ const oldStart = mapping.invert().map(newStart, -1);
2726
+ const oldEnd = mapping.invert().map(newEnd);
2727
+ const foundBeforeMark = (_a3 = nextTransaction.doc.nodeAt(newStart - 1)) == null ? void 0 : _a3.marks.some((mark) => mark.eq(step.mark));
2728
+ const foundAfterMark = (_b3 = nextTransaction.doc.nodeAt(newEnd)) == null ? void 0 : _b3.marks.some((mark) => mark.eq(step.mark));
2729
+ this.editor.emit("delete", {
2730
+ type: "mark",
2731
+ mark: step.mark,
2732
+ from: step.from,
2733
+ to: step.to,
2734
+ deletedRange: {
2735
+ from: oldStart,
2736
+ to: oldEnd
2737
+ },
2738
+ newRange: {
2739
+ from: newStart,
2740
+ to: newEnd
2741
+ },
2742
+ partial: Boolean(foundAfterMark || foundBeforeMark),
2743
+ editor: this.editor,
2744
+ transaction,
2745
+ combinedTransform: nextTransaction
2746
+ });
2747
+ }
2748
+ });
2749
+ };
2750
+ if ((_c = (_b = (_a = this.editor.options.coreExtensionOptions) == null ? void 0 : _a.delete) == null ? void 0 : _b.async) != null ? _c : true) {
2751
+ setTimeout(callback, 0);
2752
+ } else {
2753
+ callback();
2754
+ }
2755
+ }
2756
+ });
2757
+ var Drop = Extension.create({
2758
+ name: "drop",
2759
+ addProseMirrorPlugins() {
2760
+ return [
2761
+ new state.Plugin({
2762
+ key: new state.PluginKey("tiptapDrop"),
2763
+ props: {
2764
+ handleDrop: (_, e, slice, moved) => {
2765
+ this.editor.emit("drop", {
2766
+ editor: this.editor,
2767
+ event: e,
2768
+ slice,
2769
+ moved
2770
+ });
2771
+ }
2772
+ }
2773
+ })
2774
+ ];
2775
+ }
2776
+ });
2777
+ var Editable = Extension.create({
2778
+ name: "editable",
2779
+ addProseMirrorPlugins() {
2780
+ return [
2781
+ new state.Plugin({
2782
+ key: new state.PluginKey("editable"),
2783
+ props: {
2784
+ editable: () => this.editor.options.editable
2785
+ }
2786
+ })
2787
+ ];
2788
+ }
2789
+ });
2790
+ var focusEventsPluginKey = new state.PluginKey("focusEvents");
2791
+ var FocusEvents = Extension.create({
2792
+ name: "focusEvents",
2793
+ addProseMirrorPlugins() {
2794
+ const { editor } = this;
2795
+ return [
2796
+ new state.Plugin({
2797
+ key: focusEventsPluginKey,
2798
+ props: {
2799
+ handleDOMEvents: {
2800
+ focus: (view2, event) => {
2801
+ editor.isFocused = true;
2802
+ const transaction = editor.state.tr.setMeta("focus", { event }).setMeta("addToHistory", false);
2803
+ view2.dispatch(transaction);
2804
+ return false;
2805
+ },
2806
+ blur: (view2, event) => {
2807
+ editor.isFocused = false;
2808
+ const transaction = editor.state.tr.setMeta("blur", { event }).setMeta("addToHistory", false);
2809
+ view2.dispatch(transaction);
2810
+ return false;
2811
+ }
2812
+ }
2813
+ }
2814
+ })
2815
+ ];
2816
+ }
2817
+ });
2818
+ var Keymap = Extension.create({
2819
+ name: "keymap",
2820
+ addKeyboardShortcuts() {
2821
+ const handleBackspace = () => this.editor.commands.first(({ commands: commands2 }) => [
2822
+ () => commands2.undoInputRule(),
2823
+ // maybe convert first text block node to default node
2824
+ () => commands2.command(({ tr }) => {
2825
+ const { selection, doc } = tr;
2826
+ const { empty, $anchor } = selection;
2827
+ const { pos, parent } = $anchor;
2828
+ const $parentPos = $anchor.parent.isTextblock && pos > 0 ? tr.doc.resolve(pos - 1) : $anchor;
2829
+ const parentIsIsolating = $parentPos.parent.type.spec.isolating;
2830
+ const parentPos = $anchor.pos - $anchor.parentOffset;
2831
+ const isAtStart = parentIsIsolating && $parentPos.parent.childCount === 1 ? parentPos === $anchor.pos : state.Selection.atStart(doc).from === pos;
2832
+ if (!empty || !parent.type.isTextblock || parent.textContent.length || !isAtStart || isAtStart && $anchor.parent.type.name === "paragraph") {
2833
+ return false;
2834
+ }
2835
+ return commands2.clearNodes();
2836
+ }),
2837
+ () => commands2.deleteSelection(),
2838
+ () => commands2.joinBackward(),
2839
+ () => commands2.selectNodeBackward()
2840
+ ]);
2841
+ const handleDelete = () => this.editor.commands.first(({ commands: commands2 }) => [
2842
+ () => commands2.deleteSelection(),
2843
+ () => commands2.deleteCurrentNode(),
2844
+ () => commands2.joinForward(),
2845
+ () => commands2.selectNodeForward()
2846
+ ]);
2847
+ const handleEnter = () => this.editor.commands.first(({ commands: commands2 }) => [
2848
+ () => commands2.newlineInCode(),
2849
+ () => commands2.createParagraphNear(),
2850
+ () => commands2.liftEmptyBlock(),
2851
+ () => commands2.splitBlock()
2852
+ ]);
2853
+ const baseKeymap = {
2854
+ Enter: handleEnter,
2855
+ "Mod-Enter": () => this.editor.commands.exitCode(),
2856
+ Backspace: handleBackspace,
2857
+ "Mod-Backspace": handleBackspace,
2858
+ "Shift-Backspace": handleBackspace,
2859
+ Delete: handleDelete,
2860
+ "Mod-Delete": handleDelete,
2861
+ "Mod-a": () => this.editor.commands.selectAll()
2862
+ };
2863
+ const pcKeymap = {
2864
+ ...baseKeymap
2865
+ };
2866
+ const macKeymap = {
2867
+ ...baseKeymap,
2868
+ "Ctrl-h": handleBackspace,
2869
+ "Alt-Backspace": handleBackspace,
2870
+ "Ctrl-d": handleDelete,
2871
+ "Ctrl-Alt-Backspace": handleDelete,
2872
+ "Alt-Delete": handleDelete,
2873
+ "Alt-d": handleDelete,
2874
+ "Ctrl-a": () => this.editor.commands.selectTextblockStart(),
2875
+ "Ctrl-e": () => this.editor.commands.selectTextblockEnd()
2876
+ };
2877
+ if (isiOS() || isMacOS()) {
2878
+ return macKeymap;
2879
+ }
2880
+ return pcKeymap;
2881
+ },
2882
+ addProseMirrorPlugins() {
2883
+ return [
2884
+ // With this plugin we check if the whole document was selected and deleted.
2885
+ // In this case we will additionally call `clearNodes()` to convert e.g. a heading
2886
+ // to a paragraph if necessary.
2887
+ // This is an alternative to ProseMirror's `AllSelection`, which doesn’t work well
2888
+ // with many other commands.
2889
+ new state.Plugin({
2890
+ key: new state.PluginKey("clearDocument"),
2891
+ appendTransaction: (transactions, oldState, newState) => {
2892
+ if (transactions.some((tr2) => tr2.getMeta("composition"))) {
2893
+ return;
2894
+ }
2895
+ const docChanges = transactions.some((transaction) => transaction.docChanged) && !oldState.doc.eq(newState.doc);
2896
+ const ignoreTr = transactions.some((transaction) => transaction.getMeta("preventClearDocument"));
2897
+ if (!docChanges || ignoreTr) {
2898
+ return;
2899
+ }
2900
+ const { empty, from, to } = oldState.selection;
2901
+ const allFrom = state.Selection.atStart(oldState.doc).from;
2902
+ const allEnd = state.Selection.atEnd(oldState.doc).to;
2903
+ const allWasSelected = from === allFrom && to === allEnd;
2904
+ if (empty || !allWasSelected) {
2905
+ return;
2906
+ }
2907
+ const isEmpty = isNodeEmpty(newState.doc);
2908
+ if (!isEmpty) {
2909
+ return;
2910
+ }
2911
+ const tr = newState.tr;
2912
+ const state$1 = createChainableState({
2913
+ state: newState,
2914
+ transaction: tr
2915
+ });
2916
+ const { commands: commands2 } = new CommandManager({
2917
+ editor: this.editor,
2918
+ state: state$1
2919
+ });
2920
+ commands2.clearNodes();
2921
+ if (!tr.steps.length) {
2922
+ return;
2923
+ }
2924
+ return tr;
2925
+ }
2926
+ })
2927
+ ];
2928
+ }
2929
+ });
2930
+ var Paste = Extension.create({
2931
+ name: "paste",
2932
+ addProseMirrorPlugins() {
2933
+ return [
2934
+ new state.Plugin({
2935
+ key: new state.PluginKey("tiptapPaste"),
2936
+ props: {
2937
+ handlePaste: (_view, e, slice) => {
2938
+ this.editor.emit("paste", {
2939
+ editor: this.editor,
2940
+ event: e,
2941
+ slice
2942
+ });
2943
+ }
2944
+ }
2945
+ })
2946
+ ];
2947
+ }
2948
+ });
2949
+ var Tabindex = Extension.create({
2950
+ name: "tabindex",
2951
+ addProseMirrorPlugins() {
2952
+ return [
2953
+ new state.Plugin({
2954
+ key: new state.PluginKey("tabindex"),
2955
+ props: {
2956
+ attributes: () => this.editor.isEditable ? { tabindex: "0" } : {}
2957
+ }
2958
+ })
2959
+ ];
2960
+ }
2961
+ });
2962
+ var TextDirection = Extension.create({
2963
+ name: "textDirection",
2964
+ addOptions() {
2965
+ return {
2966
+ direction: void 0
2967
+ };
2968
+ },
2969
+ addGlobalAttributes() {
2970
+ if (!this.options.direction) {
2971
+ return [];
2972
+ }
2973
+ const { nodeExtensions } = splitExtensions(this.extensions);
2974
+ return [
2975
+ {
2976
+ types: nodeExtensions.filter((extension) => extension.name !== "text").map((extension) => extension.name),
2977
+ attributes: {
2978
+ dir: {
2979
+ default: this.options.direction,
2980
+ parseHTML: (element) => {
2981
+ const dir = element.getAttribute("dir");
2982
+ if (dir && (dir === "ltr" || dir === "rtl" || dir === "auto")) {
2983
+ return dir;
2984
+ }
2985
+ return this.options.direction;
2986
+ },
2987
+ renderHTML: (attributes) => {
2988
+ if (!attributes.dir) {
2989
+ return {};
2990
+ }
2991
+ return {
2992
+ dir: attributes.dir
2993
+ };
2994
+ }
2995
+ }
2996
+ }
2997
+ }
2998
+ ];
2999
+ },
3000
+ addProseMirrorPlugins() {
3001
+ return [
3002
+ new state.Plugin({
3003
+ key: new state.PluginKey("textDirection"),
3004
+ props: {
3005
+ attributes: () => {
3006
+ const direction = this.options.direction;
3007
+ if (!direction) {
3008
+ return {};
3009
+ }
3010
+ return {
3011
+ dir: direction
3012
+ };
3013
+ }
3014
+ }
3015
+ })
3016
+ ];
3017
+ }
3018
+ });
3019
+ function textblockTypeInputRule(config) {
3020
+ return new InputRule({
3021
+ find: config.find,
3022
+ handler: ({ state: state2, range, match }) => {
3023
+ const $start = state2.doc.resolve(range.from);
3024
+ const attributes = callOrReturn(config.getAttributes, void 0, match) || {};
3025
+ if (!$start.node(-1).canReplaceWith($start.index(-1), $start.indexAfter(-1), config.type)) {
3026
+ return null;
3027
+ }
3028
+ state2.tr.delete(range.from, range.to).setBlockType(range.from, range.from, config.type, attributes);
3029
+ },
3030
+ undoable: config.undoable
3031
+ });
3032
+ }
3033
+ var markdown_exports = {};
3034
+ __export(markdown_exports, {
3035
+ createAtomBlockMarkdownSpec: () => createAtomBlockMarkdownSpec,
3036
+ createBlockMarkdownSpec: () => createBlockMarkdownSpec,
3037
+ createInlineMarkdownSpec: () => createInlineMarkdownSpec,
3038
+ parseAttributes: () => parseAttributes,
3039
+ parseIndentedBlocks: () => parseIndentedBlocks,
3040
+ renderNestedMarkdownContent: () => renderNestedMarkdownContent,
3041
+ serializeAttributes: () => serializeAttributes
3042
+ });
3043
+ function parseAttributes(attrString) {
3044
+ if (!(attrString == null ? void 0 : attrString.trim())) {
3045
+ return {};
3046
+ }
3047
+ const attributes = {};
3048
+ const quotedStrings = [];
3049
+ const tempString = attrString.replace(/["']([^"']*)["']/g, (match) => {
3050
+ quotedStrings.push(match);
3051
+ return `__QUOTED_${quotedStrings.length - 1}__`;
3052
+ });
3053
+ const classMatches = tempString.match(/(?:^|\s)\.([a-zA-Z][\w-]*)/g);
3054
+ if (classMatches) {
3055
+ const classes = classMatches.map((match) => match.trim().slice(1));
3056
+ attributes.class = classes.join(" ");
3057
+ }
3058
+ const idMatch = tempString.match(/(?:^|\s)#([a-zA-Z][\w-]*)/);
3059
+ if (idMatch) {
3060
+ attributes.id = idMatch[1];
3061
+ }
3062
+ const kvRegex = /([a-zA-Z][\w-]*)\s*=\s*(__QUOTED_\d+__)/g;
3063
+ const kvMatches = Array.from(tempString.matchAll(kvRegex));
3064
+ kvMatches.forEach(([, key, quotedRef]) => {
3065
+ var _a;
3066
+ const quotedIndex = parseInt(((_a = quotedRef.match(/__QUOTED_(\d+)__/)) == null ? void 0 : _a[1]) || "0", 10);
3067
+ const quotedValue = quotedStrings[quotedIndex];
3068
+ if (quotedValue) {
3069
+ attributes[key] = quotedValue.slice(1, -1);
3070
+ }
3071
+ });
3072
+ const cleanString = tempString.replace(/(?:^|\s)\.([a-zA-Z][\w-]*)/g, "").replace(/(?:^|\s)#([a-zA-Z][\w-]*)/g, "").replace(/([a-zA-Z][\w-]*)\s*=\s*__QUOTED_\d+__/g, "").trim();
3073
+ if (cleanString) {
3074
+ const booleanAttrs = cleanString.split(/\s+/).filter(Boolean);
3075
+ booleanAttrs.forEach((attr) => {
3076
+ if (attr.match(/^[a-zA-Z][\w-]*$/)) {
3077
+ attributes[attr] = true;
3078
+ }
3079
+ });
3080
+ }
3081
+ return attributes;
3082
+ }
3083
+ function serializeAttributes(attributes) {
3084
+ if (!attributes || Object.keys(attributes).length === 0) {
3085
+ return "";
3086
+ }
3087
+ const parts = [];
3088
+ if (attributes.class) {
3089
+ const classes = String(attributes.class).split(/\s+/).filter(Boolean);
3090
+ classes.forEach((cls) => parts.push(`.${cls}`));
3091
+ }
3092
+ if (attributes.id) {
3093
+ parts.push(`#${attributes.id}`);
3094
+ }
3095
+ Object.entries(attributes).forEach(([key, value]) => {
3096
+ if (key === "class" || key === "id") {
3097
+ return;
3098
+ }
3099
+ if (value === true) {
3100
+ parts.push(key);
3101
+ } else if (value !== false && value != null) {
3102
+ parts.push(`${key}="${String(value)}"`);
3103
+ }
3104
+ });
3105
+ return parts.join(" ");
3106
+ }
3107
+ function createAtomBlockMarkdownSpec(options) {
3108
+ const {
3109
+ nodeName,
3110
+ name: markdownName,
3111
+ parseAttributes: parseAttributes2 = parseAttributes,
3112
+ serializeAttributes: serializeAttributes2 = serializeAttributes,
3113
+ defaultAttributes = {},
3114
+ requiredAttributes = [],
3115
+ allowedAttributes
3116
+ } = options;
3117
+ const blockName = markdownName || nodeName;
3118
+ const filterAttributes = (attrs) => {
3119
+ if (!allowedAttributes) {
3120
+ return attrs;
3121
+ }
3122
+ const filtered = {};
3123
+ allowedAttributes.forEach((key) => {
3124
+ if (key in attrs) {
3125
+ filtered[key] = attrs[key];
3126
+ }
3127
+ });
3128
+ return filtered;
3129
+ };
3130
+ return {
3131
+ parseMarkdown: (token, h2) => {
3132
+ const attrs = { ...defaultAttributes, ...token.attributes };
3133
+ return h2.createNode(nodeName, attrs, []);
3134
+ },
3135
+ markdownTokenizer: {
3136
+ name: nodeName,
3137
+ level: "block",
3138
+ start(src) {
3139
+ var _a;
3140
+ const regex = new RegExp(`^:::${blockName}(?:\\s|$)`, "m");
3141
+ const index = (_a = src.match(regex)) == null ? void 0 : _a.index;
3142
+ return index !== void 0 ? index : -1;
3143
+ },
3144
+ tokenize(src, _tokens, _lexer) {
3145
+ const regex = new RegExp(`^:::${blockName}(?:\\s+\\{([^}]*)\\})?\\s*:::(?:\\n|$)`);
3146
+ const match = src.match(regex);
3147
+ if (!match) {
3148
+ return void 0;
3149
+ }
3150
+ const attrString = match[1] || "";
3151
+ const attributes = parseAttributes2(attrString);
3152
+ const missingRequired = requiredAttributes.find((required) => !(required in attributes));
3153
+ if (missingRequired) {
3154
+ return void 0;
3155
+ }
3156
+ return {
3157
+ type: nodeName,
3158
+ raw: match[0],
3159
+ attributes
3160
+ };
3161
+ }
3162
+ },
3163
+ renderMarkdown: (node) => {
3164
+ const filteredAttrs = filterAttributes(node.attrs || {});
3165
+ const attrs = serializeAttributes2(filteredAttrs);
3166
+ const attrString = attrs ? ` {${attrs}}` : "";
3167
+ return `:::${blockName}${attrString} :::`;
3168
+ }
3169
+ };
3170
+ }
3171
+ function createBlockMarkdownSpec(options) {
3172
+ const {
3173
+ nodeName,
3174
+ name: markdownName,
3175
+ getContent,
3176
+ parseAttributes: parseAttributes2 = parseAttributes,
3177
+ serializeAttributes: serializeAttributes2 = serializeAttributes,
3178
+ defaultAttributes = {},
3179
+ content = "block",
3180
+ allowedAttributes
3181
+ } = options;
3182
+ const blockName = markdownName || nodeName;
3183
+ const filterAttributes = (attrs) => {
3184
+ if (!allowedAttributes) {
3185
+ return attrs;
3186
+ }
3187
+ const filtered = {};
3188
+ allowedAttributes.forEach((key) => {
3189
+ if (key in attrs) {
3190
+ filtered[key] = attrs[key];
3191
+ }
3192
+ });
3193
+ return filtered;
3194
+ };
3195
+ return {
3196
+ parseMarkdown: (token, h2) => {
3197
+ let nodeContent;
3198
+ if (getContent) {
3199
+ const contentResult = getContent(token);
3200
+ nodeContent = typeof contentResult === "string" ? [{ type: "text", text: contentResult }] : contentResult;
3201
+ } else if (content === "block") {
3202
+ nodeContent = h2.parseChildren(token.tokens || []);
3203
+ } else {
3204
+ nodeContent = h2.parseInline(token.tokens || []);
3205
+ }
3206
+ const attrs = { ...defaultAttributes, ...token.attributes };
3207
+ return h2.createNode(nodeName, attrs, nodeContent);
3208
+ },
3209
+ markdownTokenizer: {
3210
+ name: nodeName,
3211
+ level: "block",
3212
+ start(src) {
3213
+ var _a;
3214
+ const regex = new RegExp(`^:::${blockName}`, "m");
3215
+ const index = (_a = src.match(regex)) == null ? void 0 : _a.index;
3216
+ return index !== void 0 ? index : -1;
3217
+ },
3218
+ tokenize(src, _tokens, lexer) {
3219
+ var _a;
3220
+ const openingRegex = new RegExp(`^:::${blockName}(?:\\s+\\{([^}]*)\\})?\\s*\\n`);
3221
+ const openingMatch = src.match(openingRegex);
3222
+ if (!openingMatch) {
3223
+ return void 0;
3224
+ }
3225
+ const [openingTag, attrString = ""] = openingMatch;
3226
+ const attributes = parseAttributes2(attrString);
3227
+ let level = 1;
3228
+ const position = openingTag.length;
3229
+ let matchedContent = "";
3230
+ const blockPattern = /^:::([\w-]*)(\s.*)?/gm;
3231
+ const remaining = src.slice(position);
3232
+ blockPattern.lastIndex = 0;
3233
+ for (; ; ) {
3234
+ const match = blockPattern.exec(remaining);
3235
+ if (match === null) {
3236
+ break;
3237
+ }
3238
+ const matchPos = match.index;
3239
+ const blockType = match[1];
3240
+ if ((_a = match[2]) == null ? void 0 : _a.endsWith(":::")) {
3241
+ continue;
3242
+ }
3243
+ if (blockType) {
3244
+ level += 1;
3245
+ } else {
3246
+ level -= 1;
3247
+ if (level === 0) {
3248
+ const rawContent = remaining.slice(0, matchPos);
3249
+ matchedContent = rawContent.trim();
3250
+ const fullMatch = src.slice(0, position + matchPos + match[0].length);
3251
+ let contentTokens = [];
3252
+ if (matchedContent) {
3253
+ if (content === "block") {
3254
+ contentTokens = lexer.blockTokens(rawContent);
3255
+ contentTokens.forEach((token) => {
3256
+ if (token.text && (!token.tokens || token.tokens.length === 0)) {
3257
+ token.tokens = lexer.inlineTokens(token.text);
3258
+ }
3259
+ });
3260
+ while (contentTokens.length > 0) {
3261
+ const lastToken = contentTokens[contentTokens.length - 1];
3262
+ if (lastToken.type === "paragraph" && (!lastToken.text || lastToken.text.trim() === "")) {
3263
+ contentTokens.pop();
3264
+ } else {
3265
+ break;
3266
+ }
3267
+ }
3268
+ } else {
3269
+ contentTokens = lexer.inlineTokens(matchedContent);
3270
+ }
3271
+ }
3272
+ return {
3273
+ type: nodeName,
3274
+ raw: fullMatch,
3275
+ attributes,
3276
+ content: matchedContent,
3277
+ tokens: contentTokens
3278
+ };
3279
+ }
3280
+ }
3281
+ }
3282
+ return void 0;
3283
+ }
3284
+ },
3285
+ renderMarkdown: (node, h2) => {
3286
+ const filteredAttrs = filterAttributes(node.attrs || {});
3287
+ const attrs = serializeAttributes2(filteredAttrs);
3288
+ const attrString = attrs ? ` {${attrs}}` : "";
3289
+ const renderedContent = h2.renderChildren(node.content || [], "\n\n");
3290
+ return `:::${blockName}${attrString}
3291
+
3292
+ ${renderedContent}
3293
+
3294
+ :::`;
3295
+ }
3296
+ };
3297
+ }
3298
+ function parseShortcodeAttributes(attrString) {
3299
+ if (!attrString.trim()) {
3300
+ return {};
3301
+ }
3302
+ const attributes = {};
3303
+ const regex = /(\w+)=(?:"([^"]*)"|'([^']*)')/g;
3304
+ let match = regex.exec(attrString);
3305
+ while (match !== null) {
3306
+ const [, key, doubleQuoted, singleQuoted] = match;
3307
+ attributes[key] = doubleQuoted || singleQuoted;
3308
+ match = regex.exec(attrString);
3309
+ }
3310
+ return attributes;
3311
+ }
3312
+ function serializeShortcodeAttributes(attrs) {
3313
+ return Object.entries(attrs).filter(([, value]) => value !== void 0 && value !== null).map(([key, value]) => `${key}="${value}"`).join(" ");
3314
+ }
3315
+ function createInlineMarkdownSpec(options) {
3316
+ const {
3317
+ nodeName,
3318
+ name: shortcodeName,
3319
+ getContent,
3320
+ parseAttributes: parseAttributes2 = parseShortcodeAttributes,
3321
+ serializeAttributes: serializeAttributes2 = serializeShortcodeAttributes,
3322
+ defaultAttributes = {},
3323
+ selfClosing = false,
3324
+ allowedAttributes
3325
+ } = options;
3326
+ const shortcode = shortcodeName || nodeName;
3327
+ const filterAttributes = (attrs) => {
3328
+ if (!allowedAttributes) {
3329
+ return attrs;
3330
+ }
3331
+ const filtered = {};
3332
+ allowedAttributes.forEach((attr) => {
3333
+ const attrName = typeof attr === "string" ? attr : attr.name;
3334
+ const skipIfDefault = typeof attr === "string" ? void 0 : attr.skipIfDefault;
3335
+ if (attrName in attrs) {
3336
+ const value = attrs[attrName];
3337
+ if (skipIfDefault !== void 0 && value === skipIfDefault) {
3338
+ return;
3339
+ }
3340
+ filtered[attrName] = value;
3341
+ }
3342
+ });
3343
+ return filtered;
3344
+ };
3345
+ const escapedShortcode = shortcode.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3346
+ return {
3347
+ parseMarkdown: (token, h2) => {
3348
+ const attrs = { ...defaultAttributes, ...token.attributes };
3349
+ if (selfClosing) {
3350
+ return h2.createNode(nodeName, attrs);
3351
+ }
3352
+ const content = getContent ? getContent(token) : token.content || "";
3353
+ if (content) {
3354
+ return h2.createNode(nodeName, attrs, [h2.createTextNode(content)]);
3355
+ }
3356
+ return h2.createNode(nodeName, attrs, []);
3357
+ },
3358
+ markdownTokenizer: {
3359
+ name: nodeName,
3360
+ level: "inline",
3361
+ start(src) {
3362
+ const startPattern = selfClosing ? new RegExp(`\\[${escapedShortcode}\\s*[^\\]]*\\]`) : new RegExp(`\\[${escapedShortcode}\\s*[^\\]]*\\][\\s\\S]*?\\[\\/${escapedShortcode}\\]`);
3363
+ const match = src.match(startPattern);
3364
+ const index = match == null ? void 0 : match.index;
3365
+ return index !== void 0 ? index : -1;
3366
+ },
3367
+ tokenize(src, _tokens, _lexer) {
3368
+ const tokenPattern = selfClosing ? new RegExp(`^\\[${escapedShortcode}\\s*([^\\]]*)\\]`) : new RegExp(`^\\[${escapedShortcode}\\s*([^\\]]*)\\]([\\s\\S]*?)\\[\\/${escapedShortcode}\\]`);
3369
+ const match = src.match(tokenPattern);
3370
+ if (!match) {
3371
+ return void 0;
3372
+ }
3373
+ let content = "";
3374
+ let attrString = "";
3375
+ if (selfClosing) {
3376
+ const [, attrs] = match;
3377
+ attrString = attrs;
3378
+ } else {
3379
+ const [, attrs, contentMatch] = match;
3380
+ attrString = attrs;
3381
+ content = contentMatch || "";
3382
+ }
3383
+ const attributes = parseAttributes2(attrString.trim());
3384
+ return {
3385
+ type: nodeName,
3386
+ raw: match[0],
3387
+ content: content.trim(),
3388
+ attributes
3389
+ };
3390
+ }
3391
+ },
3392
+ renderMarkdown: (node) => {
3393
+ let content = "";
3394
+ if (getContent) {
3395
+ content = getContent(node);
3396
+ } else if (node.content && node.content.length > 0) {
3397
+ content = node.content.filter((child) => child.type === "text").map((child) => child.text).join("");
3398
+ }
3399
+ const filteredAttrs = filterAttributes(node.attrs || {});
3400
+ const attrs = serializeAttributes2(filteredAttrs);
3401
+ const attrString = attrs ? ` ${attrs}` : "";
3402
+ if (selfClosing) {
3403
+ return `[${shortcode}${attrString}]`;
3404
+ }
3405
+ return `[${shortcode}${attrString}]${content}[/${shortcode}]`;
3406
+ }
3407
+ };
3408
+ }
3409
+ function parseIndentedBlocks(src, config, lexer) {
3410
+ var _a, _b, _c, _d;
3411
+ const lines = src.split("\n");
3412
+ const items = [];
3413
+ let totalRaw = "";
3414
+ let i = 0;
3415
+ const baseIndentSize = config.baseIndentSize || 2;
3416
+ while (i < lines.length) {
3417
+ const currentLine = lines[i];
3418
+ const itemMatch = currentLine.match(config.itemPattern);
3419
+ if (!itemMatch) {
3420
+ if (items.length > 0) {
3421
+ break;
3422
+ } else if (currentLine.trim() === "") {
3423
+ i += 1;
3424
+ totalRaw = `${totalRaw}${currentLine}
3425
+ `;
3426
+ continue;
3427
+ } else {
3428
+ return void 0;
3429
+ }
3430
+ }
3431
+ const itemData = config.extractItemData(itemMatch);
3432
+ const { indentLevel, mainContent } = itemData;
3433
+ totalRaw = `${totalRaw}${currentLine}
3434
+ `;
3435
+ const itemContent = [mainContent];
3436
+ i += 1;
3437
+ while (i < lines.length) {
3438
+ const nextLine = lines[i];
3439
+ if (nextLine.trim() === "") {
3440
+ const nextNonEmptyIndex = lines.slice(i + 1).findIndex((l) => l.trim() !== "");
3441
+ if (nextNonEmptyIndex === -1) {
3442
+ break;
3443
+ }
3444
+ const nextNonEmpty = lines[i + 1 + nextNonEmptyIndex];
3445
+ const nextIndent2 = ((_b = (_a = nextNonEmpty.match(/^(\s*)/)) == null ? void 0 : _a[1]) == null ? void 0 : _b.length) || 0;
3446
+ if (nextIndent2 > indentLevel) {
3447
+ itemContent.push(nextLine);
3448
+ totalRaw = `${totalRaw}${nextLine}
3449
+ `;
3450
+ i += 1;
3451
+ continue;
3452
+ } else {
3453
+ break;
3454
+ }
3455
+ }
3456
+ const nextIndent = ((_d = (_c = nextLine.match(/^(\s*)/)) == null ? void 0 : _c[1]) == null ? void 0 : _d.length) || 0;
3457
+ if (nextIndent > indentLevel) {
3458
+ itemContent.push(nextLine);
3459
+ totalRaw = `${totalRaw}${nextLine}
3460
+ `;
3461
+ i += 1;
3462
+ } else {
3463
+ break;
3464
+ }
3465
+ }
3466
+ let nestedTokens;
3467
+ const nestedContent = itemContent.slice(1);
3468
+ if (nestedContent.length > 0) {
3469
+ const dedentedNested = nestedContent.map((nestedLine) => nestedLine.slice(indentLevel + baseIndentSize)).join("\n");
3470
+ if (dedentedNested.trim()) {
3471
+ if (config.customNestedParser) {
3472
+ nestedTokens = config.customNestedParser(dedentedNested);
3473
+ } else {
3474
+ nestedTokens = lexer.blockTokens(dedentedNested);
3475
+ }
3476
+ }
3477
+ }
3478
+ const token = config.createToken(itemData, nestedTokens);
3479
+ items.push(token);
3480
+ }
3481
+ if (items.length === 0) {
3482
+ return void 0;
3483
+ }
3484
+ return {
3485
+ items,
3486
+ raw: totalRaw
3487
+ };
3488
+ }
3489
+ function renderNestedMarkdownContent(node, h2, prefixOrGenerator, ctx) {
3490
+ if (!node || !Array.isArray(node.content)) {
3491
+ return "";
3492
+ }
3493
+ const prefix = typeof prefixOrGenerator === "function" ? prefixOrGenerator(ctx) : prefixOrGenerator;
3494
+ const [content, ...children] = node.content;
3495
+ const mainContent = h2.renderChildren([content]);
3496
+ const output = [`${prefix}${mainContent}`];
3497
+ if (children && children.length > 0) {
3498
+ children.forEach((child) => {
3499
+ const childContent = h2.renderChildren([child]);
3500
+ if (childContent) {
3501
+ const indentedChild = childContent.split("\n").map((line) => line ? h2.indent(line) : "").join("\n");
3502
+ output.push(indentedChild);
3503
+ }
3504
+ });
3505
+ }
3506
+ return output.join("\n");
3507
+ }
3508
+ var Node3 = class _Node extends Extendable {
3509
+ constructor() {
3510
+ super(...arguments);
3511
+ this.type = "node";
3512
+ }
3513
+ /**
3514
+ * Create a new Node instance
3515
+ * @param config - Node configuration object or a function that returns a configuration object
3516
+ */
3517
+ static create(config = {}) {
3518
+ const resolvedConfig = typeof config === "function" ? config() : config;
3519
+ return new _Node(resolvedConfig);
3520
+ }
3521
+ configure(options) {
3522
+ return super.configure(options);
3523
+ }
3524
+ extend(extendedConfig) {
3525
+ const resolvedConfig = typeof extendedConfig === "function" ? extendedConfig() : extendedConfig;
3526
+ return super.extend(resolvedConfig);
3527
+ }
3528
+ };
3529
+ var Heading = Node3.create({
3530
+ name: "heading",
3531
+ addOptions() {
3532
+ return {
3533
+ levels: [1, 2, 3, 4, 5, 6],
3534
+ HTMLAttributes: {}
3535
+ };
3536
+ },
3537
+ content: "inline*",
3538
+ group: "block",
3539
+ defining: true,
3540
+ addAttributes() {
3541
+ return {
3542
+ level: {
3543
+ default: 1,
3544
+ rendered: false
3545
+ }
3546
+ };
3547
+ },
3548
+ parseHTML() {
3549
+ return this.options.levels.map((level) => ({
3550
+ tag: `h${level}`,
3551
+ attrs: { level }
3552
+ }));
3553
+ },
3554
+ renderHTML({ node, HTMLAttributes }) {
3555
+ const hasLevel = this.options.levels.includes(node.attrs.level);
3556
+ const level = hasLevel ? node.attrs.level : this.options.levels[0];
3557
+ return [`h${level}`, mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0];
3558
+ },
3559
+ parseMarkdown: (token, helpers) => {
3560
+ return helpers.createNode("heading", { level: token.depth || 1 }, helpers.parseInline(token.tokens || []));
3561
+ },
3562
+ renderMarkdown: (node, h) => {
3563
+ var _a;
3564
+ const level = ((_a = node.attrs) == null ? void 0 : _a.level) ? parseInt(node.attrs.level, 10) : 1;
3565
+ const headingChars = "#".repeat(level);
3566
+ if (!node.content) {
3567
+ return "";
3568
+ }
3569
+ return `${headingChars} ${h.renderChildren(node.content)}`;
3570
+ },
3571
+ addCommands() {
3572
+ return {
3573
+ setHeading: (attributes) => ({ commands: commands2 }) => {
3574
+ if (!this.options.levels.includes(attributes.level)) {
3575
+ return false;
3576
+ }
3577
+ return commands2.setNode(this.name, attributes);
3578
+ },
3579
+ toggleHeading: (attributes) => ({ commands: commands2 }) => {
3580
+ if (!this.options.levels.includes(attributes.level)) {
3581
+ return false;
3582
+ }
3583
+ return commands2.toggleNode(this.name, "paragraph", attributes);
3584
+ }
3585
+ };
3586
+ },
3587
+ addKeyboardShortcuts() {
3588
+ return this.options.levels.reduce(
3589
+ (items, level) => ({
3590
+ ...items,
3591
+ ...{
3592
+ [`Mod-Alt-${level}`]: () => this.editor.commands.toggleHeading({ level })
3593
+ }
3594
+ }),
3595
+ {}
3596
+ );
3597
+ },
3598
+ addInputRules() {
3599
+ return this.options.levels.map((level) => {
3600
+ return textblockTypeInputRule({
3601
+ find: new RegExp(`^(#{${Math.min(...this.options.levels)},${level}})\\s$`),
3602
+ type: this.type,
3603
+ getAttributes: {
3604
+ level
3605
+ }
3606
+ });
3607
+ });
3608
+ }
3609
+ });
3610
+ var index_default = Heading;
3611
+ const HeadingWithSEOTag = index_default.extend({
3612
+ addAttributes() {
3613
+ return {
3614
+ ...this.parent?.(),
3615
+ // must cast to any to avoid TS error
3616
+ tag: { default: null }
3617
+ };
3618
+ }
3619
+ }).configure({ levels: [1, 2, 3, 4] });
3620
+ function useHeading(editor, props = { disabled: false }) {
3621
+ const editorState = react.useEditorState({
3622
+ editor,
3623
+ selector: (ctx) => {
3624
+ return {
3625
+ headingLevel: ctx.editor.getAttributes("heading").level,
3626
+ headingTag: ctx.editor.getAttributes("heading").tag,
3627
+ isParagraph: ctx.editor.isActive("paragraph") ?? false
3628
+ };
3629
+ }
3630
+ });
3631
+ const onChangeHeading = (value) => {
3632
+ if (!editor) return;
3633
+ editor.chain().focus();
3634
+ if (value === "p") {
3635
+ editor.chain().focus().setParagraph().run();
3636
+ return;
3637
+ }
3638
+ const level = Number(value[1]);
3639
+ editor.chain().focus().setHeading({ level }).run();
3640
+ if (!editorState.headingTag) {
3641
+ editor.chain().focus().updateAttributes("heading", { tag: `h${level}` }).run();
3642
+ }
3643
+ };
3644
+ const onChangeHeadingTag = (value) => {
3645
+ if (!editor) return;
3646
+ if (!editorState.headingLevel) return;
3647
+ editor.chain().focus().updateAttributes("heading", { tag: value }).run();
3648
+ };
3649
+ return {
3650
+ headingSelect: /* @__PURE__ */ jsxRuntime.jsxs(
3651
+ designSystem.SingleSelect,
3652
+ {
3653
+ placeholder: "Style",
3654
+ "aria-label": "Text style",
3655
+ value: editorState.headingLevel ? `h${editorState.headingLevel}` : "p",
3656
+ onChange: (v) => v && onChangeHeading(v),
3657
+ disabled: !editor || props.disabled,
3658
+ size: "S",
3659
+ children: [
3660
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "p", children: "Paragraph" }),
3661
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "h1", children: "Heading 1" }),
3662
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "h2", children: "Heading 2" }),
3663
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "h3", children: "Heading 3" }),
3664
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "h4", children: "Heading 4" })
3665
+ ]
3666
+ }
3667
+ ),
3668
+ headingTagSelect: /* @__PURE__ */ jsxRuntime.jsxs(
3669
+ designSystem.SingleSelect,
3670
+ {
3671
+ placeholder: "SEO Tag",
3672
+ "aria-label": "Heading's HTML tag for SEO purposes",
3673
+ value: editorState.headingTag,
3674
+ onChange: (v) => v && onChangeHeadingTag(v),
3675
+ disabled: !editor || props.disabled || !editorState.headingLevel,
3676
+ size: "S",
3677
+ children: [
3678
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "h1", children: "h1" }),
3679
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "h2", children: "h2" }),
3680
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "h3", children: "h3" }),
3681
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "h4", children: "h4" }),
3682
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "h5", children: "h5" }),
3683
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "h6", children: "h6" })
3684
+ ]
3685
+ }
3686
+ )
3687
+ };
3688
+ }
3689
+ function useScript(editor, props = { disabled: false }) {
3690
+ const editorState = react.useEditorState({
3691
+ editor,
3692
+ selector: (ctx) => {
3693
+ return {
3694
+ isSuperscript: ctx.editor.isActive("superscript") ?? false,
3695
+ canToggleSuperscript: ctx.editor.can().chain().toggleSuperscript().run() ?? false,
3696
+ isSubscript: ctx.editor.isActive("subscript") ?? false,
3697
+ canToggleSubscript: ctx.editor.can().chain().toggleSubscript().run() ?? false
3698
+ };
3699
+ }
3700
+ });
3701
+ const toggleSuperscript = () => {
3702
+ editor?.chain().focus().toggleSuperscript().run();
3703
+ };
3704
+ const toggleSubscript = () => {
3705
+ editor?.chain().focus().toggleSubscript().run();
3706
+ };
3707
+ return {
3708
+ superscriptButton: /* @__PURE__ */ jsxRuntime.jsx(
3709
+ ToolbarButton,
3710
+ {
3711
+ onClick: toggleSuperscript,
3712
+ icon: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3713
+ "x",
3714
+ /* @__PURE__ */ jsxRuntime.jsx("sup", { children: "2" })
3715
+ ] }),
3716
+ active: editorState.isSuperscript,
3717
+ disabled: props.disabled || !editor || !editorState.canToggleSuperscript,
3718
+ tooltip: "Superscript"
3719
+ },
3720
+ "superscript"
3721
+ ),
3722
+ subscriptButton: /* @__PURE__ */ jsxRuntime.jsx(
3723
+ ToolbarButton,
3724
+ {
3725
+ onClick: toggleSubscript,
3726
+ icon: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3727
+ "x",
3728
+ /* @__PURE__ */ jsxRuntime.jsx("sub", { children: "2" })
3729
+ ] }),
3730
+ active: editorState.isSubscript,
3731
+ disabled: props.disabled || !editor || !editorState.canToggleSubscript,
3732
+ tooltip: "Subscript"
3733
+ },
3734
+ "subscript"
3735
+ )
3736
+ };
3737
+ }
3738
+ Extension.create({
3739
+ name: "characterCount",
3740
+ addOptions() {
3741
+ return {
3742
+ limit: null,
3743
+ mode: "textSize",
3744
+ textCounter: (text) => text.length,
3745
+ wordCounter: (text) => text.split(" ").filter((word) => word !== "").length
3746
+ };
3747
+ },
3748
+ addStorage() {
3749
+ return {
3750
+ characters: () => 0,
3751
+ words: () => 0
3752
+ };
3753
+ },
3754
+ onBeforeCreate() {
3755
+ this.storage.characters = (options) => {
3756
+ const node = (options == null ? void 0 : options.node) || this.editor.state.doc;
3757
+ const mode = (options == null ? void 0 : options.mode) || this.options.mode;
3758
+ if (mode === "textSize") {
3759
+ const text = node.textBetween(0, node.content.size, void 0, " ");
3760
+ return this.options.textCounter(text);
3761
+ }
3762
+ return node.nodeSize;
3763
+ };
3764
+ this.storage.words = (options) => {
3765
+ const node = (options == null ? void 0 : options.node) || this.editor.state.doc;
3766
+ const text = node.textBetween(0, node.content.size, " ", " ");
3767
+ return this.options.wordCounter(text);
3768
+ };
3769
+ },
3770
+ addProseMirrorPlugins() {
3771
+ let initialEvaluationDone = false;
3772
+ return [
3773
+ new state.Plugin({
3774
+ key: new state.PluginKey("characterCount"),
3775
+ appendTransaction: (transactions, oldState, newState) => {
3776
+ if (initialEvaluationDone) {
3777
+ return;
3778
+ }
3779
+ const limit = this.options.limit;
3780
+ if (limit === null || limit === void 0 || limit === 0) {
3781
+ initialEvaluationDone = true;
3782
+ return;
3783
+ }
3784
+ const initialContentSize = this.storage.characters({ node: newState.doc });
3785
+ if (initialContentSize > limit) {
3786
+ const over = initialContentSize - limit;
3787
+ const from = 0;
3788
+ const to = over;
3789
+ console.warn(
3790
+ `[CharacterCount] Initial content exceeded limit of ${limit} characters. Content was automatically trimmed.`
3791
+ );
3792
+ const tr = newState.tr.deleteRange(from, to);
3793
+ initialEvaluationDone = true;
3794
+ return tr;
3795
+ }
3796
+ initialEvaluationDone = true;
3797
+ },
3798
+ filterTransaction: (transaction, state2) => {
3799
+ const limit = this.options.limit;
3800
+ if (!transaction.docChanged || limit === 0 || limit === null || limit === void 0) {
3801
+ return true;
3802
+ }
3803
+ const oldSize = this.storage.characters({ node: state2.doc });
3804
+ const newSize = this.storage.characters({ node: transaction.doc });
3805
+ if (newSize <= limit) {
3806
+ return true;
3807
+ }
3808
+ if (oldSize > limit && newSize > limit && newSize <= oldSize) {
3809
+ return true;
3810
+ }
3811
+ if (oldSize > limit && newSize > limit && newSize > oldSize) {
3812
+ return false;
3813
+ }
3814
+ const isPaste = transaction.getMeta("paste");
3815
+ if (!isPaste) {
3816
+ return false;
3817
+ }
3818
+ const pos = transaction.selection.$head.pos;
3819
+ const over = newSize - limit;
3820
+ const from = pos - over;
3821
+ const to = pos;
3822
+ transaction.deleteRange(from, to);
3823
+ const updatedSize = this.storage.characters({ node: transaction.doc });
3824
+ if (updatedSize > limit) {
3825
+ return false;
3826
+ }
3827
+ return true;
3828
+ }
3829
+ })
3830
+ ];
3831
+ }
3832
+ });
3833
+ Extension.create({
3834
+ name: "dropCursor",
3835
+ addOptions() {
3836
+ return {
3837
+ color: "currentColor",
3838
+ width: 1,
3839
+ class: void 0
3840
+ };
3841
+ },
3842
+ addProseMirrorPlugins() {
3843
+ return [dropcursor.dropCursor(this.options)];
3844
+ }
3845
+ });
3846
+ Extension.create({
3847
+ name: "focus",
3848
+ addOptions() {
3849
+ return {
3850
+ className: "has-focus",
3851
+ mode: "all"
3852
+ };
3853
+ },
3854
+ addProseMirrorPlugins() {
3855
+ return [
3856
+ new state.Plugin({
3857
+ key: new state.PluginKey("focus"),
3858
+ props: {
3859
+ decorations: ({ doc, selection }) => {
3860
+ const { isEditable, isFocused } = this.editor;
3861
+ const { anchor } = selection;
3862
+ const decorations = [];
3863
+ if (!isEditable || !isFocused) {
3864
+ return view.DecorationSet.create(doc, []);
3865
+ }
3866
+ let maxLevels = 0;
3867
+ if (this.options.mode === "deepest") {
3868
+ doc.descendants((node, pos) => {
3869
+ if (node.isText) {
3870
+ return;
3871
+ }
3872
+ const isCurrent = anchor >= pos && anchor <= pos + node.nodeSize - 1;
3873
+ if (!isCurrent) {
3874
+ return false;
3875
+ }
3876
+ maxLevels += 1;
3877
+ });
3878
+ }
3879
+ let currentLevel = 0;
3880
+ doc.descendants((node, pos) => {
3881
+ if (node.isText) {
3882
+ return false;
3883
+ }
3884
+ const isCurrent = anchor >= pos && anchor <= pos + node.nodeSize - 1;
3885
+ if (!isCurrent) {
3886
+ return false;
3887
+ }
3888
+ currentLevel += 1;
3889
+ const outOfScope = this.options.mode === "deepest" && maxLevels - currentLevel > 0 || this.options.mode === "shallowest" && currentLevel > 1;
3890
+ if (outOfScope) {
3891
+ return this.options.mode === "deepest";
3892
+ }
3893
+ decorations.push(
3894
+ view.Decoration.node(pos, pos + node.nodeSize, {
3895
+ class: this.options.className
3896
+ })
3897
+ );
3898
+ });
3899
+ return view.DecorationSet.create(doc, decorations);
3900
+ }
3901
+ }
3902
+ })
3903
+ ];
3904
+ }
3905
+ });
3906
+ var Gapcursor = Extension.create({
3907
+ name: "gapCursor",
3908
+ addProseMirrorPlugins() {
3909
+ return [gapcursor.gapCursor()];
3910
+ },
3911
+ extendNodeSchema(extension) {
3912
+ var _a;
3913
+ const context = {
3914
+ name: extension.name,
3915
+ options: extension.options,
3916
+ storage: extension.storage
3917
+ };
3918
+ return {
3919
+ allowGapCursor: (_a = callOrReturn(getExtensionField(extension, "allowGapCursor", context))) != null ? _a : null
3920
+ };
3921
+ }
3922
+ });
3923
+ var DEFAULT_DATA_ATTRIBUTE = "placeholder";
3924
+ function preparePlaceholderAttribute(attr) {
3925
+ return attr.replace(/\s+/g, "-").replace(/[^a-zA-Z0-9-]/g, "").replace(/^[0-9-]+/, "").replace(/^-+/, "").toLowerCase();
3926
+ }
3927
+ Extension.create({
3928
+ name: "placeholder",
3929
+ addOptions() {
3930
+ return {
3931
+ emptyEditorClass: "is-editor-empty",
3932
+ emptyNodeClass: "is-empty",
3933
+ dataAttribute: DEFAULT_DATA_ATTRIBUTE,
3934
+ placeholder: "Write something …",
3935
+ showOnlyWhenEditable: true,
3936
+ showOnlyCurrent: true,
3937
+ includeChildren: false
3938
+ };
3939
+ },
3940
+ addProseMirrorPlugins() {
3941
+ const dataAttribute = this.options.dataAttribute ? `data-${preparePlaceholderAttribute(this.options.dataAttribute)}` : `data-${DEFAULT_DATA_ATTRIBUTE}`;
3942
+ return [
3943
+ new state.Plugin({
3944
+ key: new state.PluginKey("placeholder"),
3945
+ props: {
3946
+ decorations: ({ doc, selection }) => {
3947
+ const active = this.editor.isEditable || !this.options.showOnlyWhenEditable;
3948
+ const { anchor } = selection;
3949
+ const decorations = [];
3950
+ if (!active) {
3951
+ return null;
3952
+ }
3953
+ const isEmptyDoc = this.editor.isEmpty;
3954
+ doc.descendants((node, pos) => {
3955
+ const hasAnchor = anchor >= pos && anchor <= pos + node.nodeSize;
3956
+ const isEmpty = !node.isLeaf && isNodeEmpty(node);
3957
+ if ((hasAnchor || !this.options.showOnlyCurrent) && isEmpty) {
3958
+ const classes = [this.options.emptyNodeClass];
3959
+ if (isEmptyDoc) {
3960
+ classes.push(this.options.emptyEditorClass);
3961
+ }
3962
+ const decoration = view.Decoration.node(pos, pos + node.nodeSize, {
3963
+ class: classes.join(" "),
3964
+ [dataAttribute]: typeof this.options.placeholder === "function" ? this.options.placeholder({
3965
+ editor: this.editor,
3966
+ node,
3967
+ pos,
3968
+ hasAnchor
3969
+ }) : this.options.placeholder
3970
+ });
3971
+ decorations.push(decoration);
3972
+ }
3973
+ return this.options.includeChildren;
3974
+ });
3975
+ return view.DecorationSet.create(doc, decorations);
3976
+ }
3977
+ }
3978
+ })
3979
+ ];
3980
+ }
3981
+ });
3982
+ Extension.create({
3983
+ name: "selection",
3984
+ addOptions() {
3985
+ return {
3986
+ className: "selection"
3987
+ };
3988
+ },
3989
+ addProseMirrorPlugins() {
3990
+ const { editor, options } = this;
3991
+ return [
3992
+ new state.Plugin({
3993
+ key: new state.PluginKey("selection"),
3994
+ props: {
3995
+ decorations(state2) {
3996
+ if (state2.selection.empty || editor.isFocused || !editor.isEditable || isNodeSelection(state2.selection) || editor.view.dragging) {
3997
+ return null;
3998
+ }
3999
+ return view.DecorationSet.create(state2.doc, [
4000
+ view.Decoration.inline(state2.selection.from, state2.selection.to, {
4001
+ class: options.className
4002
+ })
4003
+ ]);
4004
+ }
4005
+ }
4006
+ })
4007
+ ];
4008
+ }
4009
+ });
4010
+ function nodeEqualsType({ types, node }) {
4011
+ return node && Array.isArray(types) && types.includes(node.type) || (node == null ? void 0 : node.type) === types;
4012
+ }
4013
+ Extension.create({
4014
+ name: "trailingNode",
4015
+ addOptions() {
4016
+ return {
4017
+ node: void 0,
4018
+ notAfter: []
4019
+ };
4020
+ },
4021
+ addProseMirrorPlugins() {
4022
+ var _a;
4023
+ const plugin = new state.PluginKey(this.name);
4024
+ const defaultNode = this.options.node || ((_a = this.editor.schema.topNodeType.contentMatch.defaultType) == null ? void 0 : _a.name) || "paragraph";
4025
+ const disabledNodes = Object.entries(this.editor.schema.nodes).map(([, value]) => value).filter((node) => (this.options.notAfter || []).concat(defaultNode).includes(node.name));
4026
+ return [
4027
+ new state.Plugin({
4028
+ key: plugin,
4029
+ appendTransaction: (_, __, state2) => {
4030
+ const { doc, tr, schema } = state2;
4031
+ const shouldInsertNodeAtEnd = plugin.getState(state2);
4032
+ const endPosition = doc.content.size;
4033
+ const type = schema.nodes[defaultNode];
4034
+ if (!shouldInsertNodeAtEnd) {
4035
+ return;
4036
+ }
4037
+ return tr.insert(endPosition, type.create());
4038
+ },
4039
+ state: {
4040
+ init: (_, state2) => {
4041
+ const lastNode = state2.tr.doc.lastChild;
4042
+ return !nodeEqualsType({ node: lastNode, types: disabledNodes });
4043
+ },
4044
+ apply: (tr, value) => {
4045
+ if (!tr.docChanged) {
4046
+ return value;
4047
+ }
4048
+ if (tr.getMeta("__uniqueIDTransaction")) {
4049
+ return value;
4050
+ }
4051
+ const lastNode = tr.doc.lastChild;
4052
+ return !nodeEqualsType({ node: lastNode, types: disabledNodes });
4053
+ }
4054
+ }
4055
+ })
4056
+ ];
4057
+ }
4058
+ });
4059
+ Extension.create({
4060
+ name: "undoRedo",
4061
+ addOptions() {
4062
+ return {
4063
+ depth: 100,
4064
+ newGroupDelay: 500
4065
+ };
4066
+ },
4067
+ addCommands() {
4068
+ return {
4069
+ undo: () => ({ state: state2, dispatch }) => {
4070
+ return history.undo(state2, dispatch);
4071
+ },
4072
+ redo: () => ({ state: state2, dispatch }) => {
4073
+ return history.redo(state2, dispatch);
4074
+ }
4075
+ };
4076
+ },
4077
+ addProseMirrorPlugins() {
4078
+ return [history.history(this.options)];
4079
+ },
4080
+ addKeyboardShortcuts() {
4081
+ return {
4082
+ "Mod-z": () => this.editor.commands.undo(),
4083
+ "Shift-Mod-z": () => this.editor.commands.redo(),
4084
+ "Mod-y": () => this.editor.commands.redo(),
4085
+ // Russian keyboard layouts
4086
+ "Mod-я": () => this.editor.commands.undo(),
4087
+ "Shift-Mod-я": () => this.editor.commands.redo()
4088
+ };
4089
+ }
4090
+ });
4091
+ const clamp = (val, min, max) => Math.max(min, Math.min(max, val));
4092
+ const parseNum = (value, fallback) => {
4093
+ const n = Number(value);
4094
+ return Number.isFinite(n) ? n : fallback;
4095
+ };
4096
+ const TableSizeDialog = ({
4097
+ open,
4098
+ defaultRows = 3,
4099
+ defaultCols = 3,
4100
+ onClose,
4101
+ onSave
4102
+ }) => {
4103
+ const [rows, setRows] = React.useState(defaultRows);
4104
+ const [cols, setCols] = React.useState(defaultCols);
4105
+ React.useEffect(() => {
4106
+ if (open) {
4107
+ setRows(defaultRows);
4108
+ setCols(defaultCols);
4109
+ }
4110
+ }, [open, defaultRows, defaultCols]);
4111
+ const min = 1;
4112
+ const max = 10;
4113
+ const isValid = rows >= min && rows <= max && cols >= min && cols <= max;
4114
+ const handleSave = () => {
4115
+ if (!isValid) return;
4116
+ onSave(clamp(rows, min, max), clamp(cols, min, max));
4117
+ };
4118
+ return /* @__PURE__ */ jsxRuntime.jsx(
4119
+ designSystem.Dialog.Root,
4120
+ {
4121
+ open,
4122
+ onOpenChange: (v) => {
4123
+ if (!v) onClose();
4124
+ },
4125
+ children: open && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
4126
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: "Insert table" }),
4127
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, alignItems: "flex-end", children: [
4128
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { width: "100%", children: [
4129
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Rows" }),
4130
+ /* @__PURE__ */ jsxRuntime.jsx(
4131
+ designSystem.TextInput,
4132
+ {
4133
+ name: "table-rows",
4134
+ type: "number",
4135
+ value: String(rows),
4136
+ onChange: (e) => setRows(clamp(parseNum(e.target.value, rows), min, max)),
4137
+ placeholder: String(defaultRows)
4138
+ }
4139
+ ),
4140
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Hint, { children: [
4141
+ "Min ",
4142
+ min,
4143
+ ", max ",
4144
+ max
4145
+ ] })
4146
+ ] }),
4147
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { width: "100%", children: [
4148
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Columns" }),
4149
+ /* @__PURE__ */ jsxRuntime.jsx(
4150
+ designSystem.TextInput,
4151
+ {
4152
+ name: "table-cols",
4153
+ type: "number",
4154
+ value: String(cols),
4155
+ onChange: (e) => setCols(clamp(parseNum(e.target.value, cols), min, max)),
4156
+ placeholder: String(defaultCols)
4157
+ }
4158
+ ),
4159
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Hint, { children: [
4160
+ "Min ",
4161
+ min,
4162
+ ", max ",
4163
+ max
4164
+ ] })
4165
+ ] })
4166
+ ] }) }),
4167
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
4168
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, onClick: onClose, children: "Cancel" }) }),
4169
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Action, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { fullWidth: true, variant: "success-light", onClick: handleSave, disabled: !isValid, children: "Insert" }) })
4170
+ ] })
4171
+ ] })
4172
+ }
4173
+ );
4174
+ };
4175
+ function useTable(editor, props = { disabled: false }) {
4176
+ const editorState = react.useEditorState({
4177
+ editor,
4178
+ selector: (ctx) => {
4179
+ return {
4180
+ isTable: ctx.editor.isActive("table") ?? false,
4181
+ canInsertTable: ctx.editor.can().chain().insertTable().run() ?? false,
4182
+ canAddColumn: ctx.editor.can().chain().addColumnAfter().run() ?? false,
4183
+ canDeleteColumn: ctx.editor.can().chain().deleteColumn().run() ?? false,
4184
+ canAddRow: ctx.editor.can().chain().addRowAfter().run() ?? false,
4185
+ canDeleteRow: ctx.editor.can().chain().deleteRow().run() ?? false
4186
+ };
4187
+ }
4188
+ });
4189
+ const [open, setOpen] = React.useState(false);
4190
+ const handleOpenDialog = () => {
4191
+ if (!editor) return;
4192
+ setOpen(true);
4193
+ };
4194
+ const handleInsert = (rows, cols) => {
4195
+ if (!editor) return;
4196
+ editor.chain().focus().insertTable({ rows, cols, withHeaderRow: true }).run();
4197
+ setOpen(false);
4198
+ };
4199
+ const addColumn = () => editor?.chain().focus().addColumnAfter().run();
4200
+ const removeColumn = () => editor?.chain().focus().deleteColumn().run();
4201
+ const addRow = () => editor?.chain().focus().addRowAfter().run();
4202
+ const removeRow = () => editor?.chain().focus().deleteRow().run();
4203
+ return {
4204
+ tableButton: /* @__PURE__ */ jsxRuntime.jsx(
4205
+ ToolbarButton,
4206
+ {
4207
+ onClick: handleOpenDialog,
4208
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.GridNine, {}),
4209
+ active: editorState.isTable,
4210
+ disabled: props.disabled || !editor || !editorState.canInsertTable,
4211
+ tooltip: "Table"
4212
+ },
4213
+ "table"
4214
+ ),
4215
+ // Adding table manipulation buttons
4216
+ addColumnButton: /* @__PURE__ */ jsxRuntime.jsx(
4217
+ ToolbarButton,
4218
+ {
4219
+ onClick: addColumn,
4220
+ icon: /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: "+Col" }),
4221
+ active: false,
4222
+ hidden: props.disabled || !editor || !editorState.canAddColumn,
4223
+ tooltip: "Add column (to the right)"
4224
+ },
4225
+ "tableAddColumn"
4226
+ ),
4227
+ removeColumnButton: /* @__PURE__ */ jsxRuntime.jsx(
4228
+ ToolbarButton,
4229
+ {
4230
+ onClick: removeColumn,
4231
+ icon: /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: "-Col" }),
4232
+ active: false,
4233
+ hidden: props.disabled || !editor || !editorState.canDeleteColumn,
4234
+ tooltip: "Remove column"
4235
+ },
4236
+ "tableRemoveColumn"
4237
+ ),
4238
+ addRowButton: /* @__PURE__ */ jsxRuntime.jsx(
4239
+ ToolbarButton,
4240
+ {
4241
+ onClick: addRow,
4242
+ icon: /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: "+Row" }),
4243
+ active: false,
4244
+ hidden: props.disabled || !editor || !editorState.canAddRow,
4245
+ tooltip: "Add row (below)"
4246
+ },
4247
+ "tableAddRow"
4248
+ ),
4249
+ removeRowButton: /* @__PURE__ */ jsxRuntime.jsx(
4250
+ ToolbarButton,
4251
+ {
4252
+ onClick: removeRow,
4253
+ icon: /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: "-Row" }),
4254
+ active: false,
4255
+ hidden: props.disabled || !editor || !editorState.canDeleteRow,
4256
+ tooltip: "Remove row"
4257
+ },
4258
+ "tableRemoveRow"
4259
+ ),
4260
+ tableDialog: /* @__PURE__ */ jsxRuntime.jsx(
4261
+ TableSizeDialog,
4262
+ {
4263
+ open,
4264
+ onClose: () => setOpen(false),
4265
+ onSave: handleInsert,
4266
+ defaultRows: 3,
4267
+ defaultCols: 3
4268
+ }
4269
+ )
4270
+ };
4271
+ }
4272
+ function TextAlignLeft(props) {
4273
+ return /* @__PURE__ */ jsxRuntime.jsx(
4274
+ "svg",
4275
+ {
4276
+ width: "16",
4277
+ height: "16",
4278
+ viewBox: "0 0 24 24",
4279
+ fill: "currentColor",
4280
+ xmlns: "http://www.w3.org/2000/svg",
4281
+ ...props,
4282
+ children: /* @__PURE__ */ jsxRuntime.jsx(
4283
+ "path",
4284
+ {
4285
+ d: "M3 10H16M3 14H21M3 18H16M3 6H21",
4286
+ stroke: "currentColor",
4287
+ "stroke-width": "2",
4288
+ "stroke-linecap": "round",
4289
+ "stroke-linejoin": "round"
4290
+ }
4291
+ )
4292
+ }
4293
+ );
4294
+ }
4295
+ function TextAlignJustify(props) {
4296
+ return /* @__PURE__ */ jsxRuntime.jsx(
4297
+ "svg",
4298
+ {
4299
+ width: "16",
4300
+ height: "16",
4301
+ viewBox: "0 0 24 24",
4302
+ fill: "currentColor",
4303
+ xmlns: "http://www.w3.org/2000/svg",
4304
+ ...props,
4305
+ children: /* @__PURE__ */ jsxRuntime.jsx(
4306
+ "path",
4307
+ {
4308
+ d: "M3 10H21M3 14H21M3 18H21M3 6H21",
4309
+ stroke: "currentColor",
4310
+ "stroke-width": "2",
4311
+ "stroke-linecap": "round",
4312
+ "stroke-linejoin": "round"
4313
+ }
4314
+ )
4315
+ }
4316
+ );
4317
+ }
4318
+ function TextAlignRight(props) {
4319
+ return /* @__PURE__ */ jsxRuntime.jsx(
4320
+ "svg",
4321
+ {
4322
+ width: "16",
4323
+ height: "16",
4324
+ viewBox: "0 0 24 24",
4325
+ fill: "currentColor",
4326
+ xmlns: "http://www.w3.org/2000/svg",
4327
+ ...props,
4328
+ children: /* @__PURE__ */ jsxRuntime.jsx(
4329
+ "path",
4330
+ {
4331
+ d: "M8 10H21M3 14H21M8 18H21M3 6H21",
4332
+ stroke: "currentColor",
4333
+ "stroke-width": "2",
4334
+ "stroke-linecap": "round",
4335
+ "stroke-linejoin": "round"
4336
+ }
4337
+ )
4338
+ }
4339
+ );
4340
+ }
4341
+ function TextAlignCenter(props) {
4342
+ return /* @__PURE__ */ jsxRuntime.jsx(
4343
+ "svg",
4344
+ {
4345
+ width: "16",
4346
+ height: "16",
4347
+ viewBox: "0 0 24 24",
4348
+ fill: "currentColor",
4349
+ xmlns: "http://www.w3.org/2000/svg",
4350
+ ...props,
4351
+ children: /* @__PURE__ */ jsxRuntime.jsx(
4352
+ "path",
4353
+ {
4354
+ d: "M3 6H21M3 14H21M17 10H7M17 18H7",
4355
+ stroke: "currentColor",
4356
+ "stroke-width": "2",
4357
+ "stroke-linecap": "round",
4358
+ "stroke-linejoin": "round"
4359
+ }
4360
+ )
4361
+ }
4362
+ );
4363
+ }
4364
+ function useTextAlign(editor, props = { disabled: false }) {
4365
+ const editorState = react.useEditorState({
4366
+ editor,
4367
+ selector: (ctx) => {
4368
+ return {
4369
+ isTextAlignLeft: ctx.editor.isActive({ textAlign: "left" }) ?? false,
4370
+ isTextAlignRight: ctx.editor.isActive({ textAlign: "right" }) ?? false,
4371
+ isTextAlignCenter: ctx.editor.isActive({ textAlign: "center" }) ?? false,
4372
+ isTextAlignJustify: ctx.editor.isActive({ textAlign: "justify" }) ?? false,
4373
+ canToggleAlign: ctx.editor.can().chain().setTextAlign("left").run() ?? false
4374
+ };
4375
+ }
4376
+ });
4377
+ const setTextAlign = (alignment) => {
4378
+ editor.chain().focus().setTextAlign(alignment).run();
4379
+ };
4380
+ return {
4381
+ textAlignLeftButton: /* @__PURE__ */ jsxRuntime.jsx(
4382
+ ToolbarButton,
4383
+ {
4384
+ onClick: () => setTextAlign("left"),
4385
+ icon: /* @__PURE__ */ jsxRuntime.jsx(TextAlignLeft, {}),
4386
+ active: editorState.isTextAlignLeft,
4387
+ disabled: props.disabled || !editor || !editorState.canToggleAlign,
4388
+ tooltip: "Text Align Left"
4389
+ },
4390
+ "text-align-left"
4391
+ ),
4392
+ textAlignCenterButton: /* @__PURE__ */ jsxRuntime.jsx(
4393
+ ToolbarButton,
4394
+ {
4395
+ onClick: () => setTextAlign("center"),
4396
+ icon: /* @__PURE__ */ jsxRuntime.jsx(TextAlignCenter, {}),
4397
+ active: editorState.isTextAlignCenter,
4398
+ disabled: props.disabled || !editor || !editorState.canToggleAlign,
4399
+ tooltip: "Text Align Center"
4400
+ },
4401
+ "text-align-center"
4402
+ ),
4403
+ textAlignRightButton: /* @__PURE__ */ jsxRuntime.jsx(
4404
+ ToolbarButton,
4405
+ {
4406
+ onClick: () => setTextAlign("right"),
4407
+ icon: /* @__PURE__ */ jsxRuntime.jsx(TextAlignRight, {}),
4408
+ active: editorState.isTextAlignRight,
4409
+ disabled: props.disabled || !editor || !editorState.canToggleAlign,
4410
+ tooltip: "Text Align Right"
4411
+ },
4412
+ "text-align-right"
4413
+ ),
4414
+ textAlignJustifyButton: /* @__PURE__ */ jsxRuntime.jsx(
4415
+ ToolbarButton,
4416
+ {
4417
+ onClick: () => setTextAlign("justify"),
4418
+ icon: /* @__PURE__ */ jsxRuntime.jsx(TextAlignJustify, {}),
4419
+ active: editorState.isTextAlignJustify,
4420
+ disabled: props.disabled || !editor || !editorState.canToggleAlign,
4421
+ tooltip: "Text Align Justify"
4422
+ },
4423
+ "text-align-justify"
4424
+ )
4425
+ };
4426
+ }
4427
+ const extensions = [
4428
+ StarterKit__default.default.configure({
4429
+ heading: false,
4430
+ // disable default so we can use our custom version
4431
+ link: {
4432
+ openOnClick: false
4433
+ }
4434
+ }),
4435
+ HeadingWithSEOTag,
4436
+ Superscript__default.default,
4437
+ Subscript__default.default,
4438
+ Gapcursor,
4439
+ // cursor for resizing tables
4440
+ extensionTable.TableKit.configure({
4441
+ table: { resizable: true }
4442
+ }),
4443
+ TextAlign__default.default.configure({
4444
+ types: ["heading", "paragraph"]
4445
+ })
4446
+ ];
4447
+ const RichTextInput = React.forwardRef((props, forwardedRef) => {
4448
+ const { editor, field } = useTiptapEditor(props.name, "", extensions);
4449
+ const starterKit = useStarterKit(editor, { disabled: props.disabled });
4450
+ const heading = useHeading(editor, { disabled: props.disabled });
4451
+ const link = useLink(editor, { disabled: props.disabled });
4452
+ const script = useScript(editor, { disabled: props.disabled });
4453
+ const table = useTable(editor, { disabled: props.disabled });
4454
+ const textAlign = useTextAlign(editor, { disabled: props.disabled });
4455
+ return /* @__PURE__ */ jsxRuntime.jsxs(BaseTiptapInput, { editor, field, ...props, ref: forwardedRef, children: [
4456
+ heading.headingSelect,
4457
+ heading.headingTagSelect,
4458
+ /* @__PURE__ */ jsxRuntime.jsx(Spacer, { width: 8 }),
4459
+ starterKit.boldButton,
4460
+ starterKit.italicButton,
4461
+ starterKit.underlineButton,
4462
+ starterKit.strikeButton,
4463
+ script.superscriptButton,
4464
+ script.subscriptButton,
4465
+ /* @__PURE__ */ jsxRuntime.jsx(Spacer, { width: 8 }),
4466
+ textAlign.textAlignLeftButton,
4467
+ textAlign.textAlignCenterButton,
4468
+ textAlign.textAlignRightButton,
4469
+ textAlign.textAlignJustifyButton,
4470
+ /* @__PURE__ */ jsxRuntime.jsx(Spacer, { width: 8 }),
4471
+ starterKit.bulletButton,
4472
+ starterKit.orderedButton,
4473
+ /* @__PURE__ */ jsxRuntime.jsx(Spacer, { width: 8 }),
4474
+ starterKit.codeButton,
4475
+ starterKit.blockquoteButton,
4476
+ link.linkButton,
4477
+ link.linkDialog,
4478
+ /* @__PURE__ */ jsxRuntime.jsx(Spacer, { width: 8 }),
4479
+ table.tableButton,
4480
+ table.addColumnButton,
4481
+ table.removeColumnButton,
4482
+ table.addRowButton,
4483
+ table.removeRowButton,
4484
+ table.tableDialog
4485
+ ] });
4486
+ });
4487
+ exports.default = RichTextInput;
4488
+ //# sourceMappingURL=RichTextInput-BlxoJMa2.js.map