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 _, textblockTypeInputRule as N, mergeAttributes as R, findChildren as C } from "@tiptap/core";
2
- import { Plugin as I, PluginKey as $, TextSelection as M, Selection as W } from "@tiptap/pm/state";
3
- import { DecorationSet as F, Decoration as A } from "@tiptap/pm/view";
4
- import { bundledThemes as E, bundledLanguages as H, createHighlighter as j } from "shiki";
5
- var B = 4, U = /^```([a-z]+)?[\s\n]$/, K = /^~~~([a-z]+)?[\s\n]$/, V = _.create({
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 r;
29
- const { languageClassPrefix: i } = this.options;
30
- if (!i)
28
+ var o;
29
+ const { languageClassPrefix: c } = this.options;
30
+ if (!c)
31
31
  return null;
32
- const n = [...((r = e.firstElementChild) == null ? void 0 : r.classList) || []].filter((l) => l.startsWith(i)).map((l) => l.replace(i, ""))[0];
33
- return n || null;
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: r }) {
47
+ renderHTML({ node: e, HTMLAttributes: o }) {
48
48
  return [
49
49
  "pre",
50
- R(this.options.HTMLAttributes, r),
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: r }) => r.setNode(this.name, e),
63
- toggleCodeBlock: (e) => ({ commands: r }) => r.toggleNode(this.name, "paragraph", e)
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: r } = this.editor.state.selection, i = r.pos === 1;
72
- return !e || r.parent.type.name !== this.name ? !1 : i || !r.parent.textContent.length ? this.editor.commands.clearNodes() : !1;
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 r;
76
+ var o;
77
77
  if (!this.options.enableTabIndentation)
78
78
  return !1;
79
- const i = (r = this.options.tabSize) != null ? r : B, { state: t } = e, { selection: a } = t, { $from: n, empty: l } = a;
80
- if (n.parent.type !== this.type)
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 o = " ".repeat(i);
83
- return l ? e.commands.insertContent(o) : e.commands.command(({ tr: s }) => {
84
- const { from: d, to: g } = a, c = t.doc.textBetween(d, g, `
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((u) => o + u).join(`
87
+ `).map((h) => n + h).join(`
88
88
  `);
89
- return s.replaceWith(d, g, t.schema.text(c)), !0;
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 r;
94
+ var o;
95
95
  if (!this.options.enableTabIndentation)
96
96
  return !1;
