@sveltia/ui 0.62.0 → 0.63.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.
Files changed (33) hide show
  1. package/dist/components/button/button.svelte +6 -1
  2. package/dist/components/resizable-pane/resizable-handle.svelte +12 -3
  3. package/dist/components/select/select-tags.svelte +8 -1
  4. package/dist/components/text-editor/constants.d.ts +0 -1
  5. package/dist/components/text-editor/constants.js +1 -36
  6. package/dist/components/text-editor/core.js +24 -31
  7. package/dist/components/text-editor/lexical-root.svelte +0 -68
  8. package/dist/components/text-editor/shiki/cache.d.ts +3 -0
  9. package/dist/components/text-editor/shiki/cache.js +121 -0
  10. package/dist/components/text-editor/shiki/engine-entry.d.ts +2 -0
  11. package/dist/components/text-editor/shiki/engine-entry.js +20 -0
  12. package/dist/components/text-editor/shiki/facade.d.ts +16 -0
  13. package/dist/components/text-editor/shiki/facade.js +452 -0
  14. package/dist/components/text-editor/shiki/generated.d.ts +28 -0
  15. package/dist/components/text-editor/shiki/generated.js +25 -0
  16. package/dist/components/text-editor/shiki/highlighter.d.ts +11 -0
  17. package/dist/components/text-editor/shiki/highlighter.js +477 -0
  18. package/dist/components/text-editor/shiki/loader.d.ts +6 -0
  19. package/dist/components/text-editor/shiki/loader.js +102 -0
  20. package/dist/components/text-editor/shiki/theme.d.ts +12 -0
  21. package/dist/components/text-editor/shiki/theme.js +86 -0
  22. package/dist/components/text-editor/toolbar/code-language-switcher.svelte +24 -34
  23. package/dist/components/text-editor/toolbar/toggle-block-menu-item.svelte +1 -5
  24. package/dist/index.d.ts +4 -0
  25. package/dist/index.js +4 -0
  26. package/dist/services/group.svelte.d.ts +2 -1
  27. package/dist/services/group.svelte.js +183 -50
  28. package/dist/services/tree.svelte.d.ts +8 -6
  29. package/dist/services/tree.svelte.js +104 -45
  30. package/dist/shiki-engine.js +152 -0
  31. package/dist/typedefs.d.ts +52 -0
  32. package/dist/typedefs.js +29 -0
  33. package/package.json +13 -11
