svelte-streamdown 2.6.0 → 3.0.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 +135 -26
- package/dist/Block.svelte +8 -4
- package/dist/Block.svelte.d.ts +1 -0
- package/dist/Elements/Code.svelte +6 -1
- package/dist/Elements/Element.svelte +15 -14
- package/dist/Elements/Mermaid.svelte +2 -0
- package/dist/Elements/MermaidDownload.svelte +196 -0
- package/dist/Elements/MermaidDownload.svelte.d.ts +6 -0
- package/dist/Elements/fallbacks/CodeFallback.svelte +33 -0
- package/dist/Elements/fallbacks/CodeFallback.svelte.d.ts +8 -0
- package/dist/Elements/fallbacks/MathFallback.svelte +35 -0
- package/dist/Elements/fallbacks/MathFallback.svelte.d.ts +8 -0
- package/dist/Elements/fallbacks/MermaidFallback.svelte +34 -0
- package/dist/Elements/fallbacks/MermaidFallback.svelte.d.ts +8 -0
- package/dist/Elements/fallbacks/index.d.ts +3 -0
- package/dist/Elements/fallbacks/index.js +3 -0
- package/dist/Streamdown.svelte +41 -10
- package/dist/context.svelte.d.ts +31 -6
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/utils/bundledLanguages.d.ts +8 -0
- package/dist/utils/bundledLanguages.js +143 -0
- package/dist/utils/darkMode.svelte.d.ts +3 -0
- package/dist/utils/darkMode.svelte.js +49 -0
- package/dist/utils/hightlighter.svelte.d.ts +17 -19
- package/dist/utils/hightlighter.svelte.js +141 -61
- package/dist/utils/parse-incomplete-markdown.d.ts +52 -0
- package/dist/utils/parse-incomplete-markdown.js +4 -4
- package/package.json +15 -1
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { useStreamdown } from '../../context.svelte.js';
|
|
3
|
+
import type { Tokens } from 'marked';
|
|
4
|
+
|
|
5
|
+
const {
|
|
6
|
+
token,
|
|
7
|
+
id
|
|
8
|
+
}: {
|
|
9
|
+
token: Tokens.Code;
|
|
10
|
+
id: string;
|
|
11
|
+
} = $props();
|
|
12
|
+
|
|
13
|
+
const streamdown = useStreamdown();
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<div data-streamdown-mermaid={id}>
|
|
17
|
+
<div
|
|
18
|
+
style={streamdown.isMounted ? streamdown.animationBlockStyle : ''}
|
|
19
|
+
class={streamdown.theme.code.base}
|
|
20
|
+
>
|
|
21
|
+
<div class={streamdown.theme.code.header}>
|
|
22
|
+
<span class={streamdown.theme.code.language}>mermaid</span>
|
|
23
|
+
</div>
|
|
24
|
+
<div style="height: fit-content; width: 100%;" class={streamdown.theme.code.container}>
|
|
25
|
+
<pre class={streamdown.theme.code.pre}><code
|
|
26
|
+
>{#each token.text.split('\n') as line}<span class={streamdown.theme.code.line}
|
|
27
|
+
><span style={streamdown.isMounted ? streamdown.animationTextStyle : ''}
|
|
28
|
+
>{line.trim().length > 0 ? line : '\u200B'}</span
|
|
29
|
+
></span
|
|
30
|
+
>{/each}</code
|
|
31
|
+
></pre>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Tokens } from 'marked';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
token: Tokens.Code;
|
|
4
|
+
id: string;
|
|
5
|
+
};
|
|
6
|
+
declare const MermaidFallback: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
7
|
+
type MermaidFallback = ReturnType<typeof MermaidFallback>;
|
|
8
|
+
export default MermaidFallback;
|
package/dist/Streamdown.svelte
CHANGED
|
@@ -8,13 +8,14 @@
|
|
|
8
8
|
content = '',
|
|
9
9
|
class: className,
|
|
10
10
|
shikiTheme,
|
|
11
|
-
|
|
11
|
+
shikiLanguages,
|
|
12
|
+
shikiThemes,
|
|
12
13
|
parseIncompleteMarkdown,
|
|
13
14
|
defaultOrigin,
|
|
14
15
|
allowedLinkPrefixes = ['*'],
|
|
15
16
|
allowedImagePrefixes = ['*'],
|
|
16
17
|
theme,
|
|
17
|
-
mermaidConfig,
|
|
18
|
+
mermaidConfig = {},
|
|
18
19
|
katexConfig,
|
|
19
20
|
translations,
|
|
20
21
|
baseTheme,
|
|
@@ -29,8 +30,22 @@
|
|
|
29
30
|
extensions,
|
|
30
31
|
sources,
|
|
31
32
|
inlineCitationsMode = 'carousel',
|
|
33
|
+
mdxComponents,
|
|
34
|
+
components,
|
|
35
|
+
static: isStatic,
|
|
32
36
|
...snippets
|
|
33
37
|
}: StreamdownProps<Source> = $props();
|
|
38
|
+
import { useDarkMode } from './utils/darkMode.svelte.js';
|
|
39
|
+
|
|
40
|
+
const darkMode = useDarkMode();
|
|
41
|
+
|
|
42
|
+
const shikiThemedTheme = $derived(
|
|
43
|
+
shikiThemes ? Object.keys(shikiThemes)[0] || 'github-light' : darkMode.current ? 'github-dark' : 'github-light'
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const mermaidThemedTheme = $derived(
|
|
47
|
+
mermaidConfig?.theme ? mermaidConfig.theme : darkMode.current ? 'dark' : 'default'
|
|
48
|
+
);
|
|
34
49
|
|
|
35
50
|
streamdown = new StreamdownContext({
|
|
36
51
|
get element() {
|
|
@@ -52,7 +67,7 @@
|
|
|
52
67
|
return allowedImagePrefixes;
|
|
53
68
|
},
|
|
54
69
|
get shikiTheme() {
|
|
55
|
-
return shikiTheme ||
|
|
70
|
+
return shikiTheme || shikiThemedTheme;
|
|
56
71
|
},
|
|
57
72
|
get snippets() {
|
|
58
73
|
return snippets;
|
|
@@ -66,7 +81,10 @@
|
|
|
66
81
|
return baseTheme;
|
|
67
82
|
},
|
|
68
83
|
get mermaidConfig() {
|
|
69
|
-
return
|
|
84
|
+
return {
|
|
85
|
+
theme: mermaidThemedTheme,
|
|
86
|
+
...mermaidConfig
|
|
87
|
+
};
|
|
70
88
|
},
|
|
71
89
|
get katexConfig() {
|
|
72
90
|
return katexConfig;
|
|
@@ -77,8 +95,11 @@
|
|
|
77
95
|
get translations() {
|
|
78
96
|
return translations;
|
|
79
97
|
},
|
|
80
|
-
get
|
|
81
|
-
return
|
|
98
|
+
get shikiLanguages() {
|
|
99
|
+
return shikiLanguages;
|
|
100
|
+
},
|
|
101
|
+
get shikiThemes() {
|
|
102
|
+
return shikiThemes;
|
|
82
103
|
},
|
|
83
104
|
get sources() {
|
|
84
105
|
return sources;
|
|
@@ -118,18 +139,28 @@
|
|
|
118
139
|
},
|
|
119
140
|
get icons() {
|
|
120
141
|
return icons;
|
|
142
|
+
},
|
|
143
|
+
get mdxComponents() {
|
|
144
|
+
return mdxComponents;
|
|
145
|
+
},
|
|
146
|
+
get components() {
|
|
147
|
+
return components;
|
|
121
148
|
}
|
|
122
149
|
});
|
|
123
150
|
|
|
124
151
|
const id = $props.id();
|
|
125
152
|
|
|
126
|
-
const blocks = $derived(parseBlocks(content, streamdown.extensions));
|
|
153
|
+
const blocks = $derived(isStatic ? content : parseBlocks(content, streamdown.extensions));
|
|
127
154
|
</script>
|
|
128
155
|
|
|
129
156
|
<div bind:this={element} class={className}>
|
|
130
|
-
{#
|
|
131
|
-
<Block {block} />
|
|
132
|
-
{
|
|
157
|
+
{#if isStatic}
|
|
158
|
+
<Block static={isStatic} block={content} />
|
|
159
|
+
{:else}
|
|
160
|
+
{#each blocks as block, index (`${id}-block-${index}`)}
|
|
161
|
+
<Block static={isStatic} {block} />
|
|
162
|
+
{/each}
|
|
163
|
+
{/if}
|
|
133
164
|
</div>
|
|
134
165
|
|
|
135
166
|
<style global>
|
package/dist/context.svelte.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import type { Snippet } from 'svelte';
|
|
1
|
+
import type { Component, Snippet } from 'svelte';
|
|
2
2
|
import type { DeepPartialTheme, Theme } from './theme.js';
|
|
3
3
|
import type { MermaidConfig } from 'mermaid';
|
|
4
4
|
import type { KatexOptions } from 'katex';
|
|
5
|
-
import type {
|
|
5
|
+
import type { LanguageInfo } from './utils/bundledLanguages.js';
|
|
6
|
+
import type { ThemeRegistration } from 'shiki';
|
|
6
7
|
export interface StreamdownContext extends Omit<StreamdownProps, keyof Snippets | 'class' | 'theme' | 'shikiTheme' | 'inlineCitationsMode'> {
|
|
7
8
|
snippets: Snippets;
|
|
8
|
-
shikiTheme:
|
|
9
|
+
shikiTheme: string;
|
|
9
10
|
theme: Theme;
|
|
10
11
|
controls: {
|
|
11
12
|
code: boolean;
|
|
@@ -30,7 +31,7 @@ export declare class StreamdownContext<Source extends Record<string, any> = Reco
|
|
|
30
31
|
});
|
|
31
32
|
}
|
|
32
33
|
export declare const useStreamdown: () => StreamdownContext<Record<string, any>>;
|
|
33
|
-
import type { AlertToken, MathToken, SubSupToken, TableToken, THead, TBody, TFoot, THeadRow, TRow, TD, TH, Extension, GenericToken, CitationToken } from './marked/index.js';
|
|
34
|
+
import type { AlertToken, MathToken, SubSupToken, TableToken, THead, TBody, TFoot, THeadRow, TRow, TD, TH, Extension, GenericToken, CitationToken, MdxToken } from './marked/index.js';
|
|
34
35
|
import type { Tokens } from 'marked';
|
|
35
36
|
import type { ListItemToken, ListToken } from './marked/marked-list.js';
|
|
36
37
|
import type { Footnote, FootnoteRef, FootnoteToken } from './marked/marked-footnotes.js';
|
|
@@ -73,6 +74,7 @@ type TokenSnippet = {
|
|
|
73
74
|
inlineCitationPopover: CitationToken;
|
|
74
75
|
inlineCitationContent: CitationToken;
|
|
75
76
|
inlineCitationPreview: CitationToken;
|
|
77
|
+
mdx: MdxToken;
|
|
76
78
|
};
|
|
77
79
|
type PredefinedElements = keyof TokenSnippet;
|
|
78
80
|
export type Snippets<Source extends Record<string, any> = Record<string, any>> = {
|
|
@@ -83,11 +85,14 @@ export type Snippets<Source extends Record<string, any> = Record<string, any>> =
|
|
|
83
85
|
} & (K extends 'inlineCitationContent' ? {
|
|
84
86
|
source: Source;
|
|
85
87
|
key: string;
|
|
88
|
+
} : K extends 'mdx' ? {
|
|
89
|
+
props: Record<string, number | string | boolean | null | undefined>;
|
|
86
90
|
} : {})
|
|
87
91
|
]>;
|
|
88
92
|
};
|
|
89
93
|
export type StreamdownProps<Source extends Record<string, any> = Record<string, any>> = {
|
|
90
94
|
streamdown?: StreamdownContext;
|
|
95
|
+
static?: boolean;
|
|
91
96
|
sources?: {
|
|
92
97
|
[key: string]: Source;
|
|
93
98
|
};
|
|
@@ -102,8 +107,9 @@ export type StreamdownProps<Source extends Record<string, any> = Record<string,
|
|
|
102
107
|
theme?: DeepPartialTheme;
|
|
103
108
|
baseTheme?: 'tailwind' | 'shadcn';
|
|
104
109
|
mergeTheme?: boolean;
|
|
105
|
-
shikiTheme?:
|
|
106
|
-
|
|
110
|
+
shikiTheme?: string;
|
|
111
|
+
shikiLanguages?: LanguageInfo[];
|
|
112
|
+
shikiThemes?: Record<string, ThemeRegistration>;
|
|
107
113
|
mermaidConfig?: MermaidConfig;
|
|
108
114
|
katexConfig?: KatexOptions | ((inline: boolean) => KatexOptions);
|
|
109
115
|
translations?: {
|
|
@@ -151,5 +157,24 @@ export type StreamdownProps<Source extends Record<string, any> = Record<string,
|
|
|
151
157
|
token: GenericToken;
|
|
152
158
|
children: Snippet;
|
|
153
159
|
}]>;
|
|
160
|
+
mdxComponents?: Record<string, Component<{
|
|
161
|
+
token: MdxToken;
|
|
162
|
+
children: Snippet;
|
|
163
|
+
props: any;
|
|
164
|
+
}, any, any>>;
|
|
165
|
+
components?: {
|
|
166
|
+
code?: Component<{
|
|
167
|
+
token: Tokens.Code;
|
|
168
|
+
id: string;
|
|
169
|
+
}, any, any>;
|
|
170
|
+
mermaid?: Component<{
|
|
171
|
+
token: Tokens.Code;
|
|
172
|
+
id: string;
|
|
173
|
+
}, any, any>;
|
|
174
|
+
math?: Component<{
|
|
175
|
+
token: MathToken;
|
|
176
|
+
id: string;
|
|
177
|
+
}, any, any>;
|
|
178
|
+
};
|
|
154
179
|
} & Partial<Snippets<Source>>;
|
|
155
180
|
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { default as Streamdown } from './Streamdown.svelte';
|
|
2
2
|
export { useStreamdown, type StreamdownProps } from './context.svelte.js';
|
|
3
3
|
export { theme, shadcnTheme, mergeTheme, type Theme } from './theme.js';
|
|
4
|
-
export { type Extension, type StreamdownToken } from './marked/index.js';
|
|
5
|
-
export {
|
|
4
|
+
export { type Extension, type StreamdownToken, lex, parseBlocks } from './marked/index.js';
|
|
5
|
+
export { parseIncompleteMarkdown, type Plugin, IncompleteMarkdownParser } from './utils/parse-incomplete-markdown.js';
|
|
6
|
+
export { bundledLanguagesInfo, createLanguageSet, type LanguageInfo } from './utils/bundledLanguages.js';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { default as Streamdown } from './Streamdown.svelte';
|
|
2
2
|
export { useStreamdown } from './context.svelte.js';
|
|
3
3
|
export { theme, shadcnTheme, mergeTheme } from './theme.js';
|
|
4
|
-
export {} from './marked/index.js';
|
|
5
4
|
export { lex, parseBlocks } from './marked/index.js';
|
|
5
|
+
export { parseIncompleteMarkdown, IncompleteMarkdownParser } from './utils/parse-incomplete-markdown.js';
|
|
6
|
+
export { bundledLanguagesInfo, createLanguageSet } from './utils/bundledLanguages.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type LanguageInfo = {
|
|
2
|
+
id: string;
|
|
3
|
+
aliases?: string[];
|
|
4
|
+
import: () => Promise<any>;
|
|
5
|
+
};
|
|
6
|
+
export declare const bundledLanguagesInfo: LanguageInfo[];
|
|
7
|
+
export declare function createLanguageSet(languages: LanguageInfo[]): Set<string>;
|
|
8
|
+
export declare const supportedLanguages: Set<string>;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
export const bundledLanguagesInfo = [
|
|
2
|
+
// Web essentials
|
|
3
|
+
{
|
|
4
|
+
id: 'javascript',
|
|
5
|
+
aliases: ['js'],
|
|
6
|
+
import: () => import('@shikijs/langs/javascript')
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
id: 'typescript',
|
|
10
|
+
aliases: ['ts'],
|
|
11
|
+
import: () => import('@shikijs/langs/typescript')
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
id: 'html',
|
|
15
|
+
import: () => import('@shikijs/langs/html')
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: 'css',
|
|
19
|
+
import: () => import('@shikijs/langs/css')
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
id: 'json',
|
|
23
|
+
import: () => import('@shikijs/langs/json')
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
id: 'jsx',
|
|
27
|
+
import: () => import('@shikijs/langs/jsx')
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: 'tsx',
|
|
31
|
+
import: () => import('@shikijs/langs/tsx')
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: 'markdown',
|
|
35
|
+
aliases: ['md'],
|
|
36
|
+
import: () => import('@shikijs/langs/markdown')
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: 'yaml',
|
|
40
|
+
aliases: ['yml'],
|
|
41
|
+
import: () => import('@shikijs/langs/yaml')
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: 'xml',
|
|
45
|
+
import: () => import('@shikijs/langs/xml')
|
|
46
|
+
},
|
|
47
|
+
// Backend languages
|
|
48
|
+
{
|
|
49
|
+
id: 'python',
|
|
50
|
+
aliases: ['py'],
|
|
51
|
+
import: () => import('@shikijs/langs/python')
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
id: 'java',
|
|
55
|
+
import: () => import('@shikijs/langs/java')
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: 'go',
|
|
59
|
+
import: () => import('@shikijs/langs/go')
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
id: 'rust',
|
|
63
|
+
aliases: ['rs'],
|
|
64
|
+
import: () => import('@shikijs/langs/rust')
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
id: 'ruby',
|
|
68
|
+
aliases: ['rb'],
|
|
69
|
+
import: () => import('@shikijs/langs/ruby')
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
id: 'php',
|
|
73
|
+
import: () => import('@shikijs/langs/php')
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: 'c',
|
|
77
|
+
import: () => import('@shikijs/langs/c')
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: 'cpp',
|
|
81
|
+
aliases: ['c++'],
|
|
82
|
+
import: () => import('@shikijs/langs/cpp')
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
id: 'csharp',
|
|
86
|
+
aliases: ['c#', 'cs'],
|
|
87
|
+
import: () => import('@shikijs/langs/csharp')
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
id: 'sql',
|
|
91
|
+
import: () => import('@shikijs/langs/sql')
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
id: 'swift',
|
|
95
|
+
import: () => import('@shikijs/langs/swift')
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
id: 'kotlin',
|
|
99
|
+
aliases: ['kt', 'kts'],
|
|
100
|
+
import: () => import('@shikijs/langs/kotlin')
|
|
101
|
+
},
|
|
102
|
+
// Config/Shell
|
|
103
|
+
{
|
|
104
|
+
id: 'shellscript',
|
|
105
|
+
aliases: ['bash', 'sh', 'shell', 'zsh'],
|
|
106
|
+
import: () => import('@shikijs/langs/shellscript')
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
id: 'docker',
|
|
110
|
+
aliases: ['dockerfile'],
|
|
111
|
+
import: () => import('@shikijs/langs/docker')
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
id: 'toml',
|
|
115
|
+
import: () => import('@shikijs/langs/toml')
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
id: 'graphql',
|
|
119
|
+
aliases: ['gql'],
|
|
120
|
+
import: () => import('@shikijs/langs/graphql')
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
id: 'svelte',
|
|
124
|
+
import: () => import('@shikijs/langs/svelte')
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
id: 'vue',
|
|
128
|
+
import: () => import('@shikijs/langs/vue')
|
|
129
|
+
}
|
|
130
|
+
];
|
|
131
|
+
// Helper function to create a Set of all language IDs and aliases from language info
|
|
132
|
+
export function createLanguageSet(languages) {
|
|
133
|
+
const set = new Set();
|
|
134
|
+
languages.forEach((lang) => {
|
|
135
|
+
set.add(lang.id);
|
|
136
|
+
if (lang.aliases) {
|
|
137
|
+
lang.aliases.forEach((alias) => set.add(alias));
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
return set;
|
|
141
|
+
}
|
|
142
|
+
// Create a Set of all supported language IDs and aliases for fast lookup (default set)
|
|
143
|
+
export const supportedLanguages = createLanguageSet(bundledLanguagesInfo);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { onMount } from 'svelte';
|
|
2
|
+
export const useDarkMode = () => {
|
|
3
|
+
let isDark = $state(false);
|
|
4
|
+
const checkTheme = () => {
|
|
5
|
+
const elements = [document.documentElement, document.body];
|
|
6
|
+
// First check for explicit light mode
|
|
7
|
+
for (const element of elements) {
|
|
8
|
+
if (element.classList.contains('light') ||
|
|
9
|
+
element.dataset.theme === 'light' ||
|
|
10
|
+
element.style.colorScheme === 'light') {
|
|
11
|
+
isDark = false;
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
// Then check for dark mode
|
|
16
|
+
for (const element of elements) {
|
|
17
|
+
if (element.classList.contains('dark') ||
|
|
18
|
+
element.dataset.theme === 'dark' ||
|
|
19
|
+
element.style.colorScheme === 'dark') {
|
|
20
|
+
isDark = true;
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// Default to light mode if no explicit theme is set
|
|
25
|
+
isDark = false;
|
|
26
|
+
};
|
|
27
|
+
onMount(() => {
|
|
28
|
+
// Initial check
|
|
29
|
+
checkTheme();
|
|
30
|
+
// Watch for class, attribute, and style changes on html and body
|
|
31
|
+
const observer = new MutationObserver(() => {
|
|
32
|
+
checkTheme();
|
|
33
|
+
});
|
|
34
|
+
const observerOptions = {
|
|
35
|
+
attributes: true,
|
|
36
|
+
attributeFilter: ['class', 'data-theme', 'style']
|
|
37
|
+
};
|
|
38
|
+
observer.observe(document.documentElement, observerOptions);
|
|
39
|
+
observer.observe(document.body, observerOptions);
|
|
40
|
+
return () => {
|
|
41
|
+
observer.disconnect();
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
return {
|
|
45
|
+
get current() {
|
|
46
|
+
return isDark;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
};
|
|
@@ -1,32 +1,30 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import type { ThemedToken, ThemeRegistration } from 'shiki';
|
|
2
|
+
import type { HighlighterCore } from 'shiki/core';
|
|
3
|
+
import { SvelteMap } from 'svelte/reactivity';
|
|
4
|
+
import { type LanguageInfo } from './bundledLanguages.js';
|
|
5
|
+
export type Highlighter = HighlighterCore;
|
|
5
6
|
declare class HighlighterManager {
|
|
6
|
-
loadedLanguages: SvelteMap<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
loadedLanguages: SvelteMap<string, boolean | Promise<void>>;
|
|
8
|
+
highlighter: any;
|
|
9
|
+
customLanguages: Set<string>;
|
|
10
|
+
languageLoaders: Map<string, () => Promise<any>>;
|
|
11
|
+
additionalThemes: Record<string, ThemeRegistration>;
|
|
12
|
+
constructor(languages: LanguageInfo[], additionalThemes?: Record<string, ThemeRegistration>, additionalLanguages?: LanguageInfo[]);
|
|
11
13
|
private loadHighlighter;
|
|
12
|
-
private
|
|
14
|
+
private isThemeAvailable;
|
|
13
15
|
private loadLanguage;
|
|
14
16
|
private isLanguageSupported;
|
|
15
|
-
isReady(theme:
|
|
16
|
-
/**
|
|
17
|
-
* Preloads themes by creating minimal highlighter instances.
|
|
18
|
-
* This reduces flickering when switching themes.
|
|
19
|
-
*/
|
|
20
|
-
preloadThemes(highlighter: Highlighter): Promise<void>;
|
|
17
|
+
isReady(theme: string, language: string | undefined): boolean;
|
|
21
18
|
/**
|
|
22
19
|
* Ensures the highlighter is ready for the given theme and language.
|
|
23
20
|
*/
|
|
24
|
-
load(theme:
|
|
21
|
+
load(theme: string, language: string | undefined): Promise<void>;
|
|
25
22
|
/**
|
|
26
23
|
* Highlights code synchronously. Must call isReady() first.
|
|
24
|
+
* Returns plaintext tokens for unsupported languages.
|
|
27
25
|
*/
|
|
28
|
-
highlightCode(code: string, language: string | undefined, theme:
|
|
29
|
-
static create(
|
|
26
|
+
highlightCode(code: string, language: string | undefined, theme: string): ThemedToken[][];
|
|
27
|
+
static create(languages?: LanguageInfo[], additionalThemes?: Record<string, ThemeRegistration>, additionalLanguages?: LanguageInfo[]): HighlighterManager;
|
|
30
28
|
}
|
|
31
29
|
export { HighlighterManager };
|
|
32
30
|
export declare const languageExtensionMap: Record<string, string>;
|