svelte-streamdown 2.4.5 → 2.5.1

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 (46) hide show
  1. package/README.md +98 -4
  2. package/dist/Block.svelte +4 -4
  3. package/dist/Block.svelte.d.ts +0 -1
  4. package/dist/Elements/Alert.svelte +4 -1
  5. package/dist/Elements/Alert.svelte.d.ts +1 -0
  6. package/dist/Elements/Citation.svelte +260 -0
  7. package/dist/Elements/Citation.svelte.d.ts +7 -0
  8. package/dist/Elements/Code.svelte +13 -41
  9. package/dist/Elements/Code.svelte.d.ts +1 -0
  10. package/dist/Elements/Element.svelte +65 -33
  11. package/dist/Elements/FootnoteRef.svelte +41 -89
  12. package/dist/Elements/Image.svelte +5 -1
  13. package/dist/Elements/Image.svelte.d.ts +1 -0
  14. package/dist/Elements/Link.svelte +5 -1
  15. package/dist/Elements/Link.svelte.d.ts +1 -0
  16. package/dist/Elements/Math.svelte +10 -2
  17. package/dist/Elements/Math.svelte.d.ts +1 -0
  18. package/dist/Elements/Mermaid.svelte +87 -175
  19. package/dist/Elements/Mermaid.svelte.d.ts +1 -0
  20. package/dist/Elements/TableDownload.svelte +216 -0
  21. package/dist/Elements/TableDownload.svelte.d.ts +8 -0
  22. package/dist/Elements/icons.d.ts +9 -0
  23. package/dist/Elements/icons.js +175 -0
  24. package/dist/Elements/popover.svelte.d.ts +8 -0
  25. package/dist/Elements/popover.svelte.js +40 -0
  26. package/dist/Elements/stepperState.svelte.d.ts +35 -0
  27. package/dist/Elements/stepperState.svelte.js +98 -0
  28. package/dist/Streamdown.svelte +13 -4
  29. package/dist/Streamdown.svelte.d.ts +23 -2
  30. package/dist/context.svelte.d.ts +28 -11
  31. package/dist/context.svelte.js +14 -6
  32. package/dist/marked/index.d.ts +4 -2
  33. package/dist/marked/index.js +4 -2
  34. package/dist/marked/marked-align.d.ts +10 -0
  35. package/dist/marked/marked-align.js +36 -0
  36. package/dist/marked/marked-citations.d.ts +8 -0
  37. package/dist/marked/marked-citations.js +49 -0
  38. package/dist/marked/marked-table.js +36 -13
  39. package/dist/theme.d.ts +66 -21
  40. package/dist/theme.js +47 -17
  41. package/dist/utils/get.d.ts +1 -0
  42. package/dist/utils/get.js +25 -0
  43. package/dist/utils/panzoom.svelte.d.ts +1 -2
  44. package/dist/utils/panzoom.svelte.js +87 -43
  45. package/dist/utils/parse-incomplete-markdown.js +70 -1
  46. package/package.json +1 -1
package/README.md CHANGED
@@ -62,6 +62,7 @@ Full support for
62
62
  - Escaping currency symbols ($140)
63
63
  - Complex tables
64
64
  - Footnotes [^1]
65
+ - Inline citations [ref] [ref2]
65
66
 
66
67
  [^1]:
67
68
  Reference render in a popover by default.
@@ -133,11 +134,11 @@ pie title Project Time Allocation
133
134
 
134
135
  | H1 | H2 | H3 |
135
136
  | ------------------------- | --- | --- |
136
- | This cell spans 3 columns | | |
137
+ | This cell spans 3 columns |||
137
138
 
138
139
  | Header 1 | Header 2 | Header 3 |
139
140
  | ------------------------- | -------- | -------- |
140
- | This cell spans 2 columns | | Normal |
141
+ | This cell spans 2 columns || Normal |
141
142
  | Normal | Normal | Normal |
142
143
 
143
144
  #### Rowspan
@@ -153,7 +154,7 @@ pie title Project Time Allocation
153
154
  | --------------- | -------- |
154
155
  | Cell B | Cell A |
155
156
  | --------------- | -------- |
156
- | Footer | |
157
+ | Footer ||
157
158
 
158
159
  #### Column alignment
159
160
 
@@ -238,6 +239,98 @@ III. Third item
238
239
  : Topic 3 : Description 3
