comark 0.3.0 → 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.
- package/LICENSE +21 -0
- package/dist/devtools/index.d.ts +1 -0
- package/dist/devtools/index.js +1 -0
- package/dist/devtools/register.d.ts +1 -0
- package/dist/devtools/register.js +1 -0
- package/dist/devtools/registry.d.ts +1 -0
- package/dist/devtools/registry.js +1 -0
- package/dist/devtools/vite.d.ts +1 -0
- package/dist/devtools/vite.js +1 -0
- package/dist/internal/frontmatter.d.ts +1 -0
- package/dist/internal/frontmatter.js +4 -2
- package/dist/internal/parse/auto-close/index.js +25 -13
- package/dist/internal/parse/auto-close/table.js +12 -9
- package/dist/internal/parse/auto-unwrap.js +2 -10
- package/dist/internal/parse/html/html_block_rule.js +1 -1
- package/dist/internal/parse/html/html_inline_rule.js +3 -7
- package/dist/internal/parse/html/html_re.js +1 -1
- package/dist/internal/parse/html/index.js +14 -2
- package/dist/internal/parse/syntax/block-params.d.ts +9 -0
- package/dist/internal/parse/syntax/block-params.js +48 -0
- package/dist/internal/parse/syntax/brackets.d.ts +8 -0
- package/dist/internal/parse/syntax/brackets.js +20 -0
- package/dist/internal/parse/syntax/props.d.ts +5 -0
- package/dist/internal/parse/syntax/props.js +119 -0
- package/dist/internal/parse/token-processor.js +25 -24
- package/dist/internal/props-validation.js +4 -9
- package/dist/internal/stringify/attributes.js +4 -1
- package/dist/internal/stringify/handlers/a.js +1 -3
- package/dist/internal/stringify/handlers/blockquote.js +2 -4
- package/dist/internal/stringify/handlers/code.js +1 -3
- package/dist/internal/stringify/handlers/emphesis.js +1 -3
- package/dist/internal/stringify/handlers/html.js +26 -16
- package/dist/internal/stringify/handlers/img.js +1 -3
- package/dist/internal/stringify/handlers/li.js +14 -8
- package/dist/internal/stringify/handlers/mdc.js +2 -3
- package/dist/internal/stringify/handlers/ol.js +1 -1
- package/dist/internal/stringify/handlers/p.d.ts +1 -1
- package/dist/internal/stringify/handlers/p.js +4 -1
- package/dist/internal/stringify/handlers/pre.js +10 -13
- package/dist/internal/stringify/handlers/strong.js +1 -3
- package/dist/internal/stringify/handlers/table.js +7 -5
- package/dist/internal/stringify/handlers/template.js +1 -1
- package/dist/internal/stringify/handlers/ul.js +1 -1
- package/dist/internal/stringify/indent.d.ts +1 -5
- package/dist/internal/stringify/indent.js +1 -9
- package/dist/internal/stringify/state.js +1 -1
- package/dist/internal/yaml.js +1 -1
- package/dist/parse.js +14 -8
- package/dist/plugins/alert.js +1 -1
- package/dist/plugins/binding.js +1 -3
- package/dist/plugins/breaks.js +1 -1
- package/dist/plugins/emoji.js +8 -8
- package/dist/plugins/footnotes.js +19 -13
- package/dist/plugins/headings.js +2 -4
- package/dist/plugins/highlight.d.ts +1 -11
- package/dist/plugins/highlight.js +198 -103
- package/dist/plugins/json-render.js +5 -9
- package/dist/plugins/math.js +4 -6
- package/dist/plugins/mermaid.js +6 -20
- package/dist/plugins/punctuation.js +5 -6
- package/dist/plugins/security.js +2 -2
- package/dist/plugins/syntax.d.ts +49 -0
- package/dist/plugins/syntax.js +522 -0
- package/dist/plugins/task-list.d.ts +1 -1
- package/dist/plugins/task-list.js +11 -8
- package/dist/plugins/toc.js +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/utils/comark.tmLanguage.d.ts +335 -0
- package/dist/utils/comark.tmLanguage.js +597 -0
- package/dist/utils/helpers.js +1 -3
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.js +25 -3
- package/package.json +49 -51
- package/skills/skills/comark/AGENTS.md +0 -261
- package/skills/skills/comark/SKILL.md +0 -489
- package/skills/skills/comark/references/markdown-syntax.md +0 -599
- package/skills/skills/comark/references/parsing-ast.md +0 -378
- package/skills/skills/comark/references/rendering-react.md +0 -445
- package/skills/skills/comark/references/rendering-svelte.md +0 -453
- package/skills/skills/comark/references/rendering-vue.md +0 -462
- /package/skills/{skills/migrate-mdc-to-comark → migrate-mdc-to-comark}/SKILL.md +0 -0
|
@@ -1,378 +0,0 @@
|
|
|
1
|
-
# Parsing & AST Generation
|
|
2
|
-
|
|
3
|
-
Complete guide for parsing Comark documents and working with the Comark AST format.
|
|
4
|
-
|
|
5
|
-
## Table of Contents
|
|
6
|
-
|
|
7
|
-
- [String Parsing](#string-parsing)
|
|
8
|
-
- [Async Parsing with Syntax Highlighting](#async-parsing-with-syntax-highlighting)
|
|
9
|
-
- [AST Structure](#ast-structure)
|
|
10
|
-
- [Rendering AST](#rendering-ast)
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## String Parsing
|
|
15
|
-
|
|
16
|
-
The primary way to parse Comark content is using the `parse()` function:
|
|
17
|
-
|
|
18
|
-
```typescript
|
|
19
|
-
import { parse } from 'comark'
|
|
20
|
-
|
|
21
|
-
const content = `---
|
|
22
|
-
title: My Document
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
# Hello World
|
|
26
|
-
|
|
27
|
-
This is **markdown** with :icon-star component.
|
|
28
|
-
|
|
29
|
-
::alert{type="info"}
|
|
30
|
-
Important message here
|
|
31
|
-
::
|
|
32
|
-
`
|
|
33
|
-
|
|
34
|
-
const result = await parse(content)
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
### Result Structure
|
|
38
|
-
|
|
39
|
-
```typescript
|
|
40
|
-
interface ComarkTree {
|
|
41
|
-
nodes: ComarkNode[] // Parsed AST nodes
|
|
42
|
-
frontmatter: Record<string, any> // YAML frontmatter data
|
|
43
|
-
meta: {
|
|
44
|
-
toc?: any // Table of contents (from toc plugin)
|
|
45
|
-
summary?: ComarkNode[] // Summary content (from summary plugin)
|
|
46
|
-
[key: string]: any // Other plugin metadata
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
### Parse Options
|
|
52
|
-
|
|
53
|
-
```typescript
|
|
54
|
-
interface ParseOptions {
|
|
55
|
-
autoUnwrap?: boolean // Remove unnecessary <p> wrappers (default: true)
|
|
56
|
-
autoClose?: boolean // Auto-close unclosed syntax (default: true)
|
|
57
|
-
plugins?: ComarkPlugin[] // Enable plugins (e.g., highlight, emoji, toc)
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### Examples
|
|
62
|
-
|
|
63
|
-
```typescript
|
|
64
|
-
// Default parsing
|
|
65
|
-
const result = await parse(content)
|
|
66
|
-
|
|
67
|
-
// Disable auto-unwrap
|
|
68
|
-
const result = await parse(content, { autoUnwrap: false })
|
|
69
|
-
|
|
70
|
-
// Disable auto-close
|
|
71
|
-
const result = await parse(content, { autoClose: false })
|
|
72
|
-
|
|
73
|
-
// Both disabled
|
|
74
|
-
const result = await parse(content, {
|
|
75
|
-
autoUnwrap: false,
|
|
76
|
-
autoClose: false
|
|
77
|
-
})
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### Auto-Unwrap Feature
|
|
81
|
-
|
|
82
|
-
Auto-unwrap removes unnecessary paragraph wrappers from container components:
|
|
83
|
-
|
|
84
|
-
**Without auto-unwrap:**
|
|
85
|
-
```json
|
|
86
|
-
["alert", {}, ["p", {}, "Text"]]
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
**With auto-unwrap:**
|
|
90
|
-
```json
|
|
91
|
-
["alert", {}, "Text"]
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
Auto-unwrap applies to any component whose only child is a single paragraph.
|
|
95
|
-
|
|
96
|
-
### Auto-Close Feature
|
|
97
|
-
|
|
98
|
-
Auto-close automatically closes unclosed markdown syntax, essential for streaming:
|
|
99
|
-
|
|
100
|
-
```typescript
|
|
101
|
-
import { autoCloseMarkdown } from 'comark'
|
|
102
|
-
|
|
103
|
-
// Unclosed bold
|
|
104
|
-
const partial = '**bold text'
|
|
105
|
-
const closed = autoCloseMarkdown(partial)
|
|
106
|
-
// Result: '**bold text**'
|
|
107
|
-
|
|
108
|
-
// Unclosed component
|
|
109
|
-
const component = '::alert{type="info"}\nMessage'
|
|
110
|
-
const closedComponent = autoCloseMarkdown(component)
|
|
111
|
-
// Result: '::alert{type="info"}\nMessage\n::'
|
|
112
|
-
|
|
113
|
-
// Unclosed properties
|
|
114
|
-
const props = 'Text {prop="value'
|
|
115
|
-
const closedProps = autoCloseMarkdown(props)
|
|
116
|
-
// Result: 'Text {prop="value"}'
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
**Auto-close handles:**
|
|
120
|
-
- Inline markers: `*`, `**`, `***`, `~~`, backticks
|
|
121
|
-
- Brackets: `[`, `]`, `(`, `)`
|
|
122
|
-
- Comark components: `::component`
|
|
123
|
-
- Property braces: `{...}`
|
|
124
|
-
|
|
125
|
-
---
|
|
126
|
-
|
|
127
|
-
## Async Parsing with Syntax Highlighting
|
|
128
|
-
|
|
129
|
-
For syntax highlighting support, use the `highlight` plugin:
|
|
130
|
-
|
|
131
|
-
```typescript
|
|
132
|
-
import { parse } from 'comark'
|
|
133
|
-
import highlight from 'comark/plugins/highlight'
|
|
134
|
-
|
|
135
|
-
const content = `
|
|
136
|
-
# Code Example
|
|
137
|
-
|
|
138
|
-
\`\`\`javascript
|
|
139
|
-
function hello() {
|
|
140
|
-
console.log("Hello!")
|
|
141
|
-
}
|
|
142
|
-
\`\`\`
|
|
143
|
-
`
|
|
144
|
-
|
|
145
|
-
// Enable syntax highlighting
|
|
146
|
-
const result = await parse(content, {
|
|
147
|
-
plugins: [highlight()]
|
|
148
|
-
})
|
|
149
|
-
|
|
150
|
-
// With custom Shiki options
|
|
151
|
-
const result = await parse(content, {
|
|
152
|
-
plugins: [
|
|
153
|
-
highlight({
|
|
154
|
-
themes: {
|
|
155
|
-
light: 'github-light',
|
|
156
|
-
dark: 'github-dark'
|
|
157
|
-
},
|
|
158
|
-
languages: ['javascript', 'typescript', 'python']
|
|
159
|
-
})
|
|
160
|
-
]
|
|
161
|
-
})
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
### Highlight Plugin Options
|
|
165
|
-
|
|
166
|
-
```typescript
|
|
167
|
-
interface HighlightOptions {
|
|
168
|
-
registerDefaultLanguages?: boolean // default: true
|
|
169
|
-
registerDefaultThemes?: boolean // default: true
|
|
170
|
-
themes?: {
|
|
171
|
-
light?: ThemeRegistration // default: 'material-theme-lighter'
|
|
172
|
-
dark?: ThemeRegistration // default: 'material-theme-palenight'
|
|
173
|
-
}
|
|
174
|
-
languages?: Array<LanguageRegistration | LanguageRegistration[]> // Load on demand by default
|
|
175
|
-
transformers?: ShikiTransformer[]
|
|
176
|
-
preStyles?: boolean // Add pre background/foreground styles
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
### Dual Theme Support
|
|
181
|
-
|
|
182
|
-
```typescript
|
|
183
|
-
import highlight from 'comark/plugins/highlight'
|
|
184
|
-
|
|
185
|
-
const result = await parse(content, {
|
|
186
|
-
plugins: [
|
|
187
|
-
highlight({
|
|
188
|
-
themes: {
|
|
189
|
-
light: 'github-light',
|
|
190
|
-
dark: 'github-dark'
|
|
191
|
-
}
|
|
192
|
-
})
|
|
193
|
-
]
|
|
194
|
-
})
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
---
|
|
198
|
-
|
|
199
|
-
## AST Structure
|
|
200
|
-
|
|
201
|
-
Comark uses a lightweight array-based AST structure.
|
|
202
|
-
|
|
203
|
-
### Comark AST Format
|
|
204
|
-
|
|
205
|
-
```typescript
|
|
206
|
-
interface ComarkTree {
|
|
207
|
-
nodes: ComarkNode[] // Parsed AST nodes
|
|
208
|
-
frontmatter: Record<string, any> // YAML frontmatter data
|
|
209
|
-
meta: {
|
|
210
|
-
toc?: any // Table of contents (from toc plugin)
|
|
211
|
-
summary?: ComarkNode[] // Summary content (from summary plugin)
|
|
212
|
-
[key: string]: any // Other plugin metadata
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
type ComarkNode =
|
|
217
|
-
| string // Text nodes
|
|
218
|
-
| [tag: string, props?: Record<string, any>, ...children: ComarkNode[]]
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
### Node Structure
|
|
222
|
-
|
|
223
|
-
**Text Node:**
|
|
224
|
-
```json
|
|
225
|
-
"plain text content"
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
**Element Node:**
|
|
229
|
-
```json
|
|
230
|
-
["tag", { "prop": "value" }, ...children]
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
### Examples
|
|
234
|
-
|
|
235
|
-
```json
|
|
236
|
-
// Paragraph with text
|
|
237
|
-
["p", {}, "Simple paragraph"]
|
|
238
|
-
|
|
239
|
-
// Paragraph with bold text
|
|
240
|
-
["p", {}, "Text with ", ["strong", {}, "bold"], " word"]
|
|
241
|
-
|
|
242
|
-
// Heading with ID
|
|
243
|
-
["h1", { "id": "hello-world" }, "Hello World"]
|
|
244
|
-
|
|
245
|
-
// Link with attributes
|
|
246
|
-
["a", { "href": "https://example.com", "target": "_blank" }, "Link"]
|
|
247
|
-
|
|
248
|
-
// Comark Component
|
|
249
|
-
["alert", { "type": "info" }, ["p", {}, "Message"]]
|
|
250
|
-
|
|
251
|
-
// Component with slots
|
|
252
|
-
[
|
|
253
|
-
"card",
|
|
254
|
-
{},
|
|
255
|
-
["template", { "name": "header" }, ["h2", {}, "Title"]],
|
|
256
|
-
["template", { "name": "content" }, ["p", {}, "Content"]]
|
|
257
|
-
]
|
|
258
|
-
|
|
259
|
-
// Default slot: content without #slot-name becomes direct children
|
|
260
|
-
["component", {}, "hello"]
|
|
261
|
-
|
|
262
|
-
// Explicit #default wraps in a template node (equivalent in rendering)
|
|
263
|
-
["component", {}, ["template", { "name": "default" }, "hello"]]
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
### Complete AST Example
|
|
267
|
-
|
|
268
|
-
**Input:**
|
|
269
|
-
```markdown
|
|
270
|
-
---
|
|
271
|
-
title: Example
|
|
272
|
-
---
|
|
273
|
-
|
|
274
|
-
# Hello World
|
|
275
|
-
|
|
276
|
-
This is **bold** and *italic* text.
|
|
277
|
-
|
|
278
|
-
::alert{type="warning"}
|
|
279
|
-
Warning message
|
|
280
|
-
::
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
**AST:**
|
|
284
|
-
```json
|
|
285
|
-
{
|
|
286
|
-
"nodes": [
|
|
287
|
-
[
|
|
288
|
-
"h1",
|
|
289
|
-
{ "id": "hello-world" },
|
|
290
|
-
"Hello World"
|
|
291
|
-
],
|
|
292
|
-
[
|
|
293
|
-
"p",
|
|
294
|
-
{},
|
|
295
|
-
"This is ",
|
|
296
|
-
["strong", {}, "bold"],
|
|
297
|
-
" and ",
|
|
298
|
-
["em", {}, "italic"],
|
|
299
|
-
" text."
|
|
300
|
-
],
|
|
301
|
-
[
|
|
302
|
-
"alert",
|
|
303
|
-
{ "type": "warning" },
|
|
304
|
-
["p", {}, "Warning message"]
|
|
305
|
-
]
|
|
306
|
-
],
|
|
307
|
-
"frontmatter": {
|
|
308
|
-
"title": "Example"
|
|
309
|
-
},
|
|
310
|
-
"meta": {}
|
|
311
|
-
}
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
### Property Conventions
|
|
315
|
-
|
|
316
|
-
- **Boolean props:** `:bool="true"` (props starting with `:`)
|
|
317
|
-
- **Standard props:** `key="value"`
|
|
318
|
-
- **ID:** `id="value"` (from `{#value}`)
|
|
319
|
-
- **Class:** `class="value"` (from `{.value}`)
|
|
320
|
-
- **Custom data:** Any attribute name and value
|
|
321
|
-
|
|
322
|
-
---
|
|
323
|
-
|
|
324
|
-
## Rendering AST
|
|
325
|
-
|
|
326
|
-
### Render to HTML
|
|
327
|
-
|
|
328
|
-
```typescript
|
|
329
|
-
import { parse } from 'comark'
|
|
330
|
-
import { renderHTML } from '@comark/html'
|
|
331
|
-
|
|
332
|
-
const content = '# Hello World\n\nThis is **markdown**.'
|
|
333
|
-
const tree = await parse(content)
|
|
334
|
-
|
|
335
|
-
const html = renderHTML(tree)
|
|
336
|
-
console.log(html)
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
**Output:**
|
|
340
|
-
```html
|
|
341
|
-
<h1 id="hello-world">Hello World</h1>
|
|
342
|
-
<p>This is <strong>markdown</strong>.</p>
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
### Render to Markdown
|
|
346
|
-
|
|
347
|
-
Convert AST back to Comark markdown:
|
|
348
|
-
|
|
349
|
-
```typescript
|
|
350
|
-
import { parse } from 'comark'
|
|
351
|
-
import { renderMarkdown } from 'comark/render'
|
|
352
|
-
|
|
353
|
-
const content = '# Hello\n\n::alert{type="info"}\nMessage\n::'
|
|
354
|
-
const result = await parse(content)
|
|
355
|
-
|
|
356
|
-
const markdown = renderMarkdown(result.nodes)
|
|
357
|
-
console.log(markdown)
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
**Output:**
|
|
361
|
-
```markdown
|
|
362
|
-
# Hello
|
|
363
|
-
|
|
364
|
-
::alert{type="info"}
|
|
365
|
-
Message
|
|
366
|
-
::
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
### Use Cases
|
|
370
|
-
|
|
371
|
-
- Round-trip parsing (parse → modify AST → render back)
|
|
372
|
-
- AST transformation
|
|
373
|
-
- Content normalization
|
|
374
|
-
- Markdown generation from programmatic AST
|
|
375
|
-
|
|
376
|
-
---
|
|
377
|
-
|
|
378
|
-
[← Back to Main Skills Guide](../../SKILLS.md)
|