@vizel/core 0.0.1-alpha.1 → 0.0.1-alpha.3

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 (71) hide show
  1. package/LICENSE +21 -0
  2. package/dist/index.d.ts +13 -13
  3. package/dist/index.js +141 -141
  4. package/dist/index10.js +70 -110
  5. package/dist/index11.js +135 -168
  6. package/dist/index12.js +83 -74
  7. package/dist/index13.js +13 -134
  8. package/dist/index14.js +13 -146
  9. package/dist/index15.js +303 -15
  10. package/dist/index16.js +69 -14
  11. package/dist/index17.js +26 -295
  12. package/dist/index18.js +2 -2
  13. package/dist/index19.js +355 -24
  14. package/dist/index20.js +25 -264
  15. package/dist/index21.js +85 -68
  16. package/dist/index22.js +97 -353
  17. package/dist/index23.js +66 -84
  18. package/dist/index24.js +12 -36
  19. package/dist/index25.js +53 -92
  20. package/dist/index26.js +132 -96
  21. package/dist/index27.js +59 -126
  22. package/dist/index28.js +37 -53
  23. package/dist/index29.js +19 -62
  24. package/dist/index3.js +165 -60
  25. package/dist/index30.js +9 -37
  26. package/dist/index31.js +143 -19
  27. package/dist/index32.js +264 -11
  28. package/dist/index33.js +92 -9
  29. package/dist/index34.js +63 -16
  30. package/dist/index35.js +4 -58
  31. package/dist/index36.js +123 -15
  32. package/dist/index37.js +305 -42
  33. package/dist/index38.js +487 -4
  34. package/dist/index39.js +37 -112
  35. package/dist/index4.js +10 -86
  36. package/dist/index40.js +653 -301
  37. package/dist/index41.js +4 -487
  38. package/dist/index42.js +4 -48
  39. package/dist/index43.js +206 -642
  40. package/dist/index44.js +82 -4
  41. package/dist/index45.js +17 -4
  42. package/dist/index46.js +57 -237
  43. package/dist/index47.js +15 -82
  44. package/dist/index48.js +190 -274
  45. package/dist/index49.js +281 -1497
  46. package/dist/index5.js +132 -10
  47. package/dist/index50.js +1502 -5
  48. package/dist/index51.js +5 -1561
  49. package/dist/index52.js +1551 -192
  50. package/dist/index53.js +1 -1
  51. package/dist/index54.js +84 -21
  52. package/dist/index55.js +246 -10
  53. package/dist/index56.js +3 -7
  54. package/dist/index57.js +1231 -7
  55. package/dist/index58.js +731 -11
  56. package/dist/index59.js +21 -19
  57. package/dist/index6.js +48 -131
  58. package/dist/index60.js +10 -25
  59. package/dist/index61.js +6 -83
  60. package/dist/index62.js +7 -245
  61. package/dist/index63.js +11 -1229
  62. package/dist/index64.js +17 -732
  63. package/dist/index65.js +25 -3
  64. package/dist/index66.js +53 -1059
  65. package/dist/index67.js +1059 -53
  66. package/dist/index69.js +90 -3
  67. package/dist/index7.js +228 -409
  68. package/dist/index70.js +3 -90
  69. package/dist/index8.js +111 -45
  70. package/dist/index9.js +409 -228
  71. package/package.json +54 -80
