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