@@ -0,0 +1,452 @@
1
+ /**
2
+ * Thin wrapper around a Shiki highlighter instance.
3
+ *
4
+ * Adapted from Lexical’s `FacadeShiki.ts` (MIT licensed). Two things differ from upstream, both to
5
+ * keep Shiki out of the consumer’s bundle. First, the engine is loaded on demand rather than
6
+ * imported at module scope, so a page that never shows a code block never pays for it. Second,
7
+ * grammar and theme metadata comes from `generated.js` rather than `shiki/langs` and
8
+ * `shiki/themes`, whose lazy `import()` thunks would drag the whole grammar set into a bundle.
9
+ * @see https://github.com/facebook/lexical/tree/v0.49.0/packages/lexical-code-shiki
10
+ * @see https://github.com/sveltia/sveltia-cms/issues/587
11
+ */
12
+
13
+ import {
14
+ $isCodeNode as isCodeNode,
15
+ $createCodeHighlightNode as createCodeHighlightNode,
16
+ } from '@lexical/code-core';
17
+ import {
18
+ $createLineBreakNode as createLineBreakNode,
19
+ $createTabNode as createTabNode,
20
+ $getNodeByKey as getNodeByKey,
21
+ HISTORY_MERGE_TAG,
22
+ tokenizeRawText,
23
+ } from 'lexical';
24
+ import { cachePayload, getCachedPayload } from './cache.js';
25
+ import { LANGUAGES, THEMES } from './generated.js';
26
+ import { getCodeHighlighterLoaders } from './loader.js';
27
+ import { getCodeTheme } from './theme.js';
28
+
29
+ /**
30
+ * @import { CodeNode } from '@lexical/code-core';
31
+ * @import { LexicalEditor, LexicalNode, NodeKey } from 'lexical';
32
+ */
33
+
34
+ /**
35
+ * Languages that need no grammar and no engine: the content is shown verbatim. Shiki treats these
36
+ * as special languages internally; we short-circuit them so that a plain code block — the default
37
+ * for a new block — costs no network request at all.
38
+ *
39
+ * `ansi` is deliberately excluded: Shiki does render it, so it still needs the engine.
40
+ */
41
+ const PLAIN_LANGUAGES = ['', 'plain', 'plaintext', 'text', 'txt'];
42
+ const DIFF_LANGUAGE_REGEX = /^diff-([\w-]+)/i;
43
+ /**
44
+ * Loaded engine module, once `loadEngine()` has resolved.
45
+ * @type {any}
46
+ */
47
+ let engine = null;
48
+ /**
49
+ * Highlighter instance built from the loaded engine.
50
+ * @type {any}
51
+ */
52
+ let highlighter = null;
53
+ /** Set when the engine could not be fetched, so we stop retrying on every keystroke. */
54
+ let engineUnavailable = false;
55
+ /**
56
+ * Get the language a `diff-*` language wraps, if any.
57
+ * @param {string} language Language identifier.
58
+ * @returns {string | null} Wrapped language, or `null` when this is not a diff language.
59
+ */
60
+ const getDiffedLanguage = (language) => DIFF_LANGUAGE_REGEX.exec(language)?.[1] ?? null;
61
+
62
+ /**
63
+ * Whether the given language is rendered as plain text without any highlighting.
64
+ * @param {string | null | undefined} language Language identifier.
65
+ * @returns {boolean} Result.
66
+ */
67
+ export const isPlainLanguage = (language) => PLAIN_LANGUAGES.includes(language ?? '');
68
+
69
+ /**
70
+ * Whether the syntax highlighting engine is loaded and ready to tokenize.
71
+ * @returns {boolean} Result.
72
+ */
73
+ export const isEngineLoaded = () => !!highlighter;
74
+
75
+ /**
76
+ * Whether the engine failed to load. Code blocks fall back to plain text in that case instead of
77
+ * waiting forever.
78
+ * @returns {boolean} Result.
79
+ */
80
+ export const isEngineUnavailable = () => engineUnavailable;
81
+
82
+ /**
83
+ * Whether the grammar for the given language is loaded.
84
+ * @param {string} language Language identifier, like `scss` or `diff-js`.
85
+ * @returns {boolean} Result.
86
+ */
87
+ export const isCodeLanguageLoaded = (language) => {
88
+ if (!highlighter) {
89
+ return false;
90
+ }
91
+
92
+ const id = getDiffedLanguage(language) ?? language;
93
+
94
+ // Shiki handles a handful of languages without a grammar
95
+ if (engine.isSpecialLang(id)) {
96
+ return true;
97
+ }
98
+
99
+ // `getLoadedLanguages()` also returns aliases
100
+ return highlighter.getLoadedLanguages().includes(id);
101
+ };
102
+
103
+ /**
104
+ * Mark a code node dirty so the highlighting transform runs again once an async load has completed.
105
+ * @param {LexicalEditor} editor Editor instance.
106
+ * @param {NodeKey} codeNodeKey Key of the code node to refresh.
107
+ */
108
+ const refreshCodeNode = (editor, codeNodeKey) => {
109
+ editor.update(
110
+ () => {
111
+ const codeNode = getNodeByKey(codeNodeKey);
112
+
113
+ if (!isCodeNode(codeNode)) {
114
+ return;
115
+ }
116
+
117
+ const language = codeNode.getLanguage();
118
+
119
+ if (language && isCodeLanguageLoaded(language) && !codeNode.getIsSyntaxHighlightSupported()) {
120
+ codeNode.setIsSyntaxHighlightSupported(true);
121
+ }
122
+
123
+ codeNode.markDirty();
124
+ },
125
+ { tag: HISTORY_MERGE_TAG },
126
+ );
127
+ };
128
+
129
+ /**
130
+ * In-flight loads, keyed by what is being loaded.
131
+ * @type {Map<string, { promise: Promise<void>, targets: Map<NodeKey, LexicalEditor> }>}
132
+ */
133
+ const pendingLoads = new Map();
134
+
135
+ /**
136
+ * Run an asynchronous load once, however many callers ask for it while it is in flight, and refresh
137
+ * each waiting code node exactly once when it completes.
138
+ *
139
+ * The transform fires on every keystroke, so without this a burst of typing during a load would
140
+ * start a download per keystroke and then flood the editor with one update each. That storm is
141
+ * enough to starve the final re-highlight, leaving a block tokenized as of an earlier keystroke.
142
+ * @param {string} key Cache key identifying the load.
143
+ * @param {() => Promise<void>} run Work to perform on the first call.
144
+ * @param {LexicalEditor} [editor] Editor instance to refresh once the load completes.
145
+ * @param {NodeKey} [codeNodeKey] Key of the code node to refresh.
146
+ * @returns {Promise<void>} Promise resolving when the load has completed.
147
+ */
148
+ const loadOnce = (key, run, editor, codeNodeKey) => {
149
+ let entry = pendingLoads.get(key);
150
+
151
+ if (!entry) {
152
+ /** @type {Map<NodeKey, LexicalEditor>} */
153
+ const targets = new Map();
154
+
155
+ const promise = (async () => {
156
+ try {
157
+ await run();
158
+ } catch {
159
+ // Leave the block unhighlighted; the transform falls back to plain text
160
+ }
161
+
162
+ pendingLoads.delete(key);
163
+ targets.forEach((target, nodeKey) => refreshCodeNode(target, nodeKey));
164
+ })();
165
+
166
+ entry = { promise, targets };
167
+ pendingLoads.set(key, entry);
168
+ }
169
+
170
+ if (editor && codeNodeKey) {
171
+ entry.targets.set(codeNodeKey, editor);
172
+ }
173
+
174
+ return entry.promise;
175
+ };
176
+
177
+ /**
178
+ * Load the syntax highlighting engine, then refresh the given code node.
179
+ *
180
+ * Tokenizing is synchronous because it runs inside a Lexical node transform, so the engine has to
181
+ * be resident before any highlighting can happen. The transform bails out while this is in flight
182
+ * and is re-run by `refreshCodeNode()`, the same mechanism upstream already uses for grammars.
183
+ * @param {LexicalEditor} [editor] Editor instance to refresh once the engine is ready.
184
+ * @param {NodeKey} [codeNodeKey] Key of the code node to refresh.
185
+ * @returns {Promise<void> | undefined} Promise resolving when the engine is ready, or `undefined`
186
+ * when it is already loaded or known to be unavailable.
187
+ */
188
+ export const loadEngine = (editor, codeNodeKey) => {
189
+ if (highlighter || engineUnavailable) {
190
+ return undefined;
191
+ }
192
+
193
+ return loadOnce(
194
+ 'engine',
195
+ async () => {
196
+ try {
197
+ engine = await getCodeHighlighterLoaders().loadEngine();
198
+
199
+ highlighter = engine.createHighlighterCoreSync({
200
+ engine: engine.createJavaScriptRegexEngine(),
201
+ langs: [],
202
+ themes: [],
203
+ });
204
+ } catch {
205
+ engineUnavailable = true;
206
+ }
207
+ },
208
+ editor,
209
+ codeNodeKey,
210
+ );
211
+ };
212
+
213
+ /**
214
+ * Get a grammar or theme, from the cache when possible, otherwise through the configured loader.
215
+ *
216
+ * Shiki normalizes a registration in place while loading it, so the payload is cached before it is
217
+ * handed over. Caching is best-effort and never blocks: a write that fails just means the next
218
+ * session fetches again.
219
+ * @param {string} kind Payload kind, either `lang` or `theme`.
220
+ * @param {string} id Language or theme ID.
221
+ * @param {() => Promise<any>} load Loader to call on a cache miss.
222
+ * @returns {Promise<any>} Payload, or a falsy value when unavailable.
223
+ */
224
+ const resolvePayload = async (kind, id, load) => {
225
+ const cached = await getCachedPayload(kind, id);
226
+
227
+ if (cached) {
228
+ return cached;
229
+ }
230
+
231
+ const module = await load();
232
+
233
+ if (!module) {
234
+ return undefined;
235
+ }
236
+
237
+ const payload = module.default ?? module;
238
+
239
+ await cachePayload(kind, id, payload);
240
+
241
+ return payload;
242
+ };
243
+
244
+ /**
245
+ * Resolve a language alias to its canonical identifier.
246
+ * @param {string} language Language identifier or alias, like `ts`.
247
+ * @returns {string} Canonical identifier, like `typescript`. Returns the input unchanged when the
248
+ * language is unknown.
249
+ */
250
+ export const normalizeCodeLanguage = (language) =>
251
+ LANGUAGES.find(({ id, aliases }) => id === language || aliases?.includes(language))?.id ??
252
+ language;
253
+
254
+ /**
255
+ * Load the grammar for the given language, then refresh the given code node.
256
+ * @param {string} language Language identifier, like `scss` or `diff-js`.
257
+ * @param {LexicalEditor} [editor] Editor instance to refresh once the grammar is ready.
258
+ * @param {NodeKey} [codeNodeKey] Key of the code node to refresh.
259
+ * @returns {Promise<void> | undefined} Promise resolving when the grammar is ready, or `undefined`
260
+ * when it is already loaded or the language is not supported.
261
+ */
262
+ export const loadCodeLanguage = (language, editor, codeNodeKey) => {
263
+ const id = getDiffedLanguage(language) ?? language;
264
+
265
+ if (!highlighter || isCodeLanguageLoaded(id)) {
266
+ return undefined;
267
+ }
268
+
269
+ const info = LANGUAGES.find(({ id: langId, aliases }) => langId === id || aliases?.includes(id));
270
+
271
+ if (!info) {
272
+ return undefined;
273
+ }
274
+
275
+ return loadOnce(
276
+ `lang/${info.id}`,
277
+ async () => {
278
+ const payload = await resolvePayload('lang', info.id, () =>
279
+ getCodeHighlighterLoaders().loadLanguage(info.id),
280
+ );
281
+
282
+ if (payload) {
283
+ await highlighter.loadLanguage(payload);
284
+ }
285
+ },
286
+ editor,
287
+ codeNodeKey,
288
+ );
289
+ };
290
+
291
+ /**
292
+ * Whether the given theme is loaded.
293
+ * @param {string} theme Theme identifier, like `github-light`.
294
+ * @returns {boolean} Result.
295
+ */
296
+ export const isCodeThemeLoaded = (theme) => {
297
+ if (!highlighter) {
298
+ return false;
299
+ }
300
+
301
+ return engine.isSpecialTheme(theme) || highlighter.getLoadedThemes().includes(theme);
302
+ };
303
+
304
+ /**
305
+ * Load the given theme, then refresh the given code node.
306
+ * @param {string} theme Theme identifier, like `github-light`.
307
+ * @param {LexicalEditor} [editor] Editor instance to refresh once the theme is ready.
308
+ * @param {NodeKey} [codeNodeKey] Key of the code node to refresh.
309
+ * @returns {Promise<void> | undefined} Promise resolving when the theme is ready, or `undefined`
310
+ * when it is already loaded or unknown.
311
+ */
312
+ export const loadCodeTheme = (theme, editor, codeNodeKey) => {
313
+ if (!highlighter || isCodeThemeLoaded(theme)) {
314
+ return undefined;
315
+ }
316
+
317
+ if (!THEMES.some(({ id }) => id === theme)) {
318
+ return undefined;
319
+ }
320
+
321
+ return loadOnce(
322
+ `theme/${theme}`,
323
+ async () => {
324
+ const payload = await resolvePayload('theme', theme, () =>
325
+ getCodeHighlighterLoaders().loadTheme(theme),
326
+ );
327
+
328
+ if (payload) {
329
+ await highlighter.loadTheme(payload);
330
+ }
331
+ },
332
+ editor,
333
+ codeNodeKey,
334
+ );
335
+ };
336
+
337
+ /**
338
+ * Convert Shiki tokens to Lexical nodes.
339
+ * @param {any[][]} tokens Tokens, one array per line.
340
+ * @param {boolean} diff Whether the language is a `diff-*` language.
341
+ * @returns {LexicalNode[]} Lexical nodes.
342
+ */
343
+ const mapTokensToLexicalStructure = (tokens, diff) => {
344
+ /** @type {LexicalNode[]} */
345
+ const nodes = [];
346
+
347
+ tokens.forEach((line, lineIndex) => {
348
+ if (lineIndex) {
349
+ nodes.push(createLineBreakNode());
350
+ }
351
+
352
+ line.forEach((token, tokenIndex) => {
353
+ let { content: text } = token;
354
+
355
+ // Implement `diff-*` languages
356
+ if (diff && tokenIndex === 0 && text.length > 0) {
357
+ const prefixes = ['+', '-', '>', '<', ' '];
358
+ const prefixTypes = ['inserted', 'deleted', 'inserted', 'deleted', 'unchanged'];
359
+ const prefixIndex = prefixes.indexOf(text[0]);
360
+
361
+ if (prefixIndex !== -1) {
362
+ nodes.push(createCodeHighlightNode(prefixes[prefixIndex], prefixTypes[prefixIndex]));
363
+ text = text.slice(1);
364
+ }
365
+ }
366
+
367
+ const style = engine.stringifyTokenStyle(
368
+ token.htmlStyle || engine.getTokenStyleObject(token),
369
+ );
370
+
371
+ tokenizeRawText(text, {
372
+ /**
373
+ * Append a line break node.
374
+ * @returns {number} New node count.
375
+ */
376
+ linebreak: () => nodes.push(createLineBreakNode()),
377
+ /**
378
+ * Append a tab node.
379
+ * @returns {number} New node count.
380
+ */
381
+ tab: () => nodes.push(createTabNode()),
382
+ /**
383
+ * Create a highlight node carrying the token’s colour.
384
+ * @param {string} part Text fragment.
385
+ */
386
+ text: (part) => {
387
+ const node = createCodeHighlightNode(part);
388
+
389
+ node.setStyle(style);
390
+ nodes.push(node);
391
+ },
392
+ });
393
+ });
394
+ });
395
+
396
+ return nodes;
397
+ };
398
+
399
+ /**
400
+ * Tokenize a code node’s content into Lexical nodes.
401
+ *
402
+ * Unlike upstream, the theme’s background and foreground colours are not copied onto the code node.
403
+ * The block’s own colours come from `--sui-code-background-color` so that plain and highlighted
404
+ * blocks look alike and follow the app’s theme rather than Shiki’s; only the per-token colours are
405
+ * taken from the theme.
406
+ * @param {CodeNode} codeNode Code node to tokenize.
407
+ * @param {string} language Language identifier.
408
+ * @returns {LexicalNode[]} Lexical nodes.
409
+ */
410
+ export const getHighlightNodes = (codeNode, language) => {
411
+ const diffedLanguage = getDiffedLanguage(language);
412
+
413
+ const { tokens } = highlighter.codeToTokens(codeNode.getTextContent(), {
414
+ lang: diffedLanguage ?? language,
415
+ theme: codeNode.getTheme(),
416
+ });
417
+
418
+ return mapTokensToLexicalStructure(tokens, !!diffedLanguage);
419
+ };
420
+
421
+ /**
422
+ * Highlight a snippet of code as an HTML string.
423
+ *
424
+ * Unlike the editor, which builds Lexical nodes, this returns markup for rendering elsewhere, such
425
+ * as a Markdown preview. It is synchronous, so it can be called from a renderer that cannot await:
426
+ * when the engine, grammar or theme is not loaded yet, it returns `undefined` rather than blocking,
427
+ * and the caller can render the code unhighlighted. Call {@link loadCodeHighlighter} first and
428
+ * render again once it resolves to get the highlighted result.
429
+ * @param {string} code Code to highlight.
430
+ * @param {string} language Language identifier or alias, like `ts` or `diff-js`.
431
+ * @param {object} [options] Options.
432
+ * @param {string} [options.theme] Shiki theme ID. Defaults to the one matching the app’s
433
+ * appearance.
434
+ * @returns {string | undefined} HTML string, or `undefined` when the code cannot be highlighted
435
+ * yet.
436
+ */
437
+ export const highlightCodeToHTML = (code, language, { theme } = {}) => {
438
+ const id = normalizeCodeLanguage(getDiffedLanguage(language) ?? language);
439
+
440
+ if (!highlighter || isPlainLanguage(id) || !isCodeLanguageLoaded(id)) {
441
+ return undefined;
442
+ }
443
+
444
+ // Resolved only once the cheap checks pass, so bailing out early costs nothing
445
+ const resolvedTheme = theme ?? getCodeTheme();
446
+
447
+ if (!isCodeThemeLoaded(resolvedTheme)) {
448
+ return undefined;
449
+ }
450
+
451
+ return highlighter.codeToHtml(code, { lang: id, theme: resolvedTheme });
452
+ };
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Version of Shiki whose grammars and themes are fetched at runtime. Must stay in sync with the
3
+ * version bundled into `dist/shiki-engine.js`, because grammar and theme payloads are only
4
+ * guaranteed to be compatible with the matching engine.
5
+ */
6
+ export const SHIKI_VERSION: "4.4.3";
7
+ /**
8
+ * Version of this package, used to resolve the prebuilt Shiki engine chunk from a CDN.
9
+ */
10
+ export const UI_VERSION: "0.63.0";
11
+ /**
12
+ * Available syntax highlighting languages, sorted by display name.
13
+ * @type {{ id: string, name: string, aliases?: string[] }[]}
14
+ */
15
+ export const LANGUAGES: {
16
+ id: string;
17
+ name: string;
18
+ aliases?: string[];
19
+ }[];
20
+ /**
21
+ * Available syntax highlighting themes.
22
+ * @type {{ id: string, displayName: string, type: string }[]}
23
+ */
24
+ export const THEMES: {
25
+ id: string;
26
+ displayName: string;
27
+ type: string;
28
+ }[];
@@ -0,0 +1,25 @@
1
+ // Generated by `scripts/generate-shiki-metadata.js`. DO NOT EDIT.
2
+
3
+ /**
4
+ * Version of Shiki whose grammars and themes are fetched at runtime. Must stay in sync with the
5
+ * version bundled into `dist/shiki-engine.js`, because grammar and theme payloads are only
6
+ * guaranteed to be compatible with the matching engine.
7
+ */
8
+ export const SHIKI_VERSION = "4.4.3";
9
+
10
+ /**
11
+ * Version of this package, used to resolve the prebuilt Shiki engine chunk from a CDN.
12
+ */
13
+ export const UI_VERSION = "0.63.0";
14
+
15
+ /**
16
+ * Available syntax highlighting languages, sorted by display name.
17
+ * @type {{ id: string, name: string, aliases?: string[] }[]}
18
+ */
19
+ export const LANGUAGES = [{"id":"bsl","name":"1C (Enterprise)","aliases":["1c"]},{"id":"sdbl","name":"1C (Query)","aliases":["1c-query"]},{"id":"abap","name":"ABAP"},{"id":"actionscript-3","name":"ActionScript","aliases":["actionscript","as3"]},{"id":"ada","name":"Ada"},{"id":"angular-html","name":"Angular HTML"},{"id":"angular-ts","name":"Angular TypeScript"},{"id":"apache","name":"Apache Conf"},{"id":"apex","name":"Apex"},{"id":"apl","name":"APL"},{"id":"applescript","name":"AppleScript"},{"id":"ara","name":"Ara"},{"id":"asciidoc","name":"AsciiDoc","aliases":["adoc"]},{"id":"razor","name":"ASP.NET Razor"},{"id":"asm","name":"Assembly"},{"id":"astro","name":"Astro"},{"id":"ahk","name":"AutoHotkey","aliases":["ahk1"]},{"id":"ahk2","name":"AutoHotkey2"},{"id":"awk","name":"AWK"},{"id":"ballerina","name":"Ballerina"},{"id":"bat","name":"Batch File","aliases":["batch","cmd"]},{"id":"beancount","name":"Beancount"},{"id":"berry","name":"Berry","aliases":["be"]},{"id":"bibtex","name":"BibTeX"},{"id":"bicep","name":"Bicep"},{"id":"bird2","name":"BIRD2 Configuration","aliases":["bird"]},{"id":"blade","name":"Blade"},{"id":"c","name":"C"},{"id":"csharp","name":"C#","aliases":["c#","cs"]},{"id":"cpp","name":"C++","aliases":["c++"]},{"id":"c3","name":"C3"},{"id":"cadence","name":"Cadence","aliases":["cdc"]},{"id":"cairo","name":"Cairo"},{"id":"chapel","name":"Chapel","aliases":["chpl"]},{"id":"clarity","name":"Clarity"},{"id":"clojure","name":"Clojure","aliases":["clj"]},{"id":"soy","name":"Closure Templates","aliases":["closure-templates"]},{"id":"cmake","name":"CMake"},{"id":"cobol","name":"COBOL"},{"id":"codeowners","name":"CODEOWNERS"},{"id":"codeql","name":"CodeQL","aliases":["ql"]},{"id":"coffee","name":"CoffeeScript","aliases":["coffeescript"]},{"id":"common-lisp","name":"Common Lisp","aliases":["lisp"]},{"id":"crystal","name":"Crystal"},{"id":"css","name":"CSS"},{"id":"csv","name":"CSV"},{"id":"cue","name":"CUE"},{"id":"cypher","name":"Cypher","aliases":["cql"]},{"id":"d","name":"D"},{"id":"dart","name":"Dart"},{"id":"dax","name":"DAX"},{"id":"desktop","name":"Desktop"},{"id":"diff","name":"Diff"},{"id":"docker","name":"Dockerfile","aliases":["dockerfile"]},{"id":"dotenv","name":"dotEnv"},{"id":"dream-maker","name":"Dream Maker"},{"id":"edge","name":"Edge"},{"id":"elixir","name":"Elixir"},{"id":"elm","name":"Elm"},{"id":"emacs-lisp","name":"Emacs Lisp","aliases":["elisp"]},{"id":"erb","name":"ERB"},{"id":"erlang","name":"Erlang","aliases":["erl"]},{"id":"fsharp","name":"F#","aliases":["f#","fs"]},{"id":"fennel","name":"Fennel"},{"id":"fish","name":"Fish"},{"id":"fluent","name":"Fluent","aliases":["ftl"]},{"id":"fortran-fixed-form","name":"Fortran (Fixed Form)","aliases":["f","for","f77"]},{"id":"fortran-free-form","name":"Fortran (Free Form)","aliases":["f90","f95","f03","f08","f18"]},{"id":"gdresource","name":"GDResource","aliases":["tscn","tres"]},{"id":"gdscript","name":"GDScript","aliases":["gd"]},{"id":"gdshader","name":"GDShader"},{"id":"genie","name":"Genie"},{"id":"po","name":"Gettext PO","aliases":["pot","potx"]},{"id":"gherkin","name":"Gherkin"},{"id":"git-commit","name":"Git Commit Message"},{"id":"git-rebase","name":"Git Rebase Message"},{"id":"gleam","name":"Gleam"},{"id":"glimmer-js","name":"Glimmer JS","aliases":["gjs"]},{"id":"glimmer-ts","name":"Glimmer TS","aliases":["gts"]},{"id":"glsl","name":"GLSL"},{"id":"gn","name":"GN"},{"id":"smalltalk","name":"GNU Smalltalk"},{"id":"gnuplot","name":"Gnuplot"},{"id":"go","name":"Go"},{"id":"graphql","name":"GraphQL","aliases":["gql"]},{"id":"groovy","name":"Groovy"},{"id":"hack","name":"Hack"},{"id":"handlebars","name":"Handlebars","aliases":["hbs"]},{"id":"hcl","name":"HashiCorp HCL"},{"id":"haskell","name":"Haskell","aliases":["hs"]},{"id":"haxe","name":"Haxe"},{"id":"hjson","name":"Hjson"},{"id":"hlsl","name":"HLSL"},{"id":"html","name":"HTML"},{"id":"html-derivative","name":"HTML (Derivative)"},{"id":"http","name":"HTTP"},{"id":"hurl","name":"Hurl"},{"id":"hxml","name":"HXML"},{"id":"hy","name":"Hy"},{"id":"imba","name":"Imba"},{"id":"ini","name":"INI","aliases":["properties"]},{"id":"java","name":"Java"},{"id":"javascript","name":"JavaScript","aliases":["js","cjs","mjs"]},{"id":"jinja","name":"Jinja"},{"id":"jison","name":"Jison"},{"id":"json","name":"JSON"},{"id":"jsonl","name":"JSON Lines"},{"id":"jsonc","name":"JSON with Comments"},{"id":"json5","name":"JSON5"},{"id":"jsonnet","name":"Jsonnet"},{"id":"jssm","name":"JSSM","aliases":["fsl"]},{"id":"jsx","name":"JSX"},{"id":"julia","name":"Julia","aliases":["jl"]},{"id":"just","name":"Just","aliases":["justfile"]},{"id":"kdl","name":"KDL"},{"id":"kotlin","name":"Kotlin","aliases":["kt","kts"]},{"id":"kusto","name":"Kusto","aliases":["kql"]},{"id":"latex","name":"LaTeX"},{"id":"lean","name":"Lean 4","aliases":["lean4"]},{"id":"less","name":"Less"},{"id":"liquid","name":"Liquid"},{"id":"llvm","name":"LLVM IR"},{"id":"log","name":"Log file"},{"id":"logo","name":"Logo"},{"id":"lua","name":"Lua"},{"id":"luau","name":"Luau"},{"id":"make","name":"Makefile","aliases":["makefile"]},{"id":"markdown","name":"Markdown","aliases":["md"]},{"id":"marko","name":"Marko"},{"id":"matlab","name":"MATLAB"},{"id":"mdc","name":"MDC"},{"id":"mdx","name":"MDX"},{"id":"mermaid","name":"Mermaid","aliases":["mmd"]},{"id":"mipsasm","name":"MIPS Assembly","aliases":["mips"]},{"id":"mojo","name":"Mojo"},{"id":"moonbit","name":"MoonBit","aliases":["mbt","mbti"]},{"id":"move","name":"Move"},{"id":"narrat","name":"Narrat Language","aliases":["nar"]},{"id":"nextflow","name":"Nextflow","aliases":["nf"]},{"id":"nextflow-groovy","name":"Nextflow Groovy"},{"id":"nginx","name":"Nginx"},{"id":"nim","name":"Nim"},{"id":"nix","name":"Nix"},{"id":"nsis","name":"NSIS"},{"id":"nushell","name":"nushell","aliases":["nu"]},{"id":"objective-c","name":"Objective-C","aliases":["objc"]},{"id":"objective-cpp","name":"Objective-C++"},{"id":"ocaml","name":"OCaml"},{"id":"odin","name":"Odin"},{"id":"openscad","name":"OpenSCAD","aliases":["scad"]},{"id":"org","name":"Org Markup"},{"id":"pascal","name":"Pascal"},{"id":"perl","name":"Perl"},{"id":"php","name":"PHP"},{"id":"pkl","name":"Pkl"},{"id":"plsql","name":"PL/SQL"},{"id":"polar","name":"Polar"},{"id":"postcss","name":"PostCSS"},{"id":"powerquery","name":"PowerQuery"},{"id":"powershell","name":"PowerShell","aliases":["ps","ps1","pwsh"]},{"id":"prisma","name":"Prisma"},{"id":"prolog","name":"Prolog"},{"id":"proto","name":"Protocol Buffer 3","aliases":["protobuf"]},{"id":"pug","name":"Pug","aliases":["jade"]},{"id":"puppet","name":"Puppet"},{"id":"purescript","name":"PureScript"},{"id":"python","name":"Python","aliases":["py"]},{"id":"qml","name":"QML"},{"id":"qmldir","name":"QML Directory"},{"id":"qss","name":"Qt Style Sheets"},{"id":"r","name":"R"},{"id":"racket","name":"Racket"},{"id":"raku","name":"Raku","aliases":["perl6"]},{"id":"rbs","name":"RBS","aliases":["ruby-signature"]},{"id":"regexp","name":"RegExp","aliases":["regex"]},{"id":"rel","name":"Rel"},{"id":"rst","name":"reStructuredText"},{"id":"riscv","name":"RISC-V"},{"id":"coq","name":"Rocq"},{"id":"ron","name":"RON"},{"id":"rosmsg","name":"ROS Interface"},{"id":"ruby","name":"Ruby","aliases":["rb"]},{"id":"haml","name":"Ruby Haml"},{"id":"rust","name":"Rust","aliases":["rs"]},{"id":"sas","name":"SAS"},{"id":"sass","name":"Sass"},{"id":"scala","name":"Scala"},{"id":"scheme","name":"Scheme"},{"id":"scss","name":"SCSS"},{"id":"shaderlab","name":"ShaderLab","aliases":["shader"]},{"id":"shellscript","name":"Shell","aliases":["bash","sh","shell","zsh"]},{"id":"shellsession","name":"Shell Session","aliases":["console"]},{"id":"smithy","name":"Smithy"},{"id":"solidity","name":"Solidity"},{"id":"sparql","name":"SPARQL"},{"id":"splunk","name":"Splunk Query Language","aliases":["spl"]},{"id":"sql","name":"SQL"},{"id":"ssh-config","name":"SSH Config"},{"id":"stata","name":"Stata"},{"id":"stylus","name":"Stylus","aliases":["styl"]},{"id":"surrealql","name":"SurrealQL","aliases":["surql"]},{"id":"svelte","name":"Svelte"},{"id":"swift","name":"Swift"},{"id":"systemd","name":"Systemd Units"},{"id":"system-verilog","name":"SystemVerilog"},{"id":"talonscript","name":"TalonScript","aliases":["talon"]},{"id":"tasl","name":"Tasl"},{"id":"tcl","name":"Tcl"},{"id":"templ","name":"Templ"},{"id":"terraform","name":"Terraform","aliases":["tf","tfvars"]},{"id":"tex","name":"TeX"},{"id":"toml","name":"TOML"},{"id":"tsv","name":"TSV"},{"id":"tsx","name":"TSX"},{"id":"turtle","name":"Turtle"},{"id":"twig","name":"Twig"},{"id":"typescript","name":"TypeScript","aliases":["ts","cts","mts"]},{"id":"ts-tags","name":"TypeScript with Tags","aliases":["lit"]},{"id":"typespec","name":"TypeSpec","aliases":["tsp"]},{"id":"typst","name":"Typst","aliases":["typ"]},{"id":"v","name":"V"},{"id":"vala","name":"Vala"},{"id":"verilog","name":"Verilog"},{"id":"vhdl","name":"VHDL"},{"id":"viml","name":"Vim Script","aliases":["vim","vimscript"]},{"id":"vb","name":"Visual Basic"},{"id":"vue","name":"Vue"},{"id":"vue-html","name":"Vue HTML"},{"id":"vue-vine","name":"Vue Vine"},{"id":"vyper","name":"Vyper","aliases":["vy"]},{"id":"wasm","name":"WebAssembly"},{"id":"wit","name":"WebAssembly Interface Types"},{"id":"wenyan","name":"Wenyan","aliases":["文言"]},{"id":"wgsl","name":"WGSL"},{"id":"wikitext","name":"Wikitext","aliases":["mediawiki","wiki"]},{"id":"reg","name":"Windows Registry Script"},{"id":"wolfram","name":"Wolfram","aliases":["wl"]},{"id":"xml","name":"XML"},{"id":"xsl","name":"XSL"},{"id":"yaml","name":"YAML","aliases":["yml"]},{"id":"zenscript","name":"ZenScript"},{"id":"zig","name":"Zig"}];
20
+
21
+ /**
22
+ * Available syntax highlighting themes.
23
+ * @type {{ id: string, displayName: string, type: string }[]}
24
+ */
25
+ export const THEMES = [{"id":"andromeeda","displayName":"Andromeeda","type":"dark"},{"id":"aurora-x","displayName":"Aurora X","type":"dark"},{"id":"ayu-dark","displayName":"Ayu Dark","type":"dark"},{"id":"ayu-light","displayName":"Ayu Light","type":"light"},{"id":"ayu-mirage","displayName":"Ayu Mirage","type":"dark"},{"id":"catppuccin-frappe","displayName":"Catppuccin Frappé","type":"dark"},{"id":"catppuccin-latte","displayName":"Catppuccin Latte","type":"light"},{"id":"catppuccin-macchiato","displayName":"Catppuccin Macchiato","type":"dark"},{"id":"catppuccin-mocha","displayName":"Catppuccin Mocha","type":"dark"},{"id":"dark-plus","displayName":"Dark Plus","type":"dark"},{"id":"dracula","displayName":"Dracula Theme","type":"dark"},{"id":"dracula-soft","displayName":"Dracula Theme Soft","type":"dark"},{"id":"everforest-dark","displayName":"Everforest Dark","type":"dark"},{"id":"everforest-light","displayName":"Everforest Light","type":"light"},{"id":"github-dark","displayName":"GitHub Dark","type":"dark"},{"id":"github-dark-default","displayName":"GitHub Dark Default","type":"dark"},{"id":"github-dark-dimmed","displayName":"GitHub Dark Dimmed","type":"dark"},{"id":"github-dark-high-contrast","displayName":"GitHub Dark High Contrast","type":"dark"},{"id":"github-light","displayName":"GitHub Light","type":"light"},{"id":"github-light-default","displayName":"GitHub Light Default","type":"light"},{"id":"github-light-high-contrast","displayName":"GitHub Light High Contrast","type":"light"},{"id":"gruvbox-dark-hard","displayName":"Gruvbox Dark Hard","type":"dark"},{"id":"gruvbox-dark-medium","displayName":"Gruvbox Dark Medium","type":"dark"},{"id":"gruvbox-dark-soft","displayName":"Gruvbox Dark Soft","type":"dark"},{"id":"gruvbox-light-hard","displayName":"Gruvbox Light Hard","type":"light"},{"id":"gruvbox-light-medium","displayName":"Gruvbox Light Medium","type":"light"},{"id":"gruvbox-light-soft","displayName":"Gruvbox Light Soft","type":"light"},{"id":"horizon","displayName":"Horizon","type":"dark"},{"id":"horizon-bright","displayName":"Horizon Bright","type":"light"},{"id":"houston","displayName":"Houston","type":"dark"},{"id":"kanagawa-dragon","displayName":"Kanagawa Dragon","type":"dark"},{"id":"kanagawa-lotus","displayName":"Kanagawa Lotus","type":"light"},{"id":"kanagawa-wave","displayName":"Kanagawa Wave","type":"dark"},{"id":"laserwave","displayName":"LaserWave","type":"dark"},{"id":"light-plus","displayName":"Light Plus","type":"light"},{"id":"material-theme","displayName":"Material Theme","type":"dark"},{"id":"material-theme-darker","displayName":"Material Theme Darker","type":"dark"},{"id":"material-theme-lighter","displayName":"Material Theme Lighter","type":"light"},{"id":"material-theme-ocean","displayName":"Material Theme Ocean","type":"dark"},{"id":"material-theme-palenight","displayName":"Material Theme Palenight","type":"dark"},{"id":"min-dark","displayName":"Min Dark","type":"dark"},{"id":"min-light","displayName":"Min Light","type":"light"},{"id":"monokai","displayName":"Monokai","type":"dark"},{"id":"night-owl","displayName":"Night Owl","type":"dark"},{"id":"night-owl-light","displayName":"Night Owl Light","type":"light"},{"id":"nord","displayName":"Nord","type":"dark"},{"id":"one-dark-pro","displayName":"One Dark Pro","type":"dark"},{"id":"one-light","displayName":"One Light","type":"light"},{"id":"plastic","displayName":"Plastic","type":"dark"},{"id":"poimandres","displayName":"Poimandres","type":"dark"},{"id":"red","displayName":"Red","type":"dark"},{"id":"rose-pine","displayName":"Rosé Pine","type":"dark"},{"id":"rose-pine-dawn","displayName":"Rosé Pine Dawn","type":"light"},{"id":"rose-pine-moon","displayName":"Rosé Pine Moon","type":"dark"},{"id":"slack-dark","displayName":"Slack Dark","type":"dark"},{"id":"slack-ochin","displayName":"Slack Ochin","type":"light"},{"id":"snazzy-light","displayName":"Snazzy Light","type":"light"},{"id":"solarized-dark","displayName":"Solarized Dark","type":"dark"},{"id":"solarized-light","displayName":"Solarized Light","type":"light"},{"id":"synthwave-84","displayName":"Synthwave '84","type":"dark"},{"id":"tokyo-night","displayName":"Tokyo Night","type":"dark"},{"id":"vesper","displayName":"Vesper","type":"dark"},{"id":"vitesse-black","displayName":"Vitesse Black","type":"dark"},{"id":"vitesse-dark","displayName":"Vitesse Dark","type":"dark"},{"id":"vitesse-light","displayName":"Vitesse Light","type":"light"}];
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Default tokenizer backed by Shiki.
3
+ *
4
+ * Falls back to unhighlighted text whenever highlighting is impossible — a plain language, or an
5
+ * engine that has not loaded yet or could not be fetched — so a code block always renders.
6
+ * @type {CodeTokenizer}
7
+ */
8
+ export const shikiTokenizer: CodeTokenizer;
9
+ export function registerCodeHighlighting(editor: LexicalEditor, tokenizer?: CodeTokenizer | undefined): () => void;
10
+ import type { CodeTokenizer } from '../../../typedefs';
11
+ import type { LexicalEditor } from 'lexical';