@incremark/solid 0.3.3
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 +22 -0
- package/README.en.md +278 -0
- package/README.md +278 -0
- package/dist/components/AutoScrollContainer.d.ts +17 -0
- package/dist/components/AutoScrollContainer.d.ts.map +1 -0
- package/dist/components/CachedCodeRenderer.d.ts +12 -0
- package/dist/components/CachedCodeRenderer.d.ts.map +1 -0
- package/dist/components/ConfigProvider.d.ts +17 -0
- package/dist/components/ConfigProvider.d.ts.map +1 -0
- package/dist/components/Incremark.d.ts +35 -0
- package/dist/components/Incremark.d.ts.map +1 -0
- package/dist/components/IncremarkBlockquote.d.ts +7 -0
- package/dist/components/IncremarkBlockquote.d.ts.map +1 -0
- package/dist/components/IncremarkCode.d.ts +26 -0
- package/dist/components/IncremarkCode.d.ts.map +1 -0
- package/dist/components/IncremarkCodeDefault.d.ts +15 -0
- package/dist/components/IncremarkCodeDefault.d.ts.map +1 -0
- package/dist/components/IncremarkCodeMermaid.d.ts +14 -0
- package/dist/components/IncremarkCodeMermaid.d.ts.map +1 -0
- package/dist/components/IncremarkContainer.d.ts +22 -0
- package/dist/components/IncremarkContainer.d.ts.map +1 -0
- package/dist/components/IncremarkContent.d.ts +10 -0
- package/dist/components/IncremarkContent.d.ts.map +1 -0
- package/dist/components/IncremarkDefault.d.ts +11 -0
- package/dist/components/IncremarkDefault.d.ts.map +1 -0
- package/dist/components/IncremarkFootnotes.d.ts +10 -0
- package/dist/components/IncremarkFootnotes.d.ts.map +1 -0
- package/dist/components/IncremarkHeading.d.ts +7 -0
- package/dist/components/IncremarkHeading.d.ts.map +1 -0
- package/dist/components/IncremarkHtmlElement.d.ts +26 -0
- package/dist/components/IncremarkHtmlElement.d.ts.map +1 -0
- package/dist/components/IncremarkInline.d.ts +7 -0
- package/dist/components/IncremarkInline.d.ts.map +1 -0
- package/dist/components/IncremarkList.d.ts +7 -0
- package/dist/components/IncremarkList.d.ts.map +1 -0
- package/dist/components/IncremarkMath.d.ts +16 -0
- package/dist/components/IncremarkMath.d.ts.map +1 -0
- package/dist/components/IncremarkParagraph.d.ts +7 -0
- package/dist/components/IncremarkParagraph.d.ts.map +1 -0
- package/dist/components/IncremarkRenderer.d.ts +20 -0
- package/dist/components/IncremarkRenderer.d.ts.map +1 -0
- package/dist/components/IncremarkTable.d.ts +7 -0
- package/dist/components/IncremarkTable.d.ts.map +1 -0
- package/dist/components/IncremarkThematicBreak.d.ts +7 -0
- package/dist/components/IncremarkThematicBreak.d.ts.map +1 -0
- package/dist/components/SvgIcon.d.ts +14 -0
- package/dist/components/SvgIcon.d.ts.map +1 -0
- package/dist/components/ThemeProvider.d.ts +17 -0
- package/dist/components/ThemeProvider.d.ts.map +1 -0
- package/dist/components/index.d.ts +47 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/composables/index.d.ts +10 -0
- package/dist/composables/index.d.ts.map +1 -0
- package/dist/composables/useBlockTransformer.d.ts +33 -0
- package/dist/composables/useBlockTransformer.d.ts.map +1 -0
- package/dist/composables/useDefinationsContext.d.ts +7 -0
- package/dist/composables/useDefinationsContext.d.ts.map +1 -0
- package/dist/composables/useDevTools.d.ts +35 -0
- package/dist/composables/useDevTools.d.ts.map +1 -0
- package/dist/composables/useIncremark.d.ts +84 -0
- package/dist/composables/useIncremark.d.ts.map +1 -0
- package/dist/composables/useLocale.d.ts +2 -0
- package/dist/composables/useLocale.d.ts.map +1 -0
- package/dist/composables/useProvideDefinations.d.ts +36 -0
- package/dist/composables/useProvideDefinations.d.ts.map +1 -0
- package/dist/composables/useShiki.d.ts +71 -0
- package/dist/composables/useShiki.d.ts.map +1 -0
- package/dist/composables/useStreamRenderer.d.ts +25 -0
- package/dist/composables/useStreamRenderer.d.ts.map +1 -0
- package/dist/composables/useTypewriter.d.ts +48 -0
- package/dist/composables/useTypewriter.d.ts.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2123 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +27 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/animatedChunks.d.ts +20 -0
- package/dist/utils/animatedChunks.d.ts.map +1 -0
- package/dist/utils/cursor.d.ts +9 -0
- package/dist/utils/cursor.d.ts.map +1 -0
- package/package.json +74 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 wangyishuai
|
|
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.
|
|
22
|
+
|
package/README.en.md
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
# @incremark/solid
|
|
2
|
+
|
|
3
|
+
SolidJS integration library for Incremark, providing high-performance streaming Markdown rendering components.
|
|
4
|
+
|
|
5
|
+
**[🇨🇳 中文](./README.md)** | 🇺🇸 English
|
|
6
|
+
|
|
7
|
+
## Core Advantages
|
|
8
|
+
|
|
9
|
+
- 📦 **Out of the Box** - Provides `IncremarkContent` component and `useIncremark` composable
|
|
10
|
+
- ⚡ **Extreme Performance** - Incremental parsing with O(n) complexity, dual-engine support
|
|
11
|
+
- ⌨️ **Typewriter Effect** - Built-in animation effects (fade-in, typing)
|
|
12
|
+
- 🎨 **Highly Customizable** - Custom components, code blocks, containers
|
|
13
|
+
- 🎯 **Theme System** - Built-in ThemeProvider with light/dark themes
|
|
14
|
+
- 📜 **Auto Scroll** - Built-in AutoScrollContainer component
|
|
15
|
+
- 🔧 **DevTools** - Built-in developer debugging tools
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm add @incremark/core @incremark/solid
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
### Recommended: IncremarkContent Component
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { createSignal } from 'solid-js'
|
|
29
|
+
import { IncremarkContent } from '@incremark/solid'
|
|
30
|
+
import '@incremark/solid/style.css'
|
|
31
|
+
|
|
32
|
+
function App() {
|
|
33
|
+
const [content, setContent] = createSignal('')
|
|
34
|
+
const [isFinished, setIsFinished] = createSignal(false)
|
|
35
|
+
|
|
36
|
+
// Handle AI streaming output
|
|
37
|
+
async function handleStream(stream) {
|
|
38
|
+
setContent('')
|
|
39
|
+
setIsFinished(false)
|
|
40
|
+
|
|
41
|
+
for await (const chunk of stream) {
|
|
42
|
+
setContent(prev => prev + chunk)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
setIsFinished(true)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<>
|
|
50
|
+
<button onClick={() => handleStream(stream)}>Start</button>
|
|
51
|
+
<IncremarkContent
|
|
52
|
+
content={content()}
|
|
53
|
+
isFinished={isFinished()}
|
|
54
|
+
incremarkOptions={{
|
|
55
|
+
gfm: true,
|
|
56
|
+
math: true,
|
|
57
|
+
containers: true,
|
|
58
|
+
htmlTree: true
|
|
59
|
+
}}
|
|
60
|
+
/>
|
|
61
|
+
</>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Advanced: useIncremark Composable
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
import { useIncremark, Incremark } from '@incremark/solid'
|
|
70
|
+
import '@incremark/solid/style.css'
|
|
71
|
+
|
|
72
|
+
function App() {
|
|
73
|
+
const { blocks, append, finalize, reset } = useIncremark({
|
|
74
|
+
gfm: true,
|
|
75
|
+
math: true
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
async function handleStream(stream) {
|
|
79
|
+
reset()
|
|
80
|
+
for await (const chunk of stream) {
|
|
81
|
+
append(chunk)
|
|
82
|
+
}
|
|
83
|
+
finalize()
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<>
|
|
88
|
+
<button onClick={() => handleStream(stream)}>Start</button>
|
|
89
|
+
<Incremark blocks={blocks()} />
|
|
90
|
+
</>
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## IncremarkContent Component
|
|
96
|
+
|
|
97
|
+
Declarative all-in-one component, recommended for most scenarios.
|
|
98
|
+
|
|
99
|
+
### Props
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
interface IncremarkContentProps {
|
|
103
|
+
// Input (choose one)
|
|
104
|
+
content?: string // Accumulated Markdown string
|
|
105
|
+
stream?: () => AsyncGenerator<string> // Async generator function
|
|
106
|
+
|
|
107
|
+
// Status
|
|
108
|
+
isFinished?: boolean // Stream finished flag (required for content mode)
|
|
109
|
+
|
|
110
|
+
// Configuration
|
|
111
|
+
incremarkOptions?: {
|
|
112
|
+
gfm?: boolean // GFM support
|
|
113
|
+
math?: boolean // Math formulas
|
|
114
|
+
htmlTree?: boolean // HTML structured parsing
|
|
115
|
+
containers?: boolean // ::: container syntax
|
|
116
|
+
typewriter?: { // Typewriter effect
|
|
117
|
+
enabled?: boolean
|
|
118
|
+
charsPerTick?: number | [number, number]
|
|
119
|
+
tickInterval?: number
|
|
120
|
+
effect?: 'none' | 'fade-in' | 'typing'
|
|
121
|
+
cursor?: string
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Custom rendering
|
|
126
|
+
components?: ComponentMap // Custom components
|
|
127
|
+
customContainers?: Record<string, Component> // Custom containers
|
|
128
|
+
customCodeBlocks?: Record<string, Component> // Custom code blocks
|
|
129
|
+
codeBlockConfigs?: Record<string, CodeBlockConfig>
|
|
130
|
+
|
|
131
|
+
// Styling
|
|
132
|
+
showBlockStatus?: boolean // Show block status border
|
|
133
|
+
pendingClass?: string // CSS class for pending blocks
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Example: Enable Typewriter Effect
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
<IncremarkContent
|
|
141
|
+
content={content()}
|
|
142
|
+
isFinished={isFinished()}
|
|
143
|
+
incremarkOptions={{
|
|
144
|
+
gfm: true,
|
|
145
|
+
typewriter: {
|
|
146
|
+
enabled: true,
|
|
147
|
+
charsPerTick: [1, 3],
|
|
148
|
+
tickInterval: 30,
|
|
149
|
+
effect: 'fade-in'
|
|
150
|
+
}
|
|
151
|
+
}}
|
|
152
|
+
/>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Example: Custom Components
|
|
156
|
+
|
|
157
|
+
```tsx
|
|
158
|
+
import CustomHeading from './CustomHeading'
|
|
159
|
+
import WarningContainer from './WarningContainer'
|
|
160
|
+
import EchartsCodeBlock from './EchartsCodeBlock'
|
|
161
|
+
|
|
162
|
+
<IncremarkContent
|
|
163
|
+
content={content()}
|
|
164
|
+
isFinished={isFinished()}
|
|
165
|
+
components={{ heading: CustomHeading }}
|
|
166
|
+
customContainers={{ warning: WarningContainer }}
|
|
167
|
+
customCodeBlocks={{ echarts: EchartsCodeBlock }}
|
|
168
|
+
codeBlockConfigs={{ echarts: { takeOver: true } }}
|
|
169
|
+
/>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Theme System
|
|
173
|
+
|
|
174
|
+
```tsx
|
|
175
|
+
import { ThemeProvider, IncremarkContent } from '@incremark/solid'
|
|
176
|
+
|
|
177
|
+
// Built-in theme
|
|
178
|
+
<ThemeProvider theme="dark">
|
|
179
|
+
<IncremarkContent content={content()} isFinished={isFinished()} />
|
|
180
|
+
</ThemeProvider>
|
|
181
|
+
|
|
182
|
+
// Custom theme
|
|
183
|
+
<ThemeProvider theme={{ color: { brand: { primary: '#8b5cf6' } } }}>
|
|
184
|
+
<IncremarkContent content={content()} isFinished={isFinished()} />
|
|
185
|
+
</ThemeProvider>
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Auto Scroll
|
|
189
|
+
|
|
190
|
+
```tsx
|
|
191
|
+
import { createSignal } from 'solid-js'
|
|
192
|
+
import { AutoScrollContainer, IncremarkContent } from '@incremark/solid'
|
|
193
|
+
|
|
194
|
+
function App() {
|
|
195
|
+
let scrollRef: HTMLDivElement | undefined
|
|
196
|
+
const [autoScrollEnabled, setAutoScrollEnabled] = createSignal(true)
|
|
197
|
+
|
|
198
|
+
return (
|
|
199
|
+
<>
|
|
200
|
+
<AutoScrollContainer
|
|
201
|
+
ref={scrollRef}
|
|
202
|
+
enabled={autoScrollEnabled()}
|
|
203
|
+
threshold={50}
|
|
204
|
+
behavior="smooth"
|
|
205
|
+
>
|
|
206
|
+
<IncremarkContent content={content()} isFinished={isFinished()} />
|
|
207
|
+
</AutoScrollContainer>
|
|
208
|
+
|
|
209
|
+
<button onClick={() => scrollRef?.scrollToBottom()}>
|
|
210
|
+
Scroll to Bottom
|
|
211
|
+
</button>
|
|
212
|
+
</>
|
|
213
|
+
)
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## useIncremark API
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
const {
|
|
221
|
+
// State
|
|
222
|
+
markdown, // Accessor<string> - Complete Markdown
|
|
223
|
+
blocks, // Accessor<Block[]> - All blocks
|
|
224
|
+
completedBlocks, // Accessor<Block[]> - Completed blocks
|
|
225
|
+
pendingBlocks, // Accessor<Block[]> - Pending blocks
|
|
226
|
+
isLoading, // Accessor<boolean> - Is loading
|
|
227
|
+
isDisplayComplete, // Accessor<boolean> - Is display complete
|
|
228
|
+
|
|
229
|
+
// Methods
|
|
230
|
+
append, // (chunk: string) => IncrementalUpdate
|
|
231
|
+
finalize, // () => IncrementalUpdate
|
|
232
|
+
reset, // () => void
|
|
233
|
+
render, // (content: string) => IncrementalUpdate
|
|
234
|
+
|
|
235
|
+
// Typewriter controls
|
|
236
|
+
typewriter: {
|
|
237
|
+
enabled, // Accessor<boolean> - Is enabled
|
|
238
|
+
isProcessing, // Accessor<boolean> - Is processing
|
|
239
|
+
skip, // () => void - Skip animation
|
|
240
|
+
setOptions // (options) => void - Update config
|
|
241
|
+
}
|
|
242
|
+
} = useIncremark(options)
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## DevTools
|
|
246
|
+
|
|
247
|
+
```tsx
|
|
248
|
+
import { useIncremark, useDevTools, Incremark } from '@incremark/solid'
|
|
249
|
+
|
|
250
|
+
function App() {
|
|
251
|
+
const incremark = useIncremark()
|
|
252
|
+
useDevTools(incremark)
|
|
253
|
+
|
|
254
|
+
return <Incremark blocks={incremark.blocks()} />
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Math Formula Support
|
|
259
|
+
|
|
260
|
+
Built-in support, just enable `math: true`:
|
|
261
|
+
|
|
262
|
+
```tsx
|
|
263
|
+
<IncremarkContent
|
|
264
|
+
content={content()}
|
|
265
|
+
isFinished={isFinished()}
|
|
266
|
+
incremarkOptions={{ math: true }}
|
|
267
|
+
/>
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Import KaTeX styles:
|
|
271
|
+
|
|
272
|
+
```tsx
|
|
273
|
+
import 'katex/dist/katex.min.css'
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## License
|
|
277
|
+
|
|
278
|
+
MIT
|
package/README.md
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
# @incremark/solid
|
|
2
|
+
|
|
3
|
+
Incremark 的 SolidJS 集成库。
|
|
4
|
+
|
|
5
|
+
🇨🇳 中文 | **[🇺🇸 English](./README.en.md)**
|
|
6
|
+
|
|
7
|
+
## 特性
|
|
8
|
+
|
|
9
|
+
- 📦 **开箱即用** - 提供 `useIncremark` composable 和 `<IncremarkContent>` 组件
|
|
10
|
+
- ⚡ **极致性能** - 增量解析 O(n) 复杂度,双引擎支持
|
|
11
|
+
- ⌨️ **打字机效果** - 内置动画效果(fade-in、typing)
|
|
12
|
+
- 🎨 **高度可定制** - 自定义组件、代码块、容器
|
|
13
|
+
- 🎯 **主题系统** - 内置 ThemeProvider 支持亮/暗主题
|
|
14
|
+
- 📜 **自动滚动** - 内置 AutoScrollContainer 组件
|
|
15
|
+
- 🔧 **DevTools** - 内置开发者调试工具
|
|
16
|
+
|
|
17
|
+
## 安装
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm add @incremark/core @incremark/solid
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 快速开始
|
|
24
|
+
|
|
25
|
+
### 推荐:IncremarkContent 组件
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { createSignal } from 'solid-js'
|
|
29
|
+
import { IncremarkContent } from '@incremark/solid'
|
|
30
|
+
import '@incremark/solid/style.css'
|
|
31
|
+
|
|
32
|
+
function App() {
|
|
33
|
+
const [content, setContent] = createSignal('')
|
|
34
|
+
const [isFinished, setIsFinished] = createSignal(false)
|
|
35
|
+
|
|
36
|
+
// 处理 AI 流式输出
|
|
37
|
+
async function handleStream(stream) {
|
|
38
|
+
setContent('')
|
|
39
|
+
setIsFinished(false)
|
|
40
|
+
|
|
41
|
+
for await (const chunk of stream) {
|
|
42
|
+
setContent(prev => prev + chunk)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
setIsFinished(true)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<>
|
|
50
|
+
<button onClick={() => handleStream(stream)}>开始</button>
|
|
51
|
+
<IncremarkContent
|
|
52
|
+
content={content()}
|
|
53
|
+
isFinished={isFinished()}
|
|
54
|
+
incremarkOptions={{
|
|
55
|
+
gfm: true,
|
|
56
|
+
math: true,
|
|
57
|
+
containers: true,
|
|
58
|
+
htmlTree: true
|
|
59
|
+
}}
|
|
60
|
+
/>
|
|
61
|
+
</>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 高级:useIncremark Composable
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
import { useIncremark, Incremark } from '@incremark/solid'
|
|
70
|
+
import '@incremark/solid/style.css'
|
|
71
|
+
|
|
72
|
+
function App() {
|
|
73
|
+
const { blocks, append, finalize, reset } = useIncremark({
|
|
74
|
+
gfm: true,
|
|
75
|
+
math: true
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
async function handleStream(stream) {
|
|
79
|
+
reset()
|
|
80
|
+
for await (const chunk of stream) {
|
|
81
|
+
append(chunk)
|
|
82
|
+
}
|
|
83
|
+
finalize()
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<>
|
|
88
|
+
<button onClick={() => handleStream(stream)}>开始</button>
|
|
89
|
+
<Incremark blocks={blocks()} />
|
|
90
|
+
</>
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## IncremarkContent 组件
|
|
96
|
+
|
|
97
|
+
声明式一体化组件,推荐用于大多数场景。
|
|
98
|
+
|
|
99
|
+
### Props
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
interface IncremarkContentProps {
|
|
103
|
+
// 输入(选择一种)
|
|
104
|
+
content?: string // 累积的 Markdown 字符串
|
|
105
|
+
stream?: () => AsyncGenerator<string> // 异步生成器函数
|
|
106
|
+
|
|
107
|
+
// 状态
|
|
108
|
+
isFinished?: boolean // 流结束标志(content 模式必需)
|
|
109
|
+
|
|
110
|
+
// 配置
|
|
111
|
+
incremarkOptions?: {
|
|
112
|
+
gfm?: boolean // GFM 支持
|
|
113
|
+
math?: boolean // 数学公式
|
|
114
|
+
htmlTree?: boolean // HTML 结构化解析
|
|
115
|
+
containers?: boolean // ::: 容器语法
|
|
116
|
+
typewriter?: { // 打字机效果
|
|
117
|
+
enabled?: boolean
|
|
118
|
+
charsPerTick?: number | [number, number]
|
|
119
|
+
tickInterval?: number
|
|
120
|
+
effect?: 'none' | 'fade-in' | 'typing'
|
|
121
|
+
cursor?: string
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// 自定义渲染
|
|
126
|
+
components?: ComponentMap // 自定义组件
|
|
127
|
+
customContainers?: Record<string, Component> // 自定义容器
|
|
128
|
+
customCodeBlocks?: Record<string, Component> // 自定义代码块
|
|
129
|
+
codeBlockConfigs?: Record<string, CodeBlockConfig>
|
|
130
|
+
|
|
131
|
+
// 样式
|
|
132
|
+
showBlockStatus?: boolean // 显示块状态边框
|
|
133
|
+
pendingClass?: string // pending 块的 CSS 类
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### 示例:启用打字机效果
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
<IncremarkContent
|
|
141
|
+
content={content()}
|
|
142
|
+
isFinished={isFinished()}
|
|
143
|
+
incremarkOptions={{
|
|
144
|
+
gfm: true,
|
|
145
|
+
typewriter: {
|
|
146
|
+
enabled: true,
|
|
147
|
+
charsPerTick: [1, 3],
|
|
148
|
+
tickInterval: 30,
|
|
149
|
+
effect: 'fade-in'
|
|
150
|
+
}
|
|
151
|
+
}}
|
|
152
|
+
/>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### 示例:自定义组件
|
|
156
|
+
|
|
157
|
+
```tsx
|
|
158
|
+
import CustomHeading from './CustomHeading'
|
|
159
|
+
import WarningContainer from './WarningContainer'
|
|
160
|
+
import EchartsCodeBlock from './EchartsCodeBlock'
|
|
161
|
+
|
|
162
|
+
<IncremarkContent
|
|
163
|
+
content={content()}
|
|
164
|
+
isFinished={isFinished()}
|
|
165
|
+
components={{ heading: CustomHeading }}
|
|
166
|
+
customContainers={{ warning: WarningContainer }}
|
|
167
|
+
customCodeBlocks={{ echarts: EchartsCodeBlock }}
|
|
168
|
+
codeBlockConfigs={{ echarts: { takeOver: true } }}
|
|
169
|
+
/>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## 主题系统
|
|
173
|
+
|
|
174
|
+
```tsx
|
|
175
|
+
import { ThemeProvider, IncremarkContent } from '@incremark/solid'
|
|
176
|
+
|
|
177
|
+
// 内置主题
|
|
178
|
+
<ThemeProvider theme="dark">
|
|
179
|
+
<IncremarkContent content={content()} isFinished={isFinished()} />
|
|
180
|
+
</ThemeProvider>
|
|
181
|
+
|
|
182
|
+
// 自定义主题
|
|
183
|
+
<ThemeProvider theme={{ color: { brand: { primary: '#8b5cf6' } } }}>
|
|
184
|
+
<IncremarkContent content={content()} isFinished={isFinished()} />
|
|
185
|
+
</ThemeProvider>
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## 自动滚动
|
|
189
|
+
|
|
190
|
+
```tsx
|
|
191
|
+
import { createSignal } from 'solid-js'
|
|
192
|
+
import { AutoScrollContainer, IncremarkContent } from '@incremark/solid'
|
|
193
|
+
|
|
194
|
+
function App() {
|
|
195
|
+
let scrollRef: HTMLDivElement | undefined
|
|
196
|
+
const [autoScrollEnabled, setAutoScrollEnabled] = createSignal(true)
|
|
197
|
+
|
|
198
|
+
return (
|
|
199
|
+
<>
|
|
200
|
+
<AutoScrollContainer
|
|
201
|
+
ref={scrollRef}
|
|
202
|
+
enabled={autoScrollEnabled()}
|
|
203
|
+
threshold={50}
|
|
204
|
+
behavior="smooth"
|
|
205
|
+
>
|
|
206
|
+
<IncremarkContent content={content()} isFinished={isFinished()} />
|
|
207
|
+
</AutoScrollContainer>
|
|
208
|
+
|
|
209
|
+
<button onClick={() => scrollRef?.scrollToBottom()}>
|
|
210
|
+
滚动到底部
|
|
211
|
+
</button>
|
|
212
|
+
</>
|
|
213
|
+
)
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## useIncremark API
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
const {
|
|
221
|
+
// 状态
|
|
222
|
+
markdown, // Accessor<string> - 完整 Markdown
|
|
223
|
+
blocks, // Accessor<Block[]> - 所有块
|
|
224
|
+
completedBlocks, // Accessor<Block[]> - 已完成块
|
|
225
|
+
pendingBlocks, // Accessor<Block[]> - 待处理块
|
|
226
|
+
isLoading, // Accessor<boolean> - 是否加载中
|
|
227
|
+
isDisplayComplete, // Accessor<boolean> - 是否显示完成
|
|
228
|
+
|
|
229
|
+
// 方法
|
|
230
|
+
append, // (chunk: string) => IncrementalUpdate
|
|
231
|
+
finalize, // () => IncrementalUpdate
|
|
232
|
+
reset, // () => void
|
|
233
|
+
render, // (content: string) => IncrementalUpdate
|
|
234
|
+
|
|
235
|
+
// 打字机控制
|
|
236
|
+
typewriter: {
|
|
237
|
+
enabled, // Accessor<boolean> - 是否启用
|
|
238
|
+
isProcessing, // Accessor<boolean> - 是否处理中
|
|
239
|
+
skip, // () => void - 跳过动画
|
|
240
|
+
setOptions // (options) => void - 更新配置
|
|
241
|
+
}
|
|
242
|
+
} = useIncremark(options)
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## DevTools
|
|
246
|
+
|
|
247
|
+
```tsx
|
|
248
|
+
import { useIncremark, useDevTools, Incremark } from '@incremark/solid'
|
|
249
|
+
|
|
250
|
+
function App() {
|
|
251
|
+
const incremark = useIncremark()
|
|
252
|
+
useDevTools(incremark)
|
|
253
|
+
|
|
254
|
+
return <Incremark blocks={incremark.blocks()} />
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## 数学公式支持
|
|
259
|
+
|
|
260
|
+
内置支持,只需启用 `math: true`:
|
|
261
|
+
|
|
262
|
+
```tsx
|
|
263
|
+
<IncremarkContent
|
|
264
|
+
content={content()}
|
|
265
|
+
isFinished={isFinished()}
|
|
266
|
+
incremarkOptions={{ math: true }}
|
|
267
|
+
/>
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
导入 KaTeX 样式:
|
|
271
|
+
|
|
272
|
+
```tsx
|
|
273
|
+
import 'katex/dist/katex.min.css'
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## 许可证
|
|
277
|
+
|
|
278
|
+
MIT
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Component, JSX } from 'solid-js';
|
|
2
|
+
import type { Accessor } from 'solid-js';
|
|
3
|
+
export interface AutoScrollContainerProps extends JSX.HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
/** 是否启用自动滚动 */
|
|
5
|
+
enabled?: Accessor<boolean> | boolean;
|
|
6
|
+
/** 触发自动滚动的底部阈值(像素) */
|
|
7
|
+
threshold?: number;
|
|
8
|
+
/** 滚动行为 */
|
|
9
|
+
behavior?: ScrollBehavior;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* 自动滚动容器组件
|
|
13
|
+
*
|
|
14
|
+
* 当内容更新时自动滚动到底部,除非用户手动向上滚动
|
|
15
|
+
*/
|
|
16
|
+
export declare const AutoScrollContainer: Component<AutoScrollContainerProps>;
|
|
17
|
+
//# sourceMappingURL=AutoScrollContainer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutoScrollContainer.d.ts","sourceRoot":"","sources":["../../src/components/AutoScrollContainer.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAkD,GAAG,EAAE,MAAM,UAAU,CAAA;AACzF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAExC,MAAM,WAAW,wBAAyB,SAAQ,GAAG,CAAC,cAAc,CAAC,cAAc,CAAC;IAClF,eAAe;IACf,OAAO,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,OAAO,CAAA;IACrC,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW;IACX,QAAQ,CAAC,EAAE,cAAc,CAAA;CAC1B;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,CAAC,wBAAwB,CAqInE,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Component } from 'solid-js';
|
|
2
|
+
export interface CachedCodeRendererProps {
|
|
3
|
+
code: string;
|
|
4
|
+
lang: string;
|
|
5
|
+
theme: string;
|
|
6
|
+
highlighter: any;
|
|
7
|
+
onStreamStart?: () => void;
|
|
8
|
+
onStreamEnd?: () => void;
|
|
9
|
+
onStreamError?: () => void;
|
|
10
|
+
}
|
|
11
|
+
export declare const CachedCodeRenderer: Component<CachedCodeRendererProps>;
|
|
12
|
+
//# sourceMappingURL=CachedCodeRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CachedCodeRenderer.d.ts","sourceRoot":"","sources":["../../src/components/CachedCodeRenderer.tsx"],"names":[],"mappings":"AAkBA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEpC,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,GAAG,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;CAC3B;AAKD,eAAO,MAAM,kBAAkB,EAAE,SAAS,CAAC,uBAAuB,CA8IjE,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type Component, type JSX, type Accessor } from 'solid-js';
|
|
2
|
+
import type { IncremarkLocale } from '@incremark/shared';
|
|
3
|
+
export declare const LocaleContext: import("solid-js").Context<{
|
|
4
|
+
locale: Accessor<IncremarkLocale>;
|
|
5
|
+
} | undefined>;
|
|
6
|
+
export interface ConfigProviderProps {
|
|
7
|
+
/** locale 对象 */
|
|
8
|
+
locale?: IncremarkLocale;
|
|
9
|
+
children?: JSX.Element;
|
|
10
|
+
}
|
|
11
|
+
export declare const ConfigProvider: Component<ConfigProviderProps>;
|
|
12
|
+
/**
|
|
13
|
+
* 翻译函数类型
|
|
14
|
+
*/
|
|
15
|
+
export type TranslatorFn = (key: string) => string;
|
|
16
|
+
export declare function useLocale(): TranslatorFn;
|
|
17
|
+
//# sourceMappingURL=ConfigProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfigProvider.d.ts","sourceRoot":"","sources":["../../src/components/ConfigProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,GAAG,EAAuD,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAA;AACvH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAGxD,eAAO,MAAM,aAAa;YAChB,QAAQ,CAAC,eAAe,CAAC;cAC/B,CAAA;AAEJ,MAAM,WAAW,mBAAmB;IAClC,gBAAgB;IAChB,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB,QAAQ,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;CACvB;AAED,eAAO,MAAM,cAAc,EAAE,SAAS,CAAC,mBAAmB,CAazD,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;AAElD,wBAAgB,SAAS,IAAI,YAAY,CAaxC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Component } from 'solid-js';
|
|
2
|
+
import type { ParsedBlock } from '@incremark/core';
|
|
3
|
+
import type { UseIncremarkReturn } from '../composables/useIncremark';
|
|
4
|
+
import type { ComponentMap, CodeBlockConfig } from '../types';
|
|
5
|
+
export interface IncremarkProps {
|
|
6
|
+
/** 要渲染的块列表(来自 useIncremark 的 blocks) */
|
|
7
|
+
blocks?: ParsedBlock[] | (() => ParsedBlock[]);
|
|
8
|
+
/** 内容是否完全显示完成(用于控制脚注等需要在内容完全显示后才出现的元素)
|
|
9
|
+
* 如果传入了 incremark,则会自动使用 incremark.isDisplayComplete,此 prop 被忽略 */
|
|
10
|
+
isDisplayComplete?: boolean | (() => boolean);
|
|
11
|
+
/** 自定义组件映射,key 为节点类型 */
|
|
12
|
+
components?: ComponentMap;
|
|
13
|
+
/** 自定义容器组件映射,key 为容器名称(如 'warning', 'info') */
|
|
14
|
+
customContainers?: Record<string, Component<any>>;
|
|
15
|
+
/** 自定义代码块组件映射,key 为代码语言名称(如 'echart', 'mermaid') */
|
|
16
|
+
customCodeBlocks?: Record<string, Component<any>>;
|
|
17
|
+
/** 代码块配置映射,key 为代码语言名称 */
|
|
18
|
+
codeBlockConfigs?: Record<string, CodeBlockConfig>;
|
|
19
|
+
/** 待处理块的样式类名 */
|
|
20
|
+
pendingClass?: string;
|
|
21
|
+
/** 已完成块的样式类名 */
|
|
22
|
+
completedClass?: string;
|
|
23
|
+
/** 是否显示块状态边框 */
|
|
24
|
+
showBlockStatus?: boolean;
|
|
25
|
+
/** 可选:useIncremark 返回的对象(用于自动注入数据) */
|
|
26
|
+
incremark?: UseIncremarkReturn;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Incremark 主组件
|
|
30
|
+
*
|
|
31
|
+
* 渲染增量解析的 Markdown 块列表
|
|
32
|
+
*/
|
|
33
|
+
export declare const Incremark: Component<IncremarkProps>;
|
|
34
|
+
export default Incremark;
|
|
35
|
+
//# sourceMappingURL=Incremark.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Incremark.d.ts","sourceRoot":"","sources":["../../src/components/Incremark.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAO,MAAM,UAAU,CAAA;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAGlD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAI7D,MAAM,WAAW,cAAc;IAC7B,wCAAwC;IACxC,MAAM,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,MAAM,WAAW,EAAE,CAAC,CAAA;IAC9C;uEACmE;IACnE,iBAAiB,CAAC,EAAE,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,CAAA;IAC7C,wBAAwB;IACxB,UAAU,CAAC,EAAE,YAAY,CAAA;IACzB,+CAA+C;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAA;IACjD,oDAAoD;IACpD,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAA;IACjD,0BAA0B;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IAClD,gBAAgB;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,gBAAgB;IAChB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,gBAAgB;IAChB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,sCAAsC;IACtC,SAAS,CAAC,EAAE,kBAAkB,CAAA;CAC/B;AAgFD;;;;GAIG;AACH,eAAO,MAAM,SAAS,EAAE,SAAS,CAAC,cAAc,CAE/C,CAAA;AAED,eAAe,SAAS,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Blockquote } from 'mdast';
|
|
2
|
+
import { Component } from 'solid-js';
|
|
3
|
+
export interface IncremarkBlockquoteProps {
|
|
4
|
+
node: Blockquote;
|
|
5
|
+
}
|
|
6
|
+
export declare const IncremarkBlockquote: Component<IncremarkBlockquoteProps>;
|
|
7
|
+
//# sourceMappingURL=IncremarkBlockquote.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IncremarkBlockquote.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkBlockquote.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AACvC,OAAO,EAAE,SAAS,EAAO,MAAM,UAAU,CAAA;AAGzC,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,UAAU,CAAA;CACjB;AAED,eAAO,MAAM,mBAAmB,EAAE,SAAS,CAAC,wBAAwB,CAUnE,CAAA"}
|