tiptap-extension-code-block-shiki 1.1.0 → 1.2.0
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.
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Node as
|
|
2
|
-
import { Plugin as
|
|
3
|
-
import { DecorationSet as
|
|
4
|
-
import { bundledThemes as
|
|
5
|
-
var
|
|
1
|
+
import { Node as O, textblockTypeInputRule as M, mergeAttributes as R, findChildren as L } from "@tiptap/core";
|
|
2
|
+
import { Plugin as z, PluginKey as I, TextSelection as $, Selection as j } from "@tiptap/pm/state";
|
|
3
|
+
import { DecorationSet as F, Decoration as P } from "@tiptap/pm/view";
|
|
4
|
+
import { bundledThemes as E, bundledLanguages as W, createHighlighter as K } from "shiki";
|
|
5
|
+
var A = 4, U = /^```([a-z]+)?[\s\n]$/, V = /^~~~([a-z]+)?[\s\n]$/, J = O.create({
|
|
6
6
|
name: "codeBlock",
|
|
7
7
|
addOptions() {
|
|
8
8
|
return {
|
|
@@ -11,7 +11,7 @@ var B = 4, U = /^```([a-z]+)?[\s\n]$/, V = /^~~~([a-z]+)?[\s\n]$/, J = R.create(
|
|
|
11
11
|
exitOnArrowDown: !0,
|
|
12
12
|
defaultLanguage: null,
|
|
13
13
|
enableTabIndentation: !1,
|
|
14
|
-
tabSize:
|
|
14
|
+
tabSize: A,
|
|
15
15
|
HTMLAttributes: {}
|
|
16
16
|
};
|
|
17
17
|
},
|
|
@@ -25,12 +25,12 @@ var B = 4, U = /^```([a-z]+)?[\s\n]$/, V = /^~~~([a-z]+)?[\s\n]$/, J = R.create(
|
|
|
25
25
|
language: {
|
|
26
26
|
default: this.options.defaultLanguage,
|
|
27
27
|
parseHTML: (e) => {
|
|
28
|
-
var
|
|
29
|
-
const { languageClassPrefix:
|
|
30
|
-
if (!
|
|
28
|
+
var t;
|
|
29
|
+
const { languageClassPrefix: i } = this.options;
|
|
30
|
+
if (!i)
|
|
31
31
|
return null;
|
|
32
|
-
const
|
|
33
|
-
return
|
|
32
|
+
const c = [...((t = e.firstElementChild) == null ? void 0 : t.classList) || []].filter((r) => r.startsWith(i)).map((r) => r.replace(i, ""))[0];
|
|
33
|
+
return c || null;
|
|
34
34
|
},
|
|
35
35
|
rendered: !1
|
|
36
36
|
}
|
|
@@ -44,10 +44,10 @@ var B = 4, U = /^```([a-z]+)?[\s\n]$/, V = /^~~~([a-z]+)?[\s\n]$/, J = R.create(
|
|
|
44
44
|
}
|
|
45
45
|
];
|
|
46
46
|
},
|
|
47
|
-
renderHTML({ node: e, HTMLAttributes:
|
|
47
|
+
renderHTML({ node: e, HTMLAttributes: t }) {
|
|
48
48
|
return [
|
|
49
49
|
"pre",
|
|
50
|
-
|
|
50
|
+
R(this.options.HTMLAttributes, t),
|
|
51
51
|
[
|
|
52
52
|
"code",
|
|
53
53
|
{
|
|
@@ -57,10 +57,28 @@ var B = 4, U = /^```([a-z]+)?[\s\n]$/, V = /^~~~([a-z]+)?[\s\n]$/, J = R.create(
|
|
|
57
57
|
]
|
|
58
58
|
];
|
|
59
59
|
},
|
|
60
|
+
markdownTokenName: "code",
|
|
61
|
+
parseMarkdown: (e, t) => {
|
|
62
|
+
var i, o;
|
|
63
|
+
return ((i = e.raw) == null ? void 0 : i.startsWith("```")) === !1 && ((o = e.raw) == null ? void 0 : o.startsWith("~~~")) === !1 && e.codeBlockStyle !== "indented" ? [] : t.createNode(
|
|
64
|
+
"codeBlock",
|
|
65
|
+
{ language: e.lang || null },
|
|
66
|
+
e.text ? [t.createTextNode(e.text)] : []
|
|
67
|
+
);
|
|
68
|
+
},
|
|
69
|
+
renderMarkdown: (e, t) => {
|
|
70
|
+
var i;
|
|
71
|
+
let o = "";
|
|
72
|
+
const n = ((i = e.attrs) == null ? void 0 : i.language) || "";
|
|
73
|
+
return e.content ? o = [`\`\`\`${n}`, t.renderChildren(e.content), "```"].join(`
|
|
74
|
+
`) : o = `\`\`\`${n}
|
|
75
|
+
|
|
76
|
+
\`\`\``, o;
|
|
77
|
+
},
|
|
60
78
|
addCommands() {
|
|
61
79
|
return {
|
|
62
|
-
setCodeBlock: (e) => ({ commands:
|
|
63
|
-
toggleCodeBlock: (e) => ({ commands:
|
|
80
|
+
setCodeBlock: (e) => ({ commands: t }) => t.setNode(this.name, e),
|
|
81
|
+
toggleCodeBlock: (e) => ({ commands: t }) => t.toggleNode(this.name, "paragraph", e)
|
|
64
82
|
};
|
|
65
83
|
},
|
|
66
84
|
addKeyboardShortcuts() {
|
|
@@ -68,89 +86,89 @@ var B = 4, U = /^```([a-z]+)?[\s\n]$/, V = /^~~~([a-z]+)?[\s\n]$/, J = R.create(
|
|
|
68
86
|
"Mod-Alt-c": () => this.editor.commands.toggleCodeBlock(),
|
|
69
87
|
// remove code block when at start of document or code block is empty
|
|
70
88
|
Backspace: () => {
|
|
71
|
-
const { empty: e, $anchor:
|
|
72
|
-
return !e ||
|
|
89
|
+
const { empty: e, $anchor: t } = this.editor.state.selection, i = t.pos === 1;
|
|
90
|
+
return !e || t.parent.type.name !== this.name ? !1 : i || !t.parent.textContent.length ? this.editor.commands.clearNodes() : !1;
|
|
73
91
|
},
|
|
74
92
|
// handle tab indentation
|
|
75
93
|
Tab: ({ editor: e }) => {
|
|
76
|
-
var
|
|
94
|
+
var t;
|
|
77
95
|
if (!this.options.enableTabIndentation)
|
|
78
96
|
return !1;
|
|
79
|
-
const
|
|
80
|
-
if (
|
|
97
|
+
const i = (t = this.options.tabSize) != null ? t : A, { state: o } = e, { selection: n } = o, { $from: c, empty: r } = n;
|
|
98
|
+
if (c.parent.type !== this.type)
|
|
81
99
|
return !1;
|
|
82
|
-
const
|
|
83
|
-
return
|
|
84
|
-
const { from:
|
|
100
|
+
const s = " ".repeat(i);
|
|
101
|
+
return r ? e.commands.insertContent(s) : e.commands.command(({ tr: d }) => {
|
|
102
|
+
const { from: a, to: g } = n, l = o.doc.textBetween(a, g, `
|
|
85
103
|
`, `
|
|
86
104
|
`).split(`
|
|
87
|
-
`).map((h) =>
|
|
105
|
+
`).map((h) => s + h).join(`
|
|
88
106
|
`);
|
|
89
|
-
return d.replaceWith(
|
|
107
|
+
return d.replaceWith(a, g, o.schema.text(l)), !0;
|
|
90
108
|
});
|
|
91
109
|
},
|
|
92
110
|
// handle shift+tab reverse indentation
|
|
93
111
|
"Shift-Tab": ({ editor: e }) => {
|
|
94
|
-
var
|
|
112
|
+
var t;
|
|
95
113
|
if (!this.options.enableTabIndentation)
|
|
96
114
|
return !1;
|
|
97
|
-
const
|
|
98
|
-
return
|
|
115
|
+
const i = (t = this.options.tabSize) != null ? t : A, { state: o } = e, { selection: n } = o, { $from: c, empty: r } = n;
|
|
116
|
+
return c.parent.type !== this.type ? !1 : r ? e.commands.command(({ tr: s }) => {
|
|
99
117
|
var d;
|
|
100
|
-
const { pos:
|
|
118
|
+
const { pos: a } = c, g = c.start(), y = c.end(), l = o.doc.textBetween(g, y, `
|
|
101
119
|
`, `
|
|
102
120
|
`).split(`
|
|
103
121
|
`);
|
|
104
122
|
let h = 0, u = 0;
|
|
105
|
-
const
|
|
106
|
-
for (let T = 0; T <
|
|
107
|
-
if (u +
|
|
123
|
+
const p = a - g;
|
|
124
|
+
for (let T = 0; T < l.length; T += 1) {
|
|
125
|
+
if (u + l[T].length >= p) {
|
|
108
126
|
h = T;
|
|
109
127
|
break;
|
|
110
128
|
}
|
|
111
|
-
u +=
|
|
129
|
+
u += l[T].length + 1;
|
|
112
130
|
}
|
|
113
|
-
const
|
|
131
|
+
const v = ((d = l[h].match(/^ */)) == null ? void 0 : d[0]) || "", x = Math.min(v.length, i);
|
|
114
132
|
if (x === 0)
|
|
115
133
|
return !0;
|
|
116
|
-
let k =
|
|
134
|
+
let k = g;
|
|
117
135
|
for (let T = 0; T < h; T += 1)
|
|
118
|
-
k +=
|
|
119
|
-
return
|
|
120
|
-
}) : e.commands.command(({ tr:
|
|
121
|
-
const { from: d, to:
|
|
136
|
+
k += l[T].length + 1;
|
|
137
|
+
return s.delete(k, k + x), a - k <= x && s.setSelection($.create(s.doc, k)), !0;
|
|
138
|
+
}) : e.commands.command(({ tr: s }) => {
|
|
139
|
+
const { from: d, to: a } = n, m = o.doc.textBetween(d, a, `
|
|
122
140
|
`, `
|
|
123
141
|
`).split(`
|
|
124
|
-
`).map((
|
|
142
|
+
`).map((l) => {
|
|
125
143
|
var h;
|
|
126
|
-
const u = ((h =
|
|
127
|
-
return
|
|
144
|
+
const u = ((h = l.match(/^ */)) == null ? void 0 : h[0]) || "", p = Math.min(u.length, i);
|
|
145
|
+
return l.slice(p);
|
|
128
146
|
}).join(`
|
|
129
147
|
`);
|
|
130
|
-
return
|
|
148
|
+
return s.replaceWith(d, a, o.schema.text(m)), !0;
|
|
131
149
|
});
|
|
132
150
|
},
|
|
133
151
|
// exit node on triple enter
|
|
134
152
|
Enter: ({ editor: e }) => {
|
|
135
153
|
if (!this.options.exitOnTripleEnter)
|
|
136
154
|
return !1;
|
|
137
|
-
const { state:
|
|
138
|
-
if (!
|
|
155
|
+
const { state: t } = e, { selection: i } = t, { $from: o, empty: n } = i;
|
|
156
|
+
if (!n || o.parent.type !== this.type)
|
|
139
157
|
return !1;
|
|
140
|
-
const
|
|
158
|
+
const c = o.parentOffset === o.parent.nodeSize - 2, r = o.parent.textContent.endsWith(`
|
|
141
159
|
|
|
142
160
|
`);
|
|
143
|
-
return !
|
|
161
|
+
return !c || !r ? !1 : e.chain().command(({ tr: s }) => (s.delete(o.pos - 2, o.pos), !0)).exitCode().run();
|
|
144
162
|
},
|
|
145
163
|
// exit node on arrow down
|
|
146
164
|
ArrowDown: ({ editor: e }) => {
|
|
147
165
|
if (!this.options.exitOnArrowDown)
|
|
148
166
|
return !1;
|
|
149
|
-
const { state:
|
|
150
|
-
if (!
|
|
167
|
+
const { state: t } = e, { selection: i, doc: o } = t, { $from: n, empty: c } = i;
|
|
168
|
+
if (!c || n.parent.type !== this.type || !(n.parentOffset === n.parent.nodeSize - 2))
|
|
151
169
|
return !1;
|
|
152
|
-
const
|
|
153
|
-
return
|
|
170
|
+
const s = n.after();
|
|
171
|
+
return s === void 0 ? !1 : o.nodeAt(s) ? e.commands.command(({ tr: a }) => (a.setSelection(j.near(o.resolve(s))), !0)) : e.commands.exitCode();
|
|
154
172
|
}
|
|
155
173
|
};
|
|
156
174
|
},
|
|
@@ -176,159 +194,159 @@ var B = 4, U = /^```([a-z]+)?[\s\n]$/, V = /^~~~([a-z]+)?[\s\n]$/, J = R.create(
|
|
|
176
194
|
return [
|
|
177
195
|
// this plugin creates a code block for pasted content from VS Code
|
|
178
196
|
// we can also detect the copied code language
|
|
179
|
-
new
|
|
180
|
-
key: new
|
|
197
|
+
new z({
|
|
198
|
+
key: new I("codeBlockVSCodeHandler"),
|
|
181
199
|
props: {
|
|
182
|
-
handlePaste: (e,
|
|
183
|
-
if (!
|
|
200
|
+
handlePaste: (e, t) => {
|
|
201
|
+
if (!t.clipboardData || this.editor.isActive(this.type.name))
|
|
184
202
|
return !1;
|
|
185
|
-
const
|
|
186
|
-
if (!
|
|
203
|
+
const i = t.clipboardData.getData("text/plain"), o = t.clipboardData.getData("vscode-editor-data"), n = o ? JSON.parse(o) : void 0, c = n?.mode;
|
|
204
|
+
if (!i || !c)
|
|
187
205
|
return !1;
|
|
188
|
-
const { tr:
|
|
206
|
+
const { tr: r, schema: s } = e.state, d = s.text(i.replace(/\r\n?/g, `
|
|
189
207
|
`));
|
|
190
|
-
return
|
|
208
|
+
return r.replaceSelectionWith(this.type.create({ language: c }, d)), r.selection.$from.parent.type !== this.type && r.setSelection($.near(r.doc.resolve(Math.max(0, r.selection.from - 2)))), r.setMeta("paste", !0), e.dispatch(r), !0;
|
|
191
209
|
}
|
|
192
210
|
}
|
|
193
211
|
})
|
|
194
212
|
];
|
|
195
213
|
}
|
|
196
214
|
}), Z = J;
|
|
197
|
-
let f,
|
|
198
|
-
const
|
|
215
|
+
let f, w;
|
|
216
|
+
const N = /* @__PURE__ */ new Set(), D = /* @__PURE__ */ new Set(), B = /* @__PURE__ */ new Map();
|
|
199
217
|
function q(e) {
|
|
200
|
-
return e in
|
|
218
|
+
return e in E || B.has(e);
|
|
201
219
|
}
|
|
202
220
|
function G() {
|
|
203
221
|
return f;
|
|
204
222
|
}
|
|
205
223
|
function Q(e) {
|
|
206
|
-
if (!f && !
|
|
224
|
+
if (!f && !w) {
|
|
207
225
|
if (e.customThemes)
|
|
208
|
-
for (const
|
|
209
|
-
|
|
210
|
-
const
|
|
211
|
-
(
|
|
212
|
-
),
|
|
213
|
-
(
|
|
214
|
-
),
|
|
215
|
-
return
|
|
216
|
-
f =
|
|
217
|
-
}),
|
|
226
|
+
for (const n of e.customThemes)
|
|
227
|
+
n.name && B.set(n.name, n);
|
|
228
|
+
const t = e.themes.filter(
|
|
229
|
+
(n) => !!n && n in E
|
|
230
|
+
), i = e.languages.filter(
|
|
231
|
+
(n) => !!n && n in W
|
|
232
|
+
), o = [...t, ...B.values()];
|
|
233
|
+
return w = K({ themes: o, langs: i }).then((n) => {
|
|
234
|
+
f = n;
|
|
235
|
+
}), w;
|
|
218
236
|
}
|
|
219
|
-
if (
|
|
220
|
-
return
|
|
237
|
+
if (w)
|
|
238
|
+
return w;
|
|
221
239
|
}
|
|
222
|
-
async function
|
|
223
|
-
if (f && !f.getLoadedThemes().includes(e) && !
|
|
224
|
-
|
|
225
|
-
const
|
|
226
|
-
return await f.loadTheme(
|
|
240
|
+
async function b(e) {
|
|
241
|
+
if (f && !f.getLoadedThemes().includes(e) && !D.has(e) && q(e)) {
|
|
242
|
+
D.add(e);
|
|
243
|
+
const t = B.get(e) ?? e;
|
|
244
|
+
return await f.loadTheme(t), D.delete(e), !0;
|
|
227
245
|
}
|
|
228
246
|
return !1;
|
|
229
247
|
}
|
|
230
|
-
async function
|
|
231
|
-
return f && !f.getLoadedLanguages().includes(e) && !
|
|
248
|
+
async function H(e) {
|
|
249
|
+
return f && !f.getLoadedLanguages().includes(e) && !N.has(e) && e in W ? (N.add(e), await f.loadLanguage(e), N.delete(e), !0) : !1;
|
|
232
250
|
}
|
|
233
251
|
async function X({
|
|
234
252
|
doc: e,
|
|
235
|
-
name:
|
|
236
|
-
defaultTheme:
|
|
237
|
-
defaultLanguage:
|
|
238
|
-
themeModes:
|
|
239
|
-
customThemes:
|
|
253
|
+
name: t,
|
|
254
|
+
defaultTheme: i,
|
|
255
|
+
defaultLanguage: o,
|
|
256
|
+
themeModes: n,
|
|
257
|
+
customThemes: c
|
|
240
258
|
}) {
|
|
241
|
-
const
|
|
242
|
-
...
|
|
243
|
-
|
|
259
|
+
const r = L(e, (a) => a.type.name === t), s = [
|
|
260
|
+
...r.map((a) => a.node.attrs.theme),
|
|
261
|
+
i
|
|
244
262
|
], d = [
|
|
245
|
-
...
|
|
246
|
-
|
|
263
|
+
...r.map((a) => a.node.attrs.language),
|
|
264
|
+
o
|
|
247
265
|
];
|
|
248
266
|
if (f)
|
|
249
267
|
await Promise.all([
|
|
250
|
-
...
|
|
251
|
-
...d.flatMap((
|
|
268
|
+
...s.flatMap((a) => b(a)),
|
|
269
|
+
...d.flatMap((a) => !!a && H(a))
|
|
252
270
|
]);
|
|
253
271
|
else {
|
|
254
|
-
const
|
|
255
|
-
|
|
272
|
+
const a = [...s];
|
|
273
|
+
n && (n.light && !a.includes(n.light) && a.push(n.light), n.dark && !a.includes(n.dark) && a.push(n.dark)), await Q({
|
|
256
274
|
languages: d,
|
|
257
|
-
themes:
|
|
258
|
-
customThemes:
|
|
275
|
+
themes: a,
|
|
276
|
+
customThemes: c
|
|
259
277
|
});
|
|
260
278
|
}
|
|
261
279
|
}
|
|
262
280
|
function C(e) {
|
|
263
|
-
return Object.entries(e).map(([
|
|
281
|
+
return Object.entries(e).map(([t, i]) => `${t}:${i}`).join(";");
|
|
264
282
|
}
|
|
265
|
-
function
|
|
283
|
+
function _({
|
|
266
284
|
doc: e,
|
|
267
|
-
name:
|
|
268
|
-
defaultTheme:
|
|
269
|
-
defaultLanguage:
|
|
270
|
-
themes:
|
|
285
|
+
name: t,
|
|
286
|
+
defaultTheme: i,
|
|
287
|
+
defaultLanguage: o,
|
|
288
|
+
themes: n
|
|
271
289
|
}) {
|
|
272
|
-
const
|
|
273
|
-
return
|
|
274
|
-
let d =
|
|
275
|
-
const
|
|
276
|
-
if (!
|
|
277
|
-
|
|
278
|
-
const h = (
|
|
290
|
+
const c = [];
|
|
291
|
+
return L(e, (s) => s.type.name === t).forEach((s) => {
|
|
292
|
+
let d = s.pos + 1, a = s.node.attrs.language || o;
|
|
293
|
+
const g = s.node.attrs.theme || i, y = s.node.attrs.themes?.light || n?.light, m = s.node.attrs.themes?.dark || n?.dark, l = G();
|
|
294
|
+
if (!l) return;
|
|
295
|
+
l.getLoadedLanguages().includes(a) || (a = "plaintext");
|
|
296
|
+
const h = (p) => l.getLoadedThemes().includes(p) ? p : l.getLoadedThemes()[0];
|
|
279
297
|
let u;
|
|
280
|
-
if (
|
|
281
|
-
u =
|
|
282
|
-
lang:
|
|
298
|
+
if (n) {
|
|
299
|
+
u = l.codeToTokens(s.node.textContent, {
|
|
300
|
+
lang: a,
|
|
283
301
|
themes: {
|
|
284
302
|
light: h(y),
|
|
285
303
|
dark: h(m)
|
|
286
304
|
}
|
|
287
305
|
});
|
|
288
|
-
const
|
|
289
|
-
u.bg && (
|
|
290
|
-
|
|
291
|
-
style: C(
|
|
306
|
+
const p = {};
|
|
307
|
+
u.bg && (p["background-color"] = u.bg), u.fg && (p.color = u.fg), c.push(
|
|
308
|
+
P.node(s.pos, s.pos + s.node.nodeSize, {
|
|
309
|
+
style: C(p),
|
|
292
310
|
class: "shiki"
|
|
293
311
|
})
|
|
294
312
|
);
|
|
295
313
|
} else {
|
|
296
|
-
u =
|
|
297
|
-
lang:
|
|
298
|
-
theme: h(
|
|
314
|
+
u = l.codeToTokens(s.node.textContent, {
|
|
315
|
+
lang: a,
|
|
316
|
+
theme: h(g)
|
|
299
317
|
});
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
318
|
+
const p = l.getLoadedThemes().includes(g) ? g : l.getLoadedThemes()[0], S = l.getTheme(p);
|
|
319
|
+
c.push(
|
|
320
|
+
P.node(s.pos, s.pos + s.node.nodeSize, {
|
|
303
321
|
style: C({ "background-color": S.bg })
|
|
304
322
|
})
|
|
305
323
|
);
|
|
306
324
|
}
|
|
307
|
-
for (const
|
|
308
|
-
for (const S of
|
|
309
|
-
const
|
|
325
|
+
for (const p of u.tokens) {
|
|
326
|
+
for (const S of p) {
|
|
327
|
+
const v = d + S.content.length;
|
|
310
328
|
let x = "";
|
|
311
|
-
|
|
312
|
-
const k =
|
|
329
|
+
n ? x = C(S.htmlStyle || {}) : x = C({ color: S.color || "inherit" });
|
|
330
|
+
const k = P.inline(d, v, {
|
|
313
331
|
style: x
|
|
314
332
|
});
|
|
315
|
-
|
|
333
|
+
c.push(k), d = v;
|
|
316
334
|
}
|
|
317
335
|
d += 1;
|
|
318
336
|
}
|
|
319
|
-
}),
|
|
337
|
+
}), F.create(e, c);
|
|
320
338
|
}
|
|
321
339
|
function Y({
|
|
322
340
|
name: e,
|
|
323
|
-
defaultLanguage:
|
|
324
|
-
defaultTheme:
|
|
325
|
-
themes:
|
|
326
|
-
customThemes:
|
|
341
|
+
defaultLanguage: t,
|
|
342
|
+
defaultTheme: i,
|
|
343
|
+
themes: o,
|
|
344
|
+
customThemes: n
|
|
327
345
|
}) {
|
|
328
|
-
const
|
|
329
|
-
key: new
|
|
330
|
-
view(
|
|
331
|
-
class
|
|
346
|
+
const c = new z({
|
|
347
|
+
key: new I("shiki"),
|
|
348
|
+
view(r) {
|
|
349
|
+
class s {
|
|
332
350
|
constructor() {
|
|
333
351
|
this.initDecorations();
|
|
334
352
|
}
|
|
@@ -339,86 +357,86 @@ function Y({
|
|
|
339
357
|
}
|
|
340
358
|
// Initialize shiki async, and then highlight initial document
|
|
341
359
|
async initDecorations() {
|
|
342
|
-
const
|
|
360
|
+
const a = r.state.doc;
|
|
343
361
|
await X({
|
|
344
|
-
doc:
|
|
362
|
+
doc: a,
|
|
345
363
|
name: e,
|
|
346
|
-
defaultLanguage:
|
|
347
|
-
defaultTheme:
|
|
348
|
-
themeModes:
|
|
349
|
-
customThemes:
|
|
364
|
+
defaultLanguage: t,
|
|
365
|
+
defaultTheme: i,
|
|
366
|
+
themeModes: o,
|
|
367
|
+
customThemes: n ?? void 0
|
|
350
368
|
});
|
|
351
|
-
const
|
|
352
|
-
|
|
369
|
+
const g = r.state.tr.setMeta("shikiPluginForceDecoration", !0);
|
|
370
|
+
r.dispatch(g);
|
|
353
371
|
}
|
|
354
372
|
// When new codeblocks were added and they have missing themes or
|
|
355
373
|
// languages, load those and then add code decorations once again.
|
|
356
374
|
async checkUndecoratedBlocks() {
|
|
357
|
-
const
|
|
358
|
-
|
|
359
|
-
(
|
|
360
|
-
),
|
|
361
|
-
const h = [
|
|
362
|
-
return
|
|
363
|
-
|
|
364
|
-
), h.push(
|
|
375
|
+
const a = L(
|
|
376
|
+
r.state.doc,
|
|
377
|
+
(l) => l.type.name === e
|
|
378
|
+
), g = (l) => {
|
|
379
|
+
const h = [H(l.node.attrs.language)];
|
|
380
|
+
return o ? (h.push(
|
|
381
|
+
b(l.node.attrs.themes?.light || o.light)
|
|
382
|
+
), h.push(b(l.node.attrs.themes?.dark || o.dark))) : h.push(b(l.node.attrs.theme)), h;
|
|
365
383
|
};
|
|
366
384
|
if ((await Promise.all(
|
|
367
|
-
|
|
385
|
+
a.flatMap((l) => g(l))
|
|
368
386
|
)).includes(!0)) {
|
|
369
|
-
const
|
|
370
|
-
|
|
387
|
+
const l = r.state.tr.setMeta("shikiPluginForceDecoration", !0);
|
|
388
|
+
r.dispatch(l);
|
|
371
389
|
}
|
|
372
390
|
}
|
|
373
391
|
}
|
|
374
|
-
return new
|
|
392
|
+
return new s();
|
|
375
393
|
},
|
|
376
394
|
state: {
|
|
377
|
-
init: (
|
|
378
|
-
doc:
|
|
395
|
+
init: (r, { doc: s }) => _({
|
|
396
|
+
doc: s,
|
|
379
397
|
name: e,
|
|
380
|
-
defaultLanguage:
|
|
381
|
-
defaultTheme:
|
|
382
|
-
themes:
|
|
398
|
+
defaultLanguage: t,
|
|
399
|
+
defaultTheme: i,
|
|
400
|
+
themes: o
|
|
383
401
|
}),
|
|
384
|
-
apply: (
|
|
385
|
-
const
|
|
402
|
+
apply: (r, s, d, a) => {
|
|
403
|
+
const g = d.selection.$head.parent.type.name, y = a.selection.$head.parent.type.name, m = L(
|
|
386
404
|
d.doc,
|
|
387
405
|
(u) => u.type.name === e
|
|
388
|
-
),
|
|
389
|
-
|
|
406
|
+
), l = L(
|
|
407
|
+
a.doc,
|
|
390
408
|
(u) => u.type.name === e
|
|
391
|
-
), h =
|
|
409
|
+
), h = r.docChanged && // Apply decorations if:
|
|
392
410
|
// selection includes named node,
|
|
393
|
-
([
|
|
394
|
-
|
|
411
|
+
([g, y].includes(e) || // OR transaction adds/removes named node,
|
|
412
|
+
l.length !== m.length || // OR transaction has changes that completely encapsulte a node
|
|
395
413
|
// (for example, a transaction that affects the entire document).
|
|
396
414
|
// Such transactions can happen during collab syncing via y-prosemirror, for example.
|
|
397
|
-
|
|
415
|
+
r.steps.some((u) => (
|
|
398
416
|
// @ts-expect-error
|
|
399
417
|
u.from !== void 0 && // @ts-expect-error
|
|
400
|
-
u.to !== void 0 && m.some((
|
|
418
|
+
u.to !== void 0 && m.some((p) => (
|
|
401
419
|
// @ts-expect-error
|
|
402
|
-
|
|
403
|
-
|
|
420
|
+
p.pos >= u.from && // @ts-expect-error
|
|
421
|
+
p.pos + p.node.nodeSize <= u.to
|
|
404
422
|
))
|
|
405
423
|
)));
|
|
406
|
-
return
|
|
407
|
-
doc:
|
|
424
|
+
return r.getMeta("shikiPluginForceDecoration") || h ? _({
|
|
425
|
+
doc: r.doc,
|
|
408
426
|
name: e,
|
|
409
|
-
defaultLanguage:
|
|
410
|
-
defaultTheme:
|
|
411
|
-
themes:
|
|
412
|
-
}) :
|
|
427
|
+
defaultLanguage: t,
|
|
428
|
+
defaultTheme: i,
|
|
429
|
+
themes: o
|
|
430
|
+
}) : s.map(r.mapping, r.doc);
|
|
413
431
|
}
|
|
414
432
|
},
|
|
415
433
|
props: {
|
|
416
|
-
decorations(
|
|
417
|
-
return
|
|
434
|
+
decorations(r) {
|
|
435
|
+
return c.getState(r);
|
|
418
436
|
}
|
|
419
437
|
}
|
|
420
438
|
});
|
|
421
|
-
return
|
|
439
|
+
return c;
|
|
422
440
|
}
|
|
423
441
|
/* v8 ignore start -- @preserve */
|
|
424
442
|
/* v8 ignore stop -- @preserve */
|
|
@@ -432,6 +450,23 @@ const re = Z.extend({
|
|
|
432
450
|
customThemes: null
|
|
433
451
|
};
|
|
434
452
|
},
|
|
453
|
+
markdownTokenName: "code",
|
|
454
|
+
parseMarkdown(e, t) {
|
|
455
|
+
return e.raw?.startsWith("```") === !1 && e.raw?.startsWith("~~~") === !1 && e.codeBlockStyle !== "indented" ? [] : t.createNode(
|
|
456
|
+
"codeBlock",
|
|
457
|
+
{ language: e.lang || null },
|
|
458
|
+
e.text ? [t.createTextNode(e.text)] : []
|
|
459
|
+
);
|
|
460
|
+
},
|
|
461
|
+
renderMarkdown(e, t, i) {
|
|
462
|
+
const o = e.attrs?.language || "";
|
|
463
|
+
return e.content ? [`\`\`\`${o}`, t.renderChildren(e.content), "```"].join(
|
|
464
|
+
`
|
|
465
|
+
`
|
|
466
|
+
) : `\`\`\`${o}
|
|
467
|
+
|
|
468
|
+
\`\`\``;
|
|
469
|
+
},
|
|
435
470
|
addProseMirrorPlugins() {
|
|
436
471
|
return [
|
|
437
472
|
...this.parent?.() || [],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tiptap-extension-code-block-shiki",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Use Shiki syntax highlighting for codeblocks in TipTap.",
|
|
5
5
|
"repository": "timomeh/tiptap-extension-code-block-shiki",
|
|
6
6
|
"author": {
|
|
@@ -32,13 +32,14 @@
|
|
|
32
32
|
"@biomejs/biome": "2.2.6",
|
|
33
33
|
"@codecov/vite-plugin": "^1.9.1",
|
|
34
34
|
"@microsoft/api-extractor": "^7.53.1",
|
|
35
|
-
"@tiptap/core": "^3.
|
|
36
|
-
"@tiptap/extension-code-block": "^3.
|
|
37
|
-
"@tiptap/
|
|
38
|
-
"@tiptap/
|
|
35
|
+
"@tiptap/core": "^3.21.0",
|
|
36
|
+
"@tiptap/extension-code-block": "^3.21.0",
|
|
37
|
+
"@tiptap/markdown": "^3.21.0",
|
|
38
|
+
"@tiptap/pm": "^3.21.0",
|
|
39
|
+
"@tiptap/starter-kit": "^3.21.0",
|
|
39
40
|
"@vitest/coverage-v8": "^3.2.4",
|
|
40
41
|
"happy-dom": "^20.0.0",
|
|
41
|
-
"shiki": "^
|
|
42
|
+
"shiki": "^4.0.0",
|
|
42
43
|
"typescript": "^5.9.3",
|
|
43
44
|
"unplugin-dts": "1.0.0-beta.0",
|
|
44
45
|
"vite": "^7.1.9",
|
|
@@ -47,7 +48,7 @@
|
|
|
47
48
|
"peerDependencies": {
|
|
48
49
|
"@tiptap/core": "^2.3.0 || ^3.0.0",
|
|
49
50
|
"@tiptap/pm": "^2.3.0 || ^3.0.0",
|
|
50
|
-
"shiki": "^3.0.0"
|
|
51
|
+
"shiki": "^3.0.0 || ^4.0.0"
|
|
51
52
|
},
|
|
52
53
|
"keywords": [
|
|
53
54
|
"tiptap",
|