@cyberyozh/text-editor 0.1.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 (209) hide show
  1. package/README.md +102 -0
  2. package/dist/editor.css +2069 -0
  3. package/dist/editor.css.map +1 -0
  4. package/dist/editor.d.mts +45 -0
  5. package/dist/editor.d.ts +45 -0
  6. package/dist/editor.js +6155 -0
  7. package/dist/editor.js.map +1 -0
  8. package/dist/editor.mjs +6118 -0
  9. package/dist/editor.mjs.map +1 -0
  10. package/dist/render/client.d.mts +24 -0
  11. package/dist/render/client.d.ts +24 -0
  12. package/dist/render/client.js +98 -0
  13. package/dist/render/client.js.map +1 -0
  14. package/dist/render/client.mjs +74 -0
  15. package/dist/render/client.mjs.map +1 -0
  16. package/dist/render.d.mts +58 -0
  17. package/dist/render.d.ts +58 -0
  18. package/dist/render.js +2521 -0
  19. package/dist/render.js.map +1 -0
  20. package/dist/render.mjs +2484 -0
  21. package/dist/render.mjs.map +1 -0
  22. package/dist/styles/index.css +2068 -0
  23. package/package.json +92 -0
  24. package/src/editor/commands/items.ts +374 -0
  25. package/src/editor/commands/suggestion.tsx +146 -0
  26. package/src/editor/components/button/button.css +56 -0
  27. package/src/editor/components/button/button.tsx +35 -0
  28. package/src/editor/components/button/index.ts +1 -0
  29. package/src/editor/components/common-modal/common-modal.css +85 -0
  30. package/src/editor/components/common-modal/common-modal.tsx +58 -0
  31. package/src/editor/components/common-modal/index.ts +1 -0
  32. package/src/editor/components/index.ts +3 -0
  33. package/src/editor/components/input/index.ts +1 -0
  34. package/src/editor/components/input/input.css +43 -0
  35. package/src/editor/components/input/input.tsx +22 -0
  36. package/src/editor/context/dialog-command.tsx +47 -0
  37. package/src/editor/context/index.ts +2 -0
  38. package/src/editor/context/translations-context.tsx +28 -0
  39. package/src/editor/controls/bubble-menu-content.tsx +394 -0
  40. package/src/editor/controls/callout-menu.tsx +169 -0
  41. package/src/editor/controls/character-count.tsx +36 -0
  42. package/src/editor/controls/commands-list.tsx +117 -0
  43. package/src/editor/controls/drag-handle.tsx +98 -0
  44. package/src/editor/controls/emoji-picker.tsx +62 -0
  45. package/src/editor/controls/index.ts +5 -0
  46. package/src/editor/controls/table-menu.tsx +322 -0
  47. package/src/editor/dialogs/add-katex-dialog/add-katex-dialog.css +115 -0
  48. package/src/editor/dialogs/add-katex-dialog/add-katex-dialog.tsx +116 -0
  49. package/src/editor/dialogs/add-katex-dialog/index.ts +1 -0
  50. package/src/editor/dialogs/add-link-dialog/add-link-dialog.css +105 -0
  51. package/src/editor/dialogs/add-link-dialog/add-link-dialog.tsx +177 -0
  52. package/src/editor/dialogs/add-link-dialog/index.ts +1 -0
  53. package/src/editor/dialogs/add-video-dialog/add-video-dialog.css +146 -0
  54. package/src/editor/dialogs/add-video-dialog/add-video-dialog.tsx +157 -0
  55. package/src/editor/dialogs/add-video-dialog/index.ts +1 -0
  56. package/src/editor/dialogs/image-dialog/image-dialog.css +101 -0
  57. package/src/editor/dialogs/image-dialog/image-dialog.tsx +276 -0
  58. package/src/editor/dialogs/image-dialog/index.ts +1 -0
  59. package/src/editor/dialogs/index.ts +4 -0
  60. package/src/editor/editor.tsx +247 -0
  61. package/src/editor/handlers/create-image-upload-handler.ts +24 -0
  62. package/src/editor/handlers/dialog-handlers.ts +143 -0
  63. package/src/editor/handlers/index.ts +8 -0
  64. package/src/editor/index.ts +3 -0
  65. package/src/extensions/base/callout.ts +138 -0
  66. package/src/extensions/base/code-block.ts +24 -0
  67. package/src/extensions/base/compatibility.ts +493 -0
  68. package/src/extensions/base/copyable-text.ts +56 -0
  69. package/src/extensions/base/custom-quote.ts +174 -0
  70. package/src/extensions/base/figure.ts +141 -0
  71. package/src/extensions/base/index.ts +19 -0
  72. package/src/extensions/base/link.ts +18 -0
  73. package/src/extensions/base/myth-reality.ts +45 -0
  74. package/src/extensions/base/prompt.ts +109 -0
  75. package/src/extensions/base/video.ts +29 -0
  76. package/src/extensions/editor/callout.ts +43 -0
  77. package/src/extensions/editor/code-block.ts +9 -0
  78. package/src/extensions/editor/commands.ts +43 -0
  79. package/src/extensions/editor/copyable-text.ts +16 -0
  80. package/src/extensions/editor/custom-quote.ts +54 -0
  81. package/src/extensions/editor/figure.ts +20 -0
  82. package/src/extensions/editor/get-editor-extensions.ts +113 -0
  83. package/src/extensions/editor/index.ts +25 -0
  84. package/src/extensions/editor/prompt.ts +43 -0
  85. package/src/extensions/editor/video.ts +23 -0
  86. package/src/extensions/render/get-render-extensions.ts +74 -0
  87. package/src/extensions/render/index.ts +6 -0
  88. package/src/extensions/views/components/callout.tsx +70 -0
  89. package/src/extensions/views/components/code-block.tsx +73 -0
  90. package/src/extensions/views/components/copy-button.tsx +52 -0
  91. package/src/extensions/views/components/copyable-text.tsx +11 -0
  92. package/src/extensions/views/components/custom-quote.tsx +64 -0
  93. package/src/extensions/views/components/figure.tsx +63 -0
  94. package/src/extensions/views/components/index.ts +7 -0
  95. package/src/extensions/views/components/prompt.tsx +43 -0
  96. package/src/extensions/views/components/video.tsx +40 -0
  97. package/src/extensions/views/node-views/callout.tsx +51 -0
  98. package/src/extensions/views/node-views/code-block.tsx +30 -0
  99. package/src/extensions/views/node-views/copyable-text.tsx +10 -0
  100. package/src/extensions/views/node-views/custom-quote.tsx +66 -0
  101. package/src/extensions/views/node-views/figure.tsx +38 -0
  102. package/src/extensions/views/node-views/index.ts +7 -0
  103. package/src/extensions/views/node-views/prompt.tsx +35 -0
  104. package/src/extensions/views/node-views/video.tsx +19 -0
  105. package/src/icons/Check.tsx +12 -0
  106. package/src/icons/Copy.tsx +15 -0
  107. package/src/icons/DragIcon.tsx +10 -0
  108. package/src/icons/Edit.tsx +12 -0
  109. package/src/icons/Quote.tsx +10 -0
  110. package/src/icons/X.tsx +13 -0
  111. package/src/icons/color/TiptapCalloutError.tsx +25 -0
  112. package/src/icons/color/TiptapCalloutInfo.tsx +18 -0
  113. package/src/icons/color/TiptapCalloutSuccess.tsx +49 -0
  114. package/src/icons/color/TiptapCalloutWarning.tsx +28 -0
  115. package/src/icons/color/index.ts +4 -0
  116. package/src/icons/index.ts +60 -0
  117. package/src/icons/menu/AddImage.tsx +10 -0
  118. package/src/icons/menu/AlignCenter.tsx +10 -0
  119. package/src/icons/menu/AlignLeft.tsx +10 -0
  120. package/src/icons/menu/AlignRight.tsx +10 -0
  121. package/src/icons/menu/ArrowDown.tsx +13 -0
  122. package/src/icons/menu/ArrowLeft.tsx +13 -0
  123. package/src/icons/menu/ArrowRight.tsx +13 -0
  124. package/src/icons/menu/ArrowUp.tsx +13 -0
  125. package/src/icons/menu/Blockquote.tsx +7 -0
  126. package/src/icons/menu/Bold.tsx +10 -0
  127. package/src/icons/menu/BulletList.tsx +10 -0
  128. package/src/icons/menu/CalloutError.tsx +10 -0
  129. package/src/icons/menu/CalloutInfo.tsx +12 -0
  130. package/src/icons/menu/CalloutSuccess.tsx +10 -0
  131. package/src/icons/menu/CalloutWarning.tsx +12 -0
  132. package/src/icons/menu/ClearFormatting.tsx +10 -0
  133. package/src/icons/menu/Code.tsx +10 -0
  134. package/src/icons/menu/CodeBlock.tsx +10 -0
  135. package/src/icons/menu/Copyable.tsx +10 -0
  136. package/src/icons/menu/CustomQuote.tsx +17 -0
  137. package/src/icons/menu/DeleteColumn.tsx +17 -0
  138. package/src/icons/menu/DeleteRow.tsx +17 -0
  139. package/src/icons/menu/Details.tsx +10 -0
  140. package/src/icons/menu/H2.tsx +10 -0
  141. package/src/icons/menu/H3.tsx +10 -0
  142. package/src/icons/menu/H4.tsx +10 -0
  143. package/src/icons/menu/H5.tsx +10 -0
  144. package/src/icons/menu/H6.tsx +10 -0
  145. package/src/icons/menu/Highlight.tsx +13 -0
  146. package/src/icons/menu/HorizontalRule.tsx +7 -0
  147. package/src/icons/menu/Italic.tsx +10 -0
  148. package/src/icons/menu/Link.tsx +10 -0
  149. package/src/icons/menu/LinkOff.tsx +10 -0
  150. package/src/icons/menu/Math.tsx +10 -0
  151. package/src/icons/menu/MergeCells.tsx +10 -0
  152. package/src/icons/menu/MythReality.tsx +10 -0
  153. package/src/icons/menu/OrderedList.tsx +10 -0
  154. package/src/icons/menu/Prompt.tsx +18 -0
  155. package/src/icons/menu/Redo.tsx +14 -0
  156. package/src/icons/menu/SplitCells.tsx +7 -0
  157. package/src/icons/menu/Strikethrough.tsx +10 -0
  158. package/src/icons/menu/Subscript.tsx +10 -0
  159. package/src/icons/menu/Superscript.tsx +10 -0
  160. package/src/icons/menu/Table.tsx +14 -0
  161. package/src/icons/menu/TableColumnHeading.tsx +7 -0
  162. package/src/icons/menu/TableRowHeading.tsx +10 -0
  163. package/src/icons/menu/TextColor.tsx +13 -0
  164. package/src/icons/menu/Underline.tsx +10 -0
  165. package/src/icons/menu/Undo.tsx +14 -0
  166. package/src/icons/menu/Video.tsx +14 -0
  167. package/src/icons/menu/index.ts +49 -0
  168. package/src/render/index.ts +22 -0
  169. package/src/render/static-renderer-config.tsx +206 -0
  170. package/src/render/tiptap-interactivity-provider.tsx +78 -0
  171. package/src/render/tiptap-render.tsx +102 -0
  172. package/src/styles/components.css +10 -0
  173. package/src/styles/editor/base.css +39 -0
  174. package/src/styles/editor/callout-menu.css +81 -0
  175. package/src/styles/editor/controls.css +57 -0
  176. package/src/styles/editor/emoji-picker.css +113 -0
  177. package/src/styles/editor/index.css +9 -0
  178. package/src/styles/editor/menus.css +16 -0
  179. package/src/styles/editor/states.css +43 -0
  180. package/src/styles/editor/typography.css +165 -0
  181. package/src/styles/editor/utilities.css +71 -0
  182. package/src/styles/editor/variables.css +70 -0
  183. package/src/styles/extensions/callout.css +155 -0
  184. package/src/styles/extensions/code-block.css +109 -0
  185. package/src/styles/extensions/commands-list.css +83 -0
  186. package/src/styles/extensions/custom-quote.css +103 -0
  187. package/src/styles/extensions/details.css +87 -0
  188. package/src/styles/extensions/figure.css +66 -0
  189. package/src/styles/extensions/index.css +11 -0
  190. package/src/styles/extensions/math.css +32 -0
  191. package/src/styles/extensions/myth-reality.css +59 -0
  192. package/src/styles/extensions/prompt.css +75 -0
  193. package/src/styles/extensions/table.css +253 -0
  194. package/src/styles/extensions/video.css +53 -0
  195. package/src/styles/styles.css +3 -0
  196. package/src/translations/en.json +158 -0
  197. package/src/translations/ru.json +158 -0
  198. package/src/types/image-handler.ts +33 -0
  199. package/src/types/index.ts +1 -0
  200. package/src/utils/copy-to-clipboard.ts +23 -0
  201. package/src/utils/custom-emoji.ts +174 -0
  202. package/src/utils/detect-video-hosting.ts +106 -0
  203. package/src/utils/get-shared-extensions.ts +45 -0
  204. package/src/utils/get-translations.ts +25 -0
  205. package/src/utils/handle-exit-node.ts +61 -0
  206. package/src/utils/image-src-resolver.ts +74 -0
  207. package/src/utils/index.ts +2 -0
  208. package/src/utils/migrate-legacy-callouts.ts +59 -0
  209. package/src/utils/pluralize.ts +38 -0
