@incremark/svelte 0.2.6 → 0.2.7
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/dist/components/AutoScrollContainer.svelte +18 -18
- package/dist/components/Incremark.svelte +6 -6
- package/dist/components/Incremark.svelte.d.ts +2 -2
- package/dist/components/Incremark.svelte.d.ts.map +1 -1
- package/dist/components/IncremarkCode.svelte +31 -122
- package/dist/components/IncremarkCode.svelte.d.ts.map +1 -1
- package/dist/components/IncremarkContent.svelte +114 -0
- package/dist/components/IncremarkContent.svelte.d.ts +6 -0
- package/dist/components/IncremarkContent.svelte.d.ts.map +1 -0
- package/dist/components/IncremarkList.svelte +1 -0
- package/dist/components/index.d.ts +2 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +1 -0
- package/dist/components/types.d.ts +29 -3
- package/dist/components/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/stores/useDevTools.js +2 -2
- package/dist/stores/useIncremark.d.ts +4 -4
- package/dist/stores/useIncremark.d.ts.map +1 -1
- package/dist/stores/useShiki.svelte.d.ts +9 -0
- package/dist/stores/useShiki.svelte.d.ts.map +1 -0
- package/dist/stores/useShiki.svelte.js +98 -0
- package/dist/stores/useTypewriter.d.ts +0 -1
- package/dist/stores/useTypewriter.d.ts.map +1 -1
- package/dist/stores/useTypewriter.js +1 -3
- package/package.json +5 -5
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
-->
|
|
5
5
|
|
|
6
6
|
<script lang="ts">
|
|
7
|
-
import { onMount, onDestroy } from 'svelte'
|
|
7
|
+
import { onMount, onDestroy, tick } from 'svelte'
|
|
8
8
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -117,24 +117,24 @@
|
|
|
117
117
|
lastScrollTop = containerRef.scrollTop
|
|
118
118
|
lastScrollHeight = containerRef.scrollHeight
|
|
119
119
|
|
|
120
|
-
observer = new MutationObserver(() => {
|
|
120
|
+
observer = new MutationObserver(async () => {
|
|
121
121
|
// 使用 tick 等待 DOM 更新
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
122
|
+
await tick()
|
|
123
|
+
|
|
124
|
+
if (!containerRef) return
|
|
125
|
+
|
|
126
|
+
// 如果没有滚动条,重置状态
|
|
127
|
+
if (!hasScrollbar()) {
|
|
128
|
+
isUserScrolledUp = false
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// 更新 scrollHeight 记录(内容变化后)
|
|
132
|
+
lastScrollHeight = containerRef.scrollHeight
|
|
133
|
+
|
|
134
|
+
// 自动滚动
|
|
135
|
+
if (enabled && !isUserScrolledUp) {
|
|
136
|
+
scrollToBottom()
|
|
137
|
+
}
|
|
138
138
|
})
|
|
139
139
|
|
|
140
140
|
observer.observe(containerRef, {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
import { getDefinitionsContext } from '../context/definitionsContext'
|
|
13
13
|
import type { UseIncremarkReturn } from '../stores/useIncremark'
|
|
14
|
-
import type { ComponentMap,
|
|
14
|
+
import type { ComponentMap, RenderableBlock } from './types'
|
|
15
15
|
|
|
16
16
|
// 导入组件
|
|
17
17
|
import IncremarkFootnotes from './IncremarkFootnotes.svelte'
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
*/
|
|
30
30
|
interface Props {
|
|
31
31
|
/** 要渲染的块列表(来自 useIncremark 的 blocks) */
|
|
32
|
-
blocks?:
|
|
32
|
+
blocks?: RenderableBlock[] | Readable<RenderableBlock[]>
|
|
33
33
|
/** 内容是否完全显示完成(用于控制脚注等需要在内容完全显示后才出现的元素)
|
|
34
34
|
* 如果传入了 incremark,则会自动使用 incremark.isDisplayComplete,此 prop 被忽略 */
|
|
35
35
|
isDisplayComplete?: boolean
|
|
@@ -80,10 +80,10 @@
|
|
|
80
80
|
<!-- 主要内容块 -->
|
|
81
81
|
{#if incremark}
|
|
82
82
|
<!-- 使用 incremark 的 blocks store -->
|
|
83
|
-
{#each $incremarkBlocks as block (block.
|
|
83
|
+
{#each $incremarkBlocks as block (block.id)}
|
|
84
84
|
{#if (block as ParsedBlock).node.type !== 'definition' && (block as ParsedBlock).node.type !== 'footnoteDefinition'}
|
|
85
85
|
<div
|
|
86
|
-
class="incremark-block {(block as ParsedBlock).status === 'completed' ? completedClass : pendingClass} {showBlockStatus ? 'incremark-show-status' : ''} {(block as
|
|
86
|
+
class="incremark-block {(block as ParsedBlock).status === 'completed' ? completedClass : pendingClass} {showBlockStatus ? 'incremark-show-status' : ''} {(block as RenderableBlock).isLastPending ? 'incremark-last-pending' : ''}"
|
|
87
87
|
>
|
|
88
88
|
<!-- 使用 IncremarkRenderer,传递 customContainers 和 customCodeBlocks -->
|
|
89
89
|
<IncremarkRenderer
|
|
@@ -98,10 +98,10 @@
|
|
|
98
98
|
{/each}
|
|
99
99
|
{:else}
|
|
100
100
|
<!-- 使用传入的 blocks 数组 -->
|
|
101
|
-
{#each (Array.isArray(blocks) ? blocks : []) as block (block.
|
|
101
|
+
{#each (Array.isArray(blocks) ? blocks : []) as block (block.id)}
|
|
102
102
|
{#if (block as ParsedBlock).node.type !== 'definition' && (block as ParsedBlock).node.type !== 'footnoteDefinition'}
|
|
103
103
|
<div
|
|
104
|
-
class="incremark-block {(block as ParsedBlock).status === 'completed' ? completedClass : pendingClass} {showBlockStatus ? 'incremark-show-status' : ''} {block.isLastPending ? 'incremark-last-pending' : ''}"
|
|
104
|
+
class="incremark-block {(block as ParsedBlock).status === 'completed' ? completedClass : pendingClass} {showBlockStatus ? 'incremark-show-status' : ''} {(block as RenderableBlock).isLastPending ? 'incremark-last-pending' : ''}"
|
|
105
105
|
>
|
|
106
106
|
<!-- 使用 IncremarkRenderer,传递 customContainers 和 customCodeBlocks -->
|
|
107
107
|
<IncremarkRenderer
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { Component } from 'svelte';
|
|
2
2
|
import type { Readable } from 'svelte/store';
|
|
3
3
|
import type { UseIncremarkReturn } from '../stores/useIncremark';
|
|
4
|
-
import type { ComponentMap,
|
|
4
|
+
import type { ComponentMap, RenderableBlock } from './types';
|
|
5
5
|
/**
|
|
6
6
|
* 组件 Props
|
|
7
7
|
*/
|
|
8
8
|
interface Props {
|
|
9
9
|
/** 要渲染的块列表(来自 useIncremark 的 blocks) */
|
|
10
|
-
blocks?:
|
|
10
|
+
blocks?: RenderableBlock[] | Readable<RenderableBlock[]>;
|
|
11
11
|
/** 内容是否完全显示完成(用于控制脚注等需要在内容完全显示后才出现的元素)
|
|
12
12
|
* 如果传入了 incremark,则会自动使用 incremark.isDisplayComplete,此 prop 被忽略 */
|
|
13
13
|
isDisplayComplete?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Incremark.svelte.d.ts","sourceRoot":"","sources":["../../src/components/Incremark.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AACvC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAK5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"Incremark.svelte.d.ts","sourceRoot":"","sources":["../../src/components/Incremark.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AACvC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAK5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAM1D;;GAEG;AACH,UAAU,KAAK;IACb,wCAAwC;IACxC,MAAM,CAAC,EAAE,eAAe,EAAE,GAAG,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAA;IACxD;uEACmE;IACnE,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,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;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;IACzD,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;AA2FH,QAAA,MAAM,SAAS,0BAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
|
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
@file IncremarkCode.svelte - 代码块组件
|
|
3
|
-
@description 渲染 Markdown 代码块,支持 Shiki 代码高亮和 Mermaid 图表渲染
|
|
4
|
-
-->
|
|
5
|
-
|
|
6
1
|
<script lang="ts">
|
|
7
2
|
import type { Code } from 'mdast'
|
|
8
|
-
import {
|
|
3
|
+
import { useShiki } from '../stores/useShiki.svelte'
|
|
9
4
|
|
|
10
5
|
/**
|
|
11
6
|
* 组件 Props
|
|
@@ -43,8 +38,6 @@
|
|
|
43
38
|
// 状态
|
|
44
39
|
let copied = $state(false)
|
|
45
40
|
let highlightedHtml = $state('')
|
|
46
|
-
let isHighlighting = $state(false)
|
|
47
|
-
let highlightError = $state(false)
|
|
48
41
|
|
|
49
42
|
// Mermaid 支持
|
|
50
43
|
let mermaidSvg = $state('')
|
|
@@ -55,10 +48,8 @@
|
|
|
55
48
|
// 视图模式:'preview' | 'source'
|
|
56
49
|
let mermaidViewMode = $state<'preview' | 'source'>('preview')
|
|
57
50
|
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
const loadedLanguages = new Set<string>()
|
|
61
|
-
const loadedThemes = new Set<string>()
|
|
51
|
+
// 使用 Shiki 单例管理器 - 修复:传入 getter 闭包以保持响应式
|
|
52
|
+
const shiki = useShiki(() => theme)
|
|
62
53
|
|
|
63
54
|
/**
|
|
64
55
|
* 计算属性
|
|
@@ -72,18 +63,10 @@
|
|
|
72
63
|
const component = customCodeBlocks?.[language]
|
|
73
64
|
if (!component) return null
|
|
74
65
|
|
|
75
|
-
// 检查该语言的配置
|
|
76
66
|
const config = codeBlockConfigs?.[language]
|
|
77
67
|
|
|
78
|
-
|
|
79
|
-
if (
|
|
80
|
-
return component
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// 否则,默认行为:只在 completed 状态使用
|
|
84
|
-
if (blockStatus !== 'completed') {
|
|
85
|
-
return null
|
|
86
|
-
}
|
|
68
|
+
if (config?.takeOver) return component
|
|
69
|
+
if (blockStatus !== 'completed') return null
|
|
87
70
|
|
|
88
71
|
return component
|
|
89
72
|
})
|
|
@@ -95,54 +78,30 @@
|
|
|
95
78
|
mermaidViewMode = mermaidViewMode === 'preview' ? 'source' : 'preview'
|
|
96
79
|
}
|
|
97
80
|
|
|
98
|
-
/**
|
|
99
|
-
* Mermaid 渲染(带防抖动)
|
|
100
|
-
*/
|
|
101
|
-
function scheduleRenderMermaid() {
|
|
102
|
-
if (!isMermaid || !code) return
|
|
103
|
-
|
|
104
|
-
// 清除之前的定时器
|
|
105
|
-
if (mermaidTimer) {
|
|
106
|
-
clearTimeout(mermaidTimer)
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// 显示加载状态
|
|
110
|
-
mermaidLoading = true
|
|
111
|
-
|
|
112
|
-
// 防抖动延迟渲染
|
|
113
|
-
mermaidTimer = setTimeout(() => {
|
|
114
|
-
doRenderMermaid()
|
|
115
|
-
}, mermaidDelay)
|
|
116
|
-
}
|
|
117
|
-
|
|
118
81
|
/**
|
|
119
82
|
* 执行 Mermaid 渲染
|
|
120
83
|
*/
|
|
121
84
|
async function doRenderMermaid() {
|
|
122
85
|
if (!code) return
|
|
123
|
-
|
|
124
86
|
mermaidError = ''
|
|
125
87
|
|
|
126
88
|
try {
|
|
127
|
-
// 动态导入 mermaid
|
|
128
89
|
if (!mermaidRef) {
|
|
129
|
-
// @ts-ignore
|
|
90
|
+
// @ts-ignore
|
|
130
91
|
const mermaidModule = await import('mermaid')
|
|
131
92
|
mermaidRef = mermaidModule.default
|
|
132
93
|
mermaidRef.initialize({
|
|
133
94
|
startOnLoad: false,
|
|
134
95
|
theme: 'dark',
|
|
135
|
-
securityLevel: 'loose'
|
|
96
|
+
securityLevel: 'loose',
|
|
97
|
+
suppressErrorRendering: true
|
|
136
98
|
})
|
|
137
99
|
}
|
|
138
100
|
|
|
139
|
-
const mermaid = mermaidRef
|
|
140
101
|
const id = `mermaid-${Date.now()}-${Math.random().toString(36).slice(2)}`
|
|
141
|
-
|
|
142
|
-
const { svg } = await mermaid.render(id, code)
|
|
102
|
+
const { svg } = await mermaidRef.render(id, code)
|
|
143
103
|
mermaidSvg = svg
|
|
144
104
|
} catch (e: any) {
|
|
145
|
-
// 不显示错误,可能是代码还不完整
|
|
146
105
|
mermaidError = ''
|
|
147
106
|
mermaidSvg = ''
|
|
148
107
|
} finally {
|
|
@@ -153,9 +112,12 @@
|
|
|
153
112
|
/**
|
|
154
113
|
* 动态加载 shiki 并高亮
|
|
155
114
|
*/
|
|
156
|
-
async function
|
|
115
|
+
async function doHighlight() {
|
|
157
116
|
if (isMermaid) {
|
|
158
|
-
|
|
117
|
+
// Mermaid 防抖逻辑
|
|
118
|
+
if (mermaidTimer) clearTimeout(mermaidTimer)
|
|
119
|
+
mermaidLoading = true
|
|
120
|
+
mermaidTimer = setTimeout(doRenderMermaid, mermaidDelay)
|
|
159
121
|
return
|
|
160
122
|
}
|
|
161
123
|
|
|
@@ -164,54 +126,12 @@
|
|
|
164
126
|
return
|
|
165
127
|
}
|
|
166
128
|
|
|
167
|
-
isHighlighting = true
|
|
168
|
-
highlightError = false
|
|
169
|
-
|
|
170
129
|
try {
|
|
171
|
-
//
|
|
172
|
-
|
|
173
|
-
const { createHighlighter } = await import('shiki')
|
|
174
|
-
highlighterRef = await createHighlighter({
|
|
175
|
-
themes: [theme as any],
|
|
176
|
-
langs: []
|
|
177
|
-
})
|
|
178
|
-
loadedThemes.add(theme)
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const highlighter = highlighterRef
|
|
182
|
-
const lang = language
|
|
183
|
-
|
|
184
|
-
// 按需加载语言
|
|
185
|
-
if (!loadedLanguages.has(lang) && lang !== 'text') {
|
|
186
|
-
try {
|
|
187
|
-
await highlighter.loadLanguage(lang)
|
|
188
|
-
loadedLanguages.add(lang)
|
|
189
|
-
} catch {
|
|
190
|
-
// 语言不支持,标记但不阻止
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// 按需加载主题
|
|
195
|
-
if (!loadedThemes.has(theme)) {
|
|
196
|
-
try {
|
|
197
|
-
await highlighter.loadTheme(theme)
|
|
198
|
-
loadedThemes.add(theme)
|
|
199
|
-
} catch {
|
|
200
|
-
// 主题不支持
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const html = highlighter.codeToHtml(code, {
|
|
205
|
-
lang: loadedLanguages.has(lang) ? lang : 'text',
|
|
206
|
-
theme: loadedThemes.has(theme) ? theme : fallbackTheme
|
|
207
|
-
})
|
|
130
|
+
// 调用经过修复的 shiki.highlight
|
|
131
|
+
const html = await shiki.highlight(code, language, fallbackTheme)
|
|
208
132
|
highlightedHtml = html
|
|
209
133
|
} catch (e) {
|
|
210
|
-
// Shiki 不可用或加载失败
|
|
211
|
-
highlightError = true
|
|
212
134
|
highlightedHtml = ''
|
|
213
|
-
} finally {
|
|
214
|
-
isHighlighting = false
|
|
215
135
|
}
|
|
216
136
|
}
|
|
217
137
|
|
|
@@ -222,31 +142,29 @@
|
|
|
222
142
|
try {
|
|
223
143
|
await navigator.clipboard.writeText(code)
|
|
224
144
|
copied = true
|
|
225
|
-
setTimeout(() => {
|
|
226
|
-
|
|
227
|
-
}, 2000)
|
|
228
|
-
} catch {
|
|
229
|
-
// 复制失败静默处理
|
|
230
|
-
}
|
|
145
|
+
setTimeout(() => { copied = false }, 2000)
|
|
146
|
+
} catch { /* 静默处理 */ }
|
|
231
147
|
}
|
|
232
148
|
|
|
233
|
-
//
|
|
149
|
+
// 监听代码、主题、语言变化并重新渲染
|
|
234
150
|
$effect(() => {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
if (mermaidTimer) {
|
|
241
|
-
clearTimeout(mermaidTimer)
|
|
151
|
+
doHighlight()
|
|
152
|
+
|
|
153
|
+
// 返回清理函数取代 onDestroy
|
|
154
|
+
return () => {
|
|
155
|
+
if (mermaidTimer) clearTimeout(mermaidTimer)
|
|
242
156
|
}
|
|
243
157
|
})
|
|
244
158
|
</script>
|
|
245
159
|
|
|
246
|
-
<!-- 自定义代码块组件 -->
|
|
247
160
|
{#if CustomCodeBlock}
|
|
248
161
|
{@const Component = CustomCodeBlock}
|
|
249
|
-
<Component
|
|
162
|
+
<Component
|
|
163
|
+
codeStr={code}
|
|
164
|
+
lang={language}
|
|
165
|
+
completed={blockStatus === 'completed'}
|
|
166
|
+
takeOver={codeBlockConfigs?.[language]?.takeOver}
|
|
167
|
+
/>
|
|
250
168
|
{:else if isMermaid}
|
|
251
169
|
<div class="incremark-mermaid">
|
|
252
170
|
<div class="mermaid-header">
|
|
@@ -266,23 +184,18 @@
|
|
|
266
184
|
</div>
|
|
267
185
|
</div>
|
|
268
186
|
<div class="mermaid-content">
|
|
269
|
-
<!-- 加载中 -->
|
|
270
187
|
{#if mermaidLoading && !mermaidSvg}
|
|
271
188
|
<pre class="mermaid-source-code">{code}</pre>
|
|
272
|
-
<!-- 源码模式 -->
|
|
273
189
|
{:else if mermaidViewMode === 'source'}
|
|
274
190
|
<pre class="mermaid-source-code">{code}</pre>
|
|
275
|
-
<!-- 预览模式 -->
|
|
276
191
|
{:else if mermaidSvg}
|
|
277
192
|
{@html mermaidSvg}
|
|
278
|
-
<!-- 无法渲染时显示源码 -->
|
|
279
193
|
{:else}
|
|
280
194
|
<pre class="mermaid-source-code">{code}</pre>
|
|
281
195
|
{/if}
|
|
282
196
|
</div>
|
|
283
197
|
</div>
|
|
284
198
|
{:else}
|
|
285
|
-
<!-- 普通代码块 -->
|
|
286
199
|
<div class="incremark-code">
|
|
287
200
|
<div class="code-header">
|
|
288
201
|
<span class="language">{language}</span>
|
|
@@ -291,21 +204,17 @@
|
|
|
291
204
|
</button>
|
|
292
205
|
</div>
|
|
293
206
|
<div class="code-content">
|
|
294
|
-
|
|
295
|
-
{#if isHighlighting && !highlightedHtml}
|
|
207
|
+
{#if shiki.isHighlighting && !highlightedHtml}
|
|
296
208
|
<div class="code-loading">
|
|
297
209
|
<pre><code>{code}</code></pre>
|
|
298
210
|
</div>
|
|
299
|
-
<!-- 高亮后的代码 -->
|
|
300
211
|
{:else if highlightedHtml}
|
|
301
212
|
<div class="shiki-wrapper">
|
|
302
213
|
{@html highlightedHtml}
|
|
303
214
|
</div>
|
|
304
|
-
<!-- 回退:无高亮 -->
|
|
305
215
|
{:else}
|
|
306
216
|
<pre class="code-fallback"><code>{code}</code></pre>
|
|
307
217
|
{/if}
|
|
308
218
|
</div>
|
|
309
219
|
</div>
|
|
310
220
|
{/if}
|
|
311
|
-
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IncremarkCode.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkCode.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAI/B;;GAEG;AACH,UAAU,KAAK;IACb,WAAW;IACX,IAAI,EAAE,IAAI,CAAA;IACV,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,0CAA0C;IAC1C,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,eAAe;IACf,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,iCAAiC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,6BAA6B;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACtC,0BAA0B;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;IACzD,wBAAwB;IACxB,WAAW,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAA;CACjD;
|
|
1
|
+
{"version":3,"file":"IncremarkCode.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkCode.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAI/B;;GAEG;AACH,UAAU,KAAK;IACb,WAAW;IACX,IAAI,EAAE,IAAI,CAAA;IACV,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,0CAA0C;IAC1C,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,eAAe;IACf,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,iCAAiC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,6BAA6B;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACtC,0BAA0B;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;IACzD,wBAAwB;IACxB,WAAW,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAA;CACjD;AAiMH,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@file IncremarkContent.svelte - 开箱即用的 Markdown 渲染组件
|
|
3
|
+
@description 自动处理流式内容和普通内容的高级组件
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
<script lang="ts">
|
|
7
|
+
import type { Component } from 'svelte'
|
|
8
|
+
import { useIncremark, type UseIncremarkOptions } from '../stores/useIncremark'
|
|
9
|
+
import type { ComponentMap, IncremarkContentProps } from './types'
|
|
10
|
+
import Incremark from './Incremark.svelte'
|
|
11
|
+
import { get } from 'svelte/store'
|
|
12
|
+
|
|
13
|
+
let {
|
|
14
|
+
stream,
|
|
15
|
+
content,
|
|
16
|
+
components = {},
|
|
17
|
+
customContainers = {},
|
|
18
|
+
customCodeBlocks = {},
|
|
19
|
+
codeBlockConfigs = {},
|
|
20
|
+
isFinished = false,
|
|
21
|
+
incremarkOptions,
|
|
22
|
+
pendingClass = 'incremark-pending',
|
|
23
|
+
showBlockStatus = false
|
|
24
|
+
}: IncremarkContentProps = $props()
|
|
25
|
+
|
|
26
|
+
// 合并默认选项(初始化时使用)
|
|
27
|
+
const initialOptions: UseIncremarkOptions = {
|
|
28
|
+
gfm: true,
|
|
29
|
+
htmlTree: true,
|
|
30
|
+
containers: true,
|
|
31
|
+
math: true,
|
|
32
|
+
...incremarkOptions
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const { blocks, append, finalize, render, reset, isDisplayComplete, markdown, typewriter } = useIncremark(initialOptions)
|
|
36
|
+
|
|
37
|
+
// 监听 incremarkOptions 的变化,更新 typewriter 配置
|
|
38
|
+
$effect(() => {
|
|
39
|
+
if (incremarkOptions?.typewriter) {
|
|
40
|
+
typewriter.setOptions(incremarkOptions.typewriter)
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
// 派生状态
|
|
45
|
+
const isStreamMode = $derived(typeof stream === 'function')
|
|
46
|
+
|
|
47
|
+
// 保存前一个 content 值用于增量更新
|
|
48
|
+
let prevContent: string | undefined = $state(undefined)
|
|
49
|
+
let isStreaming = $state(false)
|
|
50
|
+
|
|
51
|
+
async function handleStreamInput() {
|
|
52
|
+
if (!stream || isStreaming) return
|
|
53
|
+
|
|
54
|
+
isStreaming = true
|
|
55
|
+
try {
|
|
56
|
+
const streamGen = stream()
|
|
57
|
+
|
|
58
|
+
for await (const chunk of streamGen) {
|
|
59
|
+
append(chunk)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
finalize()
|
|
63
|
+
} catch (error) {
|
|
64
|
+
console.error('Stream error: ', error)
|
|
65
|
+
finalize()
|
|
66
|
+
} finally {
|
|
67
|
+
isStreaming = false
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function handleContentInput(newContent?: string, oldContent?: string) {
|
|
72
|
+
if (!newContent) {
|
|
73
|
+
if (oldContent) {
|
|
74
|
+
reset()
|
|
75
|
+
}
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (newContent?.startsWith(oldContent ?? '')) {
|
|
80
|
+
const delta = newContent.slice((oldContent || '').length)
|
|
81
|
+
append(delta)
|
|
82
|
+
} else {
|
|
83
|
+
render(newContent)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 监听 content 变化
|
|
88
|
+
$effect(() => {
|
|
89
|
+
if (isStreamMode) {
|
|
90
|
+
handleStreamInput()
|
|
91
|
+
} else {
|
|
92
|
+
handleContentInput(content, prevContent)
|
|
93
|
+
}
|
|
94
|
+
prevContent = content
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
// 监听 isFinished 变化
|
|
98
|
+
$effect(() => {
|
|
99
|
+
if (isFinished && content === get(markdown)) {
|
|
100
|
+
finalize()
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
</script>
|
|
104
|
+
|
|
105
|
+
<Incremark
|
|
106
|
+
blocks={$blocks}
|
|
107
|
+
isDisplayComplete={$isDisplayComplete}
|
|
108
|
+
{pendingClass}
|
|
109
|
+
{showBlockStatus}
|
|
110
|
+
{components}
|
|
111
|
+
{customContainers}
|
|
112
|
+
{customCodeBlocks}
|
|
113
|
+
{codeBlockConfigs}
|
|
114
|
+
/>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Component } from 'svelte';
|
|
2
|
+
import type { IncremarkContentProps } from './types';
|
|
3
|
+
declare const IncremarkContent: Component<IncremarkContentProps, {}, "">;
|
|
4
|
+
type IncremarkContent = ReturnType<typeof IncremarkContent>;
|
|
5
|
+
export default IncremarkContent;
|
|
6
|
+
//# sourceMappingURL=IncremarkContent.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IncremarkContent.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkContent.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAEvC,OAAO,KAAK,EAAgB,qBAAqB,EAAE,MAAM,SAAS,CAAA;AA6GlE,QAAA,MAAM,gBAAgB,0CAAwC,CAAC;AAC/D,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC5D,eAAe,gBAAgB,CAAC"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* @description 导出所有组件
|
|
4
4
|
*/
|
|
5
5
|
export { default as Incremark } from './Incremark.svelte';
|
|
6
|
+
export { default as IncremarkContent } from './IncremarkContent.svelte';
|
|
6
7
|
export { default as IncremarkParagraph } from './IncremarkParagraph.svelte';
|
|
7
8
|
export { default as IncremarkInline } from './IncremarkInline.svelte';
|
|
8
9
|
export { default as IncremarkHeading } from './IncremarkHeading.svelte';
|
|
@@ -17,5 +18,5 @@ export { default as IncremarkFootnotes } from './IncremarkFootnotes.svelte';
|
|
|
17
18
|
export { default as IncremarkDefault } from './IncremarkDefault.svelte';
|
|
18
19
|
export { default as IncremarkRenderer } from './IncremarkRenderer.svelte';
|
|
19
20
|
export { default as AutoScrollContainer } from './AutoScrollContainer.svelte';
|
|
20
|
-
export type { ComponentMap,
|
|
21
|
+
export type { ComponentMap, RenderableBlock, IncremarkContentProps, CodeBlockConfig } from './types';
|
|
21
22
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAC3E,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,0BAA0B,CAAA;AACrE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AACvE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACjE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACjE,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAA;AACnE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,8BAA8B,CAAA;AAC7E,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,iCAAiC,CAAA;AACnF,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACjE,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AAC/E,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAC3E,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AACvE,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AACzE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,8BAA8B,CAAA;AAE7E,YAAY,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AACvE,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAC3E,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,0BAA0B,CAAA;AACrE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AACvE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACjE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACjE,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAA;AACnE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,8BAA8B,CAAA;AAC7E,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,iCAAiC,CAAA;AACnF,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACjE,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AAC/E,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAC3E,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AACvE,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AACzE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,8BAA8B,CAAA;AAE7E,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA"}
|
package/dist/components/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* @description 导出所有组件
|
|
4
4
|
*/
|
|
5
5
|
export { default as Incremark } from './Incremark.svelte';
|
|
6
|
+
export { default as IncremarkContent } from './IncremarkContent.svelte';
|
|
6
7
|
export { default as IncremarkParagraph } from './IncremarkParagraph.svelte';
|
|
7
8
|
export { default as IncremarkInline } from './IncremarkInline.svelte';
|
|
8
9
|
export { default as IncremarkHeading } from './IncremarkHeading.svelte';
|
|
@@ -2,17 +2,43 @@
|
|
|
2
2
|
* @file Component Types - 组件类型定义
|
|
3
3
|
* @description 定义组件相关的类型
|
|
4
4
|
*/
|
|
5
|
+
import type { Component } from 'svelte';
|
|
5
6
|
import type { ParsedBlock } from '@incremark/core';
|
|
7
|
+
import type { UseIncremarkOptions } from '../stores/useIncremark';
|
|
6
8
|
/**
|
|
7
9
|
* 组件映射类型
|
|
8
10
|
* 使用 any 以支持不同类型的组件
|
|
9
11
|
*/
|
|
10
12
|
export type ComponentMap = Partial<Record<string, any>>;
|
|
11
13
|
/**
|
|
12
|
-
*
|
|
14
|
+
* 可渲染的块类型(带 isLastPending 字段用于打字机光标)
|
|
13
15
|
*/
|
|
14
|
-
export
|
|
15
|
-
stableId: string;
|
|
16
|
+
export type RenderableBlock = ParsedBlock & {
|
|
16
17
|
isLastPending?: boolean;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* 代码块配置
|
|
21
|
+
*/
|
|
22
|
+
export interface CodeBlockConfig {
|
|
23
|
+
/** 是否从一开始就接管渲染,而不是等到 completed 状态 */
|
|
24
|
+
takeOver?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* IncremarkContent 组件 Props
|
|
28
|
+
*/
|
|
29
|
+
export interface IncremarkContentProps {
|
|
30
|
+
stream?: () => AsyncGenerator<string>;
|
|
31
|
+
content?: string;
|
|
32
|
+
components?: ComponentMap;
|
|
33
|
+
/** 自定义容器组件映射,key 为容器名称(如 'warning', 'info') */
|
|
34
|
+
customContainers?: Record<string, Component<any>>;
|
|
35
|
+
/** 自定义代码块组件映射,key 为代码语言名称(如 'echart', 'mermaid') */
|
|
36
|
+
customCodeBlocks?: Record<string, Component<any>>;
|
|
37
|
+
/** 代码块配置映射,key 为代码语言名称 */
|
|
38
|
+
codeBlockConfigs?: Record<string, CodeBlockConfig>;
|
|
39
|
+
isFinished?: boolean;
|
|
40
|
+
incremarkOptions?: UseIncremarkOptions;
|
|
41
|
+
pendingClass?: string;
|
|
42
|
+
showBlockStatus?: boolean;
|
|
17
43
|
}
|
|
18
44
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/components/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/components/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAEjE;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAA;AAEvD;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,CAAA;AAEvE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,qCAAqC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,MAAM,cAAc,CAAC,MAAM,CAAC,CAAA;IACrC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,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,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,gBAAgB,CAAC,EAAE,mBAAmB,CAAA;IACtC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B"}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export { useIncremark, type UseIncremarkOptions, type UseIncremarkReturn, type T
|
|
|
6
6
|
export { useDevTools, type UseDevToolsOptions } from './stores/useDevTools';
|
|
7
7
|
export { useBlockTransformer, type UseBlockTransformerOptions, type UseBlockTransformerReturn } from './stores/useBlockTransformer';
|
|
8
8
|
export { setDefinitionsContext, getDefinitionsContext, type DefinitionsContextValue } from './context/definitionsContext';
|
|
9
|
-
export { Incremark, IncremarkParagraph, IncremarkInline, IncremarkHeading, IncremarkCode, IncremarkList, IncremarkTable, IncremarkBlockquote, IncremarkThematicBreak, IncremarkMath, IncremarkHtmlElement, IncremarkFootnotes, IncremarkDefault, IncremarkRenderer, type ComponentMap, type
|
|
9
|
+
export { Incremark, IncremarkContent, IncremarkParagraph, IncremarkInline, IncremarkHeading, IncremarkCode, IncremarkList, IncremarkTable, IncremarkBlockquote, IncremarkThematicBreak, IncremarkMath, IncremarkHtmlElement, IncremarkFootnotes, IncremarkDefault, IncremarkRenderer, type ComponentMap, type RenderableBlock, type IncremarkContentProps, type CodeBlockConfig } from './components';
|
|
10
10
|
export { default as AutoScrollContainer } from './components/AutoScrollContainer.svelte';
|
|
11
11
|
export { default as ThemeProvider } from './ThemeProvider.svelte';
|
|
12
12
|
export type { ParsedBlock, IncrementalUpdate, ParserOptions, BlockStatus, Root, RootContent, SourceBlock, DisplayBlock, TransformerPlugin, TransformerOptions, TransformerState, AnimationEffect } from '@incremark/core';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,KAAK,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AACxJ,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAC3E,OAAO,EACL,mBAAmB,EACnB,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC/B,MAAM,8BAA8B,CAAA;AAGrC,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,KAAK,uBAAuB,EAAE,MAAM,8BAA8B,CAAA;AAGzH,OAAO,EACL,SAAS,EACT,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,sBAAsB,EACtB,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,YAAY,EACjB,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,KAAK,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AACxJ,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAC3E,OAAO,EACL,mBAAmB,EACnB,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC/B,MAAM,8BAA8B,CAAA;AAGrC,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,KAAK,uBAAuB,EAAE,MAAM,8BAA8B,CAAA;AAGzH,OAAO,EACL,SAAS,EACT,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,sBAAsB,EACtB,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACrB,MAAM,cAAc,CAAA;AAGrB,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,yCAAyC,CAAA;AACxF,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAGjE,YAAY,EACV,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,IAAI,EACJ,WAAW,EAEX,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EAChB,MAAM,iBAAiB,CAAA;AAGxB,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,UAAU,EACV,QAAQ,EACR,SAAS,EACT,eAAe,EACf,aAAa,EACb,WAAW,EACX,UAAU,EACV,mBAAmB,EACnB,cAAc,EACd,UAAU,EACV,YAAY,EACb,MAAM,iBAAiB,CAAA;AAGxB,OAAO,EACL,KAAK,YAAY,EACjB,YAAY,EACZ,SAAS,EACT,eAAe,EACf,UAAU,EACV,UAAU,EACX,MAAM,kBAAkB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ export { useBlockTransformer } from './stores/useBlockTransformer';
|
|
|
9
9
|
// Context
|
|
10
10
|
export { setDefinitionsContext, getDefinitionsContext } from './context/definitionsContext';
|
|
11
11
|
// Components
|
|
12
|
-
export { Incremark, IncremarkParagraph, IncremarkInline, IncremarkHeading, IncremarkCode, IncremarkList, IncremarkTable, IncremarkBlockquote, IncremarkThematicBreak, IncremarkMath, IncremarkHtmlElement, IncremarkFootnotes, IncremarkDefault, IncremarkRenderer } from './components';
|
|
12
|
+
export { Incremark, IncremarkContent, IncremarkParagraph, IncremarkInline, IncremarkHeading, IncremarkCode, IncremarkList, IncremarkTable, IncremarkBlockquote, IncremarkThematicBreak, IncremarkMath, IncremarkHtmlElement, IncremarkFootnotes, IncremarkDefault, IncremarkRenderer } from './components';
|
|
13
13
|
// Additional Components
|
|
14
14
|
export { default as AutoScrollContainer } from './components/AutoScrollContainer.svelte';
|
|
15
15
|
export { default as ThemeProvider } from './ThemeProvider.svelte';
|
|
@@ -29,8 +29,8 @@ export function useDevTools(incremark, options = {}) {
|
|
|
29
29
|
// 设置 parser 的 onChange 回调
|
|
30
30
|
incremark.parser.setOnChange((state) => {
|
|
31
31
|
const blocks = [
|
|
32
|
-
...state.completedBlocks
|
|
33
|
-
...state.pendingBlocks
|
|
32
|
+
...state.completedBlocks,
|
|
33
|
+
...state.pendingBlocks
|
|
34
34
|
];
|
|
35
35
|
devtools.update({
|
|
36
36
|
blocks,
|
|
@@ -30,6 +30,9 @@ export interface UseIncremarkOptions extends ParserOptions {
|
|
|
30
30
|
/** 打字机配置,传入即创建 transformer(可通过 enabled 控制是否启用) */
|
|
31
31
|
typewriter?: TypewriterOptions;
|
|
32
32
|
}
|
|
33
|
+
export type RenderableBlock = ParsedBlock & {
|
|
34
|
+
isLastPending?: boolean;
|
|
35
|
+
};
|
|
33
36
|
/**
|
|
34
37
|
* 打字机控制对象
|
|
35
38
|
*/
|
|
@@ -66,10 +69,7 @@ export interface UseIncremarkReturn {
|
|
|
66
69
|
/** 当前完整的 AST */
|
|
67
70
|
ast: Readable<Root>;
|
|
68
71
|
/** 用于渲染的 blocks(根据打字机设置自动处理) */
|
|
69
|
-
blocks: Readable<Array<
|
|
70
|
-
stableId: string;
|
|
71
|
-
isLastPending?: boolean;
|
|
72
|
-
}>>;
|
|
72
|
+
blocks: Readable<Array<RenderableBlock>>;
|
|
73
73
|
/** 是否正在加载 */
|
|
74
74
|
isLoading: Writable<boolean>;
|
|
75
75
|
/** 是否已完成(finalize) */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useIncremark.d.ts","sourceRoot":"","sources":["../../src/stores/useIncremark.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAqB,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC9E,OAAO,EACL,qBAAqB,EACrB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,IAAI,EACT,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACrB,MAAM,iBAAiB,CAAA;AAIxB;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,wBAAwB;IACxB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,oCAAoC;IACpC,YAAY,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACxC,gBAAgB;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,eAAe;IACf,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,YAAY;IACZ,OAAO,CAAC,EAAE,iBAAiB,EAAE,CAAA;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,kDAAkD;IAClD,UAAU,CAAC,EAAE,iBAAiB,CAAA;CAC/B;
|
|
1
|
+
{"version":3,"file":"useIncremark.d.ts","sourceRoot":"","sources":["../../src/stores/useIncremark.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAqB,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC9E,OAAO,EACL,qBAAqB,EACrB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,IAAI,EACT,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACrB,MAAM,iBAAiB,CAAA;AAIxB;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,wBAAwB;IACxB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,oCAAoC;IACpC,YAAY,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACxC,gBAAgB;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,eAAe;IACf,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,YAAY;IACZ,OAAO,CAAC,EAAE,iBAAiB,EAAE,CAAA;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,kDAAkD;IAClD,UAAU,CAAC,EAAE,iBAAiB,CAAA;CAC/B;AAGD,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,CAAA;AAEvE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,eAAe;IACf,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;IAC1B,aAAa;IACb,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IACtC,cAAc;IACd,YAAY,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;IAC/B,YAAY;IACZ,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;IAC3B,aAAa;IACb,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAA;IACjC,kBAAkB;IAClB,IAAI,EAAE,MAAM,IAAI,CAAA;IAChB,WAAW;IACX,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,WAAW;IACX,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,aAAa;IACb,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAA;CAC1D;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,0BAA0B;IAC1B,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;IAC1B,cAAc;IACd,eAAe,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAA;IACxC,cAAc;IACd,aAAa,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAA;IACtC,gBAAgB;IAChB,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAA;IACnB,gCAAgC;IAChC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAA;IACxC,aAAa;IACb,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;IAC5B,sBAAsB;IACtB,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;IAC9B;;;;;OAKG;IACH,iBAAiB,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;IACpC,gBAAgB;IAChB,sBAAsB,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IAC1C,WAAW;IACX,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,iBAAiB,CAAA;IAC5C,WAAW;IACX,QAAQ,EAAE,MAAM,iBAAiB,CAAA;IACjC,WAAW;IACX,KAAK,EAAE,MAAM,iBAAiB,CAAA;IAC9B,gBAAgB;IAChB,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,uCAAuC;IACvC,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,iBAAiB,CAAA;IAC9C,YAAY;IACZ,MAAM,EAAE,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAA;IAChD,YAAY;IACZ,UAAU,EAAE,kBAAkB,CAAA;CAC/B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,kBAAkB,CAyKlF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 使用 Shiki Highlighter
|
|
3
|
+
* @param themeGetter 传入一个返回主题字符串的函数,例如 () => theme
|
|
4
|
+
*/
|
|
5
|
+
export declare function useShiki(themeGetter: () => string): {
|
|
6
|
+
readonly isHighlighting: boolean;
|
|
7
|
+
highlight: (code: string, lang: string, fallbackTheme: string) => Promise<string>;
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=useShiki.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useShiki.svelte.d.ts","sourceRoot":"","sources":["../../src/stores/useShiki.svelte.ts"],"names":[],"mappings":"AAkFA;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,MAAM;;sBAOjB,MAAM,QAAQ,MAAM,iBAAiB,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;EA+B7F"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// ============ 单例管理器 ============
|
|
2
|
+
class ShikiManager {
|
|
3
|
+
static instance = null;
|
|
4
|
+
highlighters = new Map();
|
|
5
|
+
constructor() { }
|
|
6
|
+
static getInstance() {
|
|
7
|
+
if (!ShikiManager.instance) {
|
|
8
|
+
ShikiManager.instance = new ShikiManager();
|
|
9
|
+
}
|
|
10
|
+
return ShikiManager.instance;
|
|
11
|
+
}
|
|
12
|
+
async getHighlighter(theme) {
|
|
13
|
+
if (this.highlighters.has(theme)) {
|
|
14
|
+
return this.highlighters.get(theme);
|
|
15
|
+
}
|
|
16
|
+
const { createHighlighter } = await import('shiki');
|
|
17
|
+
const highlighter = await createHighlighter({
|
|
18
|
+
themes: [theme],
|
|
19
|
+
langs: []
|
|
20
|
+
});
|
|
21
|
+
const info = {
|
|
22
|
+
highlighter,
|
|
23
|
+
loadedLanguages: new Set(),
|
|
24
|
+
loadedThemes: new Set([theme])
|
|
25
|
+
};
|
|
26
|
+
this.highlighters.set(theme, info);
|
|
27
|
+
return info;
|
|
28
|
+
}
|
|
29
|
+
async loadLanguage(theme, lang) {
|
|
30
|
+
const info = this.highlighters.get(theme);
|
|
31
|
+
if (!info || info.loadedLanguages.has(lang))
|
|
32
|
+
return;
|
|
33
|
+
try {
|
|
34
|
+
await info.highlighter.loadLanguage(lang);
|
|
35
|
+
info.loadedLanguages.add(lang);
|
|
36
|
+
}
|
|
37
|
+
catch { /* 静默处理 */ }
|
|
38
|
+
}
|
|
39
|
+
async loadTheme(theme) {
|
|
40
|
+
const info = this.highlighters.get(theme);
|
|
41
|
+
if (!info || info.loadedThemes.has(theme))
|
|
42
|
+
return;
|
|
43
|
+
try {
|
|
44
|
+
await info.highlighter.loadTheme(theme);
|
|
45
|
+
info.loadedThemes.add(theme);
|
|
46
|
+
}
|
|
47
|
+
catch { /* 静默处理 */ }
|
|
48
|
+
}
|
|
49
|
+
async codeToHtml(theme, code, lang, fallbackTheme) {
|
|
50
|
+
const info = this.highlighters.get(theme);
|
|
51
|
+
if (!info)
|
|
52
|
+
throw new Error('Highlighter not found');
|
|
53
|
+
const actualLang = info.loadedLanguages.has(lang) ? lang : 'text';
|
|
54
|
+
return info.highlighter.codeToHtml(code, {
|
|
55
|
+
lang: actualLang,
|
|
56
|
+
theme: theme
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const shikiManager = ShikiManager.getInstance();
|
|
61
|
+
// ============ Svelte 5 Composable ============
|
|
62
|
+
/**
|
|
63
|
+
* 使用 Shiki Highlighter
|
|
64
|
+
* @param themeGetter 传入一个返回主题字符串的函数,例如 () => theme
|
|
65
|
+
*/
|
|
66
|
+
export function useShiki(themeGetter) {
|
|
67
|
+
// 使用 Svelte 5 的原生响应式状态
|
|
68
|
+
let isHighlighting = $state(false);
|
|
69
|
+
/**
|
|
70
|
+
* 高亮代码
|
|
71
|
+
*/
|
|
72
|
+
async function highlight(code, lang, fallbackTheme) {
|
|
73
|
+
// 关键:每次执行时通过 Getter 获取最新的主题
|
|
74
|
+
const currentTheme = themeGetter();
|
|
75
|
+
const currentFallback = fallbackTheme;
|
|
76
|
+
isHighlighting = true;
|
|
77
|
+
try {
|
|
78
|
+
const info = await shikiManager.getHighlighter(currentTheme);
|
|
79
|
+
// 按需加载语言
|
|
80
|
+
if (!info.loadedLanguages.has(lang) && lang !== 'text') {
|
|
81
|
+
await shikiManager.loadLanguage(currentTheme, lang);
|
|
82
|
+
}
|
|
83
|
+
// 按需加载主题
|
|
84
|
+
if (!info.loadedThemes.has(currentTheme)) {
|
|
85
|
+
await shikiManager.loadTheme(currentTheme);
|
|
86
|
+
}
|
|
87
|
+
return await shikiManager.codeToHtml(currentTheme, code, lang, currentFallback);
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
isHighlighting = false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
// 使用 getter 暴露只读状态,保持 UI 响应
|
|
95
|
+
get isHighlighting() { return isHighlighting; },
|
|
96
|
+
highlight
|
|
97
|
+
};
|
|
98
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTypewriter.d.ts","sourceRoot":"","sources":["../../src/stores/useTypewriter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAqB,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC9E,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,WAAW,EAGhB,KAAK,gBAAgB,
|
|
1
|
+
{"version":3,"file":"useTypewriter.d.ts","sourceRoot":"","sources":["../../src/stores/useTypewriter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAqB,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC9E,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,WAAW,EAGhB,KAAK,gBAAgB,EAEtB,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAG3E;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,YAAY;IACZ,UAAU,CAAC,EAAE,iBAAiB,CAAA;IAC9B,oBAAoB;IACpB,eAAe,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAA;IACxC,oBAAoB;IACpB,aAAa,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAA;CACvC;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,qCAAqC;IACrC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,WAAW,GAAG;QAAE,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC,CAAA;IAClE,cAAc;IACd,UAAU,EAAE,kBAAkB,CAAA;IAC9B,qBAAqB;IACrB,WAAW,EAAE,gBAAgB,CAAC,WAAW,CAAC,GAAG,IAAI,CAAA;IACjD,oCAAoC;IACpC,mBAAmB,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;CACvC;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,mBAAmB,CA4KhF"}
|
|
@@ -79,13 +79,12 @@ export function useTypewriter(options) {
|
|
|
79
79
|
const rawBlocks = derived([completedBlocks, pendingBlocks], ([$completedBlocks, $pendingBlocks]) => {
|
|
80
80
|
const result = [];
|
|
81
81
|
for (const block of $completedBlocks) {
|
|
82
|
-
result.push(
|
|
82
|
+
result.push(block);
|
|
83
83
|
}
|
|
84
84
|
for (let i = 0; i < $pendingBlocks.length; i++) {
|
|
85
85
|
const isLastPending = i === $pendingBlocks.length - 1;
|
|
86
86
|
result.push({
|
|
87
87
|
...$pendingBlocks[i],
|
|
88
|
-
stableId: `pending-${i}`,
|
|
89
88
|
isLastPending
|
|
90
89
|
});
|
|
91
90
|
}
|
|
@@ -108,7 +107,6 @@ export function useTypewriter(options) {
|
|
|
108
107
|
}
|
|
109
108
|
return {
|
|
110
109
|
id: db.id,
|
|
111
|
-
stableId: db.id,
|
|
112
110
|
status: (db.isDisplayComplete ? 'completed' : 'pending'),
|
|
113
111
|
isLastPending,
|
|
114
112
|
node,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@incremark/svelte",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"description": "Incremark Svelte 5 集成",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"svelte": "./dist/index.js",
|
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"shiki": "^3.20.0",
|
|
27
|
-
"@incremark/devtools": "0.2.
|
|
28
|
-
"@incremark/core": "0.2.
|
|
29
|
-
"@incremark/
|
|
30
|
-
"@incremark/
|
|
27
|
+
"@incremark/devtools": "0.2.7",
|
|
28
|
+
"@incremark/core": "0.2.7",
|
|
29
|
+
"@incremark/shared": "0.2.7",
|
|
30
|
+
"@incremark/theme": "0.2.7"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"svelte": "^5.0.0",
|