svmarkdown 0.1.0

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 grtsinry43
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,210 @@
1
+ # svmarkdown (Svelte Markdown)
2
+
3
+ Runtime-first Markdown rendering for Svelte.
4
+
5
+ - Parser: `markdown-it`
6
+ - Core output: custom AST/Blocks (not HTML strings)
7
+ - Renderer: declarative Svelte component tree (no DOM scan/mount pipeline)
8
+
9
+ [中文文档 (zh-CN)](./README.zh-CN.md)
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ pnpm add svmarkdown
15
+ ```
16
+
17
+ ## Quick Start
18
+
19
+ ```svelte
20
+ <script lang="ts">
21
+ import { Markdown } from 'svmarkdown'
22
+ import Link from './Link.svelte'
23
+ import Image from './Image.svelte'
24
+ import Code from './Code.svelte'
25
+
26
+ let content = $state('Visit [Svelte](https://svelte.dev) and `inline code`')
27
+
28
+ const components = {
29
+ a: Link,
30
+ img: Image,
31
+ code: Code,
32
+ }
33
+ </script>
34
+
35
+ <Markdown {content} {components} />
36
+ ```
37
+
38
+ ## Custom Component Syntax
39
+
40
+ ### 1. Container (`:::`)
41
+
42
+ just use ::: [component] key="value" to create a component block, and the content inside will be passed as `children` prop.
43
+
44
+ ```md
45
+ ::: Alert type=warning title="Heads up"
46
+ This is **Markdown children**.
47
+ :::
48
+ ```
49
+
50
+ ### 2. Fence (```)
51
+
52
+ just use ```component:[component] {"key":"value"} to create a component block, and the content inside will be passed as `children` prop.
53
+
54
+ ````md
55
+ ```component:Chart {"title":"Traffic"}
56
+ month,visits
57
+ Jan,421
58
+ Feb,530
59
+ ```
60
+ ````
61
+
62
+ ## API
63
+
64
+ ```ts
65
+ import { Markdown, createParser, parseMarkdown } from 'svmarkdown'
66
+ ```
67
+
68
+ - `parseMarkdown(markdown, options)`: parse once, returns `SvmdRoot`
69
+ - `createParser(options)`: create a reusable parser for frequent updates
70
+ - `<Markdown />`: runtime rendering with an `AST -> Svelte tree` update path
71
+
72
+ ## Parse Options
73
+
74
+ ```ts
75
+ import type { SvmdParseOptions } from 'svmarkdown'
76
+
77
+ const options: SvmdParseOptions = {
78
+ componentBlocks: {
79
+ Alert: true,
80
+ Chart: {
81
+ container: false,
82
+ fence: true,
83
+ parseFenceBodyAsMarkdown: false,
84
+ },
85
+ },
86
+ fenceComponentPrefix: 'component:',
87
+ }
88
+ ```
89
+
90
+ ## Development
91
+
92
+ ```bash
93
+ pnpm install
94
+ pnpm run typecheck
95
+ pnpm run test
96
+ pnpm run build
97
+ pnpm run play
98
+ ```
99
+
100
+ ## Advanced Extensions
101
+
102
+ ### Configure component blocks
103
+
104
+ ```ts
105
+ const parseOptions: SvmdParseOptions = {
106
+ componentBlocks: {
107
+ Alert: true,
108
+ Note: { container: true, fence: false },
109
+ Chart: { container: false, fence: true },
110
+ Card: { fence: true, parseFenceBodyAsMarkdown: true },
111
+ },
112
+ }
113
+ ```
114
+
115
+ ### Custom props parsing
116
+
117
+ ```ts
118
+ const parseOptions: SvmdParseOptions = {
119
+ componentBlocks: {
120
+ Alert: {
121
+ parseProps(raw) {
122
+ if (!raw) return {}
123
+ if (raw.startsWith('yaml:')) {
124
+ return { source: raw.slice(5).trim() }
125
+ }
126
+ return { text: raw }
127
+ },
128
+ },
129
+ },
130
+ }
131
+ ```
132
+
133
+ ### Custom fence prefix
134
+
135
+ ```ts
136
+ const parseOptions: SvmdParseOptions = {
137
+ fenceComponentPrefix: '@component:',
138
+ }
139
+ ```
140
+
141
+ ### Use markdown-it plugins
142
+
143
+ ```ts
144
+ import footnote from 'markdown-it-footnote'
145
+ import container from 'markdown-it-container'
146
+
147
+ const parseOptions: SvmdParseOptions = {
148
+ markdownItPlugins: [
149
+ footnote,
150
+ [container, 'spoiler', { marker: ':' }],
151
+ ],
152
+ }
153
+ ```
154
+
155
+ ### Provide your own MarkdownIt instance
156
+
157
+ ```ts
158
+ import MarkdownIt from 'markdown-it'
159
+
160
+ const md = new MarkdownIt({ html: true, linkify: true })
161
+ const parseOptions: SvmdParseOptions = {
162
+ markdownIt: md,
163
+ }
164
+ ```
165
+
166
+ ### Render raw HTML (unsafe)
167
+
168
+ ```svelte
169
+ <Markdown
170
+ content={md}
171
+ parseOptions={{ markdownItOptions: { html: true } }}
172
+ renderOptions={{ allowDangerousHtml: true }}
173
+ />
174
+ ```
175
+
176
+ ### Control component inference
177
+
178
+ ```svelte
179
+ <Markdown
180
+ content={md}
181
+ components={{ Alert, Chart }}
182
+ inferComponentBlocks={false}
183
+ parseOptions={{ componentBlocks: { Alert: true } }}
184
+ />
185
+ ```
186
+
187
+ ### Access component metadata
188
+
189
+ ```svelte
190
+ <script lang="ts">
191
+ export let node
192
+ export let syntax
193
+ export let source
194
+ </script>
195
+ ```
196
+
197
+ ### Render AST nodes directly
198
+
199
+ ```svelte
200
+ <script lang="ts">
201
+ import { SvmdChildren, parseMarkdown } from 'svmarkdown'
202
+ const ast = parseMarkdown(md)
203
+ </script>
204
+
205
+ <SvmdChildren nodes={ast.children} components={components} />
206
+ ```
207
+
208
+ ## License
209
+
210
+ MIT License
@@ -0,0 +1,208 @@
1
+ # svmarkdown (Svelte Markdown)
2
+
3
+ `svmarkdown` (Svelte Markdown) 是一个运行时 Markdown 渲染库:
4
+
5
+ - 解析层:`markdown-it`
6
+ - 输出格式:库自己的 AST/Blocks(非 HTML 字符串)
7
+ - 渲染结果:声明式 Svelte 组件树
8
+
9
+ ## 安装
10
+
11
+ ```bash
12
+ pnpm add svmarkdown
13
+ ```
14
+
15
+ ## 快速开始
16
+
17
+ ```svelte
18
+ <script lang="ts">
19
+ import { Markdown } from 'svmarkdown'
20
+ import Link from './Link.svelte'
21
+ import Image from './Image.svelte'
22
+ import Code from './Code.svelte'
23
+
24
+ let content = $state('Visit [Svelte](https://svelte.dev) and `inline code`')
25
+
26
+ const components = {
27
+ a: Link,
28
+ img: Image,
29
+ code: Code,
30
+ }
31
+ </script>
32
+
33
+ <Markdown {content} {components} />
34
+ ```
35
+
36
+ ## 自定义组件语法
37
+
38
+ ### 1. Container(`:::`)
39
+
40
+ 你可以使用 ::: [组件名] key="value" 来创建一个组件块,块内的内容会作为 `children` prop 传入组件。
41
+
42
+ ```md
43
+ ::: Alert type=warning title="Heads up"
44
+ 这里是 **Markdown children**。
45
+ :::
46
+ ```
47
+
48
+ ### 2. Fence(```)
49
+
50
+ 你可以使用 ```component:[组件名] {"key":"value"} 来创建一个组件块,块内的内容会作为 `children` prop 传入组件。
51
+
52
+ ````md
53
+ ```component:Chart {"title":"Traffic"}
54
+ month,visits
55
+ Jan,421
56
+ Feb,530
57
+ ```
58
+ ````
59
+
60
+ ## API
61
+
62
+ ```ts
63
+ import { Markdown, createParser, parseMarkdown } from 'svmarkdown'
64
+ ```
65
+
66
+ - `parseMarkdown(markdown, options)`:一次性解析,返回 `SvmdRoot`
67
+ - `createParser(options)`:创建可复用 parser,适合高频更新
68
+ - `<Markdown />`:运行时渲染组件,每次变更时 `AST -> Svelte` 更新链路
69
+
70
+ ## parse options 定义
71
+
72
+ ```ts
73
+ import type { SvmdParseOptions } from 'svmarkdown'
74
+
75
+ const options: SvmdParseOptions = {
76
+ componentBlocks: {
77
+ Alert: true,
78
+ Chart: {
79
+ container: false,
80
+ fence: true,
81
+ parseFenceBodyAsMarkdown: false,
82
+ },
83
+ },
84
+ fenceComponentPrefix: 'component:',
85
+ }
86
+ ```
87
+
88
+ ## 开发
89
+
90
+ ```bash
91
+ pnpm install
92
+ pnpm run typecheck
93
+ pnpm run test
94
+ pnpm run build
95
+ pnpm run play
96
+ ```
97
+
98
+ ## 高级扩展用法
99
+
100
+ ### 更多组件块配置项
101
+
102
+ ```ts
103
+ const options: SvmdParseOptions = {
104
+ componentBlocks: {
105
+ Alert: true,
106
+ Note: { container: true, fence: false },
107
+ Chart: { container: false, fence: true },
108
+ Card: { fence: true, parseFenceBodyAsMarkdown: true },
109
+ },
110
+ }
111
+ ```
112
+
113
+ ### 自定义 props 解析
114
+
115
+ ```ts
116
+ const options: SvmdParseOptions = {
117
+ componentBlocks: {
118
+ Alert: {
119
+ parseProps(raw) {
120
+ if (!raw) return {}
121
+ if (raw.startsWith('yaml:')) {
122
+ return { source: raw.slice(5).trim() }
123
+ }
124
+ return { text: raw }
125
+ },
126
+ },
127
+ },
128
+ }
129
+ ```
130
+
131
+ ### 自定义 fence 前缀
132
+
133
+ ```ts
134
+ const options: SvmdParseOptions = {
135
+ fenceComponentPrefix: '@component:',
136
+ }
137
+ ```
138
+
139
+ ### 使用 markdown-it 插件
140
+
141
+ ```ts
142
+ import footnote from 'markdown-it-footnote'
143
+ import container from 'markdown-it-container'
144
+
145
+ const options: SvmdParseOptions = {
146
+ markdownItPlugins: [
147
+ footnote,
148
+ [container, 'spoiler', { marker: ':' }],
149
+ ],
150
+ }
151
+ ```
152
+
153
+ ### 传入自定义 MarkdownIt 实例
154
+
155
+ ```ts
156
+ import MarkdownIt from 'markdown-it'
157
+
158
+ const md = new MarkdownIt({ html: true, linkify: true })
159
+ const options: SvmdParseOptions = {
160
+ markdownIt: md,
161
+ }
162
+ ```
163
+
164
+ ### 渲染原始 HTML(不安全)
165
+
166
+ ```svelte
167
+ <Markdown
168
+ content={md}
169
+ parseOptions={{ markdownItOptions: { html: true } }}
170
+ renderOptions={{ allowDangerousHtml: true }}
171
+ />
172
+ ```
173
+
174
+ ### 关闭组件块自动推断
175
+
176
+ ```svelte
177
+ <Markdown
178
+ content={md}
179
+ components={{ Alert, Chart }}
180
+ inferComponentBlocks={false}
181
+ parseOptions={{ componentBlocks: { Alert: true } }}
182
+ />
183
+ ```
184
+
185
+ ### 读取组件元信息
186
+
187
+ ```svelte
188
+ <script lang="ts">
189
+ export let node
190
+ export let syntax
191
+ export let source
192
+ </script>
193
+ ```
194
+
195
+ ### 直接渲染 AST 节点
196
+
197
+ ```svelte
198
+ <script lang="ts">
199
+ import { SvmdChildren, parseMarkdown } from 'svmarkdown'
200
+ const ast = parseMarkdown(md)
201
+ </script>
202
+
203
+ <SvmdChildren nodes={ast.children} components={components} />
204
+ ```
205
+
206
+ ## License
207
+
208
+ MIT License
@@ -0,0 +1,11 @@
1
+ import type { SvmdComponentMap, SvmdParseOptions, SvmdRenderOptions } from './types';
2
+ interface Props {
3
+ content: string;
4
+ components?: SvmdComponentMap;
5
+ parseOptions?: SvmdParseOptions;
6
+ renderOptions?: SvmdRenderOptions;
7
+ inferComponentBlocks?: boolean;
8
+ }
9
+ declare const Markdown: import("svelte").Component<Props, {}, "">;
10
+ type Markdown = ReturnType<typeof Markdown>;
11
+ export default Markdown;