239
240
  : Topic 3 : Description 3
240
241
 
242
+ ### Citation Support
243
+
244
+ Streamdown supports inline citations that allow you to reference external sources and display them in interactive popovers. Citations work out-of-the-box with a simple object structure and support nested references like this `[cloudflare.website, vercel]` will render into [cloudflare.website, vercel]
245
+
246
+ To enable inline citations, pass a `sources` object as a prop to the `Streamdown` component.
247
+
248
+ #### Basic Usage
249
+
250
+ ```svelte
251
+ <script>
252
+ import { Streamdown } from 'svelte-streamdown';
253
+
254
+ let content = `According to [smith2023], AI is advancing rapidly. See also [nested.subsection] for related work.`;
255
+
256
+ let sources = {
257
+ "smith2023": {
258
+ title: "AI Research Paper",
259
+ url: "https://example.com/paper",
260
+ content: "Detailed content of the citation..."
261
+ },
262
+ "nested": {
263
+ "subsection": {
264
+ title: "Nested Citation",
265
+ url: "https://example.com/nested"
266
+ }
267
+ }
268
+ };
269
+ </script>
270
+
271
+ <Streamdown {content} {sources} />
272
+ ```
273
+
274
+ #### Default Citation Structure
275
+
276
+ Citations work with objects containing these properties:
277
+
278
+ - `title (or name or author)`: Display title for the citation
279
+ - `url (or href, url, link or source)`: Link to the source
280
+ - `content (or text, summary or excerpt)`: Rich content to display in carousel mode
281
+
282
+
283
+ #### Display Modes
284
+
285
+ Streamdown offers two ways to display citations:
286
+
287
+ - **List View**: Shows all citations in a compact list format
288
+ - **Carousel View** (default): Step-through navigation for multiple citations with full content display
289
+
290
+ You can control the display mode using the `inlineCitationsMode` prop:
291
+
292
+ ```svelte
293
+ <!-- List view -->
294
+ <Streamdown {content} {sources} inlineCitationsMode="list" />
295
+
296
+ <!-- Carousel view (default) -->
297
+ <Streamdown {content} {sources} inlineCitationsMode="carousel" />
298
+ ```
299
+
300
+ #### Citation Popovers
301
+
302
+ Citations appear as clickable buttons that open popovers when clicked. The popover shows:
303
+ - Source title and URL (when available)
304
+ - Favicon from the source domain
305
+ - Rich content (in carousel mode)
306
+ - Navigation controls (in carousel mode for multiple citations)
307
+
308
+ #### Custom Citation Rendering
309
+
310
+ If your citation data structure doesn't match the default format, you can customize how citations are rendered using `inlineCitationPreview`, `inlineCitationContent` or `inlineCitationPopover` snippets:
311
+
312
+ ```svelte
313
+ <Streamdown {content} {sources}>
314
+ {#snippet inlineCitationPreview({ token })}
315
+ <!-- Customize the clickable citation button -->
316
+ {token.keys[0]}
317
+ {/snippet}
318
+
319
+ {#snippet inlineCitationContent({ source, key, token })}
320
+ <!-- Customize content displayed in popover -->
321
+ <div class="custom-content">
322
+ <h4>{source.customTitle || key}</h4>
323
+ <p>{source.customDescription}</p>
324
+ </div>
325
+ {/snippet}
326
+ </Streamdown>
327
+ ```
328
+
329
+ These snippets allow you to:
330
+ - **`inlineCitationPreview`**: Customize the content of the clickable button that appears in the text
331
+ - **`inlineCitationContent`**: Customize how individual citation content is displayed within popovers
332
+ - **`inlineCitationPopover`**: Completely customize the list of citations
333
+
241
334
  ## 🔄 Differences from Original React Version
242
335
 
