comark 0.3.1 → 0.3.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.
Files changed (80) hide show
  1. package/dist/devtools/index.d.ts +1 -0
  2. package/dist/devtools/index.js +1 -0
  3. package/dist/devtools/register.d.ts +1 -0
  4. package/dist/devtools/register.js +1 -0
  5. package/dist/devtools/registry.d.ts +1 -0
  6. package/dist/devtools/registry.js +1 -0
  7. package/dist/devtools/vite.d.ts +1 -0
  8. package/dist/devtools/vite.js +1 -0
  9. package/dist/internal/frontmatter.d.ts +1 -0
  10. package/dist/internal/frontmatter.js +4 -2
  11. package/dist/internal/parse/auto-close/index.js +25 -13
  12. package/dist/internal/parse/auto-close/table.js +12 -9
  13. package/dist/internal/parse/auto-unwrap.js +2 -10
  14. package/dist/internal/parse/html/html_block_rule.js +1 -1
  15. package/dist/internal/parse/html/html_inline_rule.js +3 -7
  16. package/dist/internal/parse/html/html_re.js +1 -1
  17. package/dist/internal/parse/html/index.js +14 -2
  18. package/dist/internal/parse/syntax/block-params.d.ts +9 -0
  19. package/dist/internal/parse/syntax/block-params.js +48 -0
  20. package/dist/internal/parse/syntax/brackets.d.ts +8 -0
  21. package/dist/internal/parse/syntax/brackets.js +20 -0
  22. package/dist/internal/parse/syntax/props.d.ts +5 -0
  23. package/dist/internal/parse/syntax/props.js +119 -0
  24. package/dist/internal/parse/token-processor.js +25 -24
  25. package/dist/internal/props-validation.js +4 -9
  26. package/dist/internal/stringify/attributes.js +4 -1
  27. package/dist/internal/stringify/handlers/a.js +1 -3
  28. package/dist/internal/stringify/handlers/blockquote.js +2 -4
  29. package/dist/internal/stringify/handlers/code.js +1 -3
  30. package/dist/internal/stringify/handlers/emphesis.js +1 -3
  31. package/dist/internal/stringify/handlers/html.js +26 -16
  32. package/dist/internal/stringify/handlers/img.js +1 -3
  33. package/dist/internal/stringify/handlers/li.js +14 -8
  34. package/dist/internal/stringify/handlers/mdc.js +2 -3
  35. package/dist/internal/stringify/handlers/ol.js +1 -1
  36. package/dist/internal/stringify/handlers/p.d.ts +1 -1
  37. package/dist/internal/stringify/handlers/p.js +4 -1
  38. package/dist/internal/stringify/handlers/pre.js +10 -13
  39. package/dist/internal/stringify/handlers/strong.js +1 -3
  40. package/dist/internal/stringify/handlers/table.js +7 -5
  41. package/dist/internal/stringify/handlers/template.js +1 -1
  42. package/dist/internal/stringify/handlers/ul.js +1 -1
  43. package/dist/internal/stringify/indent.d.ts +1 -5
  44. package/dist/internal/stringify/indent.js +1 -9
  45. package/dist/internal/stringify/state.js +1 -1
  46. package/dist/internal/yaml.js +1 -1
  47. package/dist/parse.js +14 -8
  48. package/dist/plugins/alert.js +1 -1
  49. package/dist/plugins/binding.js +1 -3
  50. package/dist/plugins/breaks.js +1 -1
  51. package/dist/plugins/emoji.js +8 -8
  52. package/dist/plugins/footnotes.js +19 -13
  53. package/dist/plugins/headings.js +2 -4
  54. package/dist/plugins/highlight.d.ts +1 -11
  55. package/dist/plugins/highlight.js +198 -103
  56. package/dist/plugins/json-render.js +5 -9
  57. package/dist/plugins/math.js +4 -6
  58. package/dist/plugins/mermaid.js +6 -20
  59. package/dist/plugins/punctuation.js +5 -6
  60. package/dist/plugins/security.js +2 -2
  61. package/dist/plugins/syntax.d.ts +49 -0
  62. package/dist/plugins/syntax.js +522 -0
  63. package/dist/plugins/task-list.d.ts +1 -1
  64. package/dist/plugins/task-list.js +11 -8
  65. package/dist/plugins/toc.js +1 -1
  66. package/dist/types.d.ts +1 -0
  67. package/dist/utils/comark.tmLanguage.d.ts +335 -0
  68. package/dist/utils/comark.tmLanguage.js +597 -0
  69. package/dist/utils/helpers.js +1 -3
  70. package/dist/utils/index.d.ts +5 -0
  71. package/dist/utils/index.js +25 -3
  72. package/package.json +39 -40
  73. package/skills/skills/comark/AGENTS.md +0 -261
  74. package/skills/skills/comark/SKILL.md +0 -489
  75. package/skills/skills/comark/references/markdown-syntax.md +0 -599
  76. package/skills/skills/comark/references/parsing-ast.md +0 -378
  77. package/skills/skills/comark/references/rendering-react.md +0 -445
  78. package/skills/skills/comark/references/rendering-svelte.md +0 -453
  79. package/skills/skills/comark/references/rendering-vue.md +0 -462
  80. /package/skills/{skills/migrate-mdc-to-comark → migrate-mdc-to-comark}/SKILL.md +0 -0
