svelte-streamdown 2.3.2 → 2.3.3

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
@@ -231,6 +231,13 @@ III. Third item
231
231
  > [!IMPORTANT]
232
232
  > Native support for Github style Alert
233
233
 
234
+ ### Description List
235
+
236
+ : Topic 1 : Description 1
237
+ : **Topic 2** : *Description 2*
238
+ : Topic 3 : Description 3
239
+ : Topic 3 : Description 3
240
+
234
241
  ## 🔄 Differences from Original React Version
235
242
 
236
243
  This Svelte port maintains feature parity with the original [Streamdown](https://streamdown.ai/) while adapting to Svelte's patterns:
@@ -225,6 +225,30 @@
225
225
  <FootnoteRef {token} />
226
226
  {:else if token.type === 'footnote'}
227
227
  <!-- TODO Footnotes are rendered inside the FootnoteRef popover -->
228
+ {:else if token.type === 'descriptionList'}
229
+ <Slot props={{ children, token }} render={streamdown.snippets.descriptionList}>
230
+ <dl class={streamdown.theme.descriptionList.base}>
231
+ {@render children()}
232
+ </dl>
233
+ </Slot>
234
+ {:else if token.type === 'description'}
235
+ <Slot props={{ children, token }} render={streamdown.snippets.description}>
236
+ <div class={streamdown.theme.description.base}>
237
+ {@render children()}
238
+ </div>
239
+ </Slot>
240
+ {:else if token.type === 'descriptionTerm'}
241
+ <Slot props={{ children, token }} render={streamdown.snippets.descriptionTerm}>
242
+ <dt class={streamdown.theme.descriptionTerm.base}>
243
+ {@render children()}
244
+ </dt>
245
+ </Slot>
246
+ {:else if token.type === 'descriptionDetail'}
247
+ <Slot props={{ children, token }} render={streamdown.snippets.descriptionDetail}>
248
+ <dd class={streamdown.theme.descriptionDetail.base}>
249
+ {@render children()}
250
+ </dd>
251
+ </Slot>
228
252
  {:else if token.type === 'def'}
229
253
  <!-- TODO This does not seems to be tokenized for now -->
230
254
  {:else if token.type === 'escape'}
@@ -32,6 +32,7 @@ import type { AlertToken, MathToken, SubSupToken, TableToken, THead, TBody, TFoo
32
32
  import type { Tokens } from 'marked';
33
33
  import type { ListItemToken, ListToken } from './marked/marked-list.js';
34
34
  import type { Footnote, FootnoteRef, FootnoteToken } from './marked/marked-footnotes.js';
35
+ import type { DescriptionDetailToken, DescriptionListToken, DescriptionTermToken, DescriptionToken } from './marked/marked-dl.js';
35
36
  type TokenSnippet = {
36
37
  heading: Tokens.Heading;
37
38
  paragraph: Tokens.Paragraph;
@@ -62,6 +63,10 @@ type TokenSnippet = {
62
63
  footnotePopover: FootnoteToken;
63
64
  sup: SubSupToken;
64
65
  sub: SubSupToken;
66
+ descriptionList: DescriptionListToken;
67
+ description: DescriptionToken;
68
+ descriptionTerm: DescriptionTermToken;
69
+ descriptionDetail: DescriptionDetailToken;
65
70
  };
66
71
  type PredefinedElements = keyof TokenSnippet;
67
72
  export type Snippets = {
@@ -7,6 +7,7 @@ import { type ListItemToken, type ListToken } from './marked-list.js';
7
7
  import { type BrToken } from './marked-br.js';
8
8
  import { type HrToken } from './marked-hr.js';
9
9
  import { type TableToken, type THead, type TBody, type TFoot, type THeadRow, type TRow, type TH, type TD } from './marked-table.js';
10
+ import { type DescriptionDetailToken, type DescriptionListToken, type DescriptionTermToken, type DescriptionToken } from './marked-dl.js';
10
11
  export type GenericToken = {
11
12
  type: string;
12
13
  raw: string;
@@ -19,7 +20,7 @@ export type Extension = {
19
20
  start?: TokenizerStartFunction;
20
21
  applyInBlockParsing?: boolean;
21
22
  };
22
- export type StreamdownToken = Exclude<MarkedToken, Tokens.List | Tokens.ListItem> | ListToken | ListItemToken | MathToken | AlertToken | FootnoteToken | SubSupToken | BrToken | HrToken | TableToken | THead | TBody | TFoot | THeadRow | TRow | TH | TD;
23
+ export type StreamdownToken = Exclude<MarkedToken, Tokens.List | Tokens.ListItem> | ListToken | ListItemToken | MathToken | AlertToken | FootnoteToken | SubSupToken | BrToken | HrToken | TableToken | THead | TBody | TFoot | THeadRow | TRow | TH | TD | DescriptionListToken | DescriptionToken | DescriptionDetailToken | DescriptionTermToken;
23
24
  export type { TableToken, THead, TBody, TFoot, THeadRow, TRow, TH, TD } from './marked-table.js';
24
25
  export declare const lex: (markdown: string, extensions?: Extension[]) => StreamdownToken[];
25
26
  export declare const parseBlocks: (markdown: string, extensions?: Extension[]) => string[];
@@ -7,6 +7,7 @@ import { markedList } from './marked-list.js';
7
7
  import { markedBr } from './marked-br.js';
8
8
  import { markedHr } from './marked-hr.js';
9
9
  import { markedTable } from './marked-table.js';
10
+ import { markedDl, markedDt } from './marked-dl.js';
10
11
  const parseExtensions = (...extensions) => {
11
12
  const options = {
12
13
  gfm: true,
@@ -40,12 +41,12 @@ const parseExtensions = (...extensions) => {
40
41
  return options;
41
42
  };
42
43
  export const lex = (markdown, extensions = []) => {
43
- return new Lexer(parseExtensions(markedHr, markedTable, ...markedFootnote(), markedAlert, ...markedMath, markedSub, markedSup, markedList, markedBr, ...extensions))
44
+ return new Lexer(parseExtensions(markedHr, markedTable, ...markedFootnote(), markedAlert, ...markedMath, markedSub, markedSup, markedList, markedBr, markedDl, markedDt, ...extensions))
44
45
  .lex(markdown)
45
46
  .filter((token) => token.type !== 'space' && token.type !== 'footnote');
46
47
  };
47
48
  export const parseBlocks = (markdown, extensions = []) => {
48
- const blockLexer = new Lexer(parseExtensions(markedHr, ...markedFootnote(), markedTable, ...extensions.filter(({ level, applyInBlockParsing }) => level === 'block' && applyInBlockParsing)));
49
+ const blockLexer = new Lexer(parseExtensions(markedHr, ...markedFootnote(), markedDl, markedTable, ...extensions.filter(({ level, applyInBlockParsing }) => level === 'block' && applyInBlockParsing)));
49
50
  return blockLexer.blockTokens(markdown, []).reduce((acc, block) => {
50
51
  if (block.type === 'space' || block.type === 'footnote') {
51
52
  return acc;
@@ -0,0 +1,24 @@
1
+ import type { Extension, GenericToken } from './index.js';
2
+ export declare const markedDl: Extension;
3
+ export declare const markedDt: Extension;
4
+ export type DescriptionListToken = {
5
+ type: 'descriptionList';
6
+ raw: string;
7
+ text: string;
8
+ tokens: DescriptionToken[];
9
+ };
10
+ export type DescriptionToken = {
11
+ type: 'description';
12
+ raw: string;
13
+ tokens: [DescriptionTermToken, DescriptionDetailToken];
14
+ };
15
+ export type DescriptionTermToken = {
16
+ type: 'descriptionTerm';
17
+ raw: string;
18
+ tokens: GenericToken[];
19
+ };
20
+ export type DescriptionDetailToken = {
21
+ type: 'descriptionDetail';
22
+ raw: string;
23
+ tokens: GenericToken[];
24
+ };
@@ -0,0 +1,45 @@
1
+ export const markedDl = {
2
+ name: 'descriptionList',
3
+ level: 'block', // Is this a block-level or inline-level tokenizer?
4
+ tokenizer(src) {
5
+ const rule = /^(?:[ \t]*:[^:\n]+:[ \t]?[^\n]*(?:\n|$))+/;
6
+ const match = rule.exec(src);
7
+ if (match) {
8
+ const token = {
9
+ type: 'descriptionList',
10
+ raw: match[0],
11
+ text: match[0].trim(),
12
+ tokens: this.lexer.inlineTokens(match[0].trim()).filter((t) => t.type === 'description')
13
+ };
14
+ return token;
15
+ }
16
+ }
17
+ };
18
+ export const markedDt = {
19
+ name: 'description',
20
+ level: 'inline',
21
+ tokenizer(src) {
22
+ const rule = /^\s*:([^:\n]+):([^:\n]*)(?:\n|$)/;
23
+ const match = rule.exec(src);
24
+ if (match) {
25
+ const term = match[1].trim();
26
+ const detail = match[2].trim();
27
+ return {
28
+ type: 'description',
29
+ raw: match[0],
30
+ tokens: [
31
+ {
32
+ type: 'descriptionTerm',
33
+ raw: term,
34
+ tokens: this.lexer.inlineTokens(term)
35
+ },
36
+ {
37
+ type: 'descriptionDetail',
38
+ raw: detail,
39
+ tokens: this.lexer.inlineTokens(detail)
40
+ }
41
+ ]
42
+ };
43
+ }
44
+ }
45
+ };
package/dist/theme.d.ts CHANGED
@@ -128,6 +128,18 @@ export declare const theme: {
128
128
  footnotePopover: {
129
129
  base: string;
130
130
  };
131
+ descriptionList: {
132
+ base: string;
133
+ };
134
+ description: {
135
+ base: string;
136
+ };
137
+ descriptionTerm: {
138
+ base: string;
139
+ };
140
+ descriptionDetail: {
141
+ base: string;
142
+ };
131
143
  };
132
144
  export declare const shadcnTheme: {
133
145
  link: {
@@ -257,6 +269,18 @@ export declare const shadcnTheme: {
257
269
  footnotePopover: {
258
270
  base: string;
259
271
  };
272
+ descriptionList: {
273
+ base: string;
274
+ };
275
+ description: {
276
+ base: string;
277
+ };
278
+ descriptionTerm: {
279
+ base: string;
280
+ };
281
+ descriptionDetail: {
282
+ base: string;
283
+ };
260
284
  };
261
285
  export type Theme = typeof theme;
262
286
  type DeepPartial<T> = {
@@ -391,5 +415,17 @@ export declare const mergeTheme: (customTheme?: DeepPartialTheme, baseTheme?: "t
391
415
  footnotePopover: {
392
416
  base: string;
393
417
  };
418
+ descriptionList: {
419
+ base: string;
420
+ };
421
+ description: {
422
+ base: string;
423
+ };
424
+ descriptionTerm: {
425
+ base: string;
426
+ };
427
+ descriptionDetail: {
428
+ base: string;
429
+ };
394
430
  };
395
431
  export {};
package/dist/theme.js CHANGED
@@ -128,6 +128,18 @@ export const theme = {
128
128
  },
129
129
  footnotePopover: {
130
130
  base: 'fixed z-50 max-h-[30vh] max-w-3xl overflow-y-auto rounded-lg bg-background p-4 shadow'
131
+ },
132
+ descriptionList: {
133
+ base: 'my-4 space-y-2'
134
+ },
135
+ description: {
136
+ base: 'border-l-2 border-gray-200 pl-4'
137
+ },
138
+ descriptionTerm: {
139
+ base: 'font-semibold text-gray-900'
140
+ },
141
+ descriptionDetail: {
142
+ base: 'text-gray-700 ml-4 leading-relaxed'
131
143
  }
132
144
  };
133
145
  export const shadcnTheme = {
@@ -247,7 +259,7 @@ export const shadcnTheme = {
247
259
  base: ''
248
260
  },
249
261
  em: {
250
- base: 'italic text-foreground'
262
+ base: 'italic'
251
263
  },
252
264
  del: {
253
265
  base: 'text-muted-foreground'
@@ -257,6 +269,18 @@ export const shadcnTheme = {
257
269
  },
258
270
  footnotePopover: {
259
271
  base: 'fixed z-50 max-h-[30vh] shadow max-w-3xl overflow-y-auto rounded-lg bg-background p-4'
272
+ },
273
+ descriptionList: {
274
+ base: 'my-4 space-y-2'
275
+ },
276
+ description: {
277
+ base: 'border-l-2 border-border pl-4'
278
+ },
279
+ descriptionTerm: {
280
+ base: 'font-semibold text-foreground'
281
+ },
282
+ descriptionDetail: {
283
+ base: 'text-muted-foreground ml-4 leading-relaxed'
260
284
  }
261
285
  };
262
286
  export const mergeTheme = (customTheme, baseTheme) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte-streamdown",
3
- "version": "2.3.2",
3
+ "version": "2.3.3",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",