97
- const i = (r = this.options.tabSize) != null ? r : B, { state: t } = e, { selection: a } = t, { $from: n, empty: l } = a;
98
- return n.parent.type !== this.type ? !1 : l ? e.commands.command(({ tr: o }) => {
99
- var s;
100
- const { pos: d } = n, g = n.start(), y = n.end(), c = t.doc.textBetween(g, y, `
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 u = 0, h = 0;
105
- const f = d - g;
106
- for (let T = 0; T < c.length; T += 1) {
107
- if (h + c[T].length >= f) {
108
- u = T;
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
- h += c[T].length + 1;
111
+ u += i[T].length + 1;
112
112
  }
113
- const b = ((s = c[u].match(/^ */)) == null ? void 0 : s[0]) || "", x = Math.min(b.length, i);
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 = g;
117
- for (let T = 0; T < u; T += 1)
118
- k += c[T].length + 1;
119
- return o.delete(k, k + x), d - k <= x && o.setSelection(M.create(o.doc, k)), !0;
120
- }) : e.commands.command(({ tr: o }) => {
121
- const { from: s, to: d } = a, p = t.doc.textBetween(s, d, `
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((c) => {
125
- var u;
126
- const h = ((u = c.match(/^ */)) == null ? void 0 : u[0]) || "", f = Math.min(h.length, i);
127
- return c.slice(f);
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 o.replaceWith(s, d, t.schema.text(p)), !0;
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: r } = e, { selection: i } = r, { $from: t, empty: a } = i;
138
- if (!a || t.parent.type !== this.type)
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 n = t.parentOffset === t.parent.nodeSize - 2, l = t.parent.textContent.endsWith(`
140
+ const l = a.parentOffset === a.parent.nodeSize - 2, s = a.parent.textContent.endsWith(`
141
141
 
142
142
  `);
143
- return !n || !l ? !1 : e.chain().command(({ tr: o }) => (o.delete(t.pos - 2, t.pos), !0)).exitCode().run();
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: r } = e, { selection: i, doc: t } = r, { $from: a, empty: n } = i;
150
- if (!n || a.parent.type !== this.type || !(a.parentOffset === a.parent.nodeSize - 2))
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 o = a.after();
153
- return o === void 0 ? !1 : t.nodeAt(o) ? e.commands.command(({ tr: d }) => (d.setSelection(W.near(t.resolve(o))), !0)) : e.commands.exitCode();
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
- N({
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
- N({
167
- find: K,
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 I({
180
- key: new $("codeBlockVSCodeHandler"),
179
+ new $({
180
+ key: new E("codeBlockVSCodeHandler"),
181
181
  props: {
182
- handlePaste: (e, r) => {
183
- if (!r.clipboardData || this.editor.isActive(this.type.name))
182
+ handlePaste: (e, o) => {
183
+ if (!o.clipboardData || this.editor.isActive(this.type.name))
184
184
  return !1;
185
- const i = r.clipboardData.getData("text/plain"), t = r.clipboardData.getData("vscode-editor-data"), a = t ? JSON.parse(t) : void 0, n = a?.mode;
186
- if (!i || !n)
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: l, schema: o } = e.state, s = o.text(i.replace(/\r\n?/g, `
188
+ const { tr: s, schema: n } = e.state, d = n.text(c.replace(/\r\n?/g, `
189
189
  `));
190
- return l.replaceSelectionWith(this.type.create({ language: n }, s)), l.selection.$from.parent.type !== this.type && l.setSelection(M.near(l.doc.resolve(Math.max(0, l.selection.from - 2)))), l.setMeta("paste", !0), e.dispatch(l), !0;
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
- }), J = V;
197
- let m, L;
198
- const w = /* @__PURE__ */ new Set(), D = /* @__PURE__ */ new Set();
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
- if (!m && !L) {
204
- const r = e.themes.filter(
205
- (t) => !!t && t in E
206
- ), i = e.languages.filter(
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
- return L = j({ themes: r, langs: i }).then((t) => {
210
- m = t;
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
- return m && !m.getLoadedThemes().includes(e) && !D.has(e) && e in E ? (D.add(e), await m.loadTheme(e), D.delete(e), !0) : !1;
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 O(e) {
220
- return m && !m.getLoadedLanguages().includes(e) && !w.has(e) && e in H ? (w.add(e), await m.loadLanguage(e), w.delete(e), !0) : !1;
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 G({
233
+ async function X({
223
234
  doc: e,
224
- name: r,
225
- defaultTheme: i,
226
- defaultLanguage: t,
227
- themeModes: a
235
+ name: o,
236
+ defaultTheme: c,
237
+ defaultLanguage: a,
238
+ themeModes: t,
239
+ customThemes: l
228
240
  }) {
229
- const n = C(e, (s) => s.type.name === r), l = [
230
- ...n.map((s) => s.node.attrs.theme),
231
- i
232
- ], o = [
233
- ...n.map((s) => s.node.attrs.language),
234
- t
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 (m)
248
+ if (f)
237
249
  await Promise.all([
238
- ...l.flatMap((s) => P(s)),
239
- ...o.flatMap((s) => !!s && O(s))
250
+ ...n.flatMap((r) => P(r)),
251
+ ...d.flatMap((r) => !!r && _(r))
240
252
  ]);
241
253
  else {
242
- const s = [...l];
243
- a && (a.light && !s.includes(a.light) && s.push(a.light), a.dark && !s.includes(a.dark) && s.push(a.dark)), await q({
244
- languages: o,
245
- themes: s
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 v(e) {
250
- return Object.entries(e).map(([r, i]) => `${r}:${i}`).join(";");
262
+ function C(e) {
263
+ return Object.entries(e).map(([o, c]) => `${o}:${c}`).join(";");
251
264
  }
252
- function z({
265
+ function I({
253
266
  doc: e,
254
- name: r,
255
- defaultTheme: i,
256
- defaultLanguage: t,
257
- themes: a
267
+ name: o,
268
+ defaultTheme: c,
269
+ defaultLanguage: a,
270
+ themes: t
258
271
  }) {
259
- const n = [];
260
- return C(e, (o) => o.type.name === r).forEach((o) => {
261
- let s = o.pos + 1, d = o.node.attrs.language || t;
262
- const g = o.node.attrs.theme || i, y = o.node.attrs.themes?.light || a?.light, p = o.node.attrs.themes?.dark || a?.dark, c = Z();
263
- if (!c) return;
264
- c.getLoadedLanguages().includes(d) || (d = "plaintext");
265
- const u = (f) => c.getLoadedThemes().includes(f) ? f : c.getLoadedThemes()[0];
266
- let h;
267
- if (a) {
268
- h = c.codeToTokens(o.node.textContent, {
269
- lang: d,
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: u(y),
272
- dark: u(p)
284
+ light: h(y),
285
+ dark: h(m)
273
286
  }
274
287
  });
275
- const f = {};
276
- h.bg && (f["background-color"] = h.bg), h.fg && (f.color = h.fg), n.push(
277
- A.node(o.pos, o.pos + o.node.nodeSize, {
278
- style: v(f),
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
- h = c.codeToTokens(o.node.textContent, {
284
- lang: d,
285
- theme: u(g)
296
+ u = i.codeToTokens(n.node.textContent, {
297
+ lang: r,
298
+ theme: h(p)
286
299
  });
287
- const f = c.getLoadedThemes().includes(g) ? g : c.getLoadedThemes()[0], S = c.getTheme(f);
288
- n.push(
289
- A.node(o.pos, o.pos + o.node.nodeSize, {
290
- style: v({ "background-color": S.bg })
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 f of h.tokens) {
295
- for (const S of f) {
296
- const b = s + S.content.length;
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
- a ? x = v(S.htmlStyle || {}) : x = v({ color: S.color || "inherit" });
299
- const k = A.inline(s, b, {
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
- n.push(k), s = b;
315
+ l.push(k), d = b;
303
316
  }
304
- s += 1;
317
+ d += 1;
305
318
  }
306
- }), F.create(e, n);
319
+ }), j.create(e, l);
307
320
  }
308
- function Q({
321
+ function Y({
309
322
  name: e,
310
- defaultLanguage: r,
311
- defaultTheme: i,
312
- themes: t
323
+ defaultLanguage: o,
324
+ defaultTheme: c,
325
+ themes: a,
326
+ customThemes: t
313
327
  }) {
314
- const a = new I({
315
- key: new $("shiki"),
316
- view(n) {
317
- class l {
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 s = n.state.doc;
329
- await G({
330
- doc: s,
342
+ const r = s.state.doc;
343
+ await X({
344
+ doc: r,
331
345
  name: e,
332
- defaultLanguage: r,
333
- defaultTheme: i,
334
- themeModes: t
346
+ defaultLanguage: o,
347
+ defaultTheme: c,
348
+ themeModes: a,
349
+ customThemes: t ?? void 0
335
350
  });
336
- const d = n.state.tr.setMeta("shikiPluginForceDecoration", !0);
337
- n.dispatch(d);
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 s = C(
343
- n.state.doc,
344
- (p) => p.type.name === e
345
- ), d = (p) => {
346
- const c = [O(p.node.attrs.language)];
347
- return t ? (c.push(
348
- P(p.node.attrs.themes?.light || t.light)
349
- ), c.push(P(p.node.attrs.themes?.dark || t.dark))) : c.push(P(p.node.attrs.theme)), c;
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
- s.flatMap((p) => d(p))
367
+ r.flatMap((i) => p(i))
353
368
  )).includes(!0)) {
354
- const p = n.state.tr.setMeta("shikiPluginForceDecoration", !0);
355
- n.dispatch(p);
369
+ const i = s.state.tr.setMeta("shikiPluginForceDecoration", !0);
370
+ s.dispatch(i);
356
371
  }
357
372
  }
358
373
  }
359
- return new l();
374
+ return new n();
360
375
  },
361
376
  state: {
362
- init: (n, { doc: l }) => z({
363
- doc: l,
377
+ init: (s, { doc: n }) => I({
378
+ doc: n,
364
379
  name: e,
365
- defaultLanguage: r,
366
- defaultTheme: i,
367
- themes: t
380
+ defaultLanguage: o,
381
+ defaultTheme: c,
382
+ themes: a
368
383
  }),
369
- apply: (n, l, o, s) => {
370
- const d = o.selection.$head.parent.type.name, g = s.selection.$head.parent.type.name, y = C(
371
- o.doc,
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
- ), p = C(
374
- s.doc,
388
+ ), i = v(
389
+ r.doc,
375
390
  (u) => u.type.name === e
376
- ), c = n.docChanged && // Apply decorations if:
391
+ ), h = s.docChanged && // Apply decorations if:
377
392
  // selection includes named node,
378
- ([d, g].includes(e) || // OR transaction adds/removes named node,
379
- p.length !== y.length || // OR transaction has changes that completely encapsulte a node
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
- n.steps.some((u) => (
397
+ s.steps.some((u) => (
383
398
  // @ts-expect-error
384
399
  u.from !== void 0 && // @ts-expect-error
385
- u.to !== void 0 && y.some((h) => (
400
+ u.to !== void 0 && m.some((g) => (
386
401
  // @ts-expect-error
387
- h.pos >= u.from && // @ts-expect-error
388
- h.pos + h.node.nodeSize <= u.to
402
+ g.pos >= u.from && // @ts-expect-error
403
+ g.pos + g.node.nodeSize <= u.to
389
404
  ))
390
405
  )));
391
- return n.getMeta("shikiPluginForceDecoration") || c ? z({
392
- doc: n.doc,
406
+ return s.getMeta("shikiPluginForceDecoration") || h ? I({
407
+ doc: s.doc,
393
408
  name: e,
394
- defaultLanguage: r,
395
- defaultTheme: i,
396
- themes: t
397
- }) : l.map(n.mapping, n.doc);
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(n) {
402
- return a.getState(n);
416
+ decorations(s) {
417
+ return l.getState(s);
403
418
  }
404
419
  }
405
420
  });
406
- return a;
421
+ return l;
407
422
  }
408
423
  /* v8 ignore start -- @preserve */
409
424
  /* v8 ignore stop -- @preserve */
410
- const oe = J.extend({
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
- Q({
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
- oe as CodeBlockShiki,
433
- oe as default
449
+ re as CodeBlockShiki,
450
+ re as default
434
451
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tiptap-extension-code-block-shiki",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Use Shiki syntax highlighting for codeblocks in TipTap.",
5
5
  "repository": "timomeh/tiptap-extension-code-block-shiki",
6
6
  "author": {