@@ -0,0 +1,2484 @@
1
+ // src/render/tiptap-render.tsx
2
+ import { renderToReactElement } from "@tiptap/static-renderer/pm/react";
3
+
4
+ // src/extensions/render/get-render-extensions.ts
5
+ import { Mathematics } from "@tiptap/extension-mathematics";
6
+ import { TableKit } from "@tiptap/extension-table";
7
+
8
+ // src/utils/handle-exit-node.ts
9
+ import { TextSelection } from "@tiptap/pm/state";
10
+ function handleExitNode(editor, nodeName) {
11
+ const { view, schema } = editor;
12
+ const { state } = view;
13
+ const { selection } = state;
14
+ const $pos = selection.$from;
15
+ const currentNode = $pos.node();
16
+ let depth = $pos.depth;
17
+ let isInsideTargetNode = false;
18
+ let targetNodeDepth = 0;
19
+ while (depth > 0) {
20
+ const parentNode = $pos.node(depth);
21
+ if (parentNode.type.name === nodeName) {
22
+ isInsideTargetNode = true;
23
+ targetNodeDepth = depth;
24
+ break;
25
+ }
26
+ depth--;
27
+ }
28
+ const isCurrentNodeEmptyParagraph = currentNode.type.name === "paragraph" && currentNode.content.size === 0;
29
+ if (!isInsideTargetNode || !isCurrentNodeEmptyParagraph) {
30
+ return false;
31
+ }
32
+ const { tr } = state;
33
+ const posAfterTargetNode = $pos.after(targetNodeDepth);
34
+ const targetNode = $pos.node(targetNodeDepth);
35
+ let newPosAfterTargetNode = posAfterTargetNode;
36
+ if (targetNode.childCount > 1) {
37
+ const emptyParagraphStart = $pos.before();
38
+ const emptyParagraphEnd = $pos.after();
39
+ const deletionLength = emptyParagraphEnd - emptyParagraphStart;
40
+ tr.delete(emptyParagraphStart, emptyParagraphEnd);
41
+ newPosAfterTargetNode = posAfterTargetNode - deletionLength;
42
+ }
43
+ const paragraphNode = schema.nodes.paragraph.createAndFill();
44
+ if (!paragraphNode) return false;
45
+ tr.insert(newPosAfterTargetNode, paragraphNode);
46
+ tr.setSelection(TextSelection.create(tr.doc, newPosAfterTargetNode + 1));
47
+ view.dispatch(tr);
48
+ return true;
49
+ }
50
+
51
+ // src/utils/migrate-legacy-callouts.ts
52
+ var legacyTypeMap = {
53
+ question: "info",
54
+ idea: "warning",
55
+ info: "success",
56
+ error: "error"
57
+ };
58
+ function migrateLegacyCallouts(editor) {
59
+ const { doc, schema } = editor.state;
60
+ const calloutsToMigrate = [];
61
+ doc.descendants((node, pos) => {
62
+ if (node.type.name === "callout" && node.attrs.calloutType) {
63
+ calloutsToMigrate.push({ node, pos });
64
+ }
65
+ });
66
+ if (calloutsToMigrate.length === 0) return;
67
+ const tr = editor.state.tr;
68
+ calloutsToMigrate.sort((a, b) => b.pos - a.pos);
69
+ for (const { node, pos } of calloutsToMigrate) {
70
+ const oldType = node.attrs.calloutType;
71
+ const newType = legacyTypeMap[oldType] || oldType;
72
+ const hasInlineContent = node.content.size > 0 && !node.firstChild?.isBlock;
73
+ if (hasInlineContent) {
74
+ const paragraph = schema.nodes.paragraph?.create(null, node.content);
75
+ const newContent = paragraph ? [paragraph] : [];
76
+ tr.replaceRangeWith(
77
+ pos,
78
+ pos + node.nodeSize,
79
+ schema.nodes.callout.create(
80
+ {
81
+ type: newType,
82
+ calloutType: null,
83
+ callout: null
84
+ },
85
+ newContent
86
+ )
87
+ );
88
+ } else {
89
+ tr.setNodeMarkup(pos, void 0, {
90
+ ...node.attrs,
91
+ type: newType,
92
+ calloutType: null,
93
+ callout: null
94
+ });
95
+ }
96
+ }
97
+ editor.view.dispatch(tr);
98
+ }
99
+
100
+ // src/extensions/base/callout.ts
101
+ import { mergeAttributes, Node } from "@tiptap/core";
102
+ var legacyTypeMap2 = {
103
+ question: "info",
104
+ idea: "warning",
105
+ info: "success",
106
+ error: "error"
107
+ };
108
+ var BaseCallout = Node.create({
109
+ name: "callout",
110
+ group: "block",
111
+ content: "block+",
112
+ draggable: true,
113
+ isolating: true,
114
+ addAttributes() {
115
+ return {
116
+ type: {
117
+ default: "info",
118
+ parseHTML: (element) => {
119
+ if (typeof element === "string") return "info";
120
+ const dataCallout = element.getAttribute("data-callout");
121
+ if (dataCallout) {
122
+ return dataCallout;
123
+ }
124
+ const legacyType = element.getAttribute("calloutType");
125
+ if (legacyType) {
126
+ return legacyTypeMap2[legacyType];
127
+ }
128
+ if (element.classList) {
129
+ if (element.classList.contains("callout--error")) return "error";
130
+ if (element.classList.contains("callout--question")) return "info";
131
+ if (element.classList.contains("callout--idea")) return "warning";
132
+ if (element.classList.contains("callout--info")) return "success";
133
+ }
134
+ return "info";
135
+ },
136
+ renderHTML: (attributes) => {
137
+ return {
138
+ "data-callout": attributes.type
139
+ };
140
+ }
141
+ },
142
+ bgColor: {
143
+ default: null,
144
+ parseHTML: (element) => {
145
+ if (typeof element === "string") return null;
146
+ return element.getAttribute("data-bg-color");
147
+ },
148
+ renderHTML: (attributes) => {
149
+ if (!attributes.bgColor) return {};
150
+ return {
151
+ "data-bg-color": attributes.bgColor
152
+ };
153
+ }
154
+ },
155
+ emoji: {
156
+ default: null,
157
+ parseHTML: (element) => {
158
+ if (typeof element === "string") return null;
159
+ return element.getAttribute("data-emoji");
160
+ },
161
+ renderHTML: (attributes) => {
162
+ if (!attributes.emoji) return {};
163
+ return {
164
+ "data-emoji": attributes.emoji
165
+ };
166
+ }
167
+ },
168
+ calloutType: {
169
+ default: null,
170
+ parseHTML: (element) => element.getAttribute("calloutType"),
171
+ renderHTML: () => ({})
172
+ },
173
+ callout: {
174
+ default: null,
175
+ parseHTML: (element) => element.getAttribute("callout"),
176
+ renderHTML: () => ({})
177
+ }
178
+ };
179
+ },
180
+ onCreate() {
181
+ migrateLegacyCallouts(this.editor);
182
+ },
183
+ addKeyboardShortcuts() {
184
+ return {
185
+ Enter: () => handleExitNode(this.editor, this.name)
186
+ };
187
+ },
188
+ parseHTML() {
189
+ return [
190
+ {
191
+ tag: "div[data-callout]"
192
+ },
193
+ {
194
+ tag: "callout",
195
+ priority: 51
196
+ },
197
+ {
198
+ tag: "div",
199
+ priority: 50,
200
+ getAttrs: (element) => {
201
+ if (typeof element === "string") return false;
202
+ if (element.classList.contains("callout") || element.classList.contains("callout--error") || element.classList.contains("callout--question") || element.classList.contains("callout--idea") || element.classList.contains("callout--info")) {
203
+ return {};
204
+ }
205
+ return false;
206
+ }
207
+ }
208
+ ];
209
+ },
210
+ renderHTML({ HTMLAttributes }) {
211
+ return ["div", mergeAttributes(HTMLAttributes), 0];
212
+ }
213
+ });
214
+
215
+ // src/extensions/base/code-block.ts
216
+ import { CodeBlockLowlight } from "@tiptap/extension-code-block-lowlight";
217
+ import html from "highlight.js/lib/languages/xml";
218
+ import { common, createLowlight } from "lowlight";
219
+ var lowlight = createLowlight(common);
220
+ lowlight.register("html", html);
221
+ var BaseCodeBlock = CodeBlockLowlight.configure({
222
+ lowlight
223
+ }).extend({
224
+ selectable: false,
225
+ draggable: true,
226
+ addAttributes() {
227
+ return {
228
+ language: {
229
+ default: null,
230
+ parseHTML: (element) => {
231
+ return element.querySelector("code")?.getAttribute("data-language") || "bash";
232
+ }
233
+ }
234
+ };
235
+ }
236
+ });
237
+
238
+ // src/extensions/base/copyable-text.ts
239
+ import { Mark, mergeAttributes as mergeAttributes2 } from "@tiptap/core";
240
+ var CopyableText = Mark.create({
241
+ name: "copyable-text",
242
+ addOptions() {
243
+ return {
244
+ HTMLAttributes: {
245
+ class: "copyable"
246
+ }
247
+ };
248
+ },
249
+ parseHTML() {
250
+ return [
251
+ {
252
+ tag: "span",
253
+ getAttrs: (element) => element.classList.contains("copyable") ? {} : false
254
+ }
255
+ ];
256
+ },
257
+ renderHTML({ HTMLAttributes }) {
258
+ return ["span", mergeAttributes2(this.options.HTMLAttributes, HTMLAttributes), 0];
259
+ },
260
+ addCommands() {
261
+ return {
262
+ setCopyable: (attributes) => ({ commands }) => {
263
+ return commands.setMark(this.name, attributes);
264
+ },
265
+ toggleCopyable: (attributes) => ({ commands }) => {
266
+ return commands.toggleMark(this.name, attributes);
267
+ },
268
+ unsetCopyable: () => ({ commands }) => {
269
+ return commands.unsetMark(this.name);
270
+ }
271
+ };
272
+ }
273
+ });
274
+
275
+ // src/extensions/base/custom-quote.ts
276
+ import { mergeAttributes as mergeAttributes3, Node as Node2 } from "@tiptap/core";
277
+ import { TextSelection as TextSelection2 } from "@tiptap/pm/state";
278
+ var BaseCustomQuote = Node2.create({
279
+ name: "customQuote",
280
+ group: "block",
281
+ content: "customQuoteText customQuoteAuthor customQuoteSign",
282
+ selectable: false,
283
+ draggable: true,
284
+ isolating: true,
285
+ addKeyboardShortcuts() {
286
+ return {
287
+ Enter: () => {
288
+ const { view, schema } = this.editor;
289
+ const { state } = view;
290
+ const { selection } = state;
291
+ const $pos = selection.$from;
292
+ let depth = $pos.depth;
293
+ let isInsideCustomQuote = false;
294
+ while (depth > 0) {
295
+ const parentNode = $pos.node(depth);
296
+ if (parentNode.type.name === this.name) {
297
+ isInsideCustomQuote = true;
298
+ break;
299
+ }
300
+ depth--;
301
+ }
302
+ if (!isInsideCustomQuote) {
303
+ return false;
304
+ }
305
+ const { tr } = state;
306
+ const posAfter = $pos.after(depth);
307
+ const paragraphNode = schema.nodes.paragraph.createAndFill();
308
+ if (!paragraphNode) return false;
309
+ tr.insert(posAfter, paragraphNode);
310
+ tr.setSelection(TextSelection2.create(tr.doc, posAfter + 1));
311
+ view.dispatch(tr);
312
+ return true;
313
+ }
314
+ };
315
+ },
316
+ parseHTML() {
317
+ return [
318
+ {
319
+ tag: "div[data-custom-quote]"
320
+ }
321
+ ];
322
+ },
323
+ renderHTML({ HTMLAttributes }) {
324
+ return ["div", mergeAttributes3(HTMLAttributes, { "data-custom-quote": "" }), 0];
325
+ }
326
+ });
327
+ var BaseCustomQuoteText = Node2.create({
328
+ name: "customQuoteText",
329
+ group: "block",
330
+ content: "inline*",
331
+ draggable: false,
332
+ selectable: true,
333
+ addAttributes() {
334
+ return {
335
+ open: {
336
+ default: true
337
+ }
338
+ };
339
+ },
340
+ addKeyboardShortcuts() {
341
+ return {
342
+ Enter: () => {
343
+ const { view, state } = this.editor;
344
+ const { tr, selection } = state;
345
+ const { $from } = selection;
346
+ if ($from.parent.type.name !== "customQuoteText") {
347
+ return false;
348
+ }
349
+ const posAfter = $from.after();
350
+ const nextNode = state.doc.nodeAt(posAfter);
351
+ if (!nextNode || nextNode.type.name !== "customQuoteAuthor") return false;
352
+ const nextNodeEnd = posAfter + nextNode.nodeSize - 1;
353
+ tr.setSelection(TextSelection2.create(tr.doc, nextNodeEnd));
354
+ view.dispatch(tr);
355
+ return true;
356
+ }
357
+ };
358
+ },
359
+ parseHTML() {
360
+ return [
361
+ {
362
+ tag: "div[data-custom-quote-text]"
363
+ }
364
+ ];
365
+ },
366
+ renderHTML({ HTMLAttributes }) {
367
+ return ["div", mergeAttributes3(HTMLAttributes, { "data-custom-quote-text": "" }), 0];
368
+ }
369
+ });
370
+ var BaseCustomQuoteAuthor = Node2.create({
371
+ name: "customQuoteAuthor",
372
+ group: "block",
373
+ content: "inline*",
374
+ selectable: true,
375
+ addKeyboardShortcuts() {
376
+ return {
377
+ Enter: () => {
378
+ const { view, state } = this.editor;
379
+ const { tr, selection } = state;
380
+ const { $from } = selection;
381
+ if ($from.parent.type.name !== "customQuoteAuthor") {
382
+ return false;
383
+ }
384
+ const posAfter = $from.after();
385
+ const nextNode = state.doc.nodeAt(posAfter);
386
+ if (!nextNode || nextNode.type.name !== "customQuoteSign") return false;
387
+ const nextNodeEnd = posAfter + nextNode.nodeSize - 1;
388
+ tr.setSelection(TextSelection2.create(tr.doc, nextNodeEnd));
389
+ view.dispatch(tr);
390
+ return true;
391
+ }
392
+ };
393
+ },
394
+ parseHTML() {
395
+ return [
396
+ {
397
+ tag: "div[data-custom-quote-author]"
398
+ }
399
+ ];
400
+ },
401
+ renderHTML({ HTMLAttributes }) {
402
+ return ["div", mergeAttributes3(HTMLAttributes, { "data-custom-quote-author": "" }), 0];
403
+ }
404
+ });
405
+ var BaseCustomQuoteSign = Node2.create({
406
+ name: "customQuoteSign",
407
+ group: "block",
408
+ content: "inline*",
409
+ selectable: true,
410
+ parseHTML() {
411
+ return [
412
+ {
413
+ tag: "div[data-custom-quote-sign]"
414
+ }
415
+ ];
416
+ },
417
+ renderHTML({ HTMLAttributes }) {
418
+ return ["div", mergeAttributes3(HTMLAttributes, { "data-custom-quote-sign": "" }), 0];
419
+ }
420
+ });
421
+
422
+ // src/extensions/base/link.ts
423
+ import Link from "@tiptap/extension-link";
424
+ var LinkExtension = Link.extend({
425
+ addOptions() {
426
+ return {
427
+ ...this.parent?.(),
428
+ openOnClick: false,
429
+ linkOnPaste: true,
430
+ autolink: true,
431
+ protocols: ["http", "https", "mailto", "tel"]
432
+ };
433
+ }
434
+ }).configure({
435
+ openOnClick: false,
436
+ linkOnPaste: true,
437
+ autolink: true,
438
+ protocols: ["http", "https", "mailto", "tel"]
439
+ });
440
+
441
+ // src/extensions/base/myth-reality.ts
442
+ import { mergeAttributes as mergeAttributes4, Node as Node3 } from "@tiptap/core";
443
+ var BaseMythRealityBlock = Node3.create({
444
+ name: "mythRealityBlock",
445
+ group: "block",
446
+ content: "block+",
447
+ parseHTML() {
448
+ return [{ tag: "div[data-myth-reality-block]" }];
449
+ },
450
+ renderHTML({ HTMLAttributes }) {
451
+ return [
452
+ "div",
453
+ mergeAttributes4(HTMLAttributes, { "data-myth-reality-block": "" }),
454
+ ["div", { class: "myth-reality-block-content" }, 0]
455
+ ];
456
+ }
457
+ });
458
+ var BaseMythReality = Node3.create({
459
+ name: "mythReality",
460
+ group: "block",
461
+ content: "(mythRealityBlock) (mythRealityBlock)",
462
+ draggable: true,
463
+ isolating: true,
464
+ parseHTML() {
465
+ return [{ tag: "div[data-myth-reality]" }];
466
+ },
467
+ renderHTML({ HTMLAttributes }) {
468
+ return ["div", mergeAttributes4(HTMLAttributes, { "data-myth-reality": "" }), 0];
469
+ },
470
+ addKeyboardShortcuts() {
471
+ return {
472
+ Enter: () => handleExitNode(this.editor, this.name)
473
+ };
474
+ }
475
+ });
476
+
477
+ // src/extensions/base/prompt.ts
478
+ import { Node as Node4, mergeAttributes as mergeAttributes5 } from "@tiptap/core";
479
+ import { TextSelection as TextSelection3 } from "@tiptap/pm/state";
480
+ var BasePrompt = Node4.create({
481
+ name: "prompt",
482
+ group: "block",
483
+ content: "(promptHeader | promptV2Header) (promptContent | promptV2Content)",
484
+ selectable: false,
485
+ draggable: true,
486
+ addKeyboardShortcuts() {
487
+ return {
488
+ Enter: () => {
489
+ const { view, schema } = this.editor;
490
+ const { state } = view;
491
+ const { selection } = state;
492
+ const $pos = selection.$from;
493
+ let depth = $pos.depth;
494
+ let isInsidePrompt = false;
495
+ while (depth > 0) {
496
+ const parentNode = $pos.node(depth);
497
+ if (parentNode.type.name === this.name) {
498
+ isInsidePrompt = true;
499
+ break;
500
+ }
501
+ depth--;
502
+ }
503
+ if (!isInsidePrompt) {
504
+ return false;
505
+ }
506
+ const { tr } = state;
507
+ const posAfter = $pos.after(depth);
508
+ const paragraphNode = schema.nodes.paragraph.createAndFill();
509
+ if (!paragraphNode) return false;
510
+ tr.insert(posAfter, paragraphNode);
511
+ tr.setSelection(TextSelection3.create(tr.doc, posAfter + 1));
512
+ view.dispatch(tr);
513
+ return true;
514
+ }
515
+ };
516
+ },
517
+ parseHTML() {
518
+ return [
519
+ {
520
+ tag: "div[data-prompt]"
521
+ }
522
+ ];
523
+ },
524
+ renderHTML({ HTMLAttributes }) {
525
+ return ["div", mergeAttributes5(HTMLAttributes, { "data-prompt": "" }), 0];
526
+ }
527
+ });
528
+ var BasePromptHeader = Node4.create({
529
+ name: "promptHeader",
530
+ group: "block",
531
+ content: "inline*",
532
+ selectable: true,
533
+ draggable: false,
534
+ parseHTML() {
535
+ return [
536
+ {
537
+ tag: "div[data-prompt-header]"
538
+ }
539
+ ];
540
+ },
541
+ renderHTML({ HTMLAttributes }) {
542
+ return ["div", mergeAttributes5(HTMLAttributes, { "data-prompt-header": "" }), 0];
543
+ }
544
+ // addNodeView() {
545
+ // return ReactNodeViewRenderer(PromptHeaderView);
546
+ // },
547
+ });
548
+ var BasePromptContent = Node4.create({
549
+ name: "promptContent",
550
+ group: "block",
551
+ content: "text*",
552
+ draggable: false,
553
+ selectable: true,
554
+ parseHTML() {
555
+ return [
556
+ {
557
+ tag: "div[data-prompt-content]"
558
+ }
559
+ ];
560
+ },
561
+ renderHTML({ HTMLAttributes }) {
562
+ return ["div", mergeAttributes5(HTMLAttributes, { "data-prompt-content": "" }), 0];
563
+ }
564
+ // addNodeView() {
565
+ // return ReactNodeViewRenderer(PromptContentView);
566
+ // },
567
+ });
568
+
569
+ // src/extensions/base/video.ts
570
+ import { Node as Node5 } from "@tiptap/core";
571
+ var BaseVideo = Node5.create({
572
+ name: "video",
573
+ group: "block",
574
+ selectable: true,
575
+ draggable: true,
576
+ isolating: true,
577
+ addAttributes() {
578
+ return {
579
+ src: {
580
+ default: null
581
+ }
582
+ };
583
+ },
584
+ parseHTML() {
585
+ return [
586
+ {
587
+ tag: "video-embed"
588
+ }
589
+ ];
590
+ },
591
+ renderHTML({ HTMLAttributes }) {
592
+ return ["video-embed", HTMLAttributes];
593
+ }
594
+ });
595
+
596
+ // src/extensions/base/figure.ts
597
+ import { mergeAttributes as mergeAttributes6, nodePasteRule } from "@tiptap/core";
598
+ import Image from "@tiptap/extension-image";
599
+
600
+ // src/utils/image-src-resolver.ts
601
+ function resolveImageSrc(attrs, options) {
602
+ const { fileId, src } = attrs;
603
+ const { getImageById } = options || {};
604
+ if (fileId && getImageById) {
605
+ const resolvedSrc = getImageById(fileId);
606
+ if (resolvedSrc) {
607
+ return resolvedSrc;
608
+ }
609
+ console.warn(`Failed to resolve fileId: ${fileId}`);
610
+ return "";
611
+ }
612
+ if (src) {
613
+ return src;
614
+ }
615
+ if (fileId) {
616
+ console.warn("fileId provided but no getImageById function - cannot resolve image");
617
+ return "";
618
+ }
619
+ return "";
620
+ }
621
+
622
+ // src/extensions/base/figure.ts
623
+ var BaseFigure = Image.extend({
624
+ name: "image",
625
+ group: "block",
626
+ content: "",
627
+ draggable: true,
628
+ isolating: true,
629
+ selectable: false,
630
+ addOptions() {
631
+ return {
632
+ HTMLAttributes: {},
633
+ getImageById: void 0,
634
+ onFigureClick: void 0
635
+ };
636
+ },
637
+ addAttributes() {
638
+ return {
639
+ ...this.parent?.(),
640
+ fileId: {
641
+ default: null,
642
+ parseHTML: (element) => {
643
+ const img = element.querySelector("img") || element;
644
+ return img.getAttribute("data-file-id") || element.getAttribute("data-file-id");
645
+ },
646
+ renderHTML: (attributes) => {
647
+ if (!attributes.fileId) return {};
648
+ return { "data-file-id": attributes.fileId };
649
+ }
650
+ },
651
+ caption: {
652
+ default: null,
653
+ parseHTML: (element) => element.querySelector("figcaption")?.textContent || null
654
+ }
655
+ };
656
+ },
657
+ parseHTML() {
658
+ return [
659
+ {
660
+ tag: "figure",
661
+ getAttrs: (element) => {
662
+ if (typeof element === "string") return false;
663
+ const img = element.querySelector("img");
664
+ return img ? {} : false;
665
+ }
666
+ },
667
+ {
668
+ tag: "img[src]",
669
+ getAttrs: (element) => {
670
+ if (typeof element === "string") return false;
671
+ return {};
672
+ }
673
+ }
674
+ ];
675
+ },
676
+ renderHTML({ node }) {
677
+ const resolvedSrc = resolveImageSrc(
678
+ {
679
+ fileId: node.attrs.fileId,
680
+ src: node.attrs.src
681
+ },
682
+ { getImageById: this.options.getImageById }
683
+ );
684
+ const figureAttrs = mergeAttributes6(this.options.HTMLAttributes);
685
+ const imgAttrs = {
686
+ src: resolvedSrc
687
+ };
688
+ if (node.attrs.fileId) imgAttrs["data-file-id"] = node.attrs.fileId;
689
+ if (node.attrs.alt) imgAttrs.alt = node.attrs.alt;
690
+ if (node.attrs.title) imgAttrs.title = node.attrs.title;
691
+ if (node.attrs.width) imgAttrs.width = node.attrs.width;
692
+ if (node.attrs.height) imgAttrs.height = node.attrs.height;
693
+ const hasCaption = node.attrs.caption && node.attrs.caption.trim().length > 0;
694
+ const figcaptionContent = hasCaption ? ["figcaption", {}, node.attrs.caption] : null;
695
+ return [
696
+ "figure",
697
+ figureAttrs,
698
+ ["img", imgAttrs],
699
+ ...figcaptionContent ? [figcaptionContent] : []
700
+ ];
701
+ },
702
+ addCommands() {
703
+ return {
704
+ ...this.parent?.(),
705
+ setFigure: (options) => ({ commands }) => {
706
+ return commands.insertContent({
707
+ type: this.name,
708
+ attrs: options
709
+ });
710
+ },
711
+ updateFigure: (options) => ({ commands }) => {
712
+ return commands.updateAttributes(this.name, options);
713
+ }
714
+ };
715
+ },
716
+ addPasteRules() {
717
+ return [
718
+ nodePasteRule({
719
+ find: /!\[(.*?)\]\((.*?)(?:\s+"(.*?)")?\)/g,
720
+ type: this.type,
721
+ getAttributes: (match) => {
722
+ const [, alt, src, title] = match;
723
+ return { src, alt, title };
724
+ }
725
+ })
726
+ ];
727
+ }
728
+ });
729
+
730
+ // src/utils/get-shared-extensions.ts
731
+ import StarterKit from "@tiptap/starter-kit";
732
+ import { Details, DetailsContent, DetailsSummary } from "@tiptap/extension-details";
733
+ import Highlight from "@tiptap/extension-highlight";
734
+ import Subscript from "@tiptap/extension-subscript";
735
+ import Superscript from "@tiptap/extension-superscript";
736
+ import TextAlign from "@tiptap/extension-text-align";
737
+
738
+ // node_modules/@tiptap/extension-text-style/dist/index.js
739
+ import { Mark as Mark2, mergeAttributes as mergeAttributes7 } from "@tiptap/core";
740
+ import { Extension } from "@tiptap/core";
741
+ import { Extension as Extension2 } from "@tiptap/core";
742
+ import { Extension as Extension3 } from "@tiptap/core";
743
+ import { Extension as Extension4 } from "@tiptap/core";
744
+ import { Extension as Extension5 } from "@tiptap/core";
745
+ import { Extension as Extension6 } from "@tiptap/core";
746
+ var MAX_FIND_CHILD_SPAN_DEPTH = 20;
747
+ var findChildSpans = (element, depth = 0) => {
748
+ const childSpans = [];
749
+ if (!element.children.length || depth > MAX_FIND_CHILD_SPAN_DEPTH) {
750
+ return childSpans;
751
+ }
752
+ Array.from(element.children).forEach((child) => {
753
+ if (child.tagName === "SPAN") {
754
+ childSpans.push(child);
755
+ } else if (child.children.length) {
756
+ childSpans.push(...findChildSpans(child, depth + 1));
757
+ }
758
+ });
759
+ return childSpans;
760
+ };
761
+ var mergeNestedSpanStyles = (element) => {
762
+ if (!element.children.length) {
763
+ return;
764
+ }
765
+ const childSpans = findChildSpans(element);
766
+ if (!childSpans) {
767
+ return;
768
+ }
769
+ childSpans.forEach((childSpan) => {
770
+ var _a, _b;
771
+ const childStyle = childSpan.getAttribute("style");
772
+ const closestParentSpanStyleOfChild = (_b = (_a = childSpan.parentElement) == null ? void 0 : _a.closest("span")) == null ? void 0 : _b.getAttribute("style");
773
+ childSpan.setAttribute("style", `${closestParentSpanStyleOfChild};${childStyle}`);
774
+ });
775
+ };
776
+ var TextStyle = Mark2.create({
777
+ name: "textStyle",
778
+ priority: 101,
779
+ addOptions() {
780
+ return {
781
+ HTMLAttributes: {},
782
+ mergeNestedSpanStyles: true
783
+ };
784
+ },
785
+ parseHTML() {
786
+ return [
787
+ {
788
+ tag: "span",
789
+ consuming: false,
790
+ getAttrs: (element) => {
791
+ const hasStyles = element.hasAttribute("style");
792
+ if (!hasStyles) {
793
+ return false;
794
+ }
795
+ if (this.options.mergeNestedSpanStyles) {
796
+ mergeNestedSpanStyles(element);
797
+ }
798
+ return {};
799
+ }
800
+ }
801
+ ];
802
+ },
803
+ renderHTML({ HTMLAttributes }) {
804
+ return ["span", mergeAttributes7(this.options.HTMLAttributes, HTMLAttributes), 0];
805
+ },
806
+ addCommands() {
807
+ return {
808
+ toggleTextStyle: (attributes) => ({ commands }) => {
809
+ return commands.toggleMark(this.name, attributes);
810
+ },
811
+ removeEmptyTextStyle: () => ({ tr }) => {
812
+ const { selection } = tr;
813
+ tr.doc.nodesBetween(selection.from, selection.to, (node, pos) => {
814
+ if (node.isTextblock) {
815
+ return true;
816
+ }
817
+ if (!node.marks.filter((mark) => mark.type === this.type).some((mark) => Object.values(mark.attrs).some((value) => !!value))) {
818
+ tr.removeMark(pos, pos + node.nodeSize, this.type);
819
+ }
820
+ });
821
+ return true;
822
+ }
823
+ };
824
+ }
825
+ });
826
+ var BackgroundColor = Extension.create({
827
+ name: "backgroundColor",
828
+ addOptions() {
829
+ return {
830
+ types: ["textStyle"]
831
+ };
832
+ },
833
+ addGlobalAttributes() {
834
+ return [
835
+ {
836
+ types: this.options.types,
837
+ attributes: {
838
+ backgroundColor: {
839
+ default: null,
840
+ parseHTML: (element) => {
841
+ var _a;
842
+ const styleAttr = element.getAttribute("style");
843
+ if (styleAttr) {
844
+ const decls = styleAttr.split(";").map((s) => s.trim()).filter(Boolean);
845
+ for (let i = decls.length - 1; i >= 0; i -= 1) {
846
+ const parts = decls[i].split(":");
847
+ if (parts.length >= 2) {
848
+ const prop = parts[0].trim().toLowerCase();
849
+ const val = parts.slice(1).join(":").trim();
850
+ if (prop === "background-color") {
851
+ return val.replace(/['"]+/g, "");
852
+ }
853
+ }
854
+ }
855
+ }
856
+ return (_a = element.style.backgroundColor) == null ? void 0 : _a.replace(/['"]+/g, "");
857
+ },
858
+ renderHTML: (attributes) => {
859
+ if (!attributes.backgroundColor) {
860
+ return {};
861
+ }
862
+ return {
863
+ style: `background-color: ${attributes.backgroundColor}`
864
+ };
865
+ }
866
+ }
867
+ }
868
+ }
869
+ ];
870
+ },
871
+ addCommands() {
872
+ return {
873
+ setBackgroundColor: (backgroundColor) => ({ chain }) => {
874
+ return chain().setMark("textStyle", { backgroundColor }).run();
875
+ },
876
+ unsetBackgroundColor: () => ({ chain }) => {
877
+ return chain().setMark("textStyle", { backgroundColor: null }).removeEmptyTextStyle().run();
878
+ }
879
+ };
880
+ }
881
+ });
882
+ var Color = Extension2.create({
883
+ name: "color",
884
+ addOptions() {
885
+ return {
886
+ types: ["textStyle"]
887
+ };
888
+ },
889
+ addGlobalAttributes() {
890
+ return [
891
+ {
892
+ types: this.options.types,
893
+ attributes: {
894
+ color: {
895
+ default: null,
896
+ parseHTML: (element) => {
897
+ var _a;
898
+ const styleAttr = element.getAttribute("style");
899
+ if (styleAttr) {
900
+ const decls = styleAttr.split(";").map((s) => s.trim()).filter(Boolean);
901
+ for (let i = decls.length - 1; i >= 0; i -= 1) {
902
+ const parts = decls[i].split(":");
903
+ if (parts.length >= 2) {
904
+ const prop = parts[0].trim().toLowerCase();
905
+ const val = parts.slice(1).join(":").trim();
906
+ if (prop === "color") {
907
+ return val.replace(/['"]+/g, "");
908
+ }
909
+ }
910
+ }
911
+ }
912
+ return (_a = element.style.color) == null ? void 0 : _a.replace(/['"]+/g, "");
913
+ },
914
+ renderHTML: (attributes) => {
915
+ if (!attributes.color) {
916
+ return {};
917
+ }
918
+ return {
919
+ style: `color: ${attributes.color}`
920
+ };
921
+ }
922
+ }
923
+ }
924
+ }
925
+ ];
926
+ },
927
+ addCommands() {
928
+ return {
929
+ setColor: (color) => ({ chain }) => {
930
+ return chain().setMark("textStyle", { color }).run();
931
+ },
932
+ unsetColor: () => ({ chain }) => {
933
+ return chain().setMark("textStyle", { color: null }).removeEmptyTextStyle().run();
934
+ }
935
+ };
936
+ }
937
+ });
938
+ var FontFamily = Extension3.create({
939
+ name: "fontFamily",
940
+ addOptions() {
941
+ return {
942
+ types: ["textStyle"]
943
+ };
944
+ },
945
+ addGlobalAttributes() {
946
+ return [
947
+ {
948
+ types: this.options.types,
949
+ attributes: {
950
+ fontFamily: {
951
+ default: null,
952
+ parseHTML: (element) => element.style.fontFamily,
953
+ renderHTML: (attributes) => {
954
+ if (!attributes.fontFamily) {
955
+ return {};
956
+ }
957
+ return {
958
+ style: `font-family: ${attributes.fontFamily}`
959
+ };
960
+ }
961
+ }
962
+ }
963
+ }
964
+ ];
965
+ },
966
+ addCommands() {
967
+ return {
968
+ setFontFamily: (fontFamily) => ({ chain }) => {
969
+ return chain().setMark("textStyle", { fontFamily }).run();
970
+ },
971
+ unsetFontFamily: () => ({ chain }) => {
972
+ return chain().setMark("textStyle", { fontFamily: null }).removeEmptyTextStyle().run();
973
+ }
974
+ };
975
+ }
976
+ });
977
+ var FontSize = Extension4.create({
978
+ name: "fontSize",
979
+ addOptions() {
980
+ return {
981
+ types: ["textStyle"]
982
+ };
983
+ },
984
+ addGlobalAttributes() {
985
+ return [
986
+ {
987
+ types: this.options.types,
988
+ attributes: {
989
+ fontSize: {
990
+ default: null,
991
+ parseHTML: (element) => element.style.fontSize,
992
+ renderHTML: (attributes) => {
993
+ if (!attributes.fontSize) {
994
+ return {};
995
+ }
996
+ return {
997
+ style: `font-size: ${attributes.fontSize}`
998
+ };
999
+ }
1000
+ }
1001
+ }
1002
+ }
1003
+ ];
1004
+ },
1005
+ addCommands() {
1006
+ return {
1007
+ setFontSize: (fontSize) => ({ chain }) => {
1008
+ return chain().setMark("textStyle", { fontSize }).run();
1009
+ },
1010
+ unsetFontSize: () => ({ chain }) => {
1011
+ return chain().setMark("textStyle", { fontSize: null }).removeEmptyTextStyle().run();
1012
+ }
1013
+ };
1014
+ }
1015
+ });
1016
+ var LineHeight = Extension5.create({
1017
+ name: "lineHeight",
1018
+ addOptions() {
1019
+ return {
1020
+ types: ["textStyle"]
1021
+ };
1022
+ },
1023
+ addGlobalAttributes() {
1024
+ return [
1025
+ {
1026
+ types: this.options.types,
1027
+ attributes: {
1028
+ lineHeight: {
1029
+ default: null,
1030
+ parseHTML: (element) => element.style.lineHeight,
1031
+ renderHTML: (attributes) => {
1032
+ if (!attributes.lineHeight) {
1033
+ return {};
1034
+ }
1035
+ return {
1036
+ style: `line-height: ${attributes.lineHeight}`
1037
+ };
1038
+ }
1039
+ }
1040
+ }
1041
+ }
1042
+ ];
1043
+ },
1044
+ addCommands() {
1045
+ return {
1046
+ setLineHeight: (lineHeight) => ({ chain }) => {
1047
+ return chain().setMark("textStyle", { lineHeight }).run();
1048
+ },
1049
+ unsetLineHeight: () => ({ chain }) => {
1050
+ return chain().setMark("textStyle", { lineHeight: null }).removeEmptyTextStyle().run();
1051
+ }
1052
+ };
1053
+ }
1054
+ });
1055
+ var TextStyleKit = Extension6.create({
1056
+ name: "textStyleKit",
1057
+ addExtensions() {
1058
+ const extensions = [];
1059
+ if (this.options.backgroundColor !== false) {
1060
+ extensions.push(BackgroundColor.configure(this.options.backgroundColor));
1061
+ }
1062
+ if (this.options.color !== false) {
1063
+ extensions.push(Color.configure(this.options.color));
1064
+ }
1065
+ if (this.options.fontFamily !== false) {
1066
+ extensions.push(FontFamily.configure(this.options.fontFamily));
1067
+ }
1068
+ if (this.options.fontSize !== false) {
1069
+ extensions.push(FontSize.configure(this.options.fontSize));
1070
+ }
1071
+ if (this.options.lineHeight !== false) {
1072
+ extensions.push(LineHeight.configure(this.options.lineHeight));
1073
+ }
1074
+ if (this.options.textStyle !== false) {
1075
+ extensions.push(TextStyle.configure(this.options.textStyle));
1076
+ }
1077
+ return extensions;
1078
+ }
1079
+ });
1080
+
1081
+ // src/extensions/base/compatibility.ts
1082
+ import { mergeAttributes as mergeAttributes8, Node as Node6 } from "@tiptap/core";
1083
+ import { TextSelection as TextSelection4 } from "@tiptap/pm/state";
1084
+ import Image2 from "@tiptap/extension-image";
1085
+ var BaseLegacyBookAlert = Node6.create({
1086
+ name: "calloutAlert",
1087
+ group: "block",
1088
+ content: "block+",
1089
+ draggable: true,
1090
+ isolating: true,
1091
+ addAttributes() {
1092
+ return {
1093
+ type: {
1094
+ default: "error"
1095
+ }
1096
+ };
1097
+ },
1098
+ parseHTML() {
1099
+ return [
1100
+ {
1101
+ tag: 'div[data-type="callout-alert"]'
1102
+ }
1103
+ ];
1104
+ },
1105
+ addKeyboardShortcuts() {
1106
+ return {
1107
+ Enter: () => handleExitNode(this.editor, this.name)
1108
+ };
1109
+ },
1110
+ renderHTML({ HTMLAttributes }) {
1111
+ return ["div", mergeAttributes8(HTMLAttributes, { "data-type": "callout-alert" }), 0];
1112
+ }
1113
+ });
1114
+ var BaseLegacyBookTip = Node6.create({
1115
+ name: "calloutTip",
1116
+ group: "block",
1117
+ content: "block+",
1118
+ draggable: true,
1119
+ isolating: true,
1120
+ addAttributes() {
1121
+ return {
1122
+ type: {
1123
+ default: "info"
1124
+ }
1125
+ };
1126
+ },
1127
+ parseHTML() {
1128
+ return [
1129
+ {
1130
+ tag: 'div[data-type="callout-tip"]'
1131
+ }
1132
+ ];
1133
+ },
1134
+ renderHTML({ HTMLAttributes }) {
1135
+ return ["div", mergeAttributes8(HTMLAttributes, { "data-type": "callout-tip" }), 0];
1136
+ },
1137
+ addKeyboardShortcuts() {
1138
+ return {
1139
+ Enter: () => handleExitNode(this.editor, this.name)
1140
+ };
1141
+ }
1142
+ });
1143
+ var BaseLegacySEQuote = Node6.create({
1144
+ name: "customQuoteV2",
1145
+ group: "block",
1146
+ content: "customQuoteText customQuoteAuthor customQuoteSign",
1147
+ selectable: false,
1148
+ draggable: true,
1149
+ isolating: true,
1150
+ addKeyboardShortcuts() {
1151
+ return {
1152
+ Enter: () => {
1153
+ const { view, schema } = this.editor;
1154
+ const { state } = view;
1155
+ const { selection } = state;
1156
+ const $pos = selection.$from;
1157
+ let depth = $pos.depth;
1158
+ let isInsideCustomQuoteV2 = false;
1159
+ while (depth > 0) {
1160
+ const parentNode = $pos.node(depth);
1161
+ if (parentNode.type.name === this.name) {
1162
+ isInsideCustomQuoteV2 = true;
1163
+ break;
1164
+ }
1165
+ depth--;
1166
+ }
1167
+ if (!isInsideCustomQuoteV2) {
1168
+ return false;
1169
+ }
1170
+ const { tr } = state;
1171
+ const posAfter = $pos.after(depth);
1172
+ const paragraphNode = schema.nodes.paragraph.createAndFill();
1173
+ if (!paragraphNode) return false;
1174
+ tr.insert(posAfter, paragraphNode);
1175
+ tr.setSelection(TextSelection4.create(tr.doc, posAfter + 1));
1176
+ view.dispatch(tr);
1177
+ return true;
1178
+ }
1179
+ };
1180
+ },
1181
+ parseHTML() {
1182
+ return [
1183
+ {
1184
+ tag: "div[data-custom-quote-v2]"
1185
+ }
1186
+ ];
1187
+ },
1188
+ renderHTML({ HTMLAttributes }) {
1189
+ return ["div", mergeAttributes8(HTMLAttributes, { "data-custom-quote-v2": "" }), 0];
1190
+ }
1191
+ });
1192
+ var BaseLegacyPromptSE = Node6.create({
1193
+ name: "promptV2",
1194
+ group: "block",
1195
+ content: "(promptHeader | promptV2Header) (promptContent | promptV2Content)",
1196
+ selectable: false,
1197
+ draggable: true,
1198
+ addKeyboardShortcuts() {
1199
+ return {
1200
+ Enter: () => {
1201
+ const { view, schema } = this.editor;
1202
+ const { state } = view;
1203
+ const { selection } = state;
1204
+ const $pos = selection.$from;
1205
+ let depth = $pos.depth;
1206
+ let isInsidePromptV2 = false;
1207
+ while (depth > 0) {
1208
+ const parentNode = $pos.node(depth);
1209
+ if (parentNode.type.name === this.name) {
1210
+ isInsidePromptV2 = true;
1211
+ break;
1212
+ }
1213
+ depth--;
1214
+ }
1215
+ if (!isInsidePromptV2) {
1216
+ return false;
1217
+ }
1218
+ const { tr } = state;
1219
+ const posAfter = $pos.after(depth);
1220
+ const paragraphNode = schema.nodes.paragraph.createAndFill();
1221
+ if (!paragraphNode) return false;
1222
+ tr.insert(posAfter, paragraphNode);
1223
+ tr.setSelection(TextSelection4.create(tr.doc, posAfter + 1));
1224
+ view.dispatch(tr);
1225
+ return true;
1226
+ }
1227
+ };
1228
+ },
1229
+ parseHTML() {
1230
+ return [
1231
+ {
1232
+ tag: "div[data-prompt-v2]"
1233
+ }
1234
+ ];
1235
+ },
1236
+ renderHTML({ HTMLAttributes }) {
1237
+ return ["div", mergeAttributes8(HTMLAttributes, { "data-prompt": "" }), 0];
1238
+ }
1239
+ });
1240
+ var BaseLegacyPromptSEHeader = Node6.create({
1241
+ name: "promptV2Header",
1242
+ group: "block",
1243
+ content: "inline*",
1244
+ selectable: true,
1245
+ draggable: false,
1246
+ parseHTML() {
1247
+ return [
1248
+ {
1249
+ tag: "div[data-prompt-v2-header]"
1250
+ }
1251
+ ];
1252
+ },
1253
+ renderHTML({ HTMLAttributes }) {
1254
+ return ["div", mergeAttributes8(HTMLAttributes, { "data-prompt-header": "" }), 0];
1255
+ }
1256
+ // addNodeView() {
1257
+ // return ReactNodeViewRenderer(PromptHeaderView);
1258
+ // },
1259
+ });
1260
+ var BaseLegacyPromptSEContent = Node6.create({
1261
+ name: "promptV2Content",
1262
+ group: "block",
1263
+ content: "text*",
1264
+ draggable: false,
1265
+ selectable: true,
1266
+ parseHTML() {
1267
+ return [
1268
+ {
1269
+ tag: "div[data-prompt-v2-content]"
1270
+ }
1271
+ ];
1272
+ },
1273
+ renderHTML({ HTMLAttributes }) {
1274
+ return ["div", mergeAttributes8(HTMLAttributes, { "data-prompt-content": "" }), 0];
1275
+ }
1276
+ });
1277
+ var BaseLegacyCustomBlockquote = Node6.create({
1278
+ name: "customBlockquote",
1279
+ group: "block",
1280
+ content: "block+",
1281
+ draggable: true,
1282
+ parseHTML() {
1283
+ return [
1284
+ {
1285
+ tag: 'div[data-type="custom-blockquote"]'
1286
+ }
1287
+ ];
1288
+ },
1289
+ renderHTML() {
1290
+ return ["blockquote", 0];
1291
+ }
1292
+ });
1293
+ var BaseLegacyYouTube = Node6.create({
1294
+ name: "youtube",
1295
+ group: "block",
1296
+ selectable: true,
1297
+ draggable: true,
1298
+ isolating: true,
1299
+ addAttributes() {
1300
+ return {
1301
+ src: {
1302
+ default: null
1303
+ },
1304
+ width: {
1305
+ default: 640
1306
+ },
1307
+ height: {
1308
+ default: 480
1309
+ },
1310
+ start: {
1311
+ default: 0
1312
+ }
1313
+ };
1314
+ },
1315
+ parseHTML() {
1316
+ return [
1317
+ {
1318
+ tag: 'iframe[src*="youtube.com"]'
1319
+ },
1320
+ {
1321
+ tag: 'iframe[src*="youtu.be"]'
1322
+ }
1323
+ ];
1324
+ },
1325
+ renderHTML({ HTMLAttributes }) {
1326
+ return ["video-embed", { src: HTMLAttributes.src }];
1327
+ }
1328
+ });
1329
+ var LegacyInlineLatexSE = Node6.create({
1330
+ name: "inlineLatex",
1331
+ group: "inline",
1332
+ inline: true,
1333
+ content: "text*",
1334
+ atom: true,
1335
+ addAttributes() {
1336
+ return {
1337
+ latex: {
1338
+ default: "",
1339
+ parseHTML: (element) => element.getAttribute("data-latex") || element.textContent || ""
1340
+ }
1341
+ };
1342
+ },
1343
+ parseHTML() {
1344
+ return [
1345
+ {
1346
+ tag: "span.inline-latex"
1347
+ }
1348
+ ];
1349
+ },
1350
+ renderHTML({ HTMLAttributes }) {
1351
+ return ["code", mergeAttributes8(HTMLAttributes, { class: "inline-latex" }), 0];
1352
+ }
1353
+ });
1354
+ var BaseLegacyFigure = Image2.extend({
1355
+ name: "figure",
1356
+ group: "block",
1357
+ content: "inline*",
1358
+ draggable: true,
1359
+ isolating: true,
1360
+ selectable: false,
1361
+ addOptions() {
1362
+ return {
1363
+ HTMLAttributes: {},
1364
+ getImageById: void 0
1365
+ };
1366
+ },
1367
+ addAttributes() {
1368
+ return {
1369
+ ...this.parent?.(),
1370
+ fileId: {
1371
+ default: null,
1372
+ parseHTML: (element) => {
1373
+ const img = element.querySelector("img");
1374
+ const fileIdFromImg = img?.getAttribute("fileId") || img?.getAttribute("data-file-id");
1375
+ const fileIdFromFigure = element.getAttribute("fileId") || element.getAttribute("data-file-id");
1376
+ return fileIdFromImg ?? fileIdFromFigure;
1377
+ },
1378
+ renderHTML: (attributes) => {
1379
+ if (!attributes.fileId) return {};
1380
+ return { "data-file-id": attributes.fileId };
1381
+ }
1382
+ },
1383
+ src: {
1384
+ default: null,
1385
+ parseHTML: (element) => {
1386
+ const img = element.querySelector("img") || element;
1387
+ return img.getAttribute("src");
1388
+ }
1389
+ },
1390
+ alt: {
1391
+ default: null,
1392
+ parseHTML: (element) => {
1393
+ const img = element.querySelector("img") || element;
1394
+ return img.getAttribute("alt");
1395
+ }
1396
+ },
1397
+ title: {
1398
+ default: null,
1399
+ parseHTML: (element) => {
1400
+ const img = element.querySelector("img") || element;
1401
+ return img.getAttribute("title");
1402
+ }
1403
+ },
1404
+ caption: {
1405
+ default: null,
1406
+ parseHTML: (element) => {
1407
+ const caption = element.querySelector("figcaption");
1408
+ return caption ? caption.innerText : null;
1409
+ }
1410
+ }
1411
+ };
1412
+ },
1413
+ parseHTML() {
1414
+ return [
1415
+ {
1416
+ tag: "figure",
1417
+ getAttrs: (element) => {
1418
+ if (typeof element === "string") return false;
1419
+ const img = element.querySelector("img");
1420
+ return img ? {} : false;
1421
+ }
1422
+ },
1423
+ {
1424
+ tag: "img[src]"
1425
+ }
1426
+ ];
1427
+ },
1428
+ renderHTML({ node }) {
1429
+ const resolvedSrc = resolveImageSrc(
1430
+ {
1431
+ fileId: node.attrs.fileId,
1432
+ src: node.attrs.src
1433
+ },
1434
+ { getImageById: this.options.getImageById }
1435
+ );
1436
+ const figureAttrs = mergeAttributes8(this.options.HTMLAttributes);
1437
+ const imgAttrs = {
1438
+ src: resolvedSrc
1439
+ };
1440
+ if (node.attrs.fileId) imgAttrs["data-file-id"] = node.attrs.fileId;
1441
+ if (node.attrs.alt) imgAttrs.alt = node.attrs.alt;
1442
+ if (node.attrs.title) imgAttrs.title = node.attrs.title;
1443
+ if (node.attrs.width) imgAttrs.width = node.attrs.width;
1444
+ if (node.attrs.height) imgAttrs.height = node.attrs.height;
1445
+ const hasCaption = node.attrs.caption && node.attrs.caption.trim().length > 0;
1446
+ const figcaptionContent = hasCaption ? ["figcaption", {}, node.attrs.caption] : null;
1447
+ return [
1448
+ "figure",
1449
+ figureAttrs,
1450
+ ["img", imgAttrs],
1451
+ ...figcaptionContent ? [figcaptionContent] : []
1452
+ ];
1453
+ }
1454
+ });
1455
+
1456
+ // src/utils/get-shared-extensions.ts
1457
+ function getSharedExtensions() {
1458
+ return [
1459
+ StarterKit.configure({
1460
+ codeBlock: false,
1461
+ link: false
1462
+ }),
1463
+ Highlight.configure({ multicolor: true }),
1464
+ LinkExtension,
1465
+ Superscript,
1466
+ Subscript,
1467
+ TextAlign.configure({
1468
+ types: ["heading", "paragraph"]
1469
+ }),
1470
+ TextStyleKit.configure({
1471
+ color: {
1472
+ types: ["textStyle"]
1473
+ }
1474
+ }),
1475
+ Details.configure({
1476
+ persist: true,
1477
+ HTMLAttributes: {
1478
+ class: "details"
1479
+ }
1480
+ }),
1481
+ DetailsSummary,
1482
+ DetailsContent,
1483
+ BaseMythReality,
1484
+ BaseMythRealityBlock,
1485
+ LegacyInlineLatexSE
1486
+ ];
1487
+ }
1488
+
1489
+ // src/extensions/render/get-render-extensions.ts
1490
+ function getRenderExtensions() {
1491
+ const sharedExtensions = getSharedExtensions();
1492
+ return [
1493
+ ...sharedExtensions,
1494
+ CopyableText,
1495
+ BaseCallout,
1496
+ BaseCodeBlock,
1497
+ BaseCustomQuote,
1498
+ BaseCustomQuoteText,
1499
+ BaseCustomQuoteAuthor,
1500
+ BaseCustomQuoteSign,
1501
+ BasePrompt,
1502
+ BasePromptHeader,
1503
+ BasePromptContent,
1504
+ BaseVideo,
1505
+ BaseFigure,
1506
+ // Need to update
1507
+ TableKit.configure({
1508
+ table: { resizable: false }
1509
+ }),
1510
+ Mathematics.configure({
1511
+ katexOptions: {
1512
+ throwOnError: false
1513
+ }
1514
+ }),
1515
+ // ========================================================================
1516
+ // Legacy Extensions (Deprecated - for backward compatibility only)
1517
+ // ========================================================================
1518
+ BaseLegacyBookAlert,
1519
+ BaseLegacyBookTip,
1520
+ BaseLegacySEQuote,
1521
+ BaseLegacyPromptSE,
1522
+ BaseLegacyPromptSEHeader,
1523
+ BaseLegacyPromptSEContent,
1524
+ BaseLegacyCustomBlockquote,
1525
+ BaseLegacyYouTube,
1526
+ BaseLegacyFigure
1527
+ // Update
1528
+ ];
1529
+ }
1530
+
1531
+ // src/render/static-renderer-config.tsx
1532
+ import katex from "katex";
1533
+ import hljs from "highlight.js/lib/common";
1534
+
1535
+ // src/icons/color/TiptapCalloutError.tsx
1536
+ import { jsx, jsxs } from "react/jsx-runtime";
1537
+ var SvgTiptapCalloutError = (props) => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 20 20", ...props, children: [
1538
+ /* @__PURE__ */ jsxs("g", { clipPath: "url(#tiptap-callout-error_svg__a)", children: [
1539
+ /* @__PURE__ */ jsx(
1540
+ "path",
1541
+ {
1542
+ fill: "#E03757",
1543
+ d: "M10 0C4.477 0 0 4.477 0 10s4.477 10 10 10 10-4.477 10-10S15.523 0 10 0"
1544
+ }
1545
+ ),
1546
+ /* @__PURE__ */ jsx(
1547
+ "path",
1548
+ {
1549
+ fill: "#F04760",
1550
+ d: "M4.692 15.603c6.011 0 10.885-4.874 10.885-10.885a10.9 10.9 0 0 0-.525-3.35A9.95 9.95 0 0 0 10 0C4.477 0 0 4.477 0 10a9.95 9.95 0 0 0 1.394 5.094c1.066.338 2.179.51 3.298.509"
1551
+ }
1552
+ ),
1553
+ /* @__PURE__ */ jsx(
1554
+ "path",
1555
+ {
1556
+ fill: "#fff",
1557
+ d: "M9.996 16.783a1.626 1.626 0 1 1 0-3.251 1.626 1.626 0 0 1 0 3.251m1.575-5.598c-.027.252-.14.486-.321.663a1.13 1.13 0 0 1-.674.315h-.008q-.239.027-.48.027a6 6 0 0 1-.575-.027h-.007a1.13 1.13 0 0 1-.674-.315 1.1 1.1 0 0 1-.321-.663c-.04-.366-.059-2.914-.059-3.481 0-.568.02-3.122.059-3.488.027-.252.14-.487.32-.665.183-.177.42-.289.675-.315h.007q.287-.029.576-.017.24-.012.479.017h.008c.254.027.492.14.674.319.18.177.294.412.321.664.04.366.059 2.92.059 3.488 0 .567-.02 3.113-.059 3.478"
1558
+ }
1559
+ )
1560
+ ] }),
1561
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("clipPath", { id: "tiptap-callout-error_svg__a", children: /* @__PURE__ */ jsx("path", { fill: "#fff", d: "M0 0h20v20H0z" }) }) })
1562
+ ] });
1563
+ var TiptapCalloutError_default = SvgTiptapCalloutError;
1564
+
1565
+ // src/icons/color/TiptapCalloutInfo.tsx
1566
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1567
+ var SvgTiptapCalloutInfo = (props) => /* @__PURE__ */ jsxs2("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 20 20", ...props, children: [
1568
+ /* @__PURE__ */ jsx2(
1569
+ "path",
1570
+ {
1571
+ fill: "#FE9738",
1572
+ d: "m11.654 11.196 3.51-2.75.549-4.789-4.06-2.234-1.647 2.264a2.79 2.79 0 0 1 1.531 2.28 2.8 2.8 0 0 1-1.85 2.84 3.96 3.96 0 0 0-2.624 3.728v.72c0 .937.76 1.697 1.696 1.697h2.482zm-4.895-3.32H4.277c-.937 0-1.697-.76-1.697-1.697q0-.432.06-.86C3.084 2.135 5.954-.196 9.172.015h2.482L9.888 1.797m1.353 14.796H8.759c-.937 0-1.696.76-1.696 1.696v.014c0 .938.76 1.697 1.696 1.697h2.18"
1573
+ }
1574
+ ),
1575
+ /* @__PURE__ */ jsx2(
1576
+ "path",
1577
+ {
1578
+ fill: "#FFD15B",
1579
+ d: "M11.241 14.951c-.937 0-1.697-.76-1.697-1.697v-.72a3.955 3.955 0 0 1 2.625-3.727 2.8 2.8 0 0 0 1.85-2.84A2.79 2.79 0 0 0 11.432 3.4a2.8 2.8 0 0 0-2.976 2.78 1.697 1.697 0 0 1-3.394 0q0-.434.06-.86C5.566 2.133 8.435-.198 11.654.014c3.055.2 5.527 2.653 5.75 5.706a6.2 6.2 0 0 1-4.104 6.286.56.56 0 0 0-.362.529v.72c0 .936-.76 1.696-1.697 1.696m0 5.05c-.937 0-1.697-.76-1.697-1.698v-.014a1.697 1.697 0 0 1 3.394 0v.014c0 .937-.76 1.697-1.697 1.697"
1580
+ }
1581
+ ),
1582
+ /* @__PURE__ */ jsx2(
1583
+ "path",
1584
+ {
1585
+ fill: "#FFC344",
1586
+ d: "M6.622 5.32q-.06.427-.06.86c0 .667.386 1.245.947 1.521A1.697 1.697 0 0 1 5.062 6.18q0-.432.06-.86C5.566 2.134 8.436-.197 11.654.014q.173.012.343.033C9.273.382 7.012 2.521 6.622 5.32m7.047 3.486a3.96 3.96 0 0 0-2.625 3.729v.72c0 .667.386 1.245.947 1.521a1.696 1.696 0 0 1-2.447-1.522v-.72a3.955 3.955 0 0 1 2.625-3.728 2.8 2.8 0 0 0 1.85-2.839 2.79 2.79 0 0 0-2.022-2.47 2.786 2.786 0 0 1 3.522 2.47 2.8 2.8 0 0 1-1.85 2.84m-1.678 11.02a1.696 1.696 0 0 1-2.447-1.522v-.015a1.697 1.697 0 0 1 2.448-1.523 1.7 1.7 0 0 0-.948 1.523v.014c0 .668.386 1.246.947 1.522"
1587
+ }
1588
+ )
1589
+ ] });
1590
+ var TiptapCalloutInfo_default = SvgTiptapCalloutInfo;
1591
+
1592
+ // src/icons/color/TiptapCalloutSuccess.tsx
1593
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1594
+ var SvgTiptapCalloutSuccess = (props) => /* @__PURE__ */ jsxs3("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 20 20", ...props, children: [
1595
+ /* @__PURE__ */ jsxs3("g", { clipPath: "url(#tiptap-callout-success_svg__a)", children: [
1596
+ /* @__PURE__ */ jsx3(
1597
+ "path",
1598
+ {
1599
+ fill: "#35495E",
1600
+ d: "M1.972 18.004.06 7.138a2.4 2.4 0 0 1-.035-.317 2.47 2.47 0 0 1 2.073-2.493l3.693-.652-.1 14.328z"
1601
+ }
1602
+ ),
1603
+ /* @__PURE__ */ jsx3(
1604
+ "path",
1605
+ {
1606
+ fill: "#2C3E50",
1607
+ d: "M16.186 17.528a.69.69 0 0 1-.548.517l-10.87 1.917a2.42 2.42 0 0 1-2.83-2.276 2.46 2.46 0 0 1 1.934-2.462l3.045.855h-.003l-2.742.487a1.037 1.037 0 0 0-.786 1.396 1.066 1.066 0 0 0 1.186.635l8.307-1.466z"
1608
+ }
1609
+ ),
1610
+ /* @__PURE__ */ jsx3(
1611
+ "path",
1612
+ {
1613
+ fill: "#F9EAB0",
1614
+ d: "m6.914 16.08-2.742.486a1.035 1.035 0 0 0-.786 1.396 1.066 1.066 0 0 0 1.186.635l8.307-1.466z"
1615
+ }
1616
+ ),
1617
+ /* @__PURE__ */ jsx3(
1618
+ "path",
1619
+ {
1620
+ fill: "#E64C3C",
1621
+ d: "M4.423 11.438 6.339.571a.695.695 0 0 1 .799-.559l10.785 1.902a2.47 2.47 0 0 1 2.074 2.495 3 3 0 0 1-.034.316l-1.917 10.867z"
1622
+ }
1623
+ ),
1624
+ /* @__PURE__ */ jsx3(
1625
+ "path",
1626
+ {
1627
+ fill: "#3F5C6C",
1628
+ d: "M15.668 3.612a.4.4 0 0 1-.06-.005l-7.81-1.378a.345.345 0 0 1 .12-.677l7.81 1.375a.345.345 0 0 1-.06.685M14.01 5.069a.3.3 0 0 1-.06-.005l-5.094-.897a.345.345 0 0 1 .12-.68l5.094.897a.345.345 0 0 1-.06.685"
1629
+ }
1630
+ ),
1631
+ /* @__PURE__ */ jsx3(
1632
+ "path",
1633
+ {
1634
+ fill: "#ECF0F1",
1635
+ d: "m14.727 6.608-7.131-1.26a.345.345 0 0 0-.4.28l-.6 3.395a.345.345 0 0 0 .28.4l7.13 1.26a.345.345 0 0 0 .4-.28l.6-3.396a.345.345 0 0 0-.28-.4"
1636
+ }
1637
+ ),
1638
+ /* @__PURE__ */ jsx3(
1639
+ "path",
1640
+ {
1641
+ fill: "#C03A2B",
1642
+ d: "M19.997 4.407a2 2 0 0 1-.035.317L18.045 15.59l-2.659-.81 1.542-8.738.365-2.063.373-2.11.258.045a2.47 2.47 0 0 1 2.073 2.493"
1643
+ }
1644
+ ),
1645
+ /* @__PURE__ */ jsx3(
1646
+ "path",
1647
+ {
1648
+ fill: "#802F34",
1649
+ d: "M16.007 12.78 5.22 10.88a.69.69 0 0 0-.238 1.358l10.865 1.914a1.038 1.038 0 0 1 .783 1.4 1.06 1.06 0 0 1-1.183.63L4.624 14.277a.69.69 0 0 0-.241 1.359l10.869 1.913a2.416 2.416 0 0 0 2.83-2.272 2.474 2.474 0 0 0-2.075-2.496"
1650
+ }
1651
+ ),
1652
+ /* @__PURE__ */ jsx3(
1653
+ "path",
1654
+ {
1655
+ fill: "#F9EAB0",
1656
+ d: "M16.63 15.552a1.06 1.06 0 0 1-1.182.63L4.624 14.277l.359-2.038 10.865 1.914a1.04 1.04 0 0 1 .783 1.4"
1657
+ }
1658
+ )
1659
+ ] }),
1660
+ /* @__PURE__ */ jsx3("defs", { children: /* @__PURE__ */ jsx3("clipPath", { id: "tiptap-callout-success_svg__a", children: /* @__PURE__ */ jsx3("path", { fill: "#fff", d: "M0 0h20v20H0z" }) }) })
1661
+ ] });
1662
+ var TiptapCalloutSuccess_default = SvgTiptapCalloutSuccess;
1663
+
1664
+ // src/icons/color/TiptapCalloutWarning.tsx
1665
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1666
+ var SvgTiptapCalloutWarning = (props) => /* @__PURE__ */ jsxs4("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 20 20", ...props, children: [
1667
+ /* @__PURE__ */ jsx4(
1668
+ "path",
1669
+ {
1670
+ fill: "#FFF59D",
1671
+ fillOpacity: 0.6,
1672
+ d: "M1.667 9.167a8.333 8.333 0 1 0 16.666 0 8.333 8.333 0 0 0-16.666 0"
1673
+ }
1674
+ ),
1675
+ /* @__PURE__ */ jsx4(
1676
+ "path",
1677
+ {
1678
+ fill: "#FBC02D",
1679
+ d: "M15.417 9.167c0-3.209-2.75-5.75-6.042-5.375-2.5.291-4.5 2.291-4.75 4.791a5.27 5.27 0 0 0 1.917 4.709c.583.5.958 1.208.958 2v.125h5v-.042c0-.75.333-1.5.917-2 1.208-1 2-2.5 2-4.208"
1680
+ }
1681
+ ),
1682
+ /* @__PURE__ */ jsx4(
1683
+ "path",
1684
+ {
1685
+ fill: "#FFF59D",
1686
+ d: "m12.75 8.417-1.25-.834a.45.45 0 0 0-.458 0L10 8.25l-1-.667a.45.45 0 0 0-.458 0l-1.25.834c-.084.083-.167.166-.167.291s0 .25.083.334L8.792 11v4.417h.833v-4.584c0-.083-.042-.166-.083-.25L8.167 8.875l.625-.417 1 .667a.45.45 0 0 0 .458 0l1-.667.625.417-1.375 1.708a.6.6 0 0 0-.083.25v4.584h.833V11l1.583-1.958a.32.32 0 0 0 .084-.334c-.042-.125-.084-.25-.167-.291"
1687
+ }
1688
+ ),
1689
+ /* @__PURE__ */ jsx4("path", { fill: "#5C6BC0", d: "M8.75 18.334a1.25 1.25 0 1 0 2.5 0 1.25 1.25 0 0 0-2.5 0" }),
1690
+ /* @__PURE__ */ jsx4(
1691
+ "path",
1692
+ {
1693
+ fill: "#9FA8DA",
1694
+ d: "M10.833 18.75H9.167C8.25 18.75 7.5 18 7.5 17.083V15h5v2.083c0 .917-.75 1.667-1.667 1.667"
1695
+ }
1696
+ ),
1697
+ /* @__PURE__ */ jsx4(
1698
+ "path",
1699
+ {
1700
+ fill: "#5C6BC0",
1701
+ d: "m12.5 17.083-4.833.667c.125.291.375.583.666.75l3.917-.542q.25-.375.25-.875m-5-.958v.833l5-.708v-.834z"
1702
+ }
1703
+ )
1704
+ ] });
1705
+ var TiptapCalloutWarning_default = SvgTiptapCalloutWarning;
1706
+
1707
+ // src/utils/custom-emoji.ts
1708
+ var calloutIconComponents = {
1709
+ "callout-info": TiptapCalloutInfo_default,
1710
+ "callout-success": TiptapCalloutSuccess_default,
1711
+ "callout-warning": TiptapCalloutWarning_default,
1712
+ "callout-error": TiptapCalloutError_default
1713
+ };
1714
+
1715
+ // src/extensions/views/components/callout.tsx
1716
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1717
+ var calloutIcons = {
1718
+ info: /* @__PURE__ */ jsx5(TiptapCalloutInfo_default, {}),
1719
+ warning: /* @__PURE__ */ jsx5(TiptapCalloutWarning_default, {}),
1720
+ success: /* @__PURE__ */ jsx5(TiptapCalloutSuccess_default, {}),
1721
+ error: /* @__PURE__ */ jsx5(TiptapCalloutError_default, {})
1722
+ };
1723
+ var legacyTypeMap3 = {
1724
+ question: "info",
1725
+ idea: "warning",
1726
+ info: "success",
1727
+ error: "error"
1728
+ };
1729
+ var Callout = ({ type, bgColor, emoji, children, iconWrapper, calloutType }) => {
1730
+ const isLegacySECallout = !!calloutType;
1731
+ const finalType = isLegacySECallout ? legacyTypeMap3[calloutType] : type;
1732
+ const hasCustomColor = !!bgColor;
1733
+ const className = hasCustomColor ? "callout-node" : `callout-node callout-${finalType}`;
1734
+ const style = hasCustomColor ? { backgroundColor: bgColor } : void 0;
1735
+ let icon;
1736
+ if (emoji) {
1737
+ if (emoji in calloutIconComponents) {
1738
+ const IconComponent = calloutIconComponents[emoji];
1739
+ icon = /* @__PURE__ */ jsx5(IconComponent, {});
1740
+ } else {
1741
+ icon = emoji;
1742
+ }
1743
+ } else {
1744
+ icon = calloutIcons[finalType];
1745
+ }
1746
+ const iconContent = iconWrapper ? iconWrapper(icon) : /* @__PURE__ */ jsx5("div", { className: "callout-icon", children: icon });
1747
+ return /* @__PURE__ */ jsxs5(
1748
+ "div",
1749
+ {
1750
+ className,
1751
+ "data-callout-type": hasCustomColor ? void 0 : type,
1752
+ "data-bg-color": bgColor || void 0,
1753
+ "data-emoji": emoji || void 0,
1754
+ style,
1755
+ children: [
1756
+ iconContent,
1757
+ /* @__PURE__ */ jsx5("div", { className: "callout-content-wrapper", children: /* @__PURE__ */ jsx5("div", { className: "callout-content", children }) })
1758
+ ]
1759
+ }
1760
+ );
1761
+ };
1762
+
1763
+ // src/extensions/views/components/code-block.tsx
1764
+ import { useMemo } from "react";
1765
+ import html2 from "highlight.js/lib/languages/xml";
1766
+ import { common as common2, createLowlight as createLowlight2 } from "lowlight";
1767
+
1768
+ // src/icons/Check.tsx
1769
+ import { jsx as jsx6 } from "react/jsx-runtime";
1770
+ var SvgCheck = (props) => /* @__PURE__ */ jsx6("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", ...props, children: /* @__PURE__ */ jsx6(
1771
+ "path",
1772
+ {
1773
+ fill: "currentColor",
1774
+ fillRule: "evenodd",
1775
+ d: "M20.707 5.293a1 1 0 0 1 0 1.414l-11 11a1 1 0 0 1-1.414 0l-5-5a1 1 0 1 1 1.414-1.414L9 15.586 19.293 5.293a1 1 0 0 1 1.414 0",
1776
+ clipRule: "evenodd"
1777
+ }
1778
+ ) });
1779
+ var Check_default = SvgCheck;
1780
+
1781
+ // src/icons/Copy.tsx
1782
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1783
+ var SvgCopy = (props) => /* @__PURE__ */ jsxs6("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 20 20", ...props, children: [
1784
+ /* @__PURE__ */ jsxs6("g", { fill: "currentColor", fillRule: "evenodd", clipPath: "url(#copy_svg__a)", clipRule: "evenodd", children: [
1785
+ /* @__PURE__ */ jsx7("path", { d: "M9.167 8.333a.833.833 0 0 0-.834.833v7.5c0 .46.373.834.833.834h7.5c.46 0 .834-.373.834-.834v-7.5a.833.833 0 0 0-.834-.833zm-2.5.833a2.5 2.5 0 0 1 2.5-2.5h7.5a2.5 2.5 0 0 1 2.5 2.5v7.5a2.5 2.5 0 0 1-2.5 2.5h-7.5a2.5 2.5 0 0 1-2.5-2.5z" }),
1786
+ /* @__PURE__ */ jsx7("path", { d: "M3.334 2.5a.833.833 0 0 0-.834.833v7.5a.833.833 0 0 0 .833.834h.834a.833.833 0 0 1 0 1.667h-.833a2.5 2.5 0 0 1-2.5-2.5v-7.5a2.5 2.5 0 0 1 2.5-2.5h7.5a2.5 2.5 0 0 1 2.5 2.5v.833a.833.833 0 1 1-1.667 0v-.833a.834.834 0 0 0-.833-.834z" })
1787
+ ] }),
1788
+ /* @__PURE__ */ jsx7("defs", { children: /* @__PURE__ */ jsx7("clipPath", { id: "copy_svg__a", children: /* @__PURE__ */ jsx7("path", { fill: "currentColor", d: "M0 0h20v20H0z" }) }) })
1789
+ ] });
1790
+ var Copy_default = SvgCopy;
1791
+
1792
+ // src/icons/DragIcon.tsx
1793
+ import { jsx as jsx8 } from "react/jsx-runtime";
1794
+
1795
+ // src/icons/Edit.tsx
1796
+ import { jsx as jsx9 } from "react/jsx-runtime";
1797
+ var SvgEdit = (props) => /* @__PURE__ */ jsx9("svg", { fill: "none", viewBox: "0 0 18 18", ...props, children: /* @__PURE__ */ jsx9(
1798
+ "path",
1799
+ {
1800
+ fill: "currentColor",
1801
+ fillRule: "evenodd",
1802
+ d: "M11.745.91a.833.833 0 0 1 1.179 0l4.167 4.167a.833.833 0 0 1 0 1.179L6.257 17.089a.83.83 0 0 1-.589.244H1.501a.833.833 0 0 1-.833-.833v-4.167c0-.22.088-.433.244-.589zM2.335 12.68v2.988h2.988l10-10-2.988-2.988z",
1803
+ clipRule: "evenodd"
1804
+ }
1805
+ ) });
1806
+ var Edit_default = SvgEdit;
1807
+
1808
+ // src/icons/Quote.tsx
1809
+ import { jsx as jsx10 } from "react/jsx-runtime";
1810
+ var SvgQuote = (props) => /* @__PURE__ */ jsx10("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 48 48", ...props, children: /* @__PURE__ */ jsx10(
1811
+ "path",
1812
+ {
1813
+ fill: "currentColor",
1814
+ d: "M19.284 11.242c1.2-.504 1.703-1.937 1.161-3.098l-1.897-3.989c-.542-1.122-1.859-1.626-3.02-1.122-3.292 1.394-6.119 3.214-8.364 5.42-2.75 2.595-4.608 5.577-5.615 8.868C.542 20.65 0 25.18 0 30.95v11.888a2.33 2.33 0 0 0 2.323 2.323h15.218a2.33 2.33 0 0 0 2.323-2.323V27.62a2.33 2.33 0 0 0-2.323-2.323h-7.28c.078-3.912 1.007-7.048 2.71-9.41 1.395-1.897 3.486-3.446 6.313-4.646m27.337 0c1.2-.504 1.703-1.937 1.162-3.098l-1.898-3.95a2.315 2.315 0 0 0-3.02-1.122c-3.253 1.394-6.04 3.214-8.325 5.382-2.75 2.633-4.647 5.615-5.654 8.906q-1.51 4.879-1.51 13.591V42.84a2.33 2.33 0 0 0 2.324 2.323h15.217a2.33 2.33 0 0 0 2.324-2.323V27.62a2.33 2.33 0 0 0-2.324-2.323H37.6c.077-3.911 1.007-7.047 2.71-9.41 1.394-1.897 3.485-3.446 6.312-4.646"
1815
+ }
1816
+ ) });
1817
+ var Quote_default = SvgQuote;
1818
+
1819
+ // src/icons/X.tsx
1820
+ import { jsx as jsx11 } from "react/jsx-runtime";
1821
+
1822
+ // src/icons/menu/AddImage.tsx
1823
+ import { jsx as jsx12 } from "react/jsx-runtime";
1824
+
1825
+ // src/icons/menu/AlignCenter.tsx
1826
+ import { jsx as jsx13 } from "react/jsx-runtime";
1827
+
1828
+ // src/icons/menu/AlignLeft.tsx
1829
+ import { jsx as jsx14 } from "react/jsx-runtime";
1830
+
1831
+ // src/icons/menu/AlignRight.tsx
1832
+ import { jsx as jsx15 } from "react/jsx-runtime";
1833
+
1834
+ // src/icons/menu/ArrowDown.tsx
1835
+ import { jsx as jsx16 } from "react/jsx-runtime";
1836
+
1837
+ // src/icons/menu/ArrowLeft.tsx
1838
+ import { jsx as jsx17 } from "react/jsx-runtime";
1839
+
1840
+ // src/icons/menu/ArrowRight.tsx
1841
+ import { jsx as jsx18 } from "react/jsx-runtime";
1842
+
1843
+ // src/icons/menu/ArrowUp.tsx
1844
+ import { jsx as jsx19 } from "react/jsx-runtime";
1845
+
1846
+ // src/icons/menu/Blockquote.tsx
1847
+ import { jsx as jsx20 } from "react/jsx-runtime";
1848
+
1849
+ // src/icons/menu/Bold.tsx
1850
+ import { jsx as jsx21 } from "react/jsx-runtime";
1851
+
1852
+ // src/icons/menu/BulletList.tsx
1853
+ import { jsx as jsx22 } from "react/jsx-runtime";
1854
+
1855
+ // src/icons/menu/CalloutError.tsx
1856
+ import { jsx as jsx23 } from "react/jsx-runtime";
1857
+
1858
+ // src/icons/menu/CalloutInfo.tsx
1859
+ import { jsx as jsx24 } from "react/jsx-runtime";
1860
+
1861
+ // src/icons/menu/CalloutSuccess.tsx
1862
+ import { jsx as jsx25 } from "react/jsx-runtime";
1863
+
1864
+ // src/icons/menu/CalloutWarning.tsx
1865
+ import { jsx as jsx26 } from "react/jsx-runtime";
1866
+
1867
+ // src/icons/menu/ClearFormatting.tsx
1868
+ import { jsx as jsx27 } from "react/jsx-runtime";
1869
+
1870
+ // src/icons/menu/CodeBlock.tsx
1871
+ import { jsx as jsx28 } from "react/jsx-runtime";
1872
+
1873
+ // src/icons/menu/Copyable.tsx
1874
+ import { jsx as jsx29 } from "react/jsx-runtime";
1875
+
1876
+ // src/icons/menu/CustomQuote.tsx
1877
+ import { jsx as jsx30, jsxs as jsxs7 } from "react/jsx-runtime";
1878
+
1879
+ // src/icons/menu/DeleteColumn.tsx
1880
+ import { jsx as jsx31, jsxs as jsxs8 } from "react/jsx-runtime";
1881
+
1882
+ // src/icons/menu/DeleteRow.tsx
1883
+ import { jsx as jsx32, jsxs as jsxs9 } from "react/jsx-runtime";
1884
+
1885
+ // src/icons/menu/Details.tsx
1886
+ import { jsx as jsx33 } from "react/jsx-runtime";
1887
+
1888
+ // src/icons/menu/H2.tsx
1889
+ import { jsx as jsx34 } from "react/jsx-runtime";
1890
+
1891
+ // src/icons/menu/H3.tsx
1892
+ import { jsx as jsx35 } from "react/jsx-runtime";
1893
+
1894
+ // src/icons/menu/H4.tsx
1895
+ import { jsx as jsx36 } from "react/jsx-runtime";
1896
+
1897
+ // src/icons/menu/H5.tsx
1898
+ import { jsx as jsx37 } from "react/jsx-runtime";
1899
+
1900
+ // src/icons/menu/H6.tsx
1901
+ import { jsx as jsx38 } from "react/jsx-runtime";
1902
+
1903
+ // src/icons/menu/Highlight.tsx
1904
+ import { jsx as jsx39 } from "react/jsx-runtime";
1905
+
1906
+ // src/icons/menu/HorizontalRule.tsx
1907
+ import { jsx as jsx40 } from "react/jsx-runtime";
1908
+
1909
+ // src/icons/menu/Italic.tsx
1910
+ import { jsx as jsx41 } from "react/jsx-runtime";
1911
+
1912
+ // src/icons/menu/LinkOff.tsx
1913
+ import { jsx as jsx42 } from "react/jsx-runtime";
1914
+
1915
+ // src/icons/menu/Link.tsx
1916
+ import { jsx as jsx43 } from "react/jsx-runtime";
1917
+
1918
+ // src/icons/menu/Math.tsx
1919
+ import { jsx as jsx44 } from "react/jsx-runtime";
1920
+
1921
+ // src/icons/menu/MergeCells.tsx
1922
+ import { jsx as jsx45 } from "react/jsx-runtime";
1923
+
1924
+ // src/icons/menu/MythReality.tsx
1925
+ import { jsx as jsx46 } from "react/jsx-runtime";
1926
+
1927
+ // src/icons/menu/OrderedList.tsx
1928
+ import { jsx as jsx47 } from "react/jsx-runtime";
1929
+
1930
+ // src/icons/menu/Prompt.tsx
1931
+ import { jsx as jsx48, jsxs as jsxs10 } from "react/jsx-runtime";
1932
+
1933
+ // src/icons/menu/Redo.tsx
1934
+ import { jsx as jsx49, jsxs as jsxs11 } from "react/jsx-runtime";
1935
+
1936
+ // src/icons/menu/SplitCells.tsx
1937
+ import { jsx as jsx50 } from "react/jsx-runtime";
1938
+
1939
+ // src/icons/menu/Strikethrough.tsx
1940
+ import { jsx as jsx51 } from "react/jsx-runtime";
1941
+
1942
+ // src/icons/menu/Subscript.tsx
1943
+ import { jsx as jsx52 } from "react/jsx-runtime";
1944
+
1945
+ // src/icons/menu/Superscript.tsx
1946
+ import { jsx as jsx53 } from "react/jsx-runtime";
1947
+
1948
+ // src/icons/menu/TableColumnHeading.tsx
1949
+ import { jsx as jsx54 } from "react/jsx-runtime";
1950
+
1951
+ // src/icons/menu/TableRowHeading.tsx
1952
+ import { jsx as jsx55 } from "react/jsx-runtime";
1953
+
1954
+ // src/icons/menu/Table.tsx
1955
+ import { jsx as jsx56, jsxs as jsxs12 } from "react/jsx-runtime";
1956
+
1957
+ // src/icons/menu/TextColor.tsx
1958
+ import { jsx as jsx57 } from "react/jsx-runtime";
1959
+
1960
+ // src/icons/menu/Underline.tsx
1961
+ import { jsx as jsx58 } from "react/jsx-runtime";
1962
+
1963
+ // src/icons/menu/Undo.tsx
1964
+ import { jsx as jsx59, jsxs as jsxs13 } from "react/jsx-runtime";
1965
+
1966
+ // src/icons/menu/Video.tsx
1967
+ import { jsx as jsx60, jsxs as jsxs14 } from "react/jsx-runtime";
1968
+
1969
+ // src/extensions/views/components/copy-button.tsx
1970
+ import { jsx as jsx61, jsxs as jsxs15 } from "react/jsx-runtime";
1971
+ var CopyButton = ({ iconSize = 16, color = "black" }) => {
1972
+ return /* @__PURE__ */ jsxs15(
1973
+ "button",
1974
+ {
1975
+ className: `copy-button copy-icon-${color}`,
1976
+ "data-copy-action": "copy",
1977
+ type: "button",
1978
+ children: [
1979
+ /* @__PURE__ */ jsx61(
1980
+ "span",
1981
+ {
1982
+ className: "copy-icon",
1983
+ "data-copy-icon": "default",
1984
+ children: /* @__PURE__ */ jsx61(
1985
+ Copy_default,
1986
+ {
1987
+ width: iconSize,
1988
+ height: iconSize
1989
+ }
1990
+ )
1991
+ }
1992
+ ),
1993
+ /* @__PURE__ */ jsx61(
1994
+ "span",
1995
+ {
1996
+ className: "copy-icon-success",
1997
+ "data-copy-icon": "success",
1998
+ style: { display: "none" },
1999
+ children: /* @__PURE__ */ jsx61(
2000
+ Check_default,
2001
+ {
2002
+ width: iconSize,
2003
+ height: iconSize
2004
+ }
2005
+ )
2006
+ }
2007
+ )
2008
+ ]
2009
+ }
2010
+ );
2011
+ };
2012
+
2013
+ // src/extensions/views/components/code-block.tsx
2014
+ import { jsx as jsx62, jsxs as jsxs16 } from "react/jsx-runtime";
2015
+ var CodeBlock = ({
2016
+ language,
2017
+ isEditable,
2018
+ onLanguageChange,
2019
+ children,
2020
+ translations
2021
+ }) => {
2022
+ const languagesList = useMemo(() => {
2023
+ const lowlight2 = createLowlight2(common2);
2024
+ lowlight2.register("html", html2);
2025
+ const list = lowlight2.listLanguages();
2026
+ return list.sort();
2027
+ }, []);
2028
+ const handleChange = (e) => {
2029
+ onLanguageChange?.(e.target.value);
2030
+ };
2031
+ return /* @__PURE__ */ jsxs16("div", { className: "tiptap-code-block-wrapper", children: [
2032
+ /* @__PURE__ */ jsxs16("div", { className: "tiptap-code-block-header", children: [
2033
+ isEditable ? /* @__PURE__ */ jsxs16(
2034
+ "select",
2035
+ {
2036
+ className: "tiptap-code-block-language-select",
2037
+ value: language,
2038
+ onChange: handleChange,
2039
+ children: [
2040
+ /* @__PURE__ */ jsx62("option", { value: "", children: translations?.codeBlock.selectLanguage }),
2041
+ languagesList.map((lang) => /* @__PURE__ */ jsx62(
2042
+ "option",
2043
+ {
2044
+ value: lang,
2045
+ children: lang
2046
+ },
2047
+ lang
2048
+ ))
2049
+ ]
2050
+ }
2051
+ ) : /* @__PURE__ */ jsx62("span", { className: "tiptap-code-block-language-text", children: language || translations?.codeBlock.selectLanguage }),
2052
+ /* @__PURE__ */ jsx62(
2053
+ CopyButton,
2054
+ {
2055
+ iconSize: 20,
2056
+ color: "white"
2057
+ }
2058
+ )
2059
+ ] }),
2060
+ /* @__PURE__ */ jsx62("pre", { className: "tiptap-code-block", children: /* @__PURE__ */ jsx62(
2061
+ "code",
2062
+ {
2063
+ className: "tiptap-code-block-content",
2064
+ "data-copy-content": true,
2065
+ children
2066
+ }
2067
+ ) })
2068
+ ] });
2069
+ };
2070
+
2071
+ // src/extensions/views/components/copyable-text.tsx
2072
+ import { jsx as jsx63, jsxs as jsxs17 } from "react/jsx-runtime";
2073
+ var CopyableText2 = ({ children }) => {
2074
+ return /* @__PURE__ */ jsxs17("span", { className: "copyable", children: [
2075
+ /* @__PURE__ */ jsx63("span", { "data-copy-content": true, children }),
2076
+ /* @__PURE__ */ jsx63(CopyButton, { iconSize: 16 })
2077
+ ] });
2078
+ };
2079
+
2080
+ // src/extensions/views/components/custom-quote.tsx
2081
+ import { jsx as jsx64, jsxs as jsxs18 } from "react/jsx-runtime";
2082
+ var CustomQuote = ({ children }) => /* @__PURE__ */ jsxs18("div", { "data-custom-quote": "", children: [
2083
+ /* @__PURE__ */ jsx64("div", { className: "custom-quote-divider" }),
2084
+ /* @__PURE__ */ jsx64("div", { className: "custom-quote-svg-wrapper", children: /* @__PURE__ */ jsx64(Quote_default, {}) }),
2085
+ children
2086
+ ] });
2087
+ var CustomQuoteText = ({ children, isEmpty, placeholder }) => /* @__PURE__ */ jsx64(
2088
+ "div",
2089
+ {
2090
+ "data-custom-quote-text": true,
2091
+ className: isEmpty ? "is-empty" : "",
2092
+ "data-placeholder": placeholder,
2093
+ children
2094
+ }
2095
+ );
2096
+ var CustomQuoteAuthor = ({ children, isEmpty, placeholder }) => /* @__PURE__ */ jsx64(
2097
+ "div",
2098
+ {
2099
+ "data-custom-quote-author": "",
2100
+ className: isEmpty ? "is-empty" : "",
2101
+ "data-placeholder": placeholder,
2102
+ children
2103
+ }
2104
+ );
2105
+ var CustomQuoteSign = ({ children, isEmpty, placeholder }) => /* @__PURE__ */ jsx64(
2106
+ "div",
2107
+ {
2108
+ "data-custom-quote-sign": "",
2109
+ className: isEmpty ? "is-empty" : "",
2110
+ "data-placeholder": placeholder,
2111
+ children
2112
+ }
2113
+ );
2114
+
2115
+ // src/extensions/views/components/figure.tsx
2116
+ import { jsx as jsx65, jsxs as jsxs19 } from "react/jsx-runtime";
2117
+ var Figure = ({
2118
+ src,
2119
+ alt,
2120
+ title,
2121
+ caption,
2122
+ width,
2123
+ height,
2124
+ isEditable,
2125
+ onEditClick,
2126
+ children,
2127
+ fileId,
2128
+ getImageById
2129
+ }) => {
2130
+ const resolvedSrc = resolveImageSrc({ fileId, src }, { getImageById });
2131
+ return /* @__PURE__ */ jsxs19("figure", { children: [
2132
+ resolvedSrc && /* @__PURE__ */ jsxs19("div", { className: "figure-image-container", children: [
2133
+ /* @__PURE__ */ jsx65(
2134
+ "img",
2135
+ {
2136
+ src: resolvedSrc,
2137
+ alt: alt || "",
2138
+ title,
2139
+ width: width || void 0,
2140
+ height: height || void 0
2141
+ }
2142
+ ),
2143
+ isEditable && onEditClick && /* @__PURE__ */ jsx65(
2144
+ "button",
2145
+ {
2146
+ type: "button",
2147
+ className: "figure-edit-button",
2148
+ onClick: onEditClick,
2149
+ contentEditable: false,
2150
+ "aria-label": "\u0420\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435",
2151
+ children: /* @__PURE__ */ jsx65(Edit_default, {})
2152
+ }
2153
+ )
2154
+ ] }),
2155
+ caption && /* @__PURE__ */ jsx65("figcaption", { children: caption }),
2156
+ children
2157
+ ] });
2158
+ };
2159
+
2160
+ // src/extensions/views/components/prompt.tsx
2161
+ import { jsx as jsx66, jsxs as jsxs20 } from "react/jsx-runtime";
2162
+ var PromptHeader = ({ children, isEmpty, placeholder }) => /* @__PURE__ */ jsxs20("div", { className: "prompt-header-wrapper", children: [
2163
+ /* @__PURE__ */ jsx66(
2164
+ "div",
2165
+ {
2166
+ className: isEmpty ? "is-empty" : "",
2167
+ "data-placeholder": placeholder,
2168
+ children
2169
+ }
2170
+ ),
2171
+ /* @__PURE__ */ jsx66("span", { className: "prompt-copy-icon-wrapper", children: /* @__PURE__ */ jsx66(
2172
+ CopyButton,
2173
+ {
2174
+ iconSize: 16,
2175
+ color: "prompt"
2176
+ }
2177
+ ) })
2178
+ ] });
2179
+ var PromptContent = ({ children, isEmpty, placeholder }) => /* @__PURE__ */ jsx66("div", { className: "prompt-content-wrapper", children: /* @__PURE__ */ jsx66(
2180
+ "div",
2181
+ {
2182
+ className: isEmpty ? "is-empty" : "",
2183
+ "data-placeholder": placeholder,
2184
+ "data-copy-content": true,
2185
+ children
2186
+ }
2187
+ ) });
2188
+
2189
+ // src/utils/detect-video-hosting.ts
2190
+ var VIDEO_PATTERNS = {
2191
+ youtube: /(?:https?:\/\/)?(?:www\.)?(?:youtube\.com|youtu\.be)\/(?:watch\?v=|shorts\/)?([a-zA-Z0-9_-]{11})/,
2192
+ youtubeEmbed: /(?:https?:\/\/)?(?:www\.)?(?:youtube\.com|youtube-nocookie\.com)\/embed\/([a-zA-Z0-9_-]{11})/,
2193
+ vimeo: /(?:http|https)?:\/\/(?:www\.)?vimeo\.com\/(?:channels\/(?:\w+\/)?|groups\/(?:[^/]*)?\/videos\/)?(\d+)(?:|\/\?)/,
2194
+ rutube: /^https:\/\/rutube\.ru\/video\/([\w-]+)/,
2195
+ vk: /(?:https?:\/\/)?(?:vk\.com|vkvideo\.ru)\/video(-?\d+)_(\d+)/
2196
+ };
2197
+ var detectVideoHosting = (src) => {
2198
+ if (!src || typeof src !== "string") {
2199
+ return null;
2200
+ }
2201
+ const cleanSrc = src.trim();
2202
+ if (!cleanSrc) {
2203
+ return null;
2204
+ }
2205
+ try {
2206
+ const youTubeEmbedMatch = VIDEO_PATTERNS.youtubeEmbed.exec(cleanSrc);
2207
+ if (youTubeEmbedMatch?.[1]) {
2208
+ const videoId = youTubeEmbedMatch[1];
2209
+ return {
2210
+ hosting: "youtube" /* Youtube */,
2211
+ videoId,
2212
+ embedUrl: `https://www.youtube-nocookie.com/embed/${videoId}`
2213
+ };
2214
+ }
2215
+ const youTubeMatch = VIDEO_PATTERNS.youtube.exec(cleanSrc);
2216
+ if (youTubeMatch?.[1]) {
2217
+ const videoId = youTubeMatch[1];
2218
+ return {
2219
+ hosting: "youtube" /* Youtube */,
2220
+ videoId,
2221
+ embedUrl: `https://www.youtube-nocookie.com/embed/${videoId}`
2222
+ };
2223
+ }
2224
+ const vimeoMatch = VIDEO_PATTERNS.vimeo.exec(cleanSrc);
2225
+ if (vimeoMatch?.[1]) {
2226
+ const videoId = vimeoMatch[1];
2227
+ const hashRegex = /\/(\d+)\/([a-fA-F0-9]+)/;
2228
+ const hashMatch = hashRegex.exec(cleanSrc);
2229
+ const hash = hashMatch?.[2] || null;
2230
+ const hashParam = hash ? `?h=${hash}` : "";
2231
+ return {
2232
+ hosting: "vimeo" /* Vimeo */,
2233
+ videoId,
2234
+ embedUrl: `https://player.vimeo.com/video/${videoId}${hashParam}`
2235
+ };
2236
+ }
2237
+ const ruTubeMatch = VIDEO_PATTERNS.rutube.exec(cleanSrc);
2238
+ if (ruTubeMatch?.[1]) {
2239
+ const videoId = ruTubeMatch[1];
2240
+ return {
2241
+ hosting: "rutube" /* Rutube */,
2242
+ videoId,
2243
+ embedUrl: `https://rutube.ru/play/embed/${videoId}`
2244
+ };
2245
+ }
2246
+ const vkMatch = VIDEO_PATTERNS.vk.exec(cleanSrc);
2247
+ if (vkMatch?.[1] && vkMatch?.[2]) {
2248
+ const videoId = `${vkMatch[1]}_${vkMatch[2]}`;
2249
+ return {
2250
+ hosting: "vk" /* VK */,
2251
+ videoId,
2252
+ embedUrl: `https://vk.com/video_ext.php?oid=${vkMatch[1]}&id=${vkMatch[2]}`
2253
+ };
2254
+ }
2255
+ } catch {
2256
+ }
2257
+ return null;
2258
+ };
2259
+
2260
+ // src/extensions/views/components/video.tsx
2261
+ import { jsx as jsx67, jsxs as jsxs21 } from "react/jsx-runtime";
2262
+ var Video = ({ src, children }) => {
2263
+ const videoInfo = detectVideoHosting(src);
2264
+ if (!videoInfo?.embedUrl) {
2265
+ return /* @__PURE__ */ jsxs21("div", { className: "video-node", children: [
2266
+ /* @__PURE__ */ jsx67("div", { className: "video-error", children: /* @__PURE__ */ jsx67("span", { children: "Unsupported or invalid video URL" }) }),
2267
+ children
2268
+ ] });
2269
+ }
2270
+ return /* @__PURE__ */ jsxs21(
2271
+ "div",
2272
+ {
2273
+ className: "video-node",
2274
+ "data-video": "",
2275
+ children: [
2276
+ /* @__PURE__ */ jsx67("div", { className: "video-player-wrapper", children: /* @__PURE__ */ jsx67(
2277
+ "iframe",
2278
+ {
2279
+ className: "video-iframe",
2280
+ src: videoInfo?.embedUrl,
2281
+ title: "Video Player",
2282
+ allow: "autoplay; encrypted-media",
2283
+ allowFullScreen: true
2284
+ }
2285
+ ) }),
2286
+ children
2287
+ ]
2288
+ }
2289
+ );
2290
+ };
2291
+
2292
+ // src/render/static-renderer-config.tsx
2293
+ import { jsx as jsx68 } from "react/jsx-runtime";
2294
+ var getNodeMapping = (getImageById) => ({
2295
+ callout({ node, children }) {
2296
+ return /* @__PURE__ */ jsx68(Callout, { ...node.attrs, children });
2297
+ },
2298
+ codeBlock({ node, children }) {
2299
+ const language = node.attrs.language || "";
2300
+ let codeText = "";
2301
+ if (Array.isArray(children)) {
2302
+ codeText = children.map((child) => {
2303
+ if (child?.props?.node?.text) {
2304
+ return child.props.node.text;
2305
+ }
2306
+ return "";
2307
+ }).join("");
2308
+ }
2309
+ let highlightedHtml = "";
2310
+ try {
2311
+ if (!language) {
2312
+ highlightedHtml = hljs.highlightAuto(codeText).value;
2313
+ } else {
2314
+ highlightedHtml = hljs.highlight(codeText, { language }).value;
2315
+ }
2316
+ } catch (error) {
2317
+ console.warn(`Failed to highlight code for language "${language}":`, error);
2318
+ highlightedHtml = codeText.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
2319
+ }
2320
+ return /* @__PURE__ */ jsx68(
2321
+ CodeBlock,
2322
+ {
2323
+ language,
2324
+ isEditable: false,
2325
+ children: /* @__PURE__ */ jsx68("code", { dangerouslySetInnerHTML: { __html: highlightedHtml } })
2326
+ }
2327
+ );
2328
+ },
2329
+ customQuote({ children }) {
2330
+ return /* @__PURE__ */ jsx68(CustomQuote, { children });
2331
+ },
2332
+ customQuoteText({ children }) {
2333
+ return /* @__PURE__ */ jsx68(CustomQuoteText, { children });
2334
+ },
2335
+ customQuoteAuthor({ children }) {
2336
+ return /* @__PURE__ */ jsx68(CustomQuoteAuthor, { children });
2337
+ },
2338
+ customQuoteSign({ children }) {
2339
+ return /* @__PURE__ */ jsx68(CustomQuoteSign, { children });
2340
+ },
2341
+ promptHeader({ children }) {
2342
+ return /* @__PURE__ */ jsx68(PromptHeader, { children });
2343
+ },
2344
+ promptContent({ children }) {
2345
+ return /* @__PURE__ */ jsx68(PromptContent, { children });
2346
+ },
2347
+ video({ node }) {
2348
+ return /* @__PURE__ */ jsx68(Video, { src: node.attrs.src });
2349
+ },
2350
+ figure({ node }) {
2351
+ return /* @__PURE__ */ jsx68(Figure, { ...node.attrs, getImageById });
2352
+ },
2353
+ image({ node }) {
2354
+ return /* @__PURE__ */ jsx68(Figure, { ...node.attrs, getImageById });
2355
+ },
2356
+ inlineMath({ node }) {
2357
+ const latex = node.attrs.latex || "";
2358
+ let html3 = "";
2359
+ try {
2360
+ html3 = katex.renderToString(latex, {
2361
+ throwOnError: false,
2362
+ output: "html"
2363
+ });
2364
+ } catch (error) {
2365
+ console.warn("KaTeX rendering error for inline math:", error);
2366
+ }
2367
+ return /* @__PURE__ */ jsx68(
2368
+ "span",
2369
+ {
2370
+ className: "react-renderer node-inlineMath",
2371
+ dangerouslySetInnerHTML: { __html: html3 || latex }
2372
+ }
2373
+ );
2374
+ },
2375
+ // Block math (KaTeX) - from @tiptap/extension-mathematics
2376
+ blockMath({ node }) {
2377
+ const latex = node.attrs.latex || "";
2378
+ let html3 = "";
2379
+ try {
2380
+ html3 = katex.renderToString(latex, {
2381
+ throwOnError: false,
2382
+ output: "html",
2383
+ displayMode: true
2384
+ });
2385
+ } catch (error) {
2386
+ console.warn("KaTeX rendering error for block math:", error);
2387
+ }
2388
+ return /* @__PURE__ */ jsx68("div", { className: "react-renderer node-blockMath", children: /* @__PURE__ */ jsx68(
2389
+ "div",
2390
+ {
2391
+ className: "tiptap-mathematics-render",
2392
+ "data-type": "math",
2393
+ "data-mode": "block",
2394
+ dangerouslySetInnerHTML: { __html: html3 || latex }
2395
+ }
2396
+ ) });
2397
+ },
2398
+ inlineLatex({ node }) {
2399
+ const latex = node.attrs.latex || "";
2400
+ let html3 = "";
2401
+ try {
2402
+ html3 = katex.renderToString(latex, {
2403
+ throwOnError: false,
2404
+ output: "html"
2405
+ });
2406
+ } catch (error) {
2407
+ console.warn("KaTeX rendering error for inline latex:", error);
2408
+ }
2409
+ return /* @__PURE__ */ jsx68(
2410
+ "span",
2411
+ {
2412
+ className: "react-renderer node-inlineLatex inline-latex",
2413
+ dangerouslySetInnerHTML: { __html: html3 || latex }
2414
+ }
2415
+ );
2416
+ },
2417
+ /*
2418
+ COMPATABILITY
2419
+ */
2420
+ calloutAlert({ node, children }) {
2421
+ const type = node.attrs.type || "info";
2422
+ return /* @__PURE__ */ jsx68(Callout, { type, children });
2423
+ },
2424
+ calloutTip({ node, children }) {
2425
+ const type = node.attrs.type || "info";
2426
+ return /* @__PURE__ */ jsx68(Callout, { type, children });
2427
+ },
2428
+ customQuoteV2({ children }) {
2429
+ return /* @__PURE__ */ jsx68(CustomQuote, { children });
2430
+ },
2431
+ promptV2Header({ children }) {
2432
+ return /* @__PURE__ */ jsx68(PromptHeader, { children });
2433
+ },
2434
+ promptV2Content({ children }) {
2435
+ return /* @__PURE__ */ jsx68(PromptContent, { children });
2436
+ }
2437
+ });
2438
+ var nodeMapping = getNodeMapping();
2439
+ var markMapping = {
2440
+ "copyable-text"({ children }) {
2441
+ return /* @__PURE__ */ jsx68(CopyableText2, { children });
2442
+ }
2443
+ };
2444
+
2445
+ // src/render/tiptap-render.tsx
2446
+ import "highlight.js/styles/github-dark.css";
2447
+ import "katex/dist/katex.min.css";
2448
+ import { jsx as jsx69 } from "react/jsx-runtime";
2449
+ function renderTiptapToReact(content, getImageById) {
2450
+ let parsedContent;
2451
+ try {
2452
+ if (typeof content === "string") {
2453
+ parsedContent = JSON.parse(content);
2454
+ } else {
2455
+ parsedContent = content;
2456
+ }
2457
+ } catch (error) {
2458
+ console.warn("Failed to parse Tiptap content:", error);
2459
+ parsedContent = { type: "doc", content: [{ type: "paragraph" }] };
2460
+ }
2461
+ const rendered = renderToReactElement({
2462
+ extensions: getRenderExtensions(),
2463
+ content: parsedContent,
2464
+ options: {
2465
+ nodeMapping: getNodeMapping(getImageById),
2466
+ markMapping
2467
+ }
2468
+ });
2469
+ return /* @__PURE__ */ jsx69(
2470
+ "div",
2471
+ {
2472
+ className: "tiptap",
2473
+ "data-tiptap-render": true,
2474
+ children: rendered
2475
+ }
2476
+ );
2477
+ }
2478
+ function TiptapRender({ content, getImageById }) {
2479
+ return renderTiptapToReact(content, getImageById);
2480
+ }
2481
+ export {
2482
+ TiptapRender
2483
+ };
2484
+ //# sourceMappingURL=render.mjs.map