svelte-streamdown 2.2.2 → 2.2.4
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/dist/AnimatedBlock.svelte +1 -1
- package/dist/AnimatedText.svelte +1 -1
- package/dist/Block.svelte +1 -1
- package/dist/Elements/Alert.svelte +1 -1
- package/dist/Elements/Code.svelte +32 -29
- package/dist/Elements/Element.svelte +1 -1
- package/dist/Elements/FootnoteRef.svelte +1 -1
- package/dist/Elements/Image.svelte +1 -1
- package/dist/Elements/Link.svelte +1 -1
- package/dist/Elements/Math.svelte +1 -1
- package/dist/Elements/Mermaid.svelte +1 -1
- package/dist/Elements/Table.svelte +1 -1
- package/dist/Streamdown.svelte +1 -1
- package/dist/Streamdown.svelte.d.ts +4 -0
- package/dist/{streamdown.svelte.d.ts → context.svelte.d.ts} +2 -2
- package/dist/{streamdown.svelte.js → context.svelte.js} +8 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/marked/index.js +1 -1
- package/dist/marked/marked-footnotes.js +1 -1
- package/dist/theme.d.ts +3 -0
- package/dist/theme.js +4 -2
- package/dist/utils/hightlighter.svelte.d.ts +2 -2
- package/dist/utils/hightlighter.svelte.js +4 -13
- package/package.json +1 -1
package/dist/AnimatedText.svelte
CHANGED
package/dist/Block.svelte
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import Element from './Elements/Element.svelte';
|
|
4
4
|
import { lex, type StreamdownToken } from './marked/index.js';
|
|
5
5
|
import AnimatedText from './AnimatedText.svelte';
|
|
6
|
-
import { useStreamdown } from './
|
|
6
|
+
import { useStreamdown } from './context.svelte.js';
|
|
7
7
|
import AnimatedBlock from './AnimatedBlock.svelte';
|
|
8
8
|
|
|
9
9
|
let {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
/><path d="M12 17h.01" />`
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
import { useStreamdown } from '../
|
|
16
|
+
import { useStreamdown } from '../context.svelte.js';
|
|
17
17
|
import Slot from './Slot.svelte';
|
|
18
18
|
import type { AlertToken } from '../marked/index.js';
|
|
19
19
|
import type { Snippet } from 'svelte';
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { useStreamdown } from '../
|
|
2
|
+
import { useStreamdown } from '../context.svelte.js';
|
|
3
3
|
import { save } from '../utils/save.js';
|
|
4
4
|
import { useCopy } from '../utils/copy.svelte.js';
|
|
5
5
|
import { HighlighterManager, languageExtensionMap } from '../utils/hightlighter.svelte.js';
|
|
6
6
|
import type { Tokens } from 'marked';
|
|
7
|
+
import { type ThemedToken } from 'shiki';
|
|
7
8
|
|
|
8
9
|
const {
|
|
9
10
|
token
|
|
@@ -41,6 +42,8 @@
|
|
|
41
42
|
$effect(() => {
|
|
42
43
|
void highlighter.load(theme, language as any);
|
|
43
44
|
});
|
|
45
|
+
|
|
46
|
+
const isMounted = streamdown.isMounted;
|
|
44
47
|
</script>
|
|
45
48
|
|
|
46
49
|
<div class={streamdown.theme.code.base} data-language={language}>
|
|
@@ -65,37 +68,37 @@
|
|
|
65
68
|
{/if}
|
|
66
69
|
</div>
|
|
67
70
|
<div style="height: fit-content; width: 100%;" class={streamdown.theme.code.container}>
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
{
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
language as any,
|
|
76
|
-
theme,
|
|
77
|
-
streamdown.theme.code.pre
|
|
78
|
-
)}
|
|
79
|
-
{@html code}
|
|
80
|
-
{:else}
|
|
81
|
-
{@render Skeleton()}
|
|
82
|
-
{/if}
|
|
83
|
-
</div>
|
|
71
|
+
{#if highlighter.isReady(theme, language as any)}
|
|
72
|
+
{@const tokens = highlighter.highlightCode(codeContent, language as any, theme)}
|
|
73
|
+
<pre class={streamdown.theme.code.pre}><code>{@render Tokens(tokens)}</code></pre>
|
|
74
|
+
{:else}
|
|
75
|
+
<pre class={streamdown.theme.code.pre}><code>{@render Skeleton(token.text.split('\n'))}</code
|
|
76
|
+
></pre>
|
|
77
|
+
{/if}
|
|
84
78
|
</div>
|
|
85
79
|
</div>
|
|
86
80
|
|
|
87
|
-
{#snippet
|
|
88
|
-
{
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
>
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
81
|
+
{#snippet Tokens(tokens: ThemedToken[][])}
|
|
82
|
+
{#each tokens as line}
|
|
83
|
+
<span class={streamdown.theme.code.line}>
|
|
84
|
+
{#each line as token}
|
|
85
|
+
<span
|
|
86
|
+
style={isMounted ? streamdown.animationTextStyle : undefined}
|
|
87
|
+
style:color={token.color}
|
|
88
|
+
style:background-color={token.bgColor}
|
|
89
|
+
>
|
|
90
|
+
{token.content}
|
|
91
|
+
</span>
|
|
92
|
+
{/each}
|
|
93
|
+
</span>
|
|
94
|
+
{/each}
|
|
95
|
+
{/snippet}
|
|
96
|
+
{#snippet Skeleton(lines: string[])}
|
|
97
|
+
{#each lines as line}
|
|
98
|
+
<span class={streamdown.theme.code.line}>
|
|
99
|
+
{line.trim().length > 0 ? line : '\u200B'}
|
|
100
|
+
</span>
|
|
101
|
+
{/each}
|
|
99
102
|
{/snippet}
|
|
100
103
|
{#snippet copyIcon()}
|
|
101
104
|
<svg
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import Alert from './Alert.svelte';
|
|
9
9
|
import type { StreamdownToken } from '../marked/index.js';
|
|
10
10
|
import Slot from './Slot.svelte';
|
|
11
|
-
import { useStreamdown } from '../
|
|
11
|
+
import { useStreamdown } from '../context.svelte.js';
|
|
12
12
|
import FootnoteRef from './FootnoteRef.svelte';
|
|
13
13
|
let { token, children }: { token: StreamdownToken; children: Snippet } = $props();
|
|
14
14
|
const streamdown = useStreamdown();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { onMount, untrack } from 'svelte';
|
|
3
|
-
import { useStreamdown } from '../
|
|
3
|
+
import { useStreamdown } from '../context.svelte.js';
|
|
4
4
|
import type { MathToken } from '../marked/index.js';
|
|
5
5
|
import type { KatexOptions } from 'katex';
|
|
6
6
|
import 'katex/dist/katex.min.css';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { onMount } from 'svelte';
|
|
3
|
-
import { useStreamdown } from '../
|
|
3
|
+
import { useStreamdown } from '../context.svelte.js';
|
|
4
4
|
import type { Tokens } from 'marked';
|
|
5
5
|
import type { MermaidConfig } from 'mermaid';
|
|
6
6
|
import { on } from 'svelte/events';
|
package/dist/Streamdown.svelte
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import Block from './Block.svelte';
|
|
3
|
-
import { StreamdownContext, type StreamdownProps } from './
|
|
3
|
+
import { StreamdownContext, type StreamdownProps } from './context.svelte.js';
|
|
4
4
|
import { mergeTheme, shadcnTheme } from './theme.js';
|
|
5
5
|
import { parseBlocks } from './marked/index.js';
|
|
6
6
|
|
|
@@ -21,8 +21,8 @@ export declare class StreamdownContext {
|
|
|
21
21
|
footnotes: Map<string, Footnote>;
|
|
22
22
|
};
|
|
23
23
|
isMounted: boolean;
|
|
24
|
-
animationTextStyle: string;
|
|
25
|
-
animationBlockStyle: string;
|
|
24
|
+
animationTextStyle: string | undefined;
|
|
25
|
+
animationBlockStyle: string | undefined;
|
|
26
26
|
constructor(props: Omit<StreamdownProps, keyof Snippets | 'class'> & {
|
|
27
27
|
snippets: Snippets;
|
|
28
28
|
});
|
|
@@ -5,18 +5,22 @@ export class StreamdownContext {
|
|
|
5
5
|
footnotes: new Map()
|
|
6
6
|
};
|
|
7
7
|
isMounted = $state(false);
|
|
8
|
-
animationTextStyle = $derived(
|
|
8
|
+
animationTextStyle = $derived(this.animation.enabled
|
|
9
|
+
? `animation-name: sd-${this.animation.type};
|
|
9
10
|
animation-duration: ${this.animation.duration}ms;
|
|
10
11
|
animation-timing-function: ${this.animation.timingFunction};
|
|
11
12
|
animation-iteration-count: 1;
|
|
12
13
|
animation-fill-mode: forwards;
|
|
13
14
|
white-space: pre-wrap;
|
|
14
|
-
display: inline-block;`
|
|
15
|
-
|
|
15
|
+
display: inline-block;`
|
|
16
|
+
: undefined);
|
|
17
|
+
animationBlockStyle = $derived(this.animation.enabled
|
|
18
|
+
? `animation-name: sd-${this.animation.type};
|
|
16
19
|
animation-duration: ${this.animation.duration}ms;
|
|
17
20
|
animation-timing-function: ${this.animation.timingFunction};
|
|
18
21
|
animation-iteration-count: 1;
|
|
19
|
-
animation-fill-mode: forwards;`
|
|
22
|
+
animation-fill-mode: forwards;`
|
|
23
|
+
: undefined);
|
|
20
24
|
constructor(props) {
|
|
21
25
|
bind(this, props);
|
|
22
26
|
setContext('streamdown', this);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { default as Streamdown } from './Streamdown.svelte';
|
|
2
|
-
export { useStreamdown, type StreamdownProps } from './
|
|
2
|
+
export { useStreamdown, type StreamdownProps } from './context.svelte.js';
|
|
3
3
|
export { theme, shadcnTheme, mergeTheme, type Theme } from './theme.js';
|
|
4
4
|
export { lex, parseBlocks, type StreamdownToken } from './marked/index.js';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { default as Streamdown } from './Streamdown.svelte';
|
|
2
|
-
export { useStreamdown } from './
|
|
2
|
+
export { useStreamdown } from './context.svelte.js';
|
|
3
3
|
export { theme, shadcnTheme, mergeTheme } from './theme.js';
|
|
4
4
|
export { lex, parseBlocks } from './marked/index.js';
|
package/dist/marked/index.js
CHANGED
|
@@ -49,7 +49,7 @@ const parseExtensions = (...ext) => {
|
|
|
49
49
|
};
|
|
50
50
|
const blockLexer = new Lexer(parseExtensions(markedFootnote(), markedTable()));
|
|
51
51
|
export const lex = (markdown) => {
|
|
52
|
-
return new Lexer(parseExtensions(
|
|
52
|
+
return new Lexer(parseExtensions(markedTable(), markedFootnote(), markedAlert(), markedMath(), markedSubSup(), markedList()))
|
|
53
53
|
.lex(markdown)
|
|
54
54
|
.filter((token) => token.type !== 'space' && token.type !== 'footnote');
|
|
55
55
|
};
|
package/dist/theme.d.ts
CHANGED
|
@@ -44,6 +44,7 @@ export declare const theme: {
|
|
|
44
44
|
language: string;
|
|
45
45
|
skeleton: string;
|
|
46
46
|
pre: string;
|
|
47
|
+
line: string;
|
|
47
48
|
};
|
|
48
49
|
codespan: {
|
|
49
50
|
base: string;
|
|
@@ -171,6 +172,7 @@ export declare const shadcnTheme: {
|
|
|
171
172
|
language: string;
|
|
172
173
|
skeleton: string;
|
|
173
174
|
pre: string;
|
|
175
|
+
line: string;
|
|
174
176
|
};
|
|
175
177
|
codespan: {
|
|
176
178
|
base: string;
|
|
@@ -299,6 +301,7 @@ export declare const mergeTheme: (customTheme?: Partial<Theme>, baseTheme?: "tai
|
|
|
299
301
|
language: string;
|
|
300
302
|
skeleton: string;
|
|
301
303
|
pre: string;
|
|
304
|
+
line: string;
|
|
302
305
|
};
|
|
303
306
|
codespan: {
|
|
304
307
|
base: string;
|
package/dist/theme.js
CHANGED
|
@@ -44,7 +44,8 @@ export const theme = {
|
|
|
44
44
|
button: 'cursor-pointer size-6 p-1 text-gray-600 transition-all hover:text-gray-900 rounded hover:bg-gray-100',
|
|
45
45
|
language: 'ml-1 font-mono lowercase',
|
|
46
46
|
skeleton: 'rounded-md font-mono text-transparent bg-gray-200 scale-y-90 animate-pulse whitespace-nowrap inline-block',
|
|
47
|
-
pre: 'overflow-x-auto font-mono p-0 bg-gray-100/40'
|
|
47
|
+
pre: 'overflow-x-auto font-mono p-0 bg-gray-100/40',
|
|
48
|
+
line: 'block'
|
|
48
49
|
},
|
|
49
50
|
codespan: {
|
|
50
51
|
base: 'bg-gray-100 rounded px-1.5 py-0.5 font-mono text-[0.9em]'
|
|
@@ -171,7 +172,8 @@ export const shadcnTheme = {
|
|
|
171
172
|
button: 'cursor-pointer size-6 p-1 text-muted-foreground transition-all hover:text-foreground rounded hover:bg-muted',
|
|
172
173
|
language: 'ml-1 font-mono lowercase',
|
|
173
174
|
skeleton: 'rounded-md font-mono text-transparent bg-border/80 scale-y-90 w-fit animate-pulse whitespace-nowrap inline-block',
|
|
174
|
-
pre: 'overflow-x-auto font-mono p-0 bg-muted/40'
|
|
175
|
+
pre: 'overflow-x-auto font-mono p-0 bg-muted/40',
|
|
176
|
+
line: 'block '
|
|
175
177
|
},
|
|
176
178
|
codespan: {
|
|
177
179
|
base: 'bg-muted rounded px-1.5 py-0.5 font-mono text-foreground text-[0.9em]'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type BundledLanguage, type BundledTheme } from 'shiki';
|
|
1
|
+
import { type BundledLanguage, type BundledTheme, type ThemedToken } from 'shiki';
|
|
2
2
|
import { SvelteSet } from 'svelte/reactivity';
|
|
3
3
|
export declare const loadShiki: () => Promise<[any, import("shiki").CreateHighlighterFactory<BundledLanguage, BundledTheme>]>;
|
|
4
4
|
declare class HighlighterManager {
|
|
@@ -23,7 +23,7 @@ declare class HighlighterManager {
|
|
|
23
23
|
/**
|
|
24
24
|
* Highlights code synchronously. Must call isReady() first.
|
|
25
25
|
*/
|
|
26
|
-
highlightCode(code: string, language: BundledLanguage, theme: BundledTheme
|
|
26
|
+
highlightCode(code: string, language: BundledLanguage, theme: BundledTheme): ThemedToken[][];
|
|
27
27
|
static create(preloadedThemes: BundledTheme[]): HighlighterManager;
|
|
28
28
|
}
|
|
29
29
|
export { HighlighterManager };
|
|
@@ -4,10 +4,6 @@ import { SvelteMap, SvelteSet } from 'svelte/reactivity';
|
|
|
4
4
|
const isLanguageSupported = (language) => {
|
|
5
5
|
return Object.hasOwn(bundledLanguages, language);
|
|
6
6
|
};
|
|
7
|
-
// Remove background styles from <pre> tags (inline style)
|
|
8
|
-
const removePreBackground = (html) => {
|
|
9
|
-
return html.replace(/<pre[^>]*style="[^"]*background[^";]*;?[^"]*"[^>]*>/g, (match) => match.replace(/style="[^"]*background[^";]*;?[^"]*"/, ''));
|
|
10
|
-
};
|
|
11
7
|
export const loadShiki = async () => {
|
|
12
8
|
return Promise.all([
|
|
13
9
|
import('shiki/engine/javascript').then((mod) => mod.createJavaScriptRegexEngine({ forgiving: true })),
|
|
@@ -79,21 +75,16 @@ class HighlighterManager {
|
|
|
79
75
|
/**
|
|
80
76
|
* Highlights code synchronously. Must call isReady() first.
|
|
81
77
|
*/
|
|
82
|
-
highlightCode(code, language, theme
|
|
78
|
+
highlightCode(code, language, theme) {
|
|
83
79
|
const highlighter = this.highlighters.get(`${theme}:${language}`);
|
|
84
80
|
if (!highlighter) {
|
|
85
|
-
return
|
|
81
|
+
return [];
|
|
86
82
|
}
|
|
87
|
-
|
|
83
|
+
const tokens = highlighter.codeToTokensBase(code, {
|
|
88
84
|
lang: isLanguageSupported(language) ? language : 'text',
|
|
89
85
|
theme: theme
|
|
90
86
|
});
|
|
91
|
-
|
|
92
|
-
html = removePreBackground(html);
|
|
93
|
-
if (preClassName) {
|
|
94
|
-
html = html.replace(/<pre(\s|>)/, `<pre class="${preClassName}"$1`);
|
|
95
|
-
}
|
|
96
|
-
return html;
|
|
87
|
+
return tokens;
|
|
97
88
|
}
|
|
98
89
|
static create(preloadedThemes) {
|
|
99
90
|
if (typeof window !== 'undefined' && 'STREAMDOWN_HIGHLIGHTER' in window) {
|