package/dist/index40.js CHANGED
@@ -1,329 +1,681 @@
1
- import { Node as L, createBlockMarkdownSpec as N, isActive as F, findChildren as b, defaultBlockAt as x, findParentNode as w, mergeAttributes as v } from "@tiptap/core";
2
- import { Plugin as z, PluginKey as G, TextSelection as R, Selection as D } from "./index41.js";
3
- import { GapCursor as H } from "./index52.js";
4
- var S = (t, s) => s.view.domAtPos(t).node.offsetParent !== null, W = (t, s, o) => {
5
- for (let e = t.depth; e > 0; e -= 1) {
6
- const n = t.node(e), c = s(n), r = S(t.start(e), o);
7
- if (c && r)
8
- return {
9
- pos: e > 0 ? t.before(e) : 0,
10
- start: t.start(e),
11
- depth: e,
12
- node: n
13
- };
1
+ import { Extension as H, commands as y, flattenExtensions as z, getExtensionField as C, generateJSON as L } from "@tiptap/core";
2
+ import { marked as P } from "./index52.js";
3
+ function _(e, n) {
4
+ const s = n.split(`
5
+ `).flatMap((r) => [r, ""]).map((r) => `${e}${r}`).join(`
6
+ `);
7
+ return s.slice(0, s.length - 1);
8
+ }
9
+ function O(e, n) {
10
+ const t = [];
11
+ return Array.from(e.keys()).forEach((s) => {
12
+ (!n || !n.marks || !n.marks.map((r) => r.type).includes(s)) && t.push(s);
13
+ }), t;
14
+ }
15
+ function F(e, n) {
16
+ const t = [];
17
+ return Array.from(n.entries()).forEach(([s, r]) => {
18
+ e.has(s) || t.push({ type: s, mark: r });
19
+ }), t;
20
+ }
21
+ function N(e, n, t, s) {
22
+ const r = !t, i = t && t.type === "text" && (!t.marks || t.marks.length === 0), o = t && t.type === "text" && t.marks && !s(n, new Map(t.marks.map((d) => [d.type, d]))), l = [];
23
+ if (r || i || o)
24
+ if (t && t.type === "text" && t.marks) {
25
+ const d = new Map(t.marks.map((a) => [a.type, a]));
26
+ Array.from(e.keys()).forEach((a) => {
27
+ d.has(a) || l.push(a);
28
+ });
29
+ } else (r || i) && l.push(...Array.from(e.keys()));
30
+ return l;
31
+ }
32
+ function $(e, n) {
33
+ let t = "";
34
+ return Array.from(e.keys()).reverse().forEach((s) => {
35
+ const r = e.get(s), i = n(s, r);
36
+ i && (t = i + t);
37
+ }), e.clear(), t;
38
+ }
39
+ function S(e, n, t) {
40
+ let s = "";
41
+ return Array.from(e.entries()).forEach(([r, i]) => {
42
+ const o = t(r, i);
43
+ o && (s += o), n.set(r, i);
44
+ }), s;
45
+ }
46
+ function R(e) {
47
+ const t = (e.raw || e.text || "").match(/^(\s*)[-+*]\s+\[([ xX])\]\s+/);
48
+ return t ? { isTask: !0, checked: t[2].toLowerCase() === "x", indentLevel: t[1].length } : { isTask: !1, indentLevel: 0 };
49
+ }
50
+ function E(e, n) {
51
+ return typeof e != "string" ? "json" : n;
52
+ }
53
+ var j = class {
54
+ /**
55
+ * Create a MarkdownManager.
56
+ * @param options.marked Optional marked instance to use (injected).
57
+ * @param options.markedOptions Optional options to pass to marked.setOptions
58
+ * @param options.indentation Indentation settings (style and size).
59
+ * @param options.extensions An array of Tiptap extensions to register for markdown parsing and rendering.
60
+ */
61
+ constructor(e) {
62
+ this.baseExtensions = [], this.extensions = [], this.lastParseResult = null;
63
+ var n, t, s, r, i;
64
+ this.markedInstance = (n = e?.marked) != null ? n : P, this.lexer = new this.markedInstance.Lexer(), this.indentStyle = (s = (t = e?.indentation) == null ? void 0 : t.style) != null ? s : "space", this.indentSize = (i = (r = e?.indentation) == null ? void 0 : r.size) != null ? i : 2, this.baseExtensions = e?.extensions || [], e?.markedOptions && typeof this.markedInstance.setOptions == "function" && this.markedInstance.setOptions(e.markedOptions), this.registry = /* @__PURE__ */ new Map(), this.nodeTypeRegistry = /* @__PURE__ */ new Map(), e?.extensions && (this.baseExtensions = e.extensions, z(e.extensions).forEach((l) => this.registerExtension(l, !1))), this.lexer = new this.markedInstance.Lexer();
14
65
  }
15
- }, O = (t, s) => {
16
- const { state: o, view: e, extensionManager: n } = t, { schema: c, selection: r } = o, { empty: d, $anchor: l } = r, i = !!n.extensions.find((u) => u.name === "gapCursor");
17
- if (!d || l.parent.type !== c.nodes.detailsSummary || !i || s === "right" && l.parentOffset !== l.parent.nodeSize - 2)
18
- return !1;
19
- const a = w((u) => u.type === c.nodes.details)(r);
20
- if (!a)
21
- return !1;
22
- const p = b(a.node, (u) => u.type === c.nodes.detailsContent);
23
- if (!p.length || S(a.start + p[0].pos + 1, t))
24
- return !1;
25
- const m = o.doc.resolve(a.pos + a.node.nodeSize), h = H.findFrom(m, 1, !1);
26
- if (!h)
27
- return !1;
28
- const { tr: y } = o, C = new H(h);
29
- return y.setSelection(C), y.scrollIntoView(), e.dispatch(y), !0;
30
- }, j = L.create({
31
- name: "details",
32
- content: "detailsSummary detailsContent",
33
- group: "block",
34
- defining: !0,
35
- isolating: !0,
36
- // @ts-ignore reason: `allowGapCursor` is not a valid property by default, but the `GapCursor` extension adds it to the Nodeconfig type
37
- allowGapCursor: !1,
38
- addOptions() {
66
+ /** Returns the underlying marked instance. */
67
+ get instance() {
68
+ return this.markedInstance;
69
+ }
70
+ /** Returns the correct indentCharacter (space or tab) */
71
+ get indentCharacter() {
72
+ return this.indentStyle === "space" ? " " : " ";
73
+ }
74
+ /** Returns the correct indentString repeated X times */
75
+ get indentString() {
76
+ return this.indentCharacter.repeat(this.indentSize);
77
+ }
78
+ /** Helper to quickly check whether a marked instance is available. */
79
+ hasMarked() {
80
+ return !!this.markedInstance;
81
+ }
82
+ /**
83
+ * Register a Tiptap extension (Node/Mark/Extension). This will read
84
+ * `markdownName`, `parseMarkdown`, `renderMarkdown` and `priority` from the
85
+ * extension config (using the same resolution used across the codebase).
86
+ */
87
+ registerExtension(e, n = !0) {
88
+ var t, s;
89
+ this.extensions.push(e);
90
+ const r = e.name, i = C(e, "markdownTokenName") || r, o = C(e, "parseMarkdown"), l = C(e, "renderMarkdown"), d = C(e, "markdownTokenizer"), a = (t = C(e, "markdownOptions")) != null ? t : null, c = (s = a?.indentsContent) != null ? s : !1, p = {
91
+ tokenName: i,
92
+ nodeName: r,
93
+ parseMarkdown: o,
94
+ renderMarkdown: l,
95
+ isIndenting: c,
96
+ tokenizer: d
97
+ };
98
+ if (i && o) {
99
+ const u = this.registry.get(i) || [];
100
+ u.push(p), this.registry.set(i, u);
101
+ }
102
+ if (l) {
103
+ const u = this.nodeTypeRegistry.get(r) || [];
104
+ u.push(p), this.nodeTypeRegistry.set(r, u);
105
+ }
106
+ d && this.hasMarked() && (this.registerTokenizer(d), n && (this.lexer = new this.markedInstance.Lexer()));
107
+ }
108
+ /**
109
+ * Register a custom tokenizer with marked.js for parsing non-standard markdown syntax.
110
+ */
111
+ registerTokenizer(e) {
112
+ if (!this.hasMarked())
113
+ return;
114
+ const { name: n, start: t, level: s = "inline", tokenize: r } = e, l = {
115
+ inlineTokens: (c) => this.lexer.inlineTokens(c),
116
+ blockTokens: (c) => this.lexer.blockTokens(c)
117
+ };
118
+ let d;
119
+ t ? d = typeof t == "function" ? t : (c) => c.indexOf(t) : d = (c) => {
120
+ const p = r(c, [], l);
121
+ return p && p.raw ? c.indexOf(p.raw) : -1;
122
+ };
123
+ const a = {
124
+ name: n,
125
+ level: s,
126
+ start: d,
127
+ tokenizer: (c, p) => {
128
+ const u = r(c, p, l);
129
+ if (u && u.type)
130
+ return {
131
+ ...u,
132
+ type: u.type || n,
133
+ raw: u.raw || "",
134
+ tokens: u.tokens || []
135
+ };
136
+ },
137
+ childTokens: []
138
+ };
139
+ this.markedInstance.use({
140
+ extensions: [a]
141
+ });
142
+ }
143
+ /** Get registered handlers for a token type and try each until one succeeds. */
144
+ getHandlersForToken(e) {
145
+ try {
146
+ return this.registry.get(e) || [];
147
+ } catch {
148
+ return [];
149
+ }
150
+ }
151
+ /** Get the first handler for a token type (for backwards compatibility). */
152
+ getHandlerForToken(e) {
153
+ const n = this.getHandlersForToken(e);
154
+ if (n.length > 0)
155
+ return n[0];
156
+ const t = this.getHandlersForNodeType(e);
157
+ return t.length > 0 ? t[0] : void 0;
158
+ }
159
+ /** Get registered handlers for a node type (for rendering). */
160
+ getHandlersForNodeType(e) {
161
+ try {
162
+ return this.nodeTypeRegistry.get(e) || [];
163
+ } catch {
164
+ return [];
165
+ }
166
+ }
167
+ /**
168
+ * Serialize a ProseMirror-like JSON document (or node array) to a Markdown string
169
+ * using registered renderers and fallback renderers.
170
+ */
171
+ serialize(e) {
172
+ return e ? Array.isArray(e) ? this.renderNodes(e, e) : this.renderNodes(e, e) : "";
173
+ }
174
+ /**
175
+ * Parse markdown string into Tiptap JSON document using registered extension handlers.
176
+ */
177
+ parse(e) {
178
+ if (!this.hasMarked())
179
+ throw new Error("No marked instance available for parsing");
180
+ const n = this.markedInstance.lexer(e);
39
181
  return {
40
- persist: !1,
41
- openClassName: "is-open",
42
- HTMLAttributes: {}
182
+ type: "doc",
183
+ content: this.parseTokens(n)
43
184
  };
44
- },
45
- addAttributes() {
46
- return this.options.persist ? {
47
- open: {
48
- default: !1,
49
- parseHTML: (t) => t.hasAttribute("open"),
50
- renderHTML: ({ open: t }) => t ? { open: "" } : {}
51
- }
52
- } : [];
53
- },
54
- parseHTML() {
55
- return [
56
- {
57
- tag: "details"
185
+ }
186
+ /**
187
+ * Convert an array of marked tokens into Tiptap JSON nodes using registered extension handlers.
188
+ */
189
+ parseTokens(e) {
190
+ return e.map((n) => this.parseToken(n)).filter((n) => n !== null).flatMap((n) => Array.isArray(n) ? n : [n]);
191
+ }
192
+ /**
193
+ * Parse a single token into Tiptap JSON using the appropriate registered handler.
194
+ */
195
+ parseToken(e) {
196
+ if (!e.type)
197
+ return null;
198
+ if (e.type === "list")
199
+ return this.parseListToken(e);
200
+ const n = this.getHandlersForToken(e.type), t = this.createParseHelpers();
201
+ if (n.find((r) => {
202
+ if (!r.parseMarkdown)
203
+ return !1;
204
+ const i = r.parseMarkdown(e, t), o = this.normalizeParseResult(i);
205
+ return o && (!Array.isArray(o) || o.length > 0) ? (this.lastParseResult = o, !0) : !1;
206
+ }) && this.lastParseResult) {
207
+ const r = this.lastParseResult;
208
+ return this.lastParseResult = null, r;
209
+ }
210
+ return this.parseFallbackToken(e);
211
+ }
212
+ /**
213
+ * Parse a list token, handling mixed bullet and task list items by splitting them into separate lists.
214
+ * This ensures that consecutive task items and bullet items are grouped and parsed as separate list nodes.
215
+ *
216
+ * @param token The list token to parse
217
+ * @returns Array of parsed list nodes, or null if parsing fails
218
+ */
219
+ parseListToken(e) {
220
+ if (!e.items || e.items.length === 0)
221
+ return this.parseTokenWithHandlers(e);
222
+ const n = e.items.some((l) => R(l).isTask), t = e.items.some((l) => !R(l).isTask);
223
+ if (!n || !t || this.getHandlersForToken("taskList").length === 0)
224
+ return this.parseTokenWithHandlers(e);
225
+ const s = [];
226
+ let r = [], i = null;
227
+ for (let l = 0; l < e.items.length; l += 1) {
228
+ const d = e.items[l], { isTask: a, checked: c, indentLevel: p } = R(d);
229
+ let u = d;
230
+ if (a) {
231
+ const m = (d.raw || d.text || "").split(`
232
+ `), g = m[0].match(/^\s*[-+*]\s+\[([ xX])\]\s+(.*)$/), h = g ? g[2] : "";
233
+ let k = [];
234
+ if (m.length > 1 && m.slice(1).join(`
235
+ `).trim()) {
236
+ const T = m.slice(1), v = T.filter((A) => A.trim());
237
+ if (v.length > 0) {
238
+ const A = Math.min(...v.map((x) => x.length - x.trimStart().length)), I = T.map((x) => x.trim() ? x.slice(A) : "").join(`
239
+ `).trim();
240
+ I && (k = this.markedInstance.lexer(`${I}
241
+ `));
242
+ }
243
+ }
244
+ u = {
245
+ type: "taskItem",
246
+ raw: "",
247
+ mainContent: h,
248
+ indentLevel: p,
249
+ checked: c ?? !1,
250
+ text: h,
251
+ tokens: this.lexer.inlineTokens(h),
252
+ nestedTokens: k
253
+ };
58
254
  }
59
- ];
60
- },
61
- renderHTML({ HTMLAttributes: t }) {
62
- return ["details", v(this.options.HTMLAttributes, t), 0];
63
- },
64
- ...N({
65
- nodeName: "details",
66
- content: "block"
67
- }),
68
- addNodeView() {
69
- return ({ editor: t, getPos: s, node: o, HTMLAttributes: e }) => {
70
- const n = document.createElement("div"), c = v(this.options.HTMLAttributes, e, {
71
- "data-type": this.name
72
- });
73
- Object.entries(c).forEach(([i, a]) => n.setAttribute(i, a));
74
- const r = document.createElement("button");
75
- r.type = "button", n.append(r);
76
- const d = document.createElement("div");
77
- n.append(d);
78
- const l = (i) => {
79
- if (i !== void 0)
80
- if (i) {
81
- if (n.classList.contains(this.options.openClassName))
82
- return;
83
- n.classList.add(this.options.openClassName);
84
- } else {
85
- if (!n.classList.contains(this.options.openClassName))
86
- return;
87
- n.classList.remove(this.options.openClassName);
255
+ const w = a ? "taskList" : "list";
256
+ i !== w ? (r.length > 0 && s.push({ type: i, items: r }), r = [u], i = w) : r.push(u);
257
+ }
258
+ r.length > 0 && s.push({ type: i, items: r });
259
+ const o = [];
260
+ for (let l = 0; l < s.length; l += 1) {
261
+ const d = s[l], a = { ...e, type: d.type, items: d.items }, c = this.parseToken(a);
262
+ c && (Array.isArray(c) ? o.push(...c) : o.push(c));
263
+ }
264
+ return o.length > 0 ? o : null;
265
+ }
266
+ /**
267
+ * Parse a token using registered handlers (extracted for reuse).
268
+ */
269
+ parseTokenWithHandlers(e) {
270
+ if (!e.type)
271
+ return null;
272
+ const n = this.getHandlersForToken(e.type), t = this.createParseHelpers();
273
+ if (n.find((r) => {
274
+ if (!r.parseMarkdown)
275
+ return !1;
276
+ const i = r.parseMarkdown(e, t), o = this.normalizeParseResult(i);
277
+ return o && (!Array.isArray(o) || o.length > 0) ? (this.lastParseResult = o, !0) : !1;
278
+ }) && this.lastParseResult) {
279
+ const r = this.lastParseResult;
280
+ return this.lastParseResult = null, r;
281
+ }
282
+ return this.parseFallbackToken(e);
283
+ }
284
+ /**
285
+ * Creates helper functions for parsing markdown tokens.
286
+ * @returns An object containing helper functions for parsing.
287
+ */
288
+ createParseHelpers() {
289
+ return {
290
+ parseInline: (e) => this.parseInlineTokens(e),
291
+ parseChildren: (e) => this.parseTokens(e),
292
+ createTextNode: (e, n) => ({
293
+ type: "text",
294
+ text: e,
295
+ marks: n || void 0
296
+ }),
297
+ createNode: (e, n, t) => {
298
+ const s = {
299
+ type: e,
300
+ attrs: n || void 0,
301
+ content: t || void 0
302
+ };
303
+ return (!n || Object.keys(n).length === 0) && delete s.attrs, s;
304
+ },
305
+ applyMark: (e, n, t) => ({
306
+ mark: e,
307
+ content: n,
308
+ attrs: t && Object.keys(t).length > 0 ? t : void 0
309
+ })
310
+ };
311
+ }
312
+ /**
313
+ * Escape special regex characters in a string.
314
+ */
315
+ escapeRegex(e) {
316
+ return e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
317
+ }
318
+ /**
319
+ * Parse inline tokens (bold, italic, links, etc.) into text nodes with marks.
320
+ * This is the complex part that handles mark nesting and boundaries.
321
+ */
322
+ parseInlineTokens(e) {
323
+ var n, t, s, r;
324
+ const i = [];
325
+ for (let o = 0; o < e.length; o += 1) {
326
+ const l = e[o];
327
+ if (l.type === "text")
328
+ i.push({
329
+ type: "text",
330
+ text: l.text || ""
331
+ });
332
+ else if (l.type === "html") {
333
+ const d = ((t = (n = l.raw) != null ? n : l.text) != null ? t : "").toString(), a = /^<\/[\s]*[\w-]+/i.test(d), c = d.match(/^<[\s]*([\w-]+)(\s|>|\/|$)/i);
334
+ if (!a && c && !/\/>$/.test(d)) {
335
+ const u = c[1], w = this.escapeRegex(u), M = new RegExp(`^<\\/\\s*${w}\\b`, "i");
336
+ let m = -1;
337
+ const g = [d];
338
+ for (let h = o + 1; h < e.length; h += 1) {
339
+ const k = e[h], f = ((r = (s = k.raw) != null ? s : k.text) != null ? r : "").toString();
340
+ if (g.push(f), k.type === "html" && M.test(f)) {
341
+ m = h;
342
+ break;
343
+ }
344
+ }
345
+ if (m !== -1) {
346
+ const h = g.join(""), k = {
347
+ type: "html",
348
+ raw: h,
349
+ text: h,
350
+ block: !1
351
+ }, f = this.parseHTMLToken(k);
352
+ if (f) {
353
+ const T = this.normalizeParseResult(f);
354
+ Array.isArray(T) ? i.push(...T) : T && i.push(T);
355
+ }
356
+ o = m;
357
+ continue;
88
358
  }
89
- else
90
- n.classList.toggle(this.options.openClassName);
91
- const a = new Event("toggleDetailsContent"), p = d.querySelector(':scope > div[data-type="detailsContent"]');
92
- p?.dispatchEvent(a);
93
- };
94
- return o.attrs.open && setTimeout(() => l()), r.addEventListener("click", () => {
95
- if (l(), !this.options.persist) {
96
- t.commands.focus(void 0, { scrollIntoView: !1 });
97
- return;
98
359
  }
99
- if (t.isEditable && typeof s == "function") {
100
- const { from: i, to: a } = t.state.selection;
101
- t.chain().command(({ tr: p }) => {
102
- const f = s();
103
- if (!f)
104
- return !1;
105
- const m = p.doc.nodeAt(f);
106
- return m?.type !== this.type ? !1 : (p.setNodeMarkup(f, void 0, {
107
- open: !m.attrs.open
108
- }), !0);
109
- }).setTextSelection({
110
- from: i,
111
- to: a
112
- }).focus(void 0, { scrollIntoView: !1 }).run();
360
+ const p = this.parseHTMLToken(l);
361
+ if (p) {
362
+ const u = this.normalizeParseResult(p);
363
+ Array.isArray(u) ? i.push(...u) : u && i.push(u);
113
364
  }
114
- }), {
115
- dom: n,
116
- contentDOM: d,
117
- ignoreMutation(i) {
118
- return i.type === "selection" ? !1 : !n.contains(i.target) || n === i.target;
119
- },
120
- update: (i) => i.type !== this.type ? !1 : (i.attrs.open !== void 0 && l(i.attrs.open), !0)
121
- };
122
- };
123
- },
124
- addCommands() {
125
- return {
126
- setDetails: () => ({ state: t, chain: s }) => {
127
- var o;
128
- const { schema: e, selection: n } = t, { $from: c, $to: r } = n, d = c.blockRange(r);
129
- if (!d)
130
- return !1;
131
- const l = t.doc.slice(d.start, d.end);
132
- if (!e.nodes.detailsContent.contentMatch.matchFragment(l.content))
133
- return !1;
134
- const a = ((o = l.toJSON()) == null ? void 0 : o.content) || [];
135
- return s().insertContentAt(
136
- { from: d.start, to: d.end },
137
- {
138
- type: this.name,
139
- content: [
140
- {
141
- type: "detailsSummary"
142
- },
143
- {
144
- type: "detailsContent",
145
- content: a
146
- }
147
- ]
365
+ } else if (l.type) {
366
+ const d = this.getHandlerForToken(l.type);
367
+ if (d && d.parseMarkdown) {
368
+ const a = this.createParseHelpers(), c = d.parseMarkdown(l, a);
369
+ if (this.isMarkResult(c)) {
370
+ const p = this.applyMarkToContent(c.mark, c.content, c.attrs);
371
+ i.push(...p);
372
+ } else {
373
+ const p = this.normalizeParseResult(c);
374
+ Array.isArray(p) ? i.push(...p) : p && i.push(p);
148
375
  }
149
- ).setTextSelection(d.start + 2).run();
150
- },
151
- unsetDetails: () => ({ state: t, chain: s }) => {
152
- const { selection: o, schema: e } = t, n = w((u) => u.type === this.type)(o);
153
- if (!n)
154
- return !1;
155
- const c = b(n.node, (u) => u.type === e.nodes.detailsSummary), r = b(n.node, (u) => u.type === e.nodes.detailsContent);
156
- if (!c.length || !r.length)
157
- return !1;
158
- const d = c[0], l = r[0], i = n.pos, a = t.doc.resolve(i), p = i + n.node.nodeSize, f = { from: i, to: p }, m = l.node.content.toJSON() || [], h = a.parent.type.contentMatch.defaultType, C = [h?.create(null, d.node.content).toJSON(), ...m];
159
- return s().insertContentAt(f, C).setTextSelection(i + 1).run();
376
+ } else l.tokens && i.push(...this.parseInlineTokens(l.tokens));
160
377
  }
161
- };
162
- },
163
- addKeyboardShortcuts() {
164
- return {
165
- Backspace: () => {
166
- const { schema: t, selection: s } = this.editor.state, { empty: o, $anchor: e } = s;
167
- return !o || e.parent.type !== t.nodes.detailsSummary ? !1 : e.parentOffset !== 0 ? this.editor.commands.command(({ tr: n }) => {
168
- const c = e.pos - 1, r = e.pos;
169
- return n.delete(c, r), !0;
170
- }) : this.editor.commands.unsetDetails();
171
- },
172
- // Creates a new node below it if it is closed.
173
- // Otherwise inside `DetailsContent`.
174
- Enter: ({ editor: t }) => {
175
- const { state: s, view: o } = t, { schema: e, selection: n } = s, { $head: c } = n;
176
- if (c.parent.type !== e.nodes.detailsSummary)
177
- return !1;
178
- const r = S(c.after() + 1, t), d = r ? s.doc.nodeAt(c.after()) : c.node(-2);
179
- if (!d)
180
- return !1;
181
- const l = r ? 0 : c.indexAfter(-1), i = x(d.contentMatchAt(l));
182
- if (!i || !d.canReplaceWith(l, l, i))
183
- return !1;
184
- const a = i.createAndFill();
185
- if (!a)
186
- return !1;
187
- const p = r ? c.after() + 1 : c.after(-1), f = s.tr.replaceWith(p, p, a), m = f.doc.resolve(p), h = D.near(m, 1);
188
- return f.setSelection(h), f.scrollIntoView(), o.dispatch(f), !0;
378
+ }
379
+ return i;
380
+ }
381
+ /**
382
+ * Apply a mark to content nodes.
383
+ */
384
+ applyMarkToContent(e, n, t) {
385
+ return n.map((s) => {
386
+ if (s.type === "text") {
387
+ const r = s.marks || [], i = t ? { type: e, attrs: t } : { type: e };
388
+ return {
389
+ ...s,
390
+ marks: [...r, i]
391
+ };
392
+ }
393
+ return {
394
+ ...s,
395
+ content: s.content ? this.applyMarkToContent(e, s.content, t) : void 0
396
+ };
397
+ });
398
+ }
399
+ /**
400
+ * Check if a parse result represents a mark to be applied.
401
+ */
402
+ isMarkResult(e) {
403
+ return e && typeof e == "object" && "mark" in e;
404
+ }
405
+ /**
406
+ * Normalize parse results to ensure they're valid JSONContent.
407
+ */
408
+ normalizeParseResult(e) {
409
+ return e ? this.isMarkResult(e) ? e.content : e : null;
410
+ }
411
+ /**
412
+ * Fallback parsing for common tokens when no specific handler is registered.
413
+ */
414
+ parseFallbackToken(e) {
415
+ switch (e.type) {
416
+ case "paragraph":
417
+ return {
418
+ type: "paragraph",
419
+ content: e.tokens ? this.parseInlineTokens(e.tokens) : []
420
+ };
421
+ case "heading":
422
+ return {
423
+ type: "heading",
424
+ attrs: { level: e.depth || 1 },
425
+ content: e.tokens ? this.parseInlineTokens(e.tokens) : []
426
+ };
427
+ case "text":
428
+ return {
429
+ type: "text",
430
+ text: e.text || ""
431
+ };
432
+ case "html":
433
+ return this.parseHTMLToken(e);
434
+ case "space":
435
+ return null;
436
+ default:
437
+ return e.tokens ? this.parseTokens(e.tokens) : null;
438
+ }
439
+ }
440
+ /**
441
+ * Parse HTML tokens using extensions' parseHTML methods.
442
+ * This allows HTML within markdown to be parsed according to extension rules.
443
+ */
444
+ parseHTMLToken(e) {
445
+ const n = e.text || e.raw || "";
446
+ if (!n.trim())
447
+ return null;
448
+ try {
449
+ const t = L(n, this.baseExtensions);
450
+ return t.type === "doc" && t.content ? e.block ? t.content : t.content.length === 1 && t.content[0].type === "paragraph" && t.content[0].content ? t.content[0].content : t.content : t;
451
+ } catch (t) {
452
+ throw new Error(`Failed to parse HTML in markdown: ${t}`);
453
+ }
454
+ }
455
+ renderNodeToMarkdown(e, n, t = 0, s = 0) {
456
+ var r;
457
+ if (e.type === "text")
458
+ return e.text || "";
459
+ if (!e.type)
460
+ return "";
461
+ const i = this.getHandlerForToken(e.type);
462
+ if (!i)
463
+ return "";
464
+ const o = {
465
+ renderChildren: (a, c) => {
466
+ const p = i.isIndenting ? s + 1 : s;
467
+ return !Array.isArray(a) && a.content ? this.renderNodes(a.content, e, c || "", t, p) : this.renderNodes(a, e, c || "", t, p);
189
468
  },
190
- // The default gapcursor implementation can’t handle hidden content, so we need to fix this.
191
- ArrowRight: ({ editor: t }) => O(t, "right"),
192
- // The default gapcursor implementation can’t handle hidden content, so we need to fix this.
193
- ArrowDown: ({ editor: t }) => O(t, "down")
469
+ indent: (a) => this.indentString + a,
470
+ wrapInBlock: _
471
+ }, l = {
472
+ index: t,
473
+ level: s,
474
+ parentType: n?.type,
475
+ meta: {}
194
476
  };
195
- },
196
- addProseMirrorPlugins() {
197
- return [
198
- // This plugin prevents text selections within the hidden content in `DetailsContent`.
199
- // The cursor is moved to the next visible position.
200
- new z({
201
- key: new G("detailsSelection"),
202
- appendTransaction: (t, s, o) => {
203
- const { editor: e, type: n } = this;
204
- if (e.view.composing || !t.some((u) => u.selectionSet) || !s.selection.empty || !o.selection.empty || !F(o, n.name))
205
- return;
206
- const { $from: l } = o.selection;
207
- if (S(l.pos, e))
208
- return;
209
- const a = W(l, (u) => u.type === n, e);
210
- if (!a)
211
- return;
212
- const p = b(
213
- a.node,
214
- (u) => u.type === o.schema.nodes.detailsSummary
477
+ return ((r = i.renderMarkdown) == null ? void 0 : r.call(i, e, o, l)) || "";
478
+ }
479
+ /**
480
+ * Render a node or an array of nodes. Parent type controls how children
481
+ * are joined (which determines newline insertion between children).
482
+ */
483
+ renderNodes(e, n, t = "", s = 0, r = 0) {
484
+ return Array.isArray(e) ? this.renderNodesWithMarkBoundaries(e, n, t, r) : e.type ? this.renderNodeToMarkdown(e, n, s, r) : "";
485
+ }
486
+ /**
487
+ * Render an array of nodes while properly tracking mark boundaries.
488
+ * This handles cases where marks span across multiple text nodes.
489
+ */
490
+ renderNodesWithMarkBoundaries(e, n, t = "", s = 0) {
491
+ const r = [], i = /* @__PURE__ */ new Map();
492
+ return e.forEach((o, l) => {
493
+ const d = l < e.length - 1 ? e[l + 1] : null;
494
+ if (o.type)
495
+ if (o.type === "text") {
496
+ let a = o.text || "";
497
+ const c = new Map((o.marks || []).map((h) => [h.type, h])), p = F(i, c), u = O(c, d);
498
+ let w = "";
499
+ if (u.length > 0) {
500
+ const h = a.match(/(\s+)$/);
501
+ h && (w = h[1], a = a.slice(0, -w.length));
502
+ }
503
+ u.forEach((h) => {
504
+ const k = c.get(h), f = this.getMarkClosing(h, k);
505
+ f && (a += f), i.has(h) && i.delete(h);
506
+ });
507
+ let M = "";
508
+ if (p.length > 0) {
509
+ const h = a.match(/^(\s+)/);
510
+ h && (M = h[1], a = a.slice(M.length));
511
+ }
512
+ p.forEach(({ type: h, mark: k }) => {
513
+ const f = this.getMarkOpening(h, k);
514
+ f && (a = f + a), u.includes(h) || i.set(h, k);
515
+ }), a = M + a;
516
+ const m = N(
517
+ i,
518
+ c,
519
+ d,
520
+ this.markSetsEqual.bind(this)
215
521
  );
216
- if (!p.length)
217
- return;
218
- const f = p[0], h = (s.selection.from < o.selection.from ? "forward" : "backward") === "forward" ? a.start + f.pos : a.pos + f.pos + f.node.nodeSize, y = R.create(o.doc, h);
219
- return o.tr.setSelection(y);
522
+ let g = "";
523
+ if (m.length > 0) {
524
+ const h = a.match(/(\s+)$/);
525
+ h && (g = h[1], a = a.slice(0, -g.length));
526
+ }
527
+ m.forEach((h) => {
528
+ const k = i.get(h), f = this.getMarkClosing(h, k);
529
+ f && (a += f), i.delete(h);
530
+ }), a += g, a += w, r.push(a);
531
+ } else {
532
+ const a = new Map(i), c = $(i, this.getMarkClosing.bind(this)), p = this.renderNodeToMarkdown(o, n, l, s), u = o.type === "hardBreak" ? "" : S(a, i, this.getMarkOpening.bind(this));
533
+ r.push(c + p + u);
220
534
  }
221
- })
222
- ];
535
+ }), r.join(t);
223
536
  }
224
- }), q = L.create({
225
- name: "detailsContent",
226
- content: "block+",
227
- defining: !0,
228
- selectable: !1,
229
- addOptions() {
230
- return {
231
- HTMLAttributes: {}
537
+ /**
538
+ * Get the opening markdown syntax for a mark type.
539
+ */
540
+ getMarkOpening(e, n) {
541
+ const t = this.getHandlersForNodeType(e), s = t.length > 0 ? t[0] : void 0;
542
+ if (!s || !s.renderMarkdown)
543
+ return "";
544
+ const r = "__TIPTAP_MARKDOWN_PLACEHOLDER__", i = {
545
+ type: e,
546
+ attrs: n.attrs || {},
547
+ content: [{ type: "text", text: r }]
232
548
  };
233
- },
234
- parseHTML() {
235
- return [
236
- {
237
- tag: `div[data-type="${this.name}"]`
238
- }
239
- ];
240
- },
241
- renderHTML({ HTMLAttributes: t }) {
242
- return ["div", v(this.options.HTMLAttributes, t, { "data-type": this.name }), 0];
243
- },
244
- addNodeView() {
245
- return ({ HTMLAttributes: t }) => {
246
- const s = document.createElement("div"), o = v(this.options.HTMLAttributes, t, {
247
- "data-type": this.name,
248
- hidden: "hidden"
249
- });
250
- return Object.entries(o).forEach(([e, n]) => s.setAttribute(e, n)), s.addEventListener("toggleDetailsContent", () => {
251
- s.toggleAttribute("hidden");
252
- }), {
253
- dom: s,
254
- contentDOM: s,
255
- ignoreMutation(e) {
256
- return e.type === "selection" ? !1 : !s.contains(e.target) || s === e.target;
549
+ try {
550
+ const o = s.renderMarkdown(
551
+ i,
552
+ {
553
+ renderChildren: () => r,
554
+ indent: (d) => d,
555
+ wrapInBlock: (d, a) => d + a
257
556
  },
258
- update: (e) => e.type === this.type
259
- };
557
+ { index: 0, level: 0, parentType: "text", meta: {} }
558
+ ), l = o.indexOf(r);
559
+ return l >= 0 ? o.substring(0, l) : "";
560
+ } catch (o) {
561
+ throw new Error(`Failed to get mark opening for ${e}: ${o}`);
562
+ }
563
+ }
564
+ /**
565
+ * Get the closing markdown syntax for a mark type.
566
+ */
567
+ getMarkClosing(e, n) {
568
+ const t = this.getHandlersForNodeType(e), s = t.length > 0 ? t[0] : void 0;
569
+ if (!s || !s.renderMarkdown)
570
+ return "";
571
+ const r = "__TIPTAP_MARKDOWN_PLACEHOLDER__", i = {
572
+ type: e,
573
+ attrs: n.attrs || {},
574
+ content: [{ type: "text", text: r }]
575
+ };
576
+ try {
577
+ const o = s.renderMarkdown(
578
+ i,
579
+ {
580
+ renderChildren: () => r,
581
+ indent: (a) => a,
582
+ wrapInBlock: (a, c) => a + c
583
+ },
584
+ { index: 0, level: 0, parentType: "text", meta: {} }
585
+ ), l = o.indexOf(r), d = l + r.length;
586
+ return l >= 0 ? o.substring(d) : "";
587
+ } catch (o) {
588
+ throw new Error(`Failed to get mark closing for ${e}: ${o}`);
589
+ }
590
+ }
591
+ /**
592
+ * Check if two mark sets are equal.
593
+ */
594
+ markSetsEqual(e, n) {
595
+ return e.size !== n.size ? !1 : Array.from(e.keys()).every((t) => n.has(t));
596
+ }
597
+ }, b = j, q = H.create({
598
+ name: "markdown",
599
+ addOptions() {
600
+ return {
601
+ indentation: { style: "space", size: 2 },
602
+ marked: void 0,
603
+ markedOptions: {}
260
604
  };
261
605
  },
262
- addKeyboardShortcuts() {
606
+ addCommands() {
263
607
  return {
264
- // Escape node on double enter
265
- Enter: ({ editor: t }) => {
266
- const { state: s, view: o } = t, { selection: e } = s, { $from: n, empty: c } = e, r = w(($) => $.type === this.type)(e);
267
- if (!c || !r || !r.node.childCount)
268
- return !1;
269
- const d = n.index(r.depth), { childCount: l } = r.node;
270
- if (!(l === d + 1))
271
- return !1;
272
- const a = r.node.type.contentMatch.defaultType, p = a?.createAndFill();
273
- if (!p)
274
- return !1;
275
- const f = s.doc.resolve(r.pos + 1), m = l - 1, h = r.node.child(m), y = f.posAtIndex(m, r.depth);
276
- if (!h.eq(p))
277
- return !1;
278
- const u = n.node(-3);
279
- if (!u)
280
- return !1;
281
- const A = n.indexAfter(-3), M = x(u.contentMatchAt(A));
282
- if (!M || !u.canReplaceWith(A, A, M))
283
- return !1;
284
- const E = M.createAndFill();
285
- if (!E)
286
- return !1;
287
- const { tr: g } = s, T = n.after(-2);
288
- g.replaceWith(T, T, E);
289
- const k = g.doc.resolve(T), I = D.near(k, 1);
290
- g.setSelection(I);
291
- const V = y, P = y + h.nodeSize;
292
- return g.delete(V, P), g.scrollIntoView(), o.dispatch(g), !0;
608
+ setContent: (e, n) => {
609
+ if (!n?.contentType)
610
+ return y.setContent(e, n);
611
+ if (E(e, n?.contentType) !== "markdown" || !this.editor.markdown)
612
+ return y.setContent(e, n);
613
+ const s = this.editor.markdown.parse(e);
614
+ return y.setContent(s, n);
615
+ },
616
+ insertContent: (e, n) => {
617
+ if (!n?.contentType)
618
+ return y.insertContent(e, n);
619
+ if (E(e, n?.contentType) !== "markdown" || !this.editor.markdown)
620
+ return y.insertContent(e, n);
621
+ const s = this.editor.markdown.parse(e);
622
+ return y.insertContent(s, n);
623
+ },
624
+ insertContentAt: (e, n, t) => {
625
+ if (!t?.contentType)
626
+ return y.insertContentAt(e, n, t);
627
+ if (E(n, t?.contentType) !== "markdown" || !this.editor.markdown)
628
+ return y.insertContentAt(e, n, t);
629
+ const r = this.editor.markdown.parse(n);
630
+ return y.insertContentAt(e, r, t);
293
631
  }
294
632
  };
295
633
  },
296
- ...N({
297
- nodeName: "detailsContent"
298
- })
299
- }), _ = L.create({
300
- name: "detailsSummary",
301
- content: "text*",
302
- defining: !0,
303
- selectable: !1,
304
- isolating: !0,
305
- addOptions() {
634
+ addStorage() {
306
635
  return {
307
- HTMLAttributes: {}
636
+ manager: new b({
637
+ indentation: this.options.indentation,
638
+ marked: this.options.marked,
639
+ markedOptions: this.options.markedOptions,
640
+ extensions: []
641
+ })
308
642
  };
309
643
  },
310
- parseHTML() {
311
- return [
312
- {
313
- tag: "summary"
314
- }
315
- ];
316
- },
317
- renderHTML({ HTMLAttributes: t }) {
318
- return ["summary", v(this.options.HTMLAttributes, t), 0];
319
- },
320
- ...N({
321
- nodeName: "detailsSummary",
322
- content: "inline"
323
- })
644
+ onBeforeCreate() {
645
+ if (this.editor.markdown) {
646
+ console.error(
647
+ "[tiptap][markdown]: There is already a `markdown` property on the editor instance. This might lead to unexpected behavior."
648
+ );
649
+ return;
650
+ }
651
+ if (this.storage.manager = new b({
652
+ indentation: this.options.indentation,
653
+ marked: this.options.marked,
654
+ markedOptions: this.options.markedOptions,
655
+ extensions: this.editor.extensionManager.baseExtensions
656
+ }), this.editor.markdown = this.storage.manager, this.editor.getMarkdown = () => this.storage.manager.serialize(this.editor.getJSON()), !this.editor.options.contentType || E(this.editor.options.content, this.editor.options.contentType) !== "markdown")
657
+ return;
658
+ if (!this.editor.markdown)
659
+ throw new Error(
660
+ '[tiptap][markdown]: The `contentType` option is set to "markdown", but the Markdown extension is not added to the editor. Please add the Markdown extension to use this feature.'
661
+ );
662
+ if (this.editor.options.content === void 0 || typeof this.editor.options.content != "string")
663
+ throw new Error(
664
+ '[tiptap][markdown]: The `contentType` option is set to "markdown", but the initial content is not a string. Please provide the initial content as a markdown string.'
665
+ );
666
+ const n = this.editor.markdown.parse(this.editor.options.content);
667
+ this.editor.options.content = n;
668
+ }
324
669
  });
325
670
  export {
326
- j as Details,
327
- q as DetailsContent,
328
- _ as DetailsSummary
671
+ q as Markdown,
672
+ j as MarkdownManager,
673
+ E as assumeContentType,
674
+ $ as closeMarksBeforeNode,
675
+ O as findMarksToClose,
676
+ N as findMarksToCloseAtEnd,
677
+ F as findMarksToOpen,
678
+ R as isTaskItem,
679
+ S as reopenMarksAfterNode,
680
+ _ as wrapInMarkdownBlock
329
681
  };