@incremark/svelte 0.2.3 → 0.2.5
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 +2 -1
- package/dist/components/AutoScrollContainer.svelte.d.ts +2 -1
- package/dist/components/AutoScrollContainer.svelte.d.ts.map +1 -1
- package/dist/components/Incremark.svelte +32 -46
- package/dist/components/Incremark.svelte.d.ts +6 -1
- package/dist/components/Incremark.svelte.d.ts.map +1 -1
- package/dist/components/IncremarkCode.svelte +27 -2
- package/dist/components/IncremarkCode.svelte.d.ts +4 -0
- package/dist/components/IncremarkCode.svelte.d.ts.map +1 -1
- package/dist/components/IncremarkContainer.svelte +83 -0
- package/dist/components/IncremarkContainer.svelte.d.ts +22 -0
- package/dist/components/IncremarkContainer.svelte.d.ts.map +1 -0
- package/dist/components/IncremarkFootnotes.svelte +3 -12
- package/dist/components/IncremarkFootnotes.svelte.d.ts.map +1 -1
- package/dist/components/IncremarkInline.svelte +5 -22
- package/dist/components/IncremarkInline.svelte.d.ts.map +1 -1
- package/dist/components/IncremarkList.svelte +40 -15
- package/dist/components/IncremarkList.svelte.d.ts +1 -0
- package/dist/components/IncremarkList.svelte.d.ts.map +1 -1
- package/dist/components/IncremarkRenderer.svelte +37 -3
- package/dist/components/IncremarkRenderer.svelte.d.ts +5 -1
- package/dist/components/IncremarkRenderer.svelte.d.ts.map +1 -1
- package/dist/stores/useIncremark.d.ts +7 -0
- package/dist/stores/useIncremark.d.ts.map +1 -1
- package/dist/stores/useIncremark.js +6 -1
- package/dist/stores/useTypewriter.d.ts +2 -0
- package/dist/stores/useTypewriter.d.ts.map +1 -1
- package/dist/stores/useTypewriter.js +11 -1
- package/package.json +5 -5
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
|
|
6
6
|
<script lang="ts">
|
|
7
7
|
import { onMount, onDestroy } from 'svelte'
|
|
8
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* 组件 Props
|
|
11
12
|
*/
|
|
12
|
-
interface Props {
|
|
13
|
+
interface Props extends HTMLAttributes<HTMLDivElement>{
|
|
13
14
|
/** 是否启用自动滚动 */
|
|
14
15
|
enabled?: boolean
|
|
15
16
|
/** 触发自动滚动的底部阈值(像素) */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutoScrollContainer.svelte.d.ts","sourceRoot":"","sources":["../../src/components/AutoScrollContainer.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AutoScrollContainer.svelte.d.ts","sourceRoot":"","sources":["../../src/components/AutoScrollContainer.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGpD;;GAEG;AACH,UAAU,KAAM,SAAQ,cAAc,CAAC,cAAc,CAAC;IACpD,eAAe;IACf,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW;IACX,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,UAAU;IACV,QAAQ,CAAC,EAAE,OAAO,QAAQ,EAAE,OAAO,CAAA;CACpC;AAoJH,QAAA,MAAM,mBAAmB,2CAAwC,CAAC;AAClE,KAAK,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAClE,eAAe,mBAAmB,CAAC"}
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
-->
|
|
5
5
|
|
|
6
6
|
<script lang="ts">
|
|
7
|
+
import type { Component } from 'svelte'
|
|
7
8
|
import type { Readable } from 'svelte/store'
|
|
8
|
-
import type {
|
|
9
|
+
import type { RootContent } from '@incremark/core'
|
|
9
10
|
import type { HTML } from 'mdast'
|
|
10
11
|
|
|
11
12
|
import { getDefinitionsContext } from '../context/definitionsContext'
|
|
@@ -24,6 +25,7 @@
|
|
|
24
25
|
import IncremarkHtmlElement from './IncremarkHtmlElement.svelte'
|
|
25
26
|
import IncremarkDefault from './IncremarkDefault.svelte'
|
|
26
27
|
import IncremarkFootnotes from './IncremarkFootnotes.svelte'
|
|
28
|
+
import IncremarkRenderer from './IncremarkRenderer.svelte'
|
|
27
29
|
|
|
28
30
|
/**
|
|
29
31
|
* 检查是否是 html 节点
|
|
@@ -40,6 +42,10 @@
|
|
|
40
42
|
blocks?: BlockWithStableId[] | Readable<BlockWithStableId[]>
|
|
41
43
|
/** 自定义组件映射,key 为节点类型 */
|
|
42
44
|
components?: ComponentMap
|
|
45
|
+
/** 自定义容器组件映射,key 为容器名称(如 'warning', 'info') */
|
|
46
|
+
customContainers?: Record<string, Component<any>>
|
|
47
|
+
/** 自定义代码块组件映射,key 为代码语言名称(如 'echart', 'mermaid') */
|
|
48
|
+
customCodeBlocks?: Record<string, Component<any>>
|
|
43
49
|
/** 待处理块的样式类名 */
|
|
44
50
|
pendingClass?: string
|
|
45
51
|
/** 已完成块的样式类名 */
|
|
@@ -53,28 +59,21 @@
|
|
|
53
59
|
let {
|
|
54
60
|
blocks = [],
|
|
55
61
|
components = {},
|
|
62
|
+
customContainers = {},
|
|
63
|
+
customCodeBlocks = {},
|
|
56
64
|
pendingClass = 'incremark-pending',
|
|
57
65
|
completedClass = 'incremark-completed',
|
|
58
66
|
showBlockStatus = false,
|
|
59
67
|
incremark
|
|
60
68
|
}: Props = $props()
|
|
61
69
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const footnoteReferenceOrder = $derived.by(() => {
|
|
65
|
-
try {
|
|
66
|
-
const context = getDefinitionsContext()
|
|
67
|
-
return context.footnoteReferenceOrder
|
|
68
|
-
} catch {
|
|
69
|
-
// 如果没有 context,返回 null
|
|
70
|
-
return null
|
|
71
|
-
}
|
|
72
|
-
})
|
|
70
|
+
const context = getDefinitionsContext();
|
|
71
|
+
const footnoteReferenceOrder = $derived(context?.footnoteReferenceOrder ?? []);
|
|
73
72
|
|
|
74
|
-
// 计算
|
|
75
|
-
const
|
|
73
|
+
// 计算 isDisplayComplete(当不使用 incremark 时)
|
|
74
|
+
const actualIsDisplayComplete = $derived.by(() => {
|
|
76
75
|
if (incremark) {
|
|
77
|
-
// 如果提供了 incremark,在模板中直接使用 $incremark.
|
|
76
|
+
// 如果提供了 incremark,在模板中直接使用 $incremark.isDisplayComplete
|
|
78
77
|
return false
|
|
79
78
|
}
|
|
80
79
|
// 如果手动传入 blocks,自动判断是否所有 block 都是 completed
|
|
@@ -102,13 +101,6 @@
|
|
|
102
101
|
...components
|
|
103
102
|
})
|
|
104
103
|
|
|
105
|
-
/**
|
|
106
|
-
* 获取组件
|
|
107
|
-
*/
|
|
108
|
-
function getComponent(type: string): any {
|
|
109
|
-
return mergedComponents[type] || components?.default || IncremarkDefault
|
|
110
|
-
}
|
|
111
|
-
|
|
112
104
|
// 处理 blocks(可能是 store 或数组)
|
|
113
105
|
const blocksArray = $derived.by(() => {
|
|
114
106
|
if (incremark) {
|
|
@@ -120,7 +112,7 @@
|
|
|
120
112
|
|
|
121
113
|
// 提取 incremark 的 stores(如果存在)
|
|
122
114
|
const incremarkBlocks = $derived.by(() => incremark?.blocks)
|
|
123
|
-
const
|
|
115
|
+
const incremarkIsDisplayComplete = $derived.by(() => incremark?.isDisplayComplete)
|
|
124
116
|
</script>
|
|
125
117
|
|
|
126
118
|
<div class="incremark">
|
|
@@ -132,16 +124,13 @@
|
|
|
132
124
|
<div
|
|
133
125
|
class="incremark-block {block.status === 'completed' ? completedClass : pendingClass} {showBlockStatus ? 'incremark-show-status' : ''} {(block as BlockWithStableId).isLastPending ? 'incremark-last-pending' : ''}"
|
|
134
126
|
>
|
|
135
|
-
<!--
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
{
|
|
141
|
-
|
|
142
|
-
<Component node={block.node} />
|
|
143
|
-
{/if}
|
|
144
|
-
{/if}
|
|
127
|
+
<!-- 使用 IncremarkRenderer,传递 customContainers 和 customCodeBlocks -->
|
|
128
|
+
<IncremarkRenderer
|
|
129
|
+
node={block.node}
|
|
130
|
+
customContainers={customContainers}
|
|
131
|
+
customCodeBlocks={customCodeBlocks}
|
|
132
|
+
blockStatus={block.status}
|
|
133
|
+
/>
|
|
145
134
|
</div>
|
|
146
135
|
{/if}
|
|
147
136
|
{/each}
|
|
@@ -152,28 +141,25 @@
|
|
|
152
141
|
<div
|
|
153
142
|
class="incremark-block {block.status === 'completed' ? completedClass : pendingClass} {showBlockStatus ? 'incremark-show-status' : ''} {block.isLastPending ? 'incremark-last-pending' : ''}"
|
|
154
143
|
>
|
|
155
|
-
<!--
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
{
|
|
161
|
-
|
|
162
|
-
<Component node={block.node} />
|
|
163
|
-
{/if}
|
|
164
|
-
{/if}
|
|
144
|
+
<!-- 使用 IncremarkRenderer,传递 customContainers 和 customCodeBlocks -->
|
|
145
|
+
<IncremarkRenderer
|
|
146
|
+
node={block.node}
|
|
147
|
+
customContainers={customContainers}
|
|
148
|
+
customCodeBlocks={customCodeBlocks}
|
|
149
|
+
blockStatus={block.status}
|
|
150
|
+
/>
|
|
165
151
|
</div>
|
|
166
152
|
{/if}
|
|
167
153
|
{/each}
|
|
168
154
|
{/if}
|
|
169
155
|
|
|
170
|
-
<!--
|
|
171
|
-
{#if incremark &&
|
|
156
|
+
<!-- 脚注列表(仅在内容完全显示后显示) -->
|
|
157
|
+
{#if incremark && incremarkIsDisplayComplete && footnoteReferenceOrder && $incremarkIsDisplayComplete}
|
|
172
158
|
{@const footnoteOrder = $footnoteReferenceOrder ?? []}
|
|
173
159
|
{#if footnoteOrder.length > 0}
|
|
174
160
|
<IncremarkFootnotes />
|
|
175
161
|
{/if}
|
|
176
|
-
{:else if !incremark &&
|
|
162
|
+
{:else if !incremark && actualIsDisplayComplete && footnoteReferenceOrder}
|
|
177
163
|
{@const footnoteOrder = $footnoteReferenceOrder ?? []}
|
|
178
164
|
{#if footnoteOrder.length > 0}
|
|
179
165
|
<IncremarkFootnotes />
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Component } from 'svelte';
|
|
1
2
|
import type { Readable } from 'svelte/store';
|
|
2
3
|
import type { UseIncremarkReturn } from '../stores/useIncremark';
|
|
3
4
|
import type { ComponentMap, BlockWithStableId } from './types';
|
|
@@ -9,6 +10,10 @@ interface Props {
|
|
|
9
10
|
blocks?: BlockWithStableId[] | Readable<BlockWithStableId[]>;
|
|
10
11
|
/** 自定义组件映射,key 为节点类型 */
|
|
11
12
|
components?: ComponentMap;
|
|
13
|
+
/** 自定义容器组件映射,key 为容器名称(如 'warning', 'info') */
|
|
14
|
+
customContainers?: Record<string, Component<any>>;
|
|
15
|
+
/** 自定义代码块组件映射,key 为代码语言名称(如 'echart', 'mermaid') */
|
|
16
|
+
customCodeBlocks?: Record<string, Component<any>>;
|
|
12
17
|
/** 待处理块的样式类名 */
|
|
13
18
|
pendingClass?: string;
|
|
14
19
|
/** 已完成块的样式类名 */
|
|
@@ -18,7 +23,7 @@ interface Props {
|
|
|
18
23
|
/** 可选:useIncremark 返回的对象(用于自动注入数据) */
|
|
19
24
|
incremark?: UseIncremarkReturn;
|
|
20
25
|
}
|
|
21
|
-
declare const Incremark:
|
|
26
|
+
declare const Incremark: Component<Props, {}, "">;
|
|
22
27
|
type Incremark = ReturnType<typeof Incremark>;
|
|
23
28
|
export default Incremark;
|
|
24
29
|
//# sourceMappingURL=Incremark.svelte.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Incremark.svelte.d.ts","sourceRoot":"","sources":["../../src/components/Incremark.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAK5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;
|
|
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,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAgB5D;;GAEG;AACH,UAAU,KAAK;IACb,wCAAwC;IACxC,MAAM,CAAC,EAAE,iBAAiB,EAAE,GAAG,QAAQ,CAAC,iBAAiB,EAAE,CAAC,CAAA;IAC5D,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,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;AAuIH,QAAA,MAAM,SAAS,0BAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
|
|
@@ -19,13 +19,19 @@
|
|
|
19
19
|
disableHighlight?: boolean
|
|
20
20
|
/** Mermaid 渲染延迟(毫秒),用于流式输入时防抖 */
|
|
21
21
|
mermaidDelay?: number
|
|
22
|
+
/** 自定义代码块组件映射,key 为代码语言名称 */
|
|
23
|
+
customCodeBlocks?: Record<string, any>
|
|
24
|
+
/** 块状态,用于判断是否使用自定义组件 */
|
|
25
|
+
blockStatus?: 'pending' | 'stable' | 'completed'
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
let {
|
|
25
29
|
node,
|
|
26
30
|
theme = 'github-dark',
|
|
27
31
|
disableHighlight = false,
|
|
28
|
-
mermaidDelay = 500
|
|
32
|
+
mermaidDelay = 500,
|
|
33
|
+
customCodeBlocks,
|
|
34
|
+
blockStatus = 'completed'
|
|
29
35
|
}: Props = $props()
|
|
30
36
|
|
|
31
37
|
// 状态
|
|
@@ -55,6 +61,18 @@
|
|
|
55
61
|
const code = $derived(node.value)
|
|
56
62
|
const isMermaid = $derived(language === 'mermaid')
|
|
57
63
|
|
|
64
|
+
// 检查是否有自定义代码块组件
|
|
65
|
+
const CustomCodeBlock = $derived.by(() => {
|
|
66
|
+
// 如果代码块还在 pending 状态,不使用自定义组件
|
|
67
|
+
if (blockStatus === 'pending') {
|
|
68
|
+
return null
|
|
69
|
+
}
|
|
70
|
+
return customCodeBlocks?.[language] || null
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
// 是否使用自定义组件
|
|
74
|
+
const useCustomComponent = $derived(!!CustomCodeBlock)
|
|
75
|
+
|
|
58
76
|
/**
|
|
59
77
|
* 切换 Mermaid 视图模式
|
|
60
78
|
*/
|
|
@@ -210,8 +228,15 @@
|
|
|
210
228
|
})
|
|
211
229
|
</script>
|
|
212
230
|
|
|
231
|
+
<!-- 自定义代码块组件 -->
|
|
232
|
+
{#if useCustomComponent && CustomCodeBlock}
|
|
233
|
+
<svelte:component
|
|
234
|
+
this={CustomCodeBlock}
|
|
235
|
+
codeStr={code}
|
|
236
|
+
lang={language}
|
|
237
|
+
/>
|
|
213
238
|
<!-- Mermaid 图表 -->
|
|
214
|
-
{
|
|
239
|
+
{:else if isMermaid}
|
|
215
240
|
<div class="incremark-mermaid">
|
|
216
241
|
<div class="mermaid-header">
|
|
217
242
|
<span class="language">MERMAID</span>
|
|
@@ -11,6 +11,10 @@ interface Props {
|
|
|
11
11
|
disableHighlight?: boolean;
|
|
12
12
|
/** Mermaid 渲染延迟(毫秒),用于流式输入时防抖 */
|
|
13
13
|
mermaidDelay?: number;
|
|
14
|
+
/** 自定义代码块组件映射,key 为代码语言名称 */
|
|
15
|
+
customCodeBlocks?: Record<string, any>;
|
|
16
|
+
/** 块状态,用于判断是否使用自定义组件 */
|
|
17
|
+
blockStatus?: 'pending' | 'stable' | 'completed';
|
|
14
18
|
}
|
|
15
19
|
declare const IncremarkCode: import("svelte").Component<Props, {}, "">;
|
|
16
20
|
type IncremarkCode = ReturnType<typeof IncremarkCode>;
|
|
@@ -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,eAAe;IACf,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,iCAAiC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAA;
|
|
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,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,wBAAwB;IACxB,WAAW,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAA;CACjD;AAmRH,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@file IncremarkContainer.svelte - 容器组件
|
|
3
|
+
@description 用于渲染自定义容器节点
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
<script lang="ts">
|
|
7
|
+
import type { RootContent } from 'mdast'
|
|
8
|
+
import IncremarkRenderer from './IncremarkRenderer.svelte'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 容器节点类型定义
|
|
12
|
+
* 根据 directive 解析后的结构
|
|
13
|
+
*/
|
|
14
|
+
export interface ContainerNode {
|
|
15
|
+
type: 'containerDirective' | 'leafDirective' | 'textDirective'
|
|
16
|
+
name: string
|
|
17
|
+
attributes?: Record<string, string>
|
|
18
|
+
children?: RootContent[]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 组件 Props
|
|
23
|
+
*/
|
|
24
|
+
interface Props {
|
|
25
|
+
node: ContainerNode
|
|
26
|
+
customContainers?: Record<string, any>
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let { node, customContainers = {} }: Props = $props()
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 解析 attributes 字符串为对象
|
|
33
|
+
* directive 的 attributes 可能是字符串格式,需要解析
|
|
34
|
+
*/
|
|
35
|
+
function parseOptions(attributes?: Record<string, string>): Record<string, any> {
|
|
36
|
+
if (!attributes) return {}
|
|
37
|
+
|
|
38
|
+
const options: Record<string, any> = {}
|
|
39
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
40
|
+
// 尝试解析 JSON 值
|
|
41
|
+
try {
|
|
42
|
+
options[key] = JSON.parse(value)
|
|
43
|
+
} catch {
|
|
44
|
+
// 如果不是 JSON,直接使用字符串值
|
|
45
|
+
options[key] = value
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return options
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const containerName = $derived(node.name)
|
|
52
|
+
const options = $derived(parseOptions(node.attributes))
|
|
53
|
+
const CustomContainer = $derived(customContainers?.[containerName])
|
|
54
|
+
|
|
55
|
+
// 如果没有自定义容器组件,使用默认渲染
|
|
56
|
+
const hasCustomContainer = $derived(!!CustomContainer)
|
|
57
|
+
</script>
|
|
58
|
+
|
|
59
|
+
{#if hasCustomContainer && CustomContainer}
|
|
60
|
+
<!-- 如果有自定义容器组件,使用自定义组件 -->
|
|
61
|
+
<CustomContainer
|
|
62
|
+
name={containerName}
|
|
63
|
+
options={options}
|
|
64
|
+
>
|
|
65
|
+
{#if node.children && node.children.length > 0}
|
|
66
|
+
{#each node.children as child, index (index)}
|
|
67
|
+
<IncremarkRenderer node={child} />
|
|
68
|
+
{/each}
|
|
69
|
+
{/if}
|
|
70
|
+
</CustomContainer>
|
|
71
|
+
{:else}
|
|
72
|
+
<!-- 如果没有自定义容器组件,使用默认渲染 -->
|
|
73
|
+
<div class="incremark-container incremark-container-{containerName}">
|
|
74
|
+
{#if node.children && node.children.length > 0}
|
|
75
|
+
<div class="incremark-container-content">
|
|
76
|
+
{#each node.children as child, index (index)}
|
|
77
|
+
<IncremarkRenderer node={child} />
|
|
78
|
+
{/each}
|
|
79
|
+
</div>
|
|
80
|
+
{/if}
|
|
81
|
+
</div>
|
|
82
|
+
{/if}
|
|
83
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { RootContent } from 'mdast';
|
|
2
|
+
/**
|
|
3
|
+
* 容器节点类型定义
|
|
4
|
+
* 根据 directive 解析后的结构
|
|
5
|
+
*/
|
|
6
|
+
export interface ContainerNode {
|
|
7
|
+
type: 'containerDirective' | 'leafDirective' | 'textDirective';
|
|
8
|
+
name: string;
|
|
9
|
+
attributes?: Record<string, string>;
|
|
10
|
+
children?: RootContent[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 组件 Props
|
|
14
|
+
*/
|
|
15
|
+
interface Props {
|
|
16
|
+
node: ContainerNode;
|
|
17
|
+
customContainers?: Record<string, any>;
|
|
18
|
+
}
|
|
19
|
+
declare const IncremarkContainer: import("svelte").Component<Props, {}, "">;
|
|
20
|
+
type IncremarkContainer = ReturnType<typeof IncremarkContainer>;
|
|
21
|
+
export default IncremarkContainer;
|
|
22
|
+
//# sourceMappingURL=IncremarkContainer.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IncremarkContainer.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkContainer.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAItC;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,oBAAoB,GAAG,eAAe,GAAG,eAAe,CAAA;IAC9D,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAA;CACzB;AAED;;GAEG;AACH,UAAU,KAAK;IACb,IAAI,EAAE,aAAa,CAAA;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CACvC;AAgEH,QAAA,MAAM,kBAAkB,2CAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
|
|
@@ -9,19 +9,10 @@
|
|
|
9
9
|
import { getDefinitionsContext } from '../context/definitionsContext'
|
|
10
10
|
import IncremarkRenderer from './IncremarkRenderer.svelte'
|
|
11
11
|
|
|
12
|
-
// 从 context 获取数据
|
|
13
|
-
let definations: Readable<Record<string, any>> | null = null
|
|
14
|
-
let footnoteDefinitions: Readable<Record<string, FootnoteDefinition>> | null = null
|
|
15
|
-
let footnoteReferenceOrder: Readable<string[]> | null = null
|
|
16
12
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
footnoteDefinitions = context.footnoteDefinitions
|
|
21
|
-
footnoteReferenceOrder = context.footnoteReferenceOrder
|
|
22
|
-
} catch {
|
|
23
|
-
// Context 不存在
|
|
24
|
-
}
|
|
13
|
+
const context = getDefinitionsContext()
|
|
14
|
+
const footnoteDefinitions = $derived(context?.footnoteDefinitions ?? {});
|
|
15
|
+
const footnoteReferenceOrder = $derived(context?.footnoteReferenceOrder ?? []);
|
|
25
16
|
|
|
26
17
|
/**
|
|
27
18
|
* 按引用顺序排列的脚注列表
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IncremarkFootnotes.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkFootnotes.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"IncremarkFootnotes.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkFootnotes.svelte.ts"],"names":[],"mappings":"AA4EA,QAAA,MAAM,kBAAkB,2DAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
-->
|
|
5
5
|
|
|
6
6
|
<script lang="ts">
|
|
7
|
-
import type { Readable } from 'svelte/store'
|
|
8
7
|
import type { PhrasingContent, ImageReference, LinkReference } from 'mdast'
|
|
9
8
|
import type { TextChunk } from '@incremark/core'
|
|
10
9
|
import {
|
|
@@ -72,25 +71,9 @@
|
|
|
72
71
|
|
|
73
72
|
// 获取 definitions context(可能不存在)
|
|
74
73
|
// 使用 $derived 来确保响应式
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
return context.definations
|
|
79
|
-
} catch {
|
|
80
|
-
// Context 不存在,返回 null
|
|
81
|
-
return null
|
|
82
|
-
}
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
const footnoteDefinitions = $derived.by(() => {
|
|
86
|
-
try {
|
|
87
|
-
const context = getDefinitionsContext()
|
|
88
|
-
return context.footnoteDefinitions
|
|
89
|
-
} catch {
|
|
90
|
-
// Context 不存在,返回 null
|
|
91
|
-
return null
|
|
92
|
-
}
|
|
93
|
-
})
|
|
74
|
+
const context = getDefinitionsContext()
|
|
75
|
+
const definations = $derived(context?.definations ?? {});
|
|
76
|
+
|
|
94
77
|
|
|
95
78
|
/**
|
|
96
79
|
* 获取节点的 chunks(类型安全)
|
|
@@ -173,7 +156,7 @@
|
|
|
173
156
|
|
|
174
157
|
<!-- 引用式图片(imageReference) -->
|
|
175
158
|
{#if isImageReference(node)}
|
|
176
|
-
{#if definations && $definations[node.identifier]}
|
|
159
|
+
{#if $definations && $definations[node.identifier]}
|
|
177
160
|
<img
|
|
178
161
|
class="incremark-image incremark-reference-image"
|
|
179
162
|
src={$definations[node.identifier].url}
|
|
@@ -191,7 +174,7 @@
|
|
|
191
174
|
|
|
192
175
|
<!-- 引用式链接(linkReference) -->
|
|
193
176
|
{#if isLinkReference(node)}
|
|
194
|
-
{#if definations && $definations[node.identifier]}
|
|
177
|
+
{#if $definations && $definations[node.identifier]}
|
|
195
178
|
<a
|
|
196
179
|
class="incremark-link incremark-reference-link"
|
|
197
180
|
href={$definations[node.identifier].url}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IncremarkInline.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkInline.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"IncremarkInline.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkInline.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAiC,MAAM,OAAO,CAAA;AAW3E,OAAO,eAAe,MAAM,0BAA0B,CAAC;AAGrD;;GAEG;AACH,UAAU,KAAK;IACb,aAAa;IACb,KAAK,EAAE,eAAe,EAAE,CAAA;CACzB;AAwLH,QAAA,MAAM,eAAe,2CAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
<!--
|
|
2
2
|
@file IncremarkList.svelte - 列表组件
|
|
3
|
-
@description 渲染 Markdown
|
|
3
|
+
@description 渲染 Markdown 列表(有序列表和无序列表),支持任务列表和嵌套列表
|
|
4
4
|
-->
|
|
5
5
|
|
|
6
6
|
<script lang="ts">
|
|
7
|
-
import type { List, ListItem, PhrasingContent } from 'mdast'
|
|
7
|
+
import type { List, ListItem, PhrasingContent, BlockContent } from 'mdast'
|
|
8
8
|
import IncremarkInline from './IncremarkInline.svelte'
|
|
9
|
+
import IncremarkList from './IncremarkList.svelte';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* 组件 Props
|
|
@@ -30,12 +31,12 @@
|
|
|
30
31
|
)
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
34
|
+
* 获取列表项的内联内容(来自第一个 paragraph)
|
|
35
|
+
*
|
|
35
36
|
* @param item - 列表项节点
|
|
36
37
|
* @returns 行内内容数组
|
|
37
38
|
*/
|
|
38
|
-
function
|
|
39
|
+
function getItemInlineContent(item: ListItem): PhrasingContent[] {
|
|
39
40
|
const firstChild = item.children[0]
|
|
40
41
|
if (firstChild?.type === 'paragraph') {
|
|
41
42
|
return firstChild.children as PhrasingContent[]
|
|
@@ -43,9 +44,26 @@
|
|
|
43
44
|
return []
|
|
44
45
|
}
|
|
45
46
|
|
|
47
|
+
/**
|
|
48
|
+
* 获取列表项的块级子节点(嵌套列表、代码块等)
|
|
49
|
+
* 排除第一个 paragraph,因为它已经被 getItemInlineContent 处理
|
|
50
|
+
*
|
|
51
|
+
* @param item - 列表项节点
|
|
52
|
+
* @returns 块级子节点数组
|
|
53
|
+
*/
|
|
54
|
+
function getItemBlockChildren(item: ListItem): BlockContent[] {
|
|
55
|
+
return item.children.filter((child, index) => {
|
|
56
|
+
// 第一个 paragraph 已经被处理为内联内容
|
|
57
|
+
if (index === 0 && child.type === 'paragraph') {
|
|
58
|
+
return false
|
|
59
|
+
}
|
|
60
|
+
return true
|
|
61
|
+
}) as BlockContent[]
|
|
62
|
+
}
|
|
63
|
+
|
|
46
64
|
/**
|
|
47
65
|
* 判断列表项是否是任务项
|
|
48
|
-
*
|
|
66
|
+
*
|
|
49
67
|
* @param item - 列表项节点
|
|
50
68
|
* @returns 是否是任务项
|
|
51
69
|
*/
|
|
@@ -54,30 +72,37 @@
|
|
|
54
72
|
}
|
|
55
73
|
</script>
|
|
56
74
|
|
|
57
|
-
<svelte:element
|
|
58
|
-
this={tag}
|
|
75
|
+
<svelte:element
|
|
76
|
+
this={tag}
|
|
59
77
|
class="incremark-list"
|
|
60
78
|
class:task-list={isTaskList}
|
|
61
79
|
>
|
|
62
80
|
{#each node.children as item, index (index)}
|
|
63
|
-
<li
|
|
81
|
+
<li
|
|
64
82
|
class="incremark-list-item"
|
|
65
83
|
class:task-item={isTaskItem(item)}
|
|
66
84
|
>
|
|
67
85
|
{#if isTaskItem(item)}
|
|
68
86
|
<label class="task-label">
|
|
69
|
-
<input
|
|
70
|
-
type="checkbox"
|
|
71
|
-
checked={item.checked}
|
|
72
|
-
disabled
|
|
87
|
+
<input
|
|
88
|
+
type="checkbox"
|
|
89
|
+
checked={item.checked}
|
|
90
|
+
disabled
|
|
73
91
|
class="checkbox"
|
|
74
92
|
/>
|
|
75
93
|
<span class="task-content">
|
|
76
|
-
<IncremarkInline nodes={
|
|
94
|
+
<IncremarkInline nodes={getItemInlineContent(item)} />
|
|
77
95
|
</span>
|
|
78
96
|
</label>
|
|
79
97
|
{:else}
|
|
80
|
-
<IncremarkInline nodes={
|
|
98
|
+
<IncremarkInline nodes={getItemInlineContent(item)} />
|
|
99
|
+
<!-- 递归渲染嵌套列表和其他块级内容 -->
|
|
100
|
+
{#each getItemBlockChildren(item) as child, childIndex (childIndex)}
|
|
101
|
+
{#if child.type === 'list'}
|
|
102
|
+
<IncremarkList node={child} />
|
|
103
|
+
{/if}
|
|
104
|
+
<!-- 其他块级内容可以在这里扩展 -->
|
|
105
|
+
{/each}
|
|
81
106
|
{/if}
|
|
82
107
|
</li>
|
|
83
108
|
{/each}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IncremarkList.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkList.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,
|
|
1
|
+
{"version":3,"file":"IncremarkList.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkList.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAA2C,MAAM,OAAO,CAAA;AAE1E,OAAO,aAAa,MAAM,wBAAwB,CAAC;AAGjD;;GAEG;AACH,UAAU,KAAK;IACb,WAAW;IACX,IAAI,EAAE,IAAI,CAAA;CACX;AA4FH,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
|
|
@@ -15,16 +15,25 @@
|
|
|
15
15
|
import IncremarkMath from './IncremarkMath.svelte'
|
|
16
16
|
import IncremarkHtmlElement from './IncremarkHtmlElement.svelte'
|
|
17
17
|
import IncremarkDefault from './IncremarkDefault.svelte'
|
|
18
|
+
import IncremarkContainer, { type ContainerNode } from './IncremarkContainer.svelte'
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* 组件 Props
|
|
21
22
|
*/
|
|
22
23
|
interface Props {
|
|
23
24
|
/** 要渲染的节点 */
|
|
24
|
-
node: RootContent
|
|
25
|
+
node: RootContent | ContainerNode
|
|
26
|
+
customContainers?: Record<string, any>
|
|
27
|
+
customCodeBlocks?: Record<string, any>
|
|
28
|
+
blockStatus?: 'pending' | 'stable' | 'completed'
|
|
25
29
|
}
|
|
26
30
|
|
|
27
|
-
let {
|
|
31
|
+
let {
|
|
32
|
+
node,
|
|
33
|
+
customContainers,
|
|
34
|
+
customCodeBlocks,
|
|
35
|
+
blockStatus
|
|
36
|
+
}: Props = $props()
|
|
28
37
|
|
|
29
38
|
/**
|
|
30
39
|
* 组件映射
|
|
@@ -52,14 +61,39 @@
|
|
|
52
61
|
/**
|
|
53
62
|
* 检查是否是 html 节点
|
|
54
63
|
*/
|
|
55
|
-
function isHtmlNode(node: RootContent): node is HTML {
|
|
64
|
+
function isHtmlNode(node: RootContent | ContainerNode): node is HTML {
|
|
56
65
|
return node.type === 'html'
|
|
57
66
|
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* 检查是否是容器节点
|
|
70
|
+
*/
|
|
71
|
+
function isContainerNode(node: RootContent | ContainerNode): node is ContainerNode {
|
|
72
|
+
return (node as any).type === 'containerDirective' ||
|
|
73
|
+
(node as any).type === 'leafDirective' ||
|
|
74
|
+
(node as any).type === 'textDirective'
|
|
75
|
+
}
|
|
58
76
|
</script>
|
|
59
77
|
|
|
60
78
|
<!-- HTML 节点:渲染为代码块显示源代码 -->
|
|
61
79
|
{#if isHtmlNode(node)}
|
|
62
80
|
<pre class="incremark-html-code"><code>{node.value}</code></pre>
|
|
81
|
+
<!-- 容器节点:使用容器组件,传递 customContainers -->
|
|
82
|
+
{:else if isContainerNode(node)}
|
|
83
|
+
<IncremarkContainer
|
|
84
|
+
node={node}
|
|
85
|
+
customContainers={customContainers}
|
|
86
|
+
/>
|
|
87
|
+
<!-- 代码节点:特殊处理,传递 customCodeBlocks 和 blockStatus -->
|
|
88
|
+
{:else if node.type === 'code'}
|
|
89
|
+
{@const Component = getComponent('code')}
|
|
90
|
+
{#if Component}
|
|
91
|
+
<Component
|
|
92
|
+
node={node}
|
|
93
|
+
customCodeBlocks={customCodeBlocks}
|
|
94
|
+
blockStatus={blockStatus}
|
|
95
|
+
/>
|
|
96
|
+
{/if}
|
|
63
97
|
{:else}
|
|
64
98
|
<!-- 其他节点:使用对应组件 -->
|
|
65
99
|
{@const Component = getComponent(node.type)}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import type { RootContent } from 'mdast';
|
|
2
|
+
import { type ContainerNode } from './IncremarkContainer.svelte';
|
|
2
3
|
/**
|
|
3
4
|
* 组件 Props
|
|
4
5
|
*/
|
|
5
6
|
interface Props {
|
|
6
7
|
/** 要渲染的节点 */
|
|
7
|
-
node: RootContent;
|
|
8
|
+
node: RootContent | ContainerNode;
|
|
9
|
+
customContainers?: Record<string, any>;
|
|
10
|
+
customCodeBlocks?: Record<string, any>;
|
|
11
|
+
blockStatus?: 'pending' | 'stable' | 'completed';
|
|
8
12
|
}
|
|
9
13
|
declare const IncremarkRenderer: import("svelte").Component<Props, {}, "">;
|
|
10
14
|
type IncremarkRenderer = ReturnType<typeof IncremarkRenderer>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IncremarkRenderer.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkRenderer.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAQ,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"IncremarkRenderer.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkRenderer.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAQ,MAAM,OAAO,CAAA;AAW9C,OAA2B,EAAE,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAGnF;;GAEG;AACH,UAAU,KAAK;IACb,aAAa;IACb,IAAI,EAAE,WAAW,GAAG,aAAa,CAAA;IACjC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACtC,WAAW,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAA;CACjD;AAwFH,QAAA,MAAM,iBAAiB,2CAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
|
|
@@ -73,6 +73,13 @@ export interface UseIncremarkReturn {
|
|
|
73
73
|
isLoading: Writable<boolean>;
|
|
74
74
|
/** 是否已完成(finalize) */
|
|
75
75
|
isFinalized: Writable<boolean>;
|
|
76
|
+
/**
|
|
77
|
+
* 内容是否完全显示完成
|
|
78
|
+
* - 无打字机:等于 isFinalized
|
|
79
|
+
* - 有打字机:isFinalized + 动画播放完成
|
|
80
|
+
* 适用于控制 footnote 等需要在内容完全显示后才出现的元素
|
|
81
|
+
*/
|
|
82
|
+
isDisplayComplete: Readable<boolean>;
|
|
76
83
|
/** 脚注引用的出现顺序 */
|
|
77
84
|
footnoteReferenceOrder: Writable<string[]>;
|
|
78
85
|
/** 追加内容 */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useIncremark.d.ts","sourceRoot":"","sources":["../../src/stores/useIncremark.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"useIncremark.d.ts","sourceRoot":"","sources":["../../src/stores/useIncremark.ts"],"names":[],"mappings":"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"}
|
|
@@ -61,11 +61,15 @@ export function useIncremark(options = {}) {
|
|
|
61
61
|
const isFinalized = writable(false);
|
|
62
62
|
const footnoteReferenceOrder = writable([]);
|
|
63
63
|
// 使用 useTypewriter store 管理打字机效果
|
|
64
|
-
const { blocks, typewriter, transformer } = useTypewriter({
|
|
64
|
+
const { blocks, typewriter, transformer, isAnimationComplete } = useTypewriter({
|
|
65
65
|
typewriter: options.typewriter,
|
|
66
66
|
completedBlocks,
|
|
67
67
|
pendingBlocks
|
|
68
68
|
});
|
|
69
|
+
// 内容是否完全显示完成
|
|
70
|
+
// 如果没有启用打字机:解析完成即显示完成
|
|
71
|
+
// 如果启用打字机:解析完成 + 动画完成
|
|
72
|
+
const isDisplayComplete = derived([isFinalized, isAnimationComplete], ([$isFinalized, $isAnimationComplete]) => $isFinalized && $isAnimationComplete);
|
|
69
73
|
// AST
|
|
70
74
|
const ast = derived([completedBlocks, pendingBlocks], ([$completedBlocks, $pendingBlocks]) => ({
|
|
71
75
|
type: 'root',
|
|
@@ -165,6 +169,7 @@ export function useIncremark(options = {}) {
|
|
|
165
169
|
blocks,
|
|
166
170
|
isLoading,
|
|
167
171
|
isFinalized,
|
|
172
|
+
isDisplayComplete,
|
|
168
173
|
footnoteReferenceOrder,
|
|
169
174
|
append,
|
|
170
175
|
finalize,
|
|
@@ -28,6 +28,8 @@ export interface UseTypewriterReturn {
|
|
|
28
28
|
typewriter: TypewriterControls;
|
|
29
29
|
/** transformer 实例 */
|
|
30
30
|
transformer: BlockTransformer<RootContent> | null;
|
|
31
|
+
/** 所有动画是否已完成(队列为空且没有正在处理的 block) */
|
|
32
|
+
isAnimationComplete: Readable<boolean>;
|
|
31
33
|
}
|
|
32
34
|
/**
|
|
33
35
|
* useTypewriter Store
|
|
@@ -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,EACtB,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,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;IAC3D,cAAc;IACd,UAAU,EAAE,kBAAkB,CAAA;IAC9B,qBAAqB;IACrB,WAAW,EAAE,gBAAgB,CAAC,WAAW,CAAC,GAAG,IAAI,CAAA;
|
|
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,EACtB,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,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;IAC3D,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"}
|
|
@@ -23,6 +23,7 @@ export function useTypewriter(options) {
|
|
|
23
23
|
const isTypewriterPaused = writable(false);
|
|
24
24
|
const typewriterEffect = writable(typewriterConfig?.effect ?? 'none');
|
|
25
25
|
const typewriterCursor = writable(typewriterConfig?.cursor ?? '|');
|
|
26
|
+
const isAnimationComplete = writable(true); // 初始为 true(没有动画时视为完成)
|
|
26
27
|
// 创建 transformer(如果有 typewriter 配置)
|
|
27
28
|
let transformer = null;
|
|
28
29
|
if (typewriterConfig) {
|
|
@@ -37,6 +38,14 @@ export function useTypewriter(options) {
|
|
|
37
38
|
displayBlocks.set(blocks);
|
|
38
39
|
isTypewriterProcessing.set(transformer?.isProcessing() ?? false);
|
|
39
40
|
isTypewriterPaused.set(transformer?.isPausedState() ?? false);
|
|
41
|
+
// 有 blocks 正在处理时,动画未完成
|
|
42
|
+
if (transformer?.isProcessing()) {
|
|
43
|
+
isAnimationComplete.set(false);
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
onAllComplete: () => {
|
|
47
|
+
// 所有动画完成
|
|
48
|
+
isAnimationComplete.set(true);
|
|
40
49
|
}
|
|
41
50
|
});
|
|
42
51
|
}
|
|
@@ -148,6 +157,7 @@ export function useTypewriter(options) {
|
|
|
148
157
|
return {
|
|
149
158
|
blocks,
|
|
150
159
|
typewriter: typewriterControls,
|
|
151
|
-
transformer
|
|
160
|
+
transformer,
|
|
161
|
+
isAnimationComplete: derived(isAnimationComplete, ($v) => $v)
|
|
152
162
|
};
|
|
153
163
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@incremark/svelte",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
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/core": "0.2.
|
|
28
|
-
"@incremark/
|
|
29
|
-
"@incremark/shared": "0.2.
|
|
30
|
-
"@incremark/
|
|
27
|
+
"@incremark/core": "0.2.5",
|
|
28
|
+
"@incremark/devtools": "0.2.5",
|
|
29
|
+
"@incremark/shared": "0.2.5",
|
|
30
|
+
"@incremark/theme": "0.2.5"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"svelte": "^5.0.0",
|