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
package/dist/utils/index.js
CHANGED
|
@@ -38,10 +38,12 @@ visitor) {
|
|
|
38
38
|
const res = visitor(node);
|
|
39
39
|
if (res === false) {
|
|
40
40
|
// remove the node from the parent
|
|
41
|
+
;
|
|
41
42
|
parent.splice(index, 1);
|
|
42
43
|
return true; // signal that node was removed
|
|
43
44
|
}
|
|
44
45
|
if (res !== undefined) {
|
|
46
|
+
;
|
|
45
47
|
parent[index] = res;
|
|
46
48
|
currentNode = res;
|
|
47
49
|
}
|
|
@@ -72,13 +74,29 @@ visitor) {
|
|
|
72
74
|
}
|
|
73
75
|
}
|
|
74
76
|
// #region String Utils
|
|
77
|
+
export function indent(text, { ignoreFirstLine = false, level = 1, width } = {}) {
|
|
78
|
+
const pad = width ? ' '.repeat(width) : ' '.repeat(level);
|
|
79
|
+
return text
|
|
80
|
+
.split('\n')
|
|
81
|
+
.map((line, index) => {
|
|
82
|
+
if (ignoreFirstLine && index === 0) {
|
|
83
|
+
return line;
|
|
84
|
+
}
|
|
85
|
+
return line ? pad + line : line;
|
|
86
|
+
})
|
|
87
|
+
.join('\n');
|
|
88
|
+
}
|
|
75
89
|
/**
|
|
76
90
|
* Convert a string to pascal case
|
|
77
91
|
* @param str - The string to convert
|
|
78
92
|
* @returns The pascal case string
|
|
79
93
|
*/
|
|
80
94
|
export function pascalCase(str) {
|
|
81
|
-
return str
|
|
95
|
+
return str
|
|
96
|
+
? splitByCase(str)
|
|
97
|
+
.map((p) => (p ? p[0].toUpperCase() + p.slice(1) : ''))
|
|
98
|
+
.join('')
|
|
99
|
+
: '';
|
|
82
100
|
}
|
|
83
101
|
/**
|
|
84
102
|
* Convert a string to kebab case
|
|
@@ -86,7 +104,11 @@ export function pascalCase(str) {
|
|
|
86
104
|
* @returns The kebab case string
|
|
87
105
|
*/
|
|
88
106
|
export function kebabCase(str) {
|
|
89
|
-
return str
|
|
107
|
+
return str
|
|
108
|
+
? splitByCase(str)
|
|
109
|
+
.map((p) => p.toLowerCase())
|
|
110
|
+
.join('-')
|
|
111
|
+
: '';
|
|
90
112
|
}
|
|
91
113
|
/**
|
|
92
114
|
* Convert a string to camel case
|
|
@@ -123,7 +145,7 @@ function splitByCase(str) {
|
|
|
123
145
|
const charCode = char.charCodeAt(0);
|
|
124
146
|
const isNumber = charCode >= 48 && charCode <= 57; // '0' to '9'
|
|
125
147
|
// Fast uppercase check using character codes
|
|
126
|
-
const isUpper = isNumber ? void 0 :
|
|
148
|
+
const isUpper = isNumber ? void 0 : charCode >= 65 && charCode <= 90; // 'A' to 'Z'
|
|
127
149
|
if (previousSplitter === false) {
|
|
128
150
|
if (previousUpper === false && isUpper === true) {
|
|
129
151
|
parts.push(buff);
|
package/package.json
CHANGED
|
@@ -1,26 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "comark",
|
|
3
|
-
"
|
|
4
|
-
"version": "0.3.0",
|
|
3
|
+
"version": "0.3.2",
|
|
5
4
|
"description": "Components in Markdown (Comark) parser with streaming support for Vue, React, Svelte and HTML",
|
|
6
|
-
"author": "",
|
|
7
|
-
"license": "MIT",
|
|
8
|
-
"repository": {
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/comarkdown/comark.git"
|
|
11
|
-
},
|
|
12
|
-
"bugs": {
|
|
13
|
-
"url": "https://github.com/comarkdown/comark/issues"
|
|
14
|
-
},
|
|
15
|
-
"homepage": "https://comark.dev",
|
|
16
5
|
"keywords": [
|
|
17
6
|
"markdown",
|
|
18
7
|
"mdc",
|
|
19
8
|
"parser",
|
|
9
|
+
"react",
|
|
20
10
|
"streaming",
|
|
21
|
-
"vue"
|
|
22
|
-
|
|
11
|
+
"vue"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://comark.dev",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/comarkdown/comark/issues"
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"author": "",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/comarkdown/comark.git"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"skills"
|
|
23
26
|
],
|
|
27
|
+
"type": "module",
|
|
28
|
+
"main": "./dist/index.js",
|
|
29
|
+
"module": "./dist/index.js",
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
24
31
|
"exports": {
|
|
25
32
|
".": "./dist/index.js",
|
|
26
33
|
"./plugins/*": "./dist/plugins/*.js",
|
|
@@ -28,29 +35,31 @@
|
|
|
28
35
|
"./parse": "./dist/parse.js",
|
|
29
36
|
"./render": "./dist/render.js"
|
|
30
37
|
},
|
|
31
|
-
"main": "./dist/index.js",
|
|
32
|
-
"module": "./dist/index.js",
|
|
33
|
-
"types": "./dist/index.d.ts",
|
|
34
|
-
"files": [
|
|
35
|
-
"dist",
|
|
36
|
-
"skills"
|
|
37
|
-
],
|
|
38
38
|
"publishConfig": {
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
"
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"entities": "^8.0.0",
|
|
43
|
+
"htmlparser2": "^12.0.0",
|
|
44
|
+
"js-yaml": "^4.1.1",
|
|
45
|
+
"markdown-exit": "1.0.0-beta.9"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@json-render/core": "^0.16.0",
|
|
49
|
+
"@shikijs/twoslash": "^4.0.2",
|
|
50
|
+
"@types/js-yaml": "^4.0.9",
|
|
51
|
+
"@types/markdown-it": "^14.1.2",
|
|
52
|
+
"github-slugger": "^2.0.0",
|
|
53
|
+
"hast-util-to-string": "^3.0.1",
|
|
54
|
+
"minimark": "0.2.0",
|
|
55
|
+
"tsx": "^4.21.0",
|
|
56
|
+
"twoslash": "^0.3.6",
|
|
57
|
+
"vitest": "^4.1.4"
|
|
49
58
|
},
|
|
50
59
|
"peerDependencies": {
|
|
51
|
-
"beautiful-mermaid": "
|
|
52
|
-
"katex": "
|
|
53
|
-
"shiki": "
|
|
60
|
+
"beautiful-mermaid": "^1.1.3",
|
|
61
|
+
"katex": "^0.16.45",
|
|
62
|
+
"shiki": "^4.0.0"
|
|
54
63
|
},
|
|
55
64
|
"peerDependenciesMeta": {
|
|
56
65
|
"shiki": {
|
|
@@ -63,23 +72,12 @@
|
|
|
63
72
|
"optional": true
|
|
64
73
|
}
|
|
65
74
|
},
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"minimark": "catalog:",
|
|
74
|
-
"tsx": "catalog:",
|
|
75
|
-
"twoslash": "catalog:",
|
|
76
|
-
"vitest": "catalog:"
|
|
77
|
-
},
|
|
78
|
-
"dependencies": {
|
|
79
|
-
"@comark/markdown-it": "catalog:",
|
|
80
|
-
"entities": "catalog:",
|
|
81
|
-
"htmlparser2": "catalog:",
|
|
82
|
-
"js-yaml": "catalog:",
|
|
83
|
-
"markdown-exit": "catalog:"
|
|
75
|
+
"scripts": {
|
|
76
|
+
"stub": "node ../../scripts/stub.mjs",
|
|
77
|
+
"build": "tsc",
|
|
78
|
+
"dev": "tsc --watch",
|
|
79
|
+
"test": "vitest run",
|
|
80
|
+
"release": "release-it",
|
|
81
|
+
"release:dry": "release-it --dry-run"
|
|
84
82
|
}
|
|
85
|
-
}
|
|
83
|
+
}
|
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
# Comark — AI Agents & LLM Streaming
|
|
2
|
-
|
|
3
|
-
A guide for using Comark in AI agent and LLM-powered applications where markdown is generated incrementally by a language model.
|
|
4
|
-
|
|
5
|
-
## Why Comark for AI?
|
|
6
|
-
|
|
7
|
-
LLMs stream markdown token-by-token. Standard markdown parsers expect complete input — they fail or produce broken output on partial streams. Comark was built to handle exactly this:
|
|
8
|
-
|
|
9
|
-
- **`autoClose`** (default: `true`) — incomplete syntax like `**bold text` is automatically closed on every parse, so partial tokens always render correctly
|
|
10
|
-
- **Streaming mode** — re-renders efficiently as content arrives
|
|
11
|
-
- **Caret indicator** — shows a live cursor during generation
|
|
12
|
-
- **ANSI rendering** — styled terminal output for CLI agents
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## Vue
|
|
17
|
-
|
|
18
|
-
```vue
|
|
19
|
-
<script setup lang="ts">
|
|
20
|
-
import { ref } from 'vue'
|
|
21
|
-
import { Comark } from '@comark/vue'
|
|
22
|
-
|
|
23
|
-
const content = ref('')
|
|
24
|
-
const streaming = ref(false)
|
|
25
|
-
|
|
26
|
-
async function generate(prompt: string) {
|
|
27
|
-
content.value = ''
|
|
28
|
-
streaming.value = true
|
|
29
|
-
|
|
30
|
-
const res = await fetch('/api/chat', {
|
|
31
|
-
method: 'POST',
|
|
32
|
-
body: JSON.stringify({ prompt }),
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
const reader = res.body!.getReader()
|
|
36
|
-
const decoder = new TextDecoder()
|
|
37
|
-
|
|
38
|
-
while (true) {
|
|
39
|
-
const { done, value } = await reader.read()
|
|
40
|
-
if (done) break
|
|
41
|
-
content.value += decoder.decode(value, { stream: true })
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
streaming.value = false
|
|
45
|
-
}
|
|
46
|
-
</script>
|
|
47
|
-
|
|
48
|
-
<template>
|
|
49
|
-
<Comark :streaming="streaming" caret>{{ content }}</Comark>
|
|
50
|
-
</template>
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
---
|
|
54
|
-
|
|
55
|
-
## React
|
|
56
|
-
|
|
57
|
-
```tsx
|
|
58
|
-
import { useState } from 'react'
|
|
59
|
-
import { Comark } from '@comark/react'
|
|
60
|
-
|
|
61
|
-
export default function Chat() {
|
|
62
|
-
const [content, setContent] = useState('')
|
|
63
|
-
const [streaming, setStreaming] = useState(false)
|
|
64
|
-
|
|
65
|
-
async function generate(prompt: string) {
|
|
66
|
-
setContent('')
|
|
67
|
-
setStreaming(true)
|
|
68
|
-
|
|
69
|
-
const res = await fetch('/api/chat', {
|
|
70
|
-
method: 'POST',
|
|
71
|
-
body: JSON.stringify({ prompt }),
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
const reader = res.body!.getReader()
|
|
75
|
-
const decoder = new TextDecoder()
|
|
76
|
-
|
|
77
|
-
while (true) {
|
|
78
|
-
const { done, value } = await reader.read()
|
|
79
|
-
if (done) break
|
|
80
|
-
setContent(prev => prev + decoder.decode(value, { stream: true }))
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
setStreaming(false)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return <Comark streaming={streaming} caret>{content}</Comark>
|
|
87
|
-
}
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
---
|
|
91
|
-
|
|
92
|
-
## Svelte
|
|
93
|
-
|
|
94
|
-
```svelte
|
|
95
|
-
<script lang="ts">
|
|
96
|
-
import { Comark } from '@comark/svelte'
|
|
97
|
-
|
|
98
|
-
let content = $state('')
|
|
99
|
-
let streaming = $state(false)
|
|
100
|
-
|
|
101
|
-
async function generate(prompt: string) {
|
|
102
|
-
content = ''
|
|
103
|
-
streaming = true
|
|
104
|
-
|
|
105
|
-
const res = await fetch('/api/chat', {
|
|
106
|
-
method: 'POST',
|
|
107
|
-
body: JSON.stringify({ prompt }),
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
const reader = res.body!.getReader()
|
|
111
|
-
const decoder = new TextDecoder()
|
|
112
|
-
|
|
113
|
-
while (true) {
|
|
114
|
-
const { done, value } = await reader.read()
|
|
115
|
-
if (done) break
|
|
116
|
-
content += decoder.decode(value, { stream: true })
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
streaming = false
|
|
120
|
-
}
|
|
121
|
-
</script>
|
|
122
|
-
|
|
123
|
-
<Comark markdown={content} {streaming} caret />
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
---
|
|
127
|
-
|
|
128
|
-
## Terminal / CLI Agents
|
|
129
|
-
|
|
130
|
-
Use `@comark/ansi` to render LLM markdown output in terminal-based agents:
|
|
131
|
-
|
|
132
|
-
```typescript
|
|
133
|
-
import { log } from '@comark/ansi'
|
|
134
|
-
|
|
135
|
-
// Print a complete LLM response to stdout with ANSI styling
|
|
136
|
-
await log(llmResponse)
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
For streaming terminal output, use `createLog` with a custom `write` function:
|
|
140
|
-
|
|
141
|
-
```typescript
|
|
142
|
-
import { createLog } from '@comark/ansi'
|
|
143
|
-
|
|
144
|
-
const logStream = createLog({
|
|
145
|
-
write: (s) => process.stdout.write(s),
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
// Call after each chunk to show partial output
|
|
149
|
-
await logStream(partialMarkdown)
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
---
|
|
153
|
-
|
|
154
|
-
## Caret Customization
|
|
155
|
-
|
|
156
|
-
The `caret` prop appends a blinking cursor to the last text node while `streaming` is `true`. Customize it with a CSS class:
|
|
157
|
-
|
|
158
|
-
```vue
|
|
159
|
-
<Comark :streaming="streaming" :caret="{ class: 'animate-blink' }">{{ content }}</Comark>
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
```tsx
|
|
163
|
-
<Comark streaming={streaming} caret={{ class: 'animate-blink' }}>{content}</Comark>
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
```svelte
|
|
167
|
-
<Comark markdown={content} {streaming} caret={{ class: 'animate-blink' }} />
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
---
|
|
171
|
-
|
|
172
|
-
## With Custom Components
|
|
173
|
-
|
|
174
|
-
If your LLM produces Comark component syntax (e.g., `::alert`), register components before streaming begins:
|
|
175
|
-
|
|
176
|
-
```vue
|
|
177
|
-
<script setup lang="ts">
|
|
178
|
-
import { Comark } from '@comark/vue'
|
|
179
|
-
import Alert from './Alert.vue'
|
|
180
|
-
import CodeBlock from './CodeBlock.vue'
|
|
181
|
-
</script>
|
|
182
|
-
|
|
183
|
-
<template>
|
|
184
|
-
<Comark :components="{ alert: Alert, pre: CodeBlock }" :streaming="streaming" caret>
|
|
185
|
-
{{ content }}
|
|
186
|
-
</Comark>
|
|
187
|
-
</template>
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
---
|
|
191
|
-
|
|
192
|
-
## With Syntax Highlighting
|
|
193
|
-
|
|
194
|
-
Syntax highlighting works during streaming — each re-parse will highlight newly completed code blocks:
|
|
195
|
-
|
|
196
|
-
```vue
|
|
197
|
-
<script setup lang="ts">
|
|
198
|
-
import { Comark } from '@comark/vue'
|
|
199
|
-
import highlight from '@comark/vue/plugins/highlight'
|
|
200
|
-
import githubDark from '@shikijs/themes/github-dark'
|
|
201
|
-
|
|
202
|
-
const plugins = [highlight({ themes: { light: githubDark, dark: githubDark } })]
|
|
203
|
-
</script>
|
|
204
|
-
|
|
205
|
-
<template>
|
|
206
|
-
<Suspense>
|
|
207
|
-
<Comark :plugins="plugins" :streaming="streaming" caret>{{ content }}</Comark>
|
|
208
|
-
</Suspense>
|
|
209
|
-
</template>
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
```tsx
|
|
213
|
-
import { Comark } from '@comark/react'
|
|
214
|
-
import highlight from '@comark/react/plugins/highlight'
|
|
215
|
-
import githubDark from '@shikijs/themes/github-dark'
|
|
216
|
-
|
|
217
|
-
const plugins = [highlight({ themes: { light: githubDark, dark: githubDark } })]
|
|
218
|
-
|
|
219
|
-
export default function Chat({ content, streaming }) {
|
|
220
|
-
return (
|
|
221
|
-
<Comark plugins={plugins} streaming={streaming} caret>
|
|
222
|
-
{content}
|
|
223
|
-
</Comark>
|
|
224
|
-
)
|
|
225
|
-
}
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
---
|
|
229
|
-
|
|
230
|
-
## defineComarkComponent for AI Chat
|
|
231
|
-
|
|
232
|
-
Pre-configure a Comark component for your AI chat UI once, then reuse it everywhere:
|
|
233
|
-
|
|
234
|
-
```typescript
|
|
235
|
-
// comark.ts
|
|
236
|
-
import { defineComarkComponent } from '@comark/vue'
|
|
237
|
-
import highlight from '@comark/vue/plugins/highlight'
|
|
238
|
-
import math, { Math } from '@comark/vue/plugins/math'
|
|
239
|
-
import githubDark from '@shikijs/themes/github-dark'
|
|
240
|
-
import Alert from './components/Alert.vue'
|
|
241
|
-
|
|
242
|
-
export const ChatComark = defineComarkComponent({
|
|
243
|
-
name: 'ChatComark',
|
|
244
|
-
plugins: [
|
|
245
|
-
math(),
|
|
246
|
-
highlight({ themes: { light: githubDark, dark: githubDark } }),
|
|
247
|
-
],
|
|
248
|
-
components: { Math, alert: Alert },
|
|
249
|
-
autoClose: true,
|
|
250
|
-
})
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
```vue
|
|
254
|
-
<template>
|
|
255
|
-
<ChatComark :streaming="streaming" caret>{{ content }}</ChatComark>
|
|
256
|
-
</template>
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
---
|
|
260
|
-
|
|
261
|
-
[← Back to Skills Guide](./SKILL.md)
|