@humanspeak/svelte-markdown 1.4.1 → 1.4.2

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
@@ -356,22 +356,34 @@ Both approaches work for any tag name. Snippet overrides take precedence over co
356
356
 
357
357
  ## Marked Extensions
358
358
 
359
- Use third-party [marked extensions](https://marked.js.org/using_advanced#extensions) via the `extensions` prop. The component handles registering tokenizers internally you just provide renderers for the custom token types.
359
+ Use [marked extensions](https://marked.js.org/using_advanced#extensions) via the `extensions` prop. SvelteMarkdown ships first-class extensions for KaTeX, Mermaid, GitHub-style alerts, and footnotes from the `@humanspeak/svelte-markdown/extensions` subpath — no third-party packages required. Third-party extensions still work too; the component handles registering tokenizers internally and you just provide renderers for the custom token types.
360
360
 
361
361
  ### KaTeX Math Rendering
362
362
 
363
+ The package includes built-in `markedKatex` and `KatexRenderer` helpers. Install `katex` as an optional peer dependency and load its CSS:
364
+
363
365
  ```bash
364
- npm install marked-katex-extension katex
366
+ npm install katex
365
367
  ```
366
368
 
369
+ **Default delimiter set** (mirrors KaTeX's own [`auto-render`](https://katex.org/docs/autorender.html) defaults):
370
+
371
+ | Delimiter pair | Level | `displayMode` |
372
+ | -------------------------------------------------------------- | ------ | ------------- |
373
+ | `\(...\)` | inline | `false` |
374
+ | `\[...\]` (own-line) | block | `true` |
375
+ | `$$...$$` (own-line) | block | `true` |
376
+ | `\begin{equation}...\end{equation}` and other AMS environments | block | `true` |
377
+
378
+ Single-dollar inline (`$x^2$`) is **off** by default — KaTeX itself excludes it from auto-render to avoid currency-string clashes like `$5,000`. Pass `{ singleDollarInline: true }` to enable it; it uses a whitespace-bounded rule so currency strings still won't match.
379
+
367
380
  **Component renderer approach:**
368
381
 
369
382
  ```svelte
370
383
  <script lang="ts">
371
384
  import SvelteMarkdown from '@humanspeak/svelte-markdown'
372
385
  import type { RendererComponent, Renderers } from '@humanspeak/svelte-markdown'
373
- import markedKatex from 'marked-katex-extension'
374
- import KatexRenderer from './KatexRenderer.svelte'
386
+ import { markedKatex, KatexRenderer } from '@humanspeak/svelte-markdown/extensions'
375
387
 
376
388
  interface KatexRenderers extends Renderers {
377
389
  inlineKatex: RendererComponent
@@ -385,56 +397,45 @@ npm install marked-katex-extension katex
385
397
  </script>
386
398
 
387
399
  <svelte:head>
388
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.28/dist/katex.min.css" crossorigin="anonymous" />
400
+ <link
401
+ rel="stylesheet"
402
+ href="https://cdn.jsdelivr.net/npm/katex@0.16.45/dist/katex.min.css"
403
+ crossorigin="anonymous"
404
+ />
389
405
  </svelte:head>
390
406
 
391
407
  <SvelteMarkdown
392
- source="Euler's identity: $e^{{i\pi}} + 1 = 0$"
393
- extensions={[markedKatex({ throwOnError: false })]}
408
+ source={`Euler's identity: \\(e^{i\\pi} + 1 = 0\\)`}
409
+ extensions={[markedKatex()]}
394
410
  {renderers}
395
411
  />
396
412
  ```
397
413
 
398
- Where `KatexRenderer.svelte` is:
399
-
400
- ```svelte
401
- <script lang="ts">
402
- import katex from 'katex'
403
-
404
- interface Props {
405
- text: string
406
- displayMode?: boolean
407
- }
408
- const { text, displayMode = false }: Props = $props()
409
-
410
- const html = $derived(katex.renderToString(text, { throwOnError: false, displayMode }))
411
- </script>
412
-
413
- {@html html}
414
- ```
414
+ `KatexRenderer` hardcodes `throwOnError: false` so a single malformed expression renders as a tinted error span instead of throwing — if you need stricter behavior, supply your own component for the `inlineKatex` / `blockKatex` keys.
415
415
 
416
416
  **Snippet override approach** (no separate component file needed):
417
417
 
418
418
  ```svelte
419
419
  <script lang="ts">
420
420
  import SvelteMarkdown from '@humanspeak/svelte-markdown'
421
+ import { markedKatex } from '@humanspeak/svelte-markdown/extensions'
421
422
  import katex from 'katex'
422
- import markedKatex from 'marked-katex-extension'
423
423
  </script>
424
424
 
425
425
  <svelte:head>
426
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.28/dist/katex.min.css" crossorigin="anonymous" />
426
+ <link
427
+ rel="stylesheet"
428
+ href="https://cdn.jsdelivr.net/npm/katex@0.16.45/dist/katex.min.css"
429
+ crossorigin="anonymous"
430
+ />
427
431
  </svelte:head>
428
432
 
429
- <SvelteMarkdown
430
- source="Euler's identity: $e^{{i\pi}} + 1 = 0$"
431
- extensions={[markedKatex({ throwOnError: false })]}
432
- >
433
+ <SvelteMarkdown source={`Euler's identity: \\(e^{i\\pi} + 1 = 0\\)`} extensions={[markedKatex()]}>
433
434
  {#snippet inlineKatex(props)}
434
- {@html katex.renderToString(props.text, { displayMode: false })}
435
+ {@html katex.renderToString(props.text, { throwOnError: false, displayMode: false })}
435
436
  {/snippet}
436
437
  {#snippet blockKatex(props)}
437
- {@html katex.renderToString(props.text, { displayMode: true })}
438
+ {@html katex.renderToString(props.text, { throwOnError: false, displayMode: true })}
438
439
  {/snippet}
439
440
  </SvelteMarkdown>
440
441
  ```
@@ -575,7 +576,7 @@ Marked extensions define custom token types with a `name` property (e.g., `inlin
575
576
  To find the token type names for any extension, check its source or documentation for the `name` field in its `extensions` array:
576
577
 
577
578
  ```js
578
- // Example: marked-katex-extension registers tokens named "inlineKatex" and "blockKatex"
579
+ // Example: markedKatex (built-in) registers tokens named "inlineKatex" and "blockKatex"
579
580
  // → use renderers={{ inlineKatex: ..., blockKatex: ... }}
580
581
  // → or {#snippet inlineKatex(props)} and {#snippet blockKatex(props)}
581
582
 
@@ -7,6 +7,7 @@
7
7
  * import { markedMermaid, MermaidRenderer } from '@humanspeak/svelte-markdown/extensions'
8
8
  * import { markedAlert, AlertRenderer } from '@humanspeak/svelte-markdown/extensions'
9
9
  * import { markedFootnote, FootnoteRef, FootnoteSection } from '@humanspeak/svelte-markdown/extensions'
10
+ * import { markedKatex, KatexRenderer } from '@humanspeak/svelte-markdown/extensions'
10
11
  * ```
11
12
  *
12
13
  * @module @humanspeak/svelte-markdown/extensions
@@ -14,4 +15,6 @@
14
15
  export { AlertRenderer, markedAlert } from './alert/index.js';
15
16
  export type { AlertType } from './alert/index.js';
16
17
  export { FootnoteRef, FootnoteSection, markedFootnote } from './footnote/index.js';
18
+ export { BLOCK_KATEX_TOKEN, INLINE_KATEX_TOKEN, KatexRenderer, markedKatex } from './katex/index.js';
19
+ export type { MarkedKatexOptions } from './katex/index.js';
17
20
  export { MermaidRenderer, markedMermaid } from './mermaid/index.js';
@@ -7,10 +7,12 @@
7
7
  * import { markedMermaid, MermaidRenderer } from '@humanspeak/svelte-markdown/extensions'
8
8
  * import { markedAlert, AlertRenderer } from '@humanspeak/svelte-markdown/extensions'
9
9
  * import { markedFootnote, FootnoteRef, FootnoteSection } from '@humanspeak/svelte-markdown/extensions'
10
+ * import { markedKatex, KatexRenderer } from '@humanspeak/svelte-markdown/extensions'
10
11
  * ```
11
12
  *
12
13
  * @module @humanspeak/svelte-markdown/extensions
13
14
  */
14
15
  export { AlertRenderer, markedAlert } from './alert/index.js';
15
16
  export { FootnoteRef, FootnoteSection, markedFootnote } from './footnote/index.js';
17
+ export { BLOCK_KATEX_TOKEN, INLINE_KATEX_TOKEN, KatexRenderer, markedKatex } from './katex/index.js';
16
18
  export { MermaidRenderer, markedMermaid } from './mermaid/index.js';
@@ -0,0 +1,40 @@
1
+ <!--
2
+ @component
3
+ Renders an `inlineKatex` or `blockKatex` token (produced by {@link markedKatex})
4
+ to KaTeX HTML.
5
+
6
+ Pair with the matching extension via the `renderers` prop:
7
+
8
+ ```svelte
9
+ <SvelteMarkdown
10
+ source={markdown}
11
+ extensions={[markedKatex()]}
12
+ renderers={{ inlineKatex: KatexRenderer, blockKatex: KatexRenderer }}
13
+ />
14
+ ```
15
+
16
+ Requires `katex` to be installed (it's an optional peer dependency of
17
+ `@humanspeak/svelte-markdown`) and `katex/dist/katex.css` to be loaded — either
18
+ imported directly or pulled in via the CDN tag KaTeX recommends.
19
+
20
+ Hardcodes `throwOnError: false` so a single malformed expression renders as a
21
+ red KaTeX error span instead of throwing. If you need stricter behavior, pass
22
+ your own component for `inlineKatex` / `blockKatex` instead.
23
+ -->
24
+ <script lang="ts">
25
+ import katex from 'katex'
26
+
27
+ interface Props {
28
+ /** TeX/LaTeX source to render. Token's inner content for delimiter pairs, or the full `\begin{env}...\end{env}` string for AMS environments. */
29
+ text: string
30
+ /** When `true`, render in display style (block); otherwise inline. */
31
+ displayMode?: boolean
32
+ }
33
+
34
+ const { text, displayMode = false }: Props = $props()
35
+
36
+ const html = $derived(katex.renderToString(text, { throwOnError: false, displayMode }))
37
+ </script>
38
+
39
+ <!-- trunk-ignore(eslint/svelte/no-at-html-tags) -->
40
+ {@html html}
@@ -0,0 +1,31 @@
1
+ interface Props {
2
+ /** TeX/LaTeX source to render. Token's inner content for delimiter pairs, or the full `\begin{env}...\end{env}` string for AMS environments. */
3
+ text: string;
4
+ /** When `true`, render in display style (block); otherwise inline. */
5
+ displayMode?: boolean;
6
+ }
7
+ /**
8
+ * Renders an `inlineKatex` or `blockKatex` token (produced by {@link markedKatex})
9
+ * to KaTeX HTML.
10
+ *
11
+ * Pair with the matching extension via the `renderers` prop:
12
+ *
13
+ * ```svelte
14
+ * <SvelteMarkdown
15
+ * source={markdown}
16
+ * extensions={[markedKatex()]}
17
+ * renderers={{ inlineKatex: KatexRenderer, blockKatex: KatexRenderer }}
18
+ * />
19
+ * ```
20
+ *
21
+ * Requires `katex` to be installed (it's an optional peer dependency of
22
+ * `@humanspeak/svelte-markdown`) and `katex/dist/katex.css` to be loaded — either
23
+ * imported directly or pulled in via the CDN tag KaTeX recommends.
24
+ *
25
+ * Hardcodes `throwOnError: false` so a single malformed expression renders as a
26
+ * red KaTeX error span instead of throwing. If you need stricter behavior, pass
27
+ * your own component for `inlineKatex` / `blockKatex` instead.
28
+ */
29
+ declare const KatexRenderer: import("svelte").Component<Props, {}, "">;
30
+ type KatexRenderer = ReturnType<typeof KatexRenderer>;
31
+ export default KatexRenderer;
@@ -0,0 +1,3 @@
1
+ export { default as KatexRenderer } from './KatexRenderer.svelte';
2
+ export { BLOCK_KATEX_TOKEN, INLINE_KATEX_TOKEN, markedKatex } from './markedKatex.js';
3
+ export type { MarkedKatexOptions } from './markedKatex.js';
@@ -0,0 +1,2 @@
1
+ export { default as KatexRenderer } from './KatexRenderer.svelte';
2
+ export { BLOCK_KATEX_TOKEN, INLINE_KATEX_TOKEN, markedKatex } from './markedKatex.js';
@@ -0,0 +1,70 @@
1
+ import type { MarkedExtension } from 'marked';
2
+ /** Token type emitted for inline math (`\(...\)`, opt-in `$...$`). */
3
+ export declare const INLINE_KATEX_TOKEN = "inlineKatex";
4
+ /** Token type emitted for block math (`\[...\]`, `$$...$$`, AMS environments). */
5
+ export declare const BLOCK_KATEX_TOKEN = "blockKatex";
6
+ /**
7
+ * Options for the {@link markedKatex} factory.
8
+ */
9
+ export interface MarkedKatexOptions {
10
+ /**
11
+ * When `true`, also tokenize `$...$` (inline) and `$$...$$` (inline) as
12
+ * math, using the standard whitespace-boundary rule that prevents
13
+ * currency strings like `$5,000` from being parsed as a math expression.
14
+ *
15
+ * Off by default. KaTeX's own `auto-render` extension excludes `$...$`
16
+ * from its defaults with the comment "LaTeX uses $…$, but it ruins the
17
+ * display of normal `$` in text" — we follow the same opinion.
18
+ *
19
+ * Block-level `$$...$$` (own-line delimiters) is always enabled, and is
20
+ * unaffected by this option.
21
+ *
22
+ * @defaultValue `false`
23
+ */
24
+ singleDollarInline?: boolean;
25
+ }
26
+ /**
27
+ * Creates a marked extension that tokenizes KaTeX math expressions into
28
+ * custom `inlineKatex` and `blockKatex` tokens.
29
+ *
30
+ * Default delimiter set (mirrors KaTeX's own `auto-render` defaults):
31
+ *
32
+ * | Delimiter pair | Level | `displayMode` |
33
+ * |---|---|---|
34
+ * | `\(...\)` | inline | `false` |
35
+ * | `\[...\]` (own-line) | block | `true` |
36
+ * | `$$...$$` (own-line) | block | `true` |
37
+ * | `\begin{equation}...\end{equation}` and other AMS envs | block | `true` |
38
+ *
39
+ * Supported AMS environments: `equation`, `align`, `alignat`, `gather`, `CD`,
40
+ * plus their starred variants (e.g. `equation*`).
41
+ *
42
+ * `$...$` inline is **off** by default — KaTeX itself opts out of single-
43
+ * dollar inline because of currency-string clashes (`$5,000` etc.). Pass
44
+ * `{ singleDollarInline: true }` to enable it; when enabled it uses the
45
+ * whitespace-boundary rule from upstream `marked-katex-extension` so
46
+ * currency strings still won't match.
47
+ *
48
+ * @example
49
+ * ```svelte
50
+ * <script lang="ts">
51
+ * import SvelteMarkdown from '@humanspeak/svelte-markdown'
52
+ * import { markedKatex, KatexRenderer } from '@humanspeak/svelte-markdown/extensions'
53
+ *
54
+ * const renderers = { inlineKatex: KatexRenderer, blockKatex: KatexRenderer }
55
+ * </script>
56
+ *
57
+ * <SvelteMarkdown
58
+ * source={markdown}
59
+ * extensions={[markedKatex()]}
60
+ * {renderers}
61
+ * />
62
+ * ```
63
+ *
64
+ * Pair with `KatexRenderer` from the same subpath, or supply your own
65
+ * component that accepts `{ text: string; displayMode?: boolean }`.
66
+ *
67
+ * @param options - {@link MarkedKatexOptions}
68
+ * @returns A `MarkedExtension` containing one block-level and one inline tokenizer
69
+ */
70
+ export declare function markedKatex(options?: MarkedKatexOptions): MarkedExtension;
@@ -0,0 +1,159 @@
1
+ /** Token type emitted for inline math (`\(...\)`, opt-in `$...$`). */
2
+ export const INLINE_KATEX_TOKEN = 'inlineKatex';
3
+ /** Token type emitted for block math (`\[...\]`, `$$...$$`, AMS environments). */
4
+ export const BLOCK_KATEX_TOKEN = 'blockKatex';
5
+ const AMS_ENVIRONMENTS = ['equation', 'align', 'alignat', 'gather', 'CD'];
6
+ // `\\*` in the JS string becomes `\*` in the regex source, which matches a
7
+ // literal `*` (the AMS un-numbered variant). Without the escape, `equation*`
8
+ // in a regex would mean "equatio + zero-or-more n", which silently fails to
9
+ // match `\begin{equation*}`.
10
+ const AMS_NAMES = AMS_ENVIRONMENTS.flatMap((n) => [n, `${n}\\*`]).join('|');
11
+ const blockBracketRule = /^\\\[[ \t]*\n([\s\S]+?)\n[ \t]*\\\](?:\n|$)/;
12
+ const blockDollarRule = /^\$\$[ \t]*\n([\s\S]+?)\n[ \t]*\$\$(?:\n|$)/;
13
+ const blockAmsRule = new RegExp(`^\\\\begin\\{(${AMS_NAMES})\\}[\\s\\S]+?\\\\end\\{\\1\\}(?:\\n|$)?`);
14
+ const inlineParenRule = /^\\\(([\s\S]+?)\\\)/;
15
+ // Mirrors the "standard" rule from upstream marked-katex-extension: requires a
16
+ // whitespace, end-of-string, or punctuation boundary after the closing `$` so
17
+ // strings like `$5,000` do not match.
18
+ const inlineDollarRule = /^\$(?!\$)((?:\\.|[^\\\n$])+?)\$(?=[\s?!.,:?!。,:]|$)/;
19
+ const earliestIndex = (src, needles) => {
20
+ let best = -1;
21
+ for (const needle of needles) {
22
+ const i = src.indexOf(needle);
23
+ if (i !== -1 && (best === -1 || i < best))
24
+ best = i;
25
+ }
26
+ return best === -1 ? undefined : best;
27
+ };
28
+ /**
29
+ * Creates a marked extension that tokenizes KaTeX math expressions into
30
+ * custom `inlineKatex` and `blockKatex` tokens.
31
+ *
32
+ * Default delimiter set (mirrors KaTeX's own `auto-render` defaults):
33
+ *
34
+ * | Delimiter pair | Level | `displayMode` |
35
+ * |---|---|---|
36
+ * | `\(...\)` | inline | `false` |
37
+ * | `\[...\]` (own-line) | block | `true` |
38
+ * | `$$...$$` (own-line) | block | `true` |
39
+ * | `\begin{equation}...\end{equation}` and other AMS envs | block | `true` |
40
+ *
41
+ * Supported AMS environments: `equation`, `align`, `alignat`, `gather`, `CD`,
42
+ * plus their starred variants (e.g. `equation*`).
43
+ *
44
+ * `$...$` inline is **off** by default — KaTeX itself opts out of single-
45
+ * dollar inline because of currency-string clashes (`$5,000` etc.). Pass
46
+ * `{ singleDollarInline: true }` to enable it; when enabled it uses the
47
+ * whitespace-boundary rule from upstream `marked-katex-extension` so
48
+ * currency strings still won't match.
49
+ *
50
+ * @example
51
+ * ```svelte
52
+ * <script lang="ts">
53
+ * import SvelteMarkdown from '@humanspeak/svelte-markdown'
54
+ * import { markedKatex, KatexRenderer } from '@humanspeak/svelte-markdown/extensions'
55
+ *
56
+ * const renderers = { inlineKatex: KatexRenderer, blockKatex: KatexRenderer }
57
+ * </script>
58
+ *
59
+ * <SvelteMarkdown
60
+ * source={markdown}
61
+ * extensions={[markedKatex()]}
62
+ * {renderers}
63
+ * />
64
+ * ```
65
+ *
66
+ * Pair with `KatexRenderer` from the same subpath, or supply your own
67
+ * component that accepts `{ text: string; displayMode?: boolean }`.
68
+ *
69
+ * @param options - {@link MarkedKatexOptions}
70
+ * @returns A `MarkedExtension` containing one block-level and one inline tokenizer
71
+ */
72
+ export function markedKatex(options = {}) {
73
+ const { singleDollarInline = false } = options;
74
+ // The token-cache hash serializes functions via `fn.toString()`, which
75
+ // can't see option values that live in a closure (our tokenizers'
76
+ // source code is identical regardless of `singleDollarInline`). This
77
+ // marker makes the option visible to JSON.stringify so two
78
+ // `markedKatex({ ... })` calls with different options produce
79
+ // different cache keys — without it, toggling the option at runtime
80
+ // returns stale tokens. Cast because `MarkedExtension` doesn't permit
81
+ // arbitrary fields, but Marked.use() shallow-spreads our object into
82
+ // `defaults`, so the marker survives.
83
+ const ext = {
84
+ _humanspeakKatexConfig: JSON.stringify({ singleDollarInline }),
85
+ extensions: [
86
+ {
87
+ name: BLOCK_KATEX_TOKEN,
88
+ level: 'block',
89
+ start(src) {
90
+ return earliestIndex(src, ['\\[', '$$', '\\begin{']);
91
+ },
92
+ tokenizer(src) {
93
+ const bracket = src.match(blockBracketRule);
94
+ if (bracket) {
95
+ return {
96
+ type: BLOCK_KATEX_TOKEN,
97
+ raw: bracket[0],
98
+ text: bracket[1].trim(),
99
+ displayMode: true
100
+ };
101
+ }
102
+ const dollar = src.match(blockDollarRule);
103
+ if (dollar) {
104
+ return {
105
+ type: BLOCK_KATEX_TOKEN,
106
+ raw: dollar[0],
107
+ text: dollar[1].trim(),
108
+ displayMode: true
109
+ };
110
+ }
111
+ const ams = src.match(blockAmsRule);
112
+ if (ams) {
113
+ // KaTeX parses `\begin{...}...\end{...}` natively, so
114
+ // pass the entire matched string through as `text`.
115
+ return {
116
+ type: BLOCK_KATEX_TOKEN,
117
+ raw: ams[0],
118
+ text: ams[0].replace(/\n$/, '').trim(),
119
+ displayMode: true
120
+ };
121
+ }
122
+ }
123
+ },
124
+ {
125
+ name: INLINE_KATEX_TOKEN,
126
+ level: 'inline',
127
+ start(src) {
128
+ const needles = ['\\('];
129
+ if (singleDollarInline)
130
+ needles.push('$');
131
+ return earliestIndex(src, needles);
132
+ },
133
+ tokenizer(src) {
134
+ const paren = src.match(inlineParenRule);
135
+ if (paren) {
136
+ return {
137
+ type: INLINE_KATEX_TOKEN,
138
+ raw: paren[0],
139
+ text: paren[1].trim(),
140
+ displayMode: false
141
+ };
142
+ }
143
+ if (singleDollarInline) {
144
+ const dollar = src.match(inlineDollarRule);
145
+ if (dollar) {
146
+ return {
147
+ type: INLINE_KATEX_TOKEN,
148
+ raw: dollar[0],
149
+ text: dollar[1].trim(),
150
+ displayMode: false
151
+ };
152
+ }
153
+ }
154
+ }
155
+ }
156
+ ]
157
+ };
158
+ return ext;
159
+ }
package/dist/types.d.ts CHANGED
@@ -204,9 +204,13 @@ export type SvelteMarkdownProps<T extends Renderers = Renderers> = {
204
204
  *
205
205
  * @example
206
206
  * ```svelte
207
+ * <script lang="ts">
208
+ * import { markedKatex, KatexRenderer } from '@humanspeak/svelte-markdown/extensions'
209
+ * </script>
210
+ *
207
211
  * <SvelteMarkdown
208
212
  * source={markdown}
209
- * extensions={[markedKatex({ throwOnError: false })]}
213
+ * extensions={[markedKatex()]}
210
214
  * renderers={{ inlineKatex: KatexRenderer, blockKatex: KatexRenderer }}
211
215
  * />
212
216
  * ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@humanspeak/svelte-markdown",
3
- "version": "1.4.1",
3
+ "version": "1.4.2",
4
4
  "description": "Fast, customizable markdown renderer for Svelte with built-in caching, TypeScript support, and Svelte 5 runes",
5
5
  "keywords": [
6
6
  "svelte",
@@ -70,60 +70,63 @@
70
70
  "@humanspeak/memory-cache": "^1.0.6",
71
71
  "github-slugger": "^2.0.0",
72
72
  "htmlparser2": "^12.0.0",
73
- "marked": "^18.0.0"
73
+ "marked": "^18.0.3"
74
74
  },
75
75
  "devDependencies": {
76
76
  "@eslint/compat": "^2.0.5",
77
77
  "@eslint/js": "^10.0.1",
78
- "@playwright/cli": "^0.1.6",
78
+ "@playwright/cli": "^0.1.11",
79
79
  "@playwright/test": "^1.59.1",
80
80
  "@sveltejs/adapter-auto": "^7.0.1",
81
- "@sveltejs/kit": "^2.57.1",
81
+ "@sveltejs/kit": "^2.59.0",
82
82
  "@sveltejs/package": "^2.5.7",
83
83
  "@sveltejs/vite-plugin-svelte": "^7.0.0",
84
84
  "@testing-library/jest-dom": "^6.9.1",
85
85
  "@testing-library/svelte": "^5.3.1",
86
86
  "@testing-library/user-event": "^14.6.1",
87
87
  "@types/katex": "^0.16.8",
88
- "@types/node": "^25.5.2",
89
- "@typescript-eslint/eslint-plugin": "^8.58.1",
90
- "@typescript-eslint/parser": "^8.58.1",
91
- "@vitest/coverage-v8": "^4.1.4",
92
- "eslint": "^10.2.0",
88
+ "@types/node": "^25.6.0",
89
+ "@typescript-eslint/eslint-plugin": "^8.59.2",
90
+ "@typescript-eslint/parser": "^8.59.2",
91
+ "@vitest/coverage-v8": "^4.1.5",
92
+ "eslint": "^10.3.0",
93
93
  "eslint-config-prettier": "^10.1.8",
94
94
  "eslint-plugin-import": "^2.32.0",
95
- "eslint-plugin-svelte": "^3.17.0",
95
+ "eslint-plugin-svelte": "^3.17.1",
96
96
  "eslint-plugin-unused-imports": "^4.4.1",
97
- "globals": "^17.4.0",
97
+ "globals": "^17.6.0",
98
98
  "husky": "^9.1.7",
99
- "jsdom": "^29.0.2",
99
+ "jsdom": "^29.1.1",
100
100
  "katex": "^0.16.45",
101
- "marked-katex-extension": "^5.1.8",
102
101
  "mermaid": "^11.14.0",
103
102
  "mprocs": "^0.9.2",
104
- "prettier": "^3.8.1",
103
+ "prettier": "^3.8.3",
105
104
  "prettier-plugin-organize-imports": "^4.3.0",
106
105
  "prettier-plugin-svelte": "^3.5.1",
107
- "prettier-plugin-tailwindcss": "^0.7.2",
106
+ "prettier-plugin-tailwindcss": "^0.8.0",
108
107
  "publint": "^0.3.18",
109
- "svelte": "^5.55.2",
110
- "svelte-check": "^4.4.6",
111
- "typescript": "^6.0.2",
112
- "typescript-eslint": "^8.58.1",
113
- "vite": "^8.0.8",
114
- "vitest": "^4.1.4"
108
+ "svelte": "^5.55.5",
109
+ "svelte-check": "^4.4.7",
110
+ "typescript": "^6.0.3",
111
+ "typescript-eslint": "^8.59.2",
112
+ "vite": "^8.0.10",
113
+ "vitest": "^4.1.5"
115
114
  },
116
115
  "peerDependencies": {
116
+ "katex": ">=0.16.0",
117
117
  "mermaid": ">=10.0.0",
118
118
  "svelte": "^5.0.0"
119
119
  },
120
120
  "peerDependenciesMeta": {
121
+ "katex": {
122
+ "optional": true
123
+ },
121
124
  "mermaid": {
122
125
  "optional": true
123
126
  }
124
127
  },
125
128
  "volta": {
126
- "node": "24.14.0"
129
+ "node": "24.15.0"
127
130
  },
128
131
  "publishConfig": {
129
132
  "access": "public"