@@ -1,453 +0,0 @@
1
- # Svelte Rendering Guide
2
-
3
- Complete guide for rendering Comark AST in Svelte 5 applications.
4
-
5
- ## Table of Contents
6
-
7
- - [Basic Usage](#basic-usage)
8
- - [Custom Components](#custom-components)
9
- - [Dynamic Component Resolution](#dynamic-component-resolution)
10
- - [Slots Support](#slots-support)
11
- - [Props Mapping](#props-mapping)
12
- - [Streaming Mode](#streaming-mode)
13
- - [Prose Components](#prose-components)
14
- - [Experimental Async](#experimental-async)
15
- - [Custom Props Handling](#custom-props-handling)
16
- - [CSS Class](#css-class)
17
-
18
- ---
19
-
20
- ## Basic Usage
21
-
22
- Use the `Comark` component to render markdown:
23
-
24
- ```svelte
25
- <script lang="ts">
26
- import { Comark } from '@comark/svelte'
27
-
28
- const content = `
29
- # Hello World
30
-
31
- This is **markdown** content.
32
-
33
- ::alert{type="info"}
34
- Important message
35
- ::
36
- `
37
- </script>
38
-
39
- <Comark markdown={content} />
40
- ```
41
-
42
- ---
43
-
44
- ## Custom Components
45
-
46
- Map custom Svelte components to Comark elements:
47
-
48
- ```svelte
49
- <script lang="ts">
50
- import { Comark } from '@comark/svelte'
51
- import CustomHeading from './CustomHeading.svelte'
52
- import CustomAlert from './CustomAlert.svelte'
53
- import CustomCard from './CustomCard.svelte'
54
-
55
- const customComponents = {
56
- h1: CustomHeading,
57
- h2: CustomHeading,
58
- alert: CustomAlert,
59
- card: CustomCard,
60
- }
61
- </script>
62
-
63
- <Comark markdown={content} components={customComponents} />
64
- ```
65
-
66
- ### Component Resolution Order
67
-
68
- Components are resolved by checking these keys in order:
69
- 1. `Prose{PascalTag}` — e.g., `ProseH1` for `<h1>` tags
70
- 2. `PascalTag` — e.g., `Alert` for `::alert` components
71
- 3. `tag` — e.g., `alert` for `::alert` components
72
-
73
- ### Custom Component Example
74
-
75
- Custom components receive AST node attributes as props and children as a Svelte `children` snippet:
76
-
77
- ```svelte
78
- <!-- CustomHeading.svelte -->
79
- <script lang="ts">
80
- import type { Snippet } from 'svelte'
81
-
82
- let { id, children }: { id?: string, children?: Snippet } = $props()
83
- </script>
84
-
85
- <h1 {id} class="custom-heading">
86
- {@render children?.()}
87
- </h1>
88
- ```
89
-
90
- ### Alert Component Example
91
-
92
- ```svelte
93
- <!-- CustomAlert.svelte -->
94
- <script lang="ts">
95
- import type { Snippet } from 'svelte'
96
-
97
- let {
98
- type = 'info',
99
- children,
100
- }: {
101
- type?: 'info' | 'warning' | 'error' | 'success'
102
- children?: Snippet
103
- } = $props()
104
-
105
- const icons = {
106
- info: '\u2139\uFE0F',
107
- warning: '\u26A0\uFE0F',
108
- error: '\u274C',
109
- success: '\u2705',
110
- }
111
- </script>
112
-
113
- <div class="alert alert-{type}" role="alert">
114
- <div class="alert-icon">{icons[type]}</div>
115
- <div class="alert-content">{@render children?.()}</div>
116
- </div>
117
- ```
118
-
119
- ---
120
-
121
- ## Dynamic Component Resolution
122
-
123
- Load components dynamically using `componentsManifest`:
124
-
125
- ```svelte
126
- <script lang="ts">
127
- import { Comark } from '@comark/svelte'
128
-
129
- const componentMap: Record<string, () => Promise<any>> = {
130
- 'alert': () => import('./Alert.svelte'),
131
- 'card': () => import('./Card.svelte'),
132
- 'button': () => import('./Button.svelte'),
133
- }
134
-
135
- async function loadComponent(name: string) {
136
- if (componentMap[name]) {
137
- const mod = await componentMap[name]()
138
- return mod.default
139
- }
140
- throw new Error(`Component ${name} not found`)
141
- }
142
- </script>
143
-
144
- <Comark markdown={content} componentsManifest={loadComponent} />
145
- ```
146
-
147
- ---
148
-
149
- ## Slots Support
150
-
151
- Comark components with named slots work in Svelte using the `children` snippet pattern:
152
-
153
- ### Markdown with Slots
154
-
155
- ```markdown
156
- ::card
157
- #header
158
- ## Card Title
159
-
160
- #default
161
- Main content here with **markdown** support
162
-
163
- #footer
164
- Footer text
165
- ::
166
- ```
167
-
168
- ### Custom Component with Slots
169
-
170
- In Svelte 5, children are passed as implicit slot content and received as a `Snippet`:
171
-
172
- ```svelte
173
- <!-- Card.svelte -->
174
- <script lang="ts">
175
- import type { Snippet } from 'svelte'
176
-
177
- let {
178
- children,
179
- }: {
180
- children?: Snippet
181
- } = $props()
182
- </script>
183
-
184
- <div class="card">
185
- {@render children?.()}
186
- </div>
187
-
188
- <style>
189
- .card {
190
- border: 1px solid #e5e7eb;
191
- border-radius: 0.5rem;
192
- overflow: hidden;
193
- padding: 1rem;
194
- }
195
- </style>
196
- ```
197
-
198
- Note: Named slots from Comark (`#header`, `#content`, `#footer`) are rendered as `template` elements in the AST. The Svelte renderer passes all children (including named slot templates) as a single `children` snippet. To handle named slots individually, access the `__node` prop and filter children by template name.
199
-
200
- ---
201
-
202
- ## Props Mapping
203
-
204
- The Svelte renderer maps AST attributes to component props:
205
-
206
- ### Attribute Mapping
207
-
208
- ```
209
- // Markdown attribute → Svelte prop
210
- {class="foo"} → class="foo" (pass-through)
211
- {className="foo"} → class="foo" (mapped)
212
- {style="color: red"} → style="color: red" (pass-through as string)
213
- {tabindex="0"} → tabindex="0" (pass-through)
214
- {:bool="true"} → bool={true} (parsed from string)
215
- {:count="5"} → count={5} (parsed as number)
216
- {:data='{"key":"val"}'} → data={{key:"val"}} (parsed as object)
217
- ```
218
-
219
- Svelte is closer to HTML than React, so most attributes pass through unchanged. The only mapping is `className` → `class`. Colon-prefixed attributes (`:prop="value"`) are parsed as typed values (boolean, number, JSON).
220
-
221
- ### Boolean Props
222
-
223
- ```
224
- // Markdown: ::component{:disabled="true"}
225
- // Svelte prop: disabled={true}
226
-
227
- // Markdown: ::component{:visible="false"}
228
- // Svelte prop: visible={false}
229
- ```
230
-
231
- ### Number Props
232
-
233
- ```
234
- // Markdown: ::component{:count="5"}
235
- // Svelte prop: count={5}
236
-
237
- // Markdown: ::component{:max="100"}
238
- // Svelte prop: max={100}
239
- ```
240
-
241
- ### Object/Array Props
242
-
243
- ```
244
- // Markdown: ::component{:config='{"theme":"dark"}'}
245
- // Svelte prop: config={{theme:"dark"}}
246
-
247
- // Markdown: ::component{:items='["a","b","c"]'}
248
- // Svelte prop: items={["a","b","c"]}
249
- ```
250
-
251
- ---
252
-
253
- ## Streaming Mode
254
-
255
- Use the `Comark` component with `$state` for streaming content:
256
-
257
- ```svelte
258
- <script lang="ts">
259
- import { Comark } from '@comark/svelte'
260
-
261
- let content = $state('')
262
- let isStreaming = $state(false)
263
-
264
- async function streamContent() {
265
- isStreaming = true
266
- const response = await fetch('/api/content.md')
267
- const reader = response.body!.getReader()
268
- const decoder = new TextDecoder()
269
-
270
- while (true) {
271
- const { done, value } = await reader.read()
272
- if (done) break
273
- content += decoder.decode(value, { stream: true })
274
- }
275
-
276
- isStreaming = false
277
- }
278
- </script>
279
-
280
- <Comark markdown={content} streaming={isStreaming} caret />
281
- ```
282
-
283
- The `caret` prop appends a blinking cursor indicator to the last text node during streaming. Customize with a CSS class:
284
-
285
- ```svelte
286
- <Comark markdown={content} streaming={isStreaming} caret={{ class: 'my-caret' }} />
287
- ```
288
-
289
- `autoClose` is enabled by default — incomplete syntax like `**bold text` is automatically closed on every parse.
290
-
291
- ---
292
-
293
- ## Prose Components
294
-
295
- Override native HTML elements using the `Prose` prefix:
296
-
297
- ```svelte
298
- <script lang="ts">
299
- import { Comark } from '@comark/svelte'
300
- import ProseH1 from './ProseH1.svelte'
301
- import ProseA from './ProseA.svelte'
302
- import ProsePre from './ProsePre.svelte'
303
-
304
- const components = { ProseH1, ProseA, ProsePre }
305
- </script>
306
-
307
- <Comark markdown={content} {components} />
308
- ```
309
-
310
- ### Tailwind CSS Prose
311
-
312
- ```svelte
313
- <article class="prose prose-lg dark:prose-dark max-w-none">
314
- <Comark markdown={content} />
315
- </article>
316
- ```
317
-
318
- ---
319
-
320
- ## Experimental Async
321
-
322
- The `ComarkAsync` component uses Svelte's experimental `await` in `$derived` for a declarative approach. Requires `experimental.async` in your Svelte config:
323
-
324
- ```js
325
- // svelte.config.js
326
- const config = {
327
- compilerOptions: {
328
- experimental: { async: true },
329
- },
330
- }
331
- export default config
332
- ```
333
-
334
- Usage with `<svelte:boundary>`:
335
-
336
- ```svelte
337
- <script lang="ts">
338
- import { ComarkAsync } from '@comark/svelte/async'
339
- </script>
340
-
341
- <svelte:boundary>
342
- <ComarkAsync markdown={content} />
343
- {#snippet pending()}
344
- <p>Loading...</p>
345
- {/snippet}
346
- {#snippet failed(error, reset)}
347
- <p>Error: {error.message}</p>
348
- <button onclick={reset}>Retry</button>
349
- {/snippet}
350
- </svelte:boundary>
351
- ```
352
-
353
- ---
354
-
355
- ## Custom Props Handling
356
-
357
- Access props in custom components:
358
-
359
- ```svelte
360
- <!-- CustomAlert.svelte -->
361
- <script lang="ts">
362
- import type { Snippet } from 'svelte'
363
-
364
- let {
365
- type = 'info',
366
- count,
367
- data,
368
- children,
369
- }: {
370
- type?: string // From {type="info"}
371
- count?: number // From {:count="5"}
372
- data?: object // From {:data='{"key":"val"}'}
373
- children?: Snippet
374
- } = $props()
375
- </script>
376
-
377
- <div
378
- class="alert alert-{type}"
379
- data-count={count}
380
- data-info={JSON.stringify(data)}
381
- role="alert"
382
- >
383
- {@render children?.()}
384
- </div>
385
- ```
386
-
387
- ### Working with Complex Props
388
-
389
- ```svelte
390
- <!-- DataTable.svelte -->
391
- <script lang="ts">
392
- import type { Snippet } from 'svelte'
393
-
394
- let {
395
- columns = [],
396
- sortable = false,
397
- striped = false,
398
- children,
399
- }: {
400
- columns?: string[] // From {:columns='["Name","Age"]'}
401
- sortable?: boolean // From {:sortable="true"}
402
- striped?: boolean // From {:striped="true"}
403
- children?: Snippet
404
- } = $props()
405
- </script>
406
-
407
- <table class:table-striped={striped}>
408
- {#if columns.length > 0}
409
- <thead>
410
- <tr>
411
- {#each columns as col (col)}
412
- <th>
413
- {col}
414
- {#if sortable}<button>↕</button>{/if}
415
- </th>
416
- {/each}
417
- </tr>
418
- </thead>
419
- {/if}
420
- <tbody>{@render children?.()}</tbody>
421
- </table>
422
- ```
423
-
424
- **Usage in Markdown:**
425
-
426
- ```markdown
427
- ::data-table{:columns='["Name", "Age", "Email"]' :sortable="true" :striped="true"}
428
- Table content here
429
- ::
430
- ```
431
-
432
- ---
433
-
434
- ## CSS Class
435
-
436
- Add a custom wrapper class:
437
-
438
- ```svelte
439
- <Comark markdown={content} class="prose dark:prose-dark" />
440
- ```
441
-
442
- ### With Tailwind CSS
443
-
444
- ```svelte
445
- <Comark
446
- markdown={content}
447
- class="prose prose-slate lg:prose-xl dark:prose-invert max-w-none"
448
- />
449
- ```
450
-
451
- ---
452
-
453
- [← Back to Main Skills Guide](../SKILL.md)