243
336
  This Svelte port maintains feature parity with the original [Streamdown](https://streamdown.ai/) while adapting to Svelte's patterns:
@@ -369,6 +462,7 @@ This heading will use a custom component!`;
369
462
  | Prop | Type | Default | Description |
370
463
  | -------------------------- | -------------------------------------------------------------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
371
464
  | `content` | `string` | - | **Required.** The markdown content to render |
465
+ | `sources` | `Record<string, any>` | - | Citation data object for inline citations |
372
466
  | `class` | `string` | - | CSS class names for the wrapper element |
373
467
  | `parseIncompleteMarkdown` | `boolean` | `true` | Parse and fix incomplete markdown syntax |
374
468
  | `defaultOrigin` | `string` | - | Default origin for relative URLs |
@@ -405,7 +499,7 @@ This heading will use a custom component!`;
405
499
 
406
500
  **Tables**: `table`, `thead`, `tbody`, `tr`, `th`, `td`, `tfoot`
407
501
 
408
- **Special Content**: `blockquote`, `hr`, `alert`, `mermaid`, `math`, `footnoteRef`
502
+ **Special Content**: `blockquote`, `hr`, `alert`, `mermaid`, `math`, `footnoteRef`, `inlineCitation`
409
503
 
410
504
  **Note**: The above elements are **supported by Streamdown** and should be customized using individual props or the theme system.
411
505
 
package/dist/Block.svelte CHANGED
@@ -4,17 +4,17 @@
4
4
  import { lex, type StreamdownToken } from './marked/index.js';
5
5
  import AnimatedText from './AnimatedText.svelte';
6
6
  import { useStreamdown } from './context.svelte.js';
7
+ import { getContext } from 'svelte';
7
8
 
8
9
  let {
9
- block,
10
- insideFootnote = false
10
+ block
11
11
  }: {
12
12
  block: string;
13
- insideFootnote?: boolean;
14
13
  } = $props();
15
14
 
16
15
  const streamdown = useStreamdown();
17
16
  const tokens = $derived(lex(parseIncompleteMarkdown(block.trim()), streamdown.extensions));
17
+ const insidePopover = getContext('POPOVER');
18
18
  </script>
19
19
 
20
20
  {#snippet renderChildren(tokens: StreamdownToken[])}
@@ -24,7 +24,7 @@
24
24
  {@const isTextOnlyNode = children.length === 0}
25
25
  <Element {token}>
26
26
  {#if isTextOnlyNode}
27
- {#if streamdown.animation.enabled && !insideFootnote}
27
+ {#if streamdown.animation.enabled && !insidePopover}
28
28
  <AnimatedText text={'text' in token ? token.text : ''} />
29
29
  {:else}
30
30
  {'text' in token ? token.text : ''}
@@ -1,6 +1,5 @@
1
1
  type $$ComponentProps = {
2
2
  block: string;
3
- insideFootnote?: boolean;
4
3
  };
5
4
  declare const Block: import("svelte").Component<$$ComponentProps, {}, "">;
6
5
  type Block = ReturnType<typeof Block>;
@@ -22,8 +22,10 @@
22
22
 
23
23
  const {
24
24
  children,
25
- token
25
+ token,
26
+ id
26
27
  }: {
28
+ id: string;
27
29
  children: Snippet;
28
30
  token: AlertToken;
29
31
  } = $props();
@@ -37,6 +39,7 @@
37
39
  render={streamdown.snippets.alert}
38
40
  >
39
41
  <div
42
+ data-streamdown-alert={id}
40
43
  style={streamdown.isMounted ? streamdown.animationBlockStyle : ''}
41
44
  class={`${streamdown.theme.alert.base} ${streamdown.theme.alert[token.variant]}`}
42
45
  >
@@ -1,6 +1,7 @@
1
1
  import type { AlertToken } from '../marked/index.js';
2
2
  import type { Snippet } from 'svelte';
3
3
  type $$ComponentProps = {
4
+ id: string;
4
5
  children: Snippet;
5
6
  token: AlertToken;
6
7
  };
@@ -0,0 +1,260 @@
1
+ <script lang="ts">
2
+ import { useStreamdown } from '../context.svelte.js';
3
+ import Slot from './Slot.svelte';
4
+ import { useClickOutside } from '../utils/useClickOutside.svelte.js';
5
+ import { scale } from 'svelte/transition';
6
+ import Block from '../Block.svelte';
7
+ import { useKeyDown } from '../utils/useKeyDown.svelte.js';
8
+ import type { CitationToken } from '../marked/marked-citations.js';
9
+ import { StepperState } from './stepperState.svelte.js';
10
+ import { Popover } from './popover.svelte.js';
11
+ import { get } from '../utils/get.js';
12
+ import { chevronLeft, chevronRight } from './icons.js';
13
+
14
+ const {
15
+ token
16
+ }: {
17
+ token: CitationToken;
18
+ } = $props();
19
+ const streamdown = useStreamdown();
20
+ const id = $props.id();
21
+ const popover = new Popover();
22
+
23
+ const citationWithSources = $derived.by(() => {
24
+ return token.keys.reduce((acc, key) => {
25
+ const source = get<Record<string, any>>(streamdown.sources, key);
26
+ const safeUrl = (url: string | null) => {
27
+ if (url == null) return null;
28
+ try {
29
+ return new URL(url);
30
+ } catch (error) {
31
+ return null;
32
+ }
33
+ };
34
+ if (source) {
35
+ const url = safeUrl(source.url ?? source.href ?? source.link ?? source.source);
36
+ acc.push({
37
+ key,
38
+ title: source.title ?? source.name ?? source.author ?? null,
39
+ url,
40
+ host: url ? url.host.replace('www.', '') : null,
41
+ favicon: url ? `https://www.google.com/s2/favicons?domain=${url.hostname}&sz=128` : null,
42
+ content: source.content ?? source.text ?? source.summary ?? source.excerpt ?? null,
43
+ source
44
+ });
45
+ }
46
+ return acc;
47
+ }, [] as CitationWithSource[]);
48
+ });
49
+ useKeyDown({
50
+ keys: ['Escape'],
51
+ get isActive() {
52
+ return popover.isOpen;
53
+ },
54
+ callback: () => {
55
+ popover.isOpen = false;
56
+ }
57
+ });
58
+ const clickOutside = useClickOutside({
59
+ get isActive() {
60
+ return popover.isOpen;
61
+ },
62
+ callback: () => {
63
+ popover.isOpen = false;
64
+ }
65
+ });
66
+
67
+ const stepper = new StepperState({
68
+ get items() {
69
+ return citationWithSources;
70
+ },
71
+ keyFramesOptions: { duration: 200, easing: 'ease-in-out', fill: 'forwards' }
72
+ });
73
+
74
+ type CitationWithSource = Record<string, any> & {
75
+ key: string;
76
+ title: string | null;
77
+ url: URL | null;
78
+ favicon: string | null;
79
+ content: string | null;
80
+ source: Record<string, any>;
81
+ };
82
+ </script>
83
+
84
+ {#if popover.isOpen}
85
+ <dialog
86
+ data-streamdown-citation-popover={id}
87
+ id={'citation-popover-' + id}
88
+ aria-modal="false"
89
+ transition:scale|global={{ start: 0.95, duration: 200 }}
90
+ {@attach clickOutside.attachment}
91
+ {@attach popover.popoverAttachment}
92
+ open
93
+ class={`${streamdown.theme.components.popover}`}
94
+ style:max-width="400px"
95
+ >
96
+ <Slot
97
+ props={{
98
+ token,
99
+ isOpen: popover.isOpen
100
+ }}
101
+ render={streamdown.snippets.inlineCitationPopover}
102
+ >
103
+ {#if streamdown.inlineCitationsMode === 'carousel'}
104
+ {@render carouselView()}
105
+ {:else}
106
+ {@render listView()}
107
+ {/if}
108
+ </Slot>
109
+ </dialog>
110
+ {/if}
111
+
112
+ {#snippet listView()}
113
+ <div class={streamdown.theme.inlineCitation.list.base}>
114
+ {#each citationWithSources as { favicon, key, source, title, url }}
115
+ <Slot render={streamdown.snippets.inlineCitationContent} props={{ source, key, token }}>
116
+ <a
117
+ class={streamdown.theme.inlineCitation.list.item}
118
+ href={url?.toString()}
119
+ target="_blank"
120
+ rel="noopener noreferrer"
121
+ >
122
+ {#if title}
123
+ <span class={streamdown.theme.inlineCitation.list.title}>{title}</span>
124
+ {/if}
125
+ {#if url}
126
+ <span class={streamdown.theme.inlineCitation.list.url}>
127
+ {#if favicon}
128
+ <img
129
+ src={favicon}
130
+ alt={title || url.host}
131
+ class={streamdown.theme.inlineCitation.list.favicon}
132
+ />
133
+ {/if}
134
+ {url.host}{url.pathname === '/' ? '' : url.pathname}
135
+ </span>
136
+ {/if}
137
+ </a>
138
+ </Slot>
139
+ {/each}
140
+ </div>
141
+ {/snippet}
142
+
143
+ {#snippet carouselView()}
144
+ {#if citationWithSources.length > 1}
145
+ <div class={streamdown.theme.inlineCitation.carousel.header}>
146
+ <div class={streamdown.theme.inlineCitation.carousel.stepCounter}>
147
+ {stepper.activeStep + 1}
148
+ / {citationWithSources.length}
149
+ </div>
150
+ <div class={streamdown.theme.inlineCitation.carousel.buttons}>
151
+ <button
152
+ disabled={!stepper.canGoPrevious}
153
+ class={streamdown.theme.components.button}
154
+ onclick={() => stepper.previous()}
155
+ >
156
+ {@render (streamdown.icons?.chevronLeft || chevronLeft)()}
157
+ </button>
158
+ <button
159
+ disabled={!stepper.canGoNext}
160
+ class={streamdown.theme.components.button}
161
+ onclick={() => stepper.next()}
162
+ >
163
+ {@render (streamdown.icons?.chevronRight || chevronRight)()}
164
+ </button>
165
+ </div>
166
+ </div>
167
+ {/if}
168
+ <div
169
+ use:stepper.scroller
170
+ style:height={Number.isFinite(stepper.stepHeights[stepper.activeStep])
171
+ ? `${stepper.stepHeights[stepper.activeStep]}px`
172
+ : 'auto'}
173
+ style:overflow="hidden"
174
+ style:position="relative"
175
+ style:transition-duration="200ms"
176
+ style:transition-timing-function="ease-in-out"
177
+ aria-label="Citations-${id}"
178
+ >
179
+ <div
180
+ bind:this={stepper.stepContainer}
181
+ style:display="grid"
182
+ style:transition-duration={`${200}ms`}
183
+ style:width="100%"
184
+ style:grid-template-columns="repeat({citationWithSources.length}, 100%)"
185
+ >
186
+ {#each citationWithSources as { favicon, key, source, title, url, content }, index}
187
+ <div
188
+ bind:offsetHeight={stepper.stepHeights[index]}
189
+ data-step={index}
190
+ tabindex={stepper.activeStep === index ? 0 : -1}
191
+ inert={stepper.activeStep !== index}
192
+ role="tabpanel"
193
+ style:height="fit-content"
194
+ style:width="100%"
195
+ style:flex-grow="1"
196
+ aria-label="Citation-${id}"
197
+ >
198
+ <Slot render={streamdown.snippets.inlineCitationContent} props={{ source, key, token }}>
199
+ {#if url || title}
200
+ <div class="mb-4">
201
+ {#if title}
202
+ <div class={streamdown.theme.inlineCitation.carousel.title}>
203
+ {title}
204
+ </div>
205
+ {/if}
206
+ {#if url}
207
+ <a
208
+ href={url.toString()}
209
+ target="_blank"
210
+ rel="noopener noreferrer"
211
+ class={streamdown.theme.inlineCitation.carousel.url}
212
+ >
213
+ {#if favicon}
214
+ <img
215
+ src={favicon}
216
+ alt={title || url.host}
217
+ class={streamdown.theme.inlineCitation.carousel.favicon}
218
+ />
219
+ {/if}
220
+ <!-- Skip search params -->
221
+ {url.host}{url.pathname === '/' ? '' : url.pathname}
222
+ </a>
223
+ {/if}
224
+ </div>
225
+ {/if}
226
+ {#if content}
227
+ <Block block={content} />
228
+ {/if}
229
+ </Slot>
230
+ </div>
231
+ {/each}
232
+ </div>
233
+ </div>
234
+ {/snippet}
235
+
236
+ {#if citationWithSources.length > 0}
237
+ <button
238
+ data-streamdown-citation-preview={id}
239
+ style={streamdown.animationBlockStyle}
240
+ bind:this={popover.reference}
241
+ class={streamdown.theme.inlineCitation.preview}
242
+ onclick={() => (popover.isOpen = !popover.isOpen)}
243
+ aria-expanded={popover.isOpen}
244
+ aria-haspopup="dialog"
245
+ aria-controls={'citation-popover-' + id}
246
+ {@attach clickOutside.attachment}
247
+ >
248
+ <Slot
249
+ render={streamdown.snippets.inlineCitationPreview}
250
+ props={{
251
+ token
252
+ }}
253
+ >
254
+ {citationWithSources[0]?.url?.host ??
255
+ citationWithSources[0]?.title ??
256
+ citationWithSources[0]?.key}
257
+ {citationWithSources.length > 1 ? ` +${citationWithSources.length - 1}` : ''}
258
+ </Slot>
259
+ </button>
260
+ {/if}
@@ -0,0 +1,7 @@
1
+ import type { CitationToken } from '../marked/marked-citations.js';
2
+ type $$ComponentProps = {
3
+ token: CitationToken;
4
+ };
5
+ declare const Citation: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type Citation = ReturnType<typeof Citation>;
7
+ export default Citation;
@@ -6,11 +6,14 @@
6
6
  import type { Tokens } from 'marked';
7
7
  import { type ThemedToken } from 'shiki';
8
8
  import { untrack } from 'svelte';
9
+ import { checkIcon, copyIcon, downloadIcon } from './icons.js';
9
10
 
10
11
  const {
11
- token
12
+ token,
13
+ id
12
14
  }: {
13
15
  token: Tokens.Code;
16
+ id: string;
14
17
  } = $props();
15
18
 
16
19
  const streamdown = useStreamdown();
@@ -48,6 +51,7 @@
48
51
  </script>
49
52
 
50
53
  <div
54
+ data-streamdown-code={id}
51
55
  style={streamdown.isMounted ? streamdown.animationBlockStyle : ''}
52
56
  class={streamdown.theme.code.base}
53
57
  >
@@ -56,16 +60,20 @@
56
60
  {#if streamdown.controls.code}
57
61
  <div class={streamdown.theme.code.buttons}>
58
62
  <button
59
- class={streamdown.theme.code.button}
63
+ class={streamdown.theme.components.button}
60
64
  onclick={downloadCode}
61
- title="Download file"
65
+ title="Download code"
62
66
  type="button"
63
67
  >
64
68
  {@render (streamdown.icons?.download || downloadIcon)()}
65
69
  </button>
66
70
 
67
- <button class={streamdown.theme.code.button} onclick={copy.copy} type="button">
68
- {@render (streamdown.icons?.copy || copyIcon)()}
71
+ <button class={streamdown.theme.components.button} onclick={copy.copy} type="button">
72
+ {#if copy.isCopied}
73
+ {@render (streamdown.icons?.check || checkIcon)()}
74
+ {:else}
75
+ {@render (streamdown.icons?.copy || copyIcon)()}
76
+ {/if}
69
77
  </button>
70
78
  </div>
71
79
  {/if}
@@ -107,39 +115,3 @@
107
115
  </span>
108
116
  {/each}
109
117
  {/snippet}
110
-
111
- {#snippet copyIcon()}
112
- <svg
113
- xmlns="http://www.w3.org/2000/svg"
114
- width="100%"
115
- height="100%"
116
- viewBox="0 0 24 24"
117
- fill="none"
118
- stroke="currentColor"
119
- stroke-width="2"
120
- stroke-linecap="round"
121
- stroke-linejoin="round"
122
- class="lucide lucide-clipboard-icon lucide-clipboard"
123
- ><rect width="8" height="4" x="8" y="2" rx="1" ry="1" /><path
124
- d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"
125
- /></svg
126
- >
127
- {/snippet}
128
-
129
- {#snippet downloadIcon()}
130
- <svg
131
- xmlns="http://www.w3.org/2000/svg"
132
- width="100%"
133
- height="100%"
134
- viewBox="0 0 24 24"
135
- fill="none"
136
- stroke="currentColor"
137
- stroke-width="2"
138
- stroke-linecap="round"
139
- stroke-linejoin="round"
140
- class="lucide lucide-download-icon lucide-download"
141
- ><path d="M12 15V3" /><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /><path
142
- d="m7 10 5 5 5-5"
143
- /></svg
144
- >
145
- {/snippet}
@@ -1,6 +1,7 @@
1
1
  import type { Tokens } from 'marked';
2
2
  type $$ComponentProps = {
3
3
  token: Tokens.Code;
4
+ id: string;
4
5
  };
5
6
  declare const Code: import("svelte").Component<$$ComponentProps, {}, "">;
6
7
  type Code = ReturnType<typeof Code>;