@incremark/svelte 0.2.5 → 0.2.6
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/Incremark.svelte +35 -72
- package/dist/components/Incremark.svelte.d.ts +7 -0
- package/dist/components/Incremark.svelte.d.ts.map +1 -1
- package/dist/components/IncremarkBlockquote.svelte +3 -7
- package/dist/components/IncremarkBlockquote.svelte.d.ts.map +1 -1
- package/dist/components/IncremarkCode.svelte +25 -14
- package/dist/components/IncremarkCode.svelte.d.ts +6 -0
- package/dist/components/IncremarkCode.svelte.d.ts.map +1 -1
- package/dist/components/IncremarkList.svelte +9 -12
- package/dist/components/IncremarkList.svelte.d.ts +0 -1
- package/dist/components/IncremarkList.svelte.d.ts.map +1 -1
- package/dist/components/IncremarkRenderer.svelte +18 -16
- package/dist/components/IncremarkRenderer.svelte.d.ts +3 -0
- package/dist/components/IncremarkRenderer.svelte.d.ts.map +1 -1
- package/dist/stores/useIncremark.d.ts +1 -0
- package/dist/stores/useIncremark.d.ts.map +1 -1
- package/dist/stores/useIncremark.js +34 -27
- package/dist/stores/useTypewriter.d.ts +1 -0
- package/dist/stores/useTypewriter.d.ts.map +1 -1
- package/dist/stores/useTypewriter.js +3 -1
- package/package.json +5 -5
|
@@ -6,24 +6,14 @@
|
|
|
6
6
|
<script lang="ts">
|
|
7
7
|
import type { Component } from 'svelte'
|
|
8
8
|
import type { Readable } from 'svelte/store'
|
|
9
|
-
import type { RootContent } from '@incremark/core'
|
|
9
|
+
import type { RootContent, ParsedBlock } from '@incremark/core'
|
|
10
10
|
import type { HTML } from 'mdast'
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
import { getDefinitionsContext } from '../context/definitionsContext'
|
|
13
13
|
import type { UseIncremarkReturn } from '../stores/useIncremark'
|
|
14
14
|
import type { ComponentMap, BlockWithStableId } from './types'
|
|
15
|
-
|
|
16
|
-
//
|
|
17
|
-
import IncremarkParagraph from './IncremarkParagraph.svelte'
|
|
18
|
-
import IncremarkHeading from './IncremarkHeading.svelte'
|
|
19
|
-
import IncremarkCode from './IncremarkCode.svelte'
|
|
20
|
-
import IncremarkList from './IncremarkList.svelte'
|
|
21
|
-
import IncremarkTable from './IncremarkTable.svelte'
|
|
22
|
-
import IncremarkBlockquote from './IncremarkBlockquote.svelte'
|
|
23
|
-
import IncremarkThematicBreak from './IncremarkThematicBreak.svelte'
|
|
24
|
-
import IncremarkMath from './IncremarkMath.svelte'
|
|
25
|
-
import IncremarkHtmlElement from './IncremarkHtmlElement.svelte'
|
|
26
|
-
import IncremarkDefault from './IncremarkDefault.svelte'
|
|
15
|
+
|
|
16
|
+
// 导入组件
|
|
27
17
|
import IncremarkFootnotes from './IncremarkFootnotes.svelte'
|
|
28
18
|
import IncremarkRenderer from './IncremarkRenderer.svelte'
|
|
29
19
|
|
|
@@ -40,12 +30,17 @@
|
|
|
40
30
|
interface Props {
|
|
41
31
|
/** 要渲染的块列表(来自 useIncremark 的 blocks) */
|
|
42
32
|
blocks?: BlockWithStableId[] | Readable<BlockWithStableId[]>
|
|
33
|
+
/** 内容是否完全显示完成(用于控制脚注等需要在内容完全显示后才出现的元素)
|
|
34
|
+
* 如果传入了 incremark,则会自动使用 incremark.isDisplayComplete,此 prop 被忽略 */
|
|
35
|
+
isDisplayComplete?: boolean
|
|
43
36
|
/** 自定义组件映射,key 为节点类型 */
|
|
44
37
|
components?: ComponentMap
|
|
45
38
|
/** 自定义容器组件映射,key 为容器名称(如 'warning', 'info') */
|
|
46
39
|
customContainers?: Record<string, Component<any>>
|
|
47
40
|
/** 自定义代码块组件映射,key 为代码语言名称(如 'echart', 'mermaid') */
|
|
48
41
|
customCodeBlocks?: Record<string, Component<any>>
|
|
42
|
+
/** 代码块配置映射,key 为代码语言名称 */
|
|
43
|
+
codeBlockConfigs?: Record<string, { takeOver?: boolean }>
|
|
49
44
|
/** 待处理块的样式类名 */
|
|
50
45
|
pendingClass?: string
|
|
51
46
|
/** 已完成块的样式类名 */
|
|
@@ -58,9 +53,11 @@
|
|
|
58
53
|
|
|
59
54
|
let {
|
|
60
55
|
blocks = [],
|
|
56
|
+
isDisplayComplete = false,
|
|
61
57
|
components = {},
|
|
62
58
|
customContainers = {},
|
|
63
59
|
customCodeBlocks = {},
|
|
60
|
+
codeBlockConfigs = {},
|
|
64
61
|
pendingClass = 'incremark-pending',
|
|
65
62
|
completedClass = 'incremark-completed',
|
|
66
63
|
showBlockStatus = false,
|
|
@@ -70,83 +67,49 @@
|
|
|
70
67
|
const context = getDefinitionsContext();
|
|
71
68
|
const footnoteReferenceOrder = $derived(context?.footnoteReferenceOrder ?? []);
|
|
72
69
|
|
|
73
|
-
//
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const blocksArray = Array.isArray(blocks) ? blocks : []
|
|
81
|
-
return blocksArray.length > 0 && blocksArray.every(b => b.status === 'completed')
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
// 默认组件映射
|
|
85
|
-
const defaultComponents: ComponentMap = {
|
|
86
|
-
paragraph: IncremarkParagraph,
|
|
87
|
-
heading: IncremarkHeading,
|
|
88
|
-
code: IncremarkCode,
|
|
89
|
-
list: IncremarkList,
|
|
90
|
-
table: IncremarkTable,
|
|
91
|
-
blockquote: IncremarkBlockquote,
|
|
92
|
-
thematicBreak: IncremarkThematicBreak,
|
|
93
|
-
math: IncremarkMath,
|
|
94
|
-
inlineMath: IncremarkMath,
|
|
95
|
-
htmlElement: IncremarkHtmlElement
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// 合并用户组件和默认组件
|
|
99
|
-
const mergedComponents = $derived({
|
|
100
|
-
...defaultComponents,
|
|
101
|
-
...components
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
// 处理 blocks(可能是 store 或数组)
|
|
105
|
-
const blocksArray = $derived.by(() => {
|
|
106
|
-
if (incremark) {
|
|
107
|
-
// 如果提供了 incremark,在模板中直接使用 incremark.blocks(store)
|
|
108
|
-
return []
|
|
109
|
-
}
|
|
110
|
-
return Array.isArray(blocks) ? blocks : []
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
// 提取 incremark 的 stores(如果存在)
|
|
114
|
-
const incremarkBlocks = $derived.by(() => incremark?.blocks)
|
|
115
|
-
const incremarkIsDisplayComplete = $derived.by(() => incremark?.isDisplayComplete)
|
|
70
|
+
// 当使用 incremark 时,从 incremark 对象中提取 blocks 和 isDisplayComplete
|
|
71
|
+
const incremarkBlocks = $derived(
|
|
72
|
+
incremark ? (incremark as any).blocks : []
|
|
73
|
+
);
|
|
74
|
+
const incremarkIsDisplayComplete = $derived(
|
|
75
|
+
incremark ? (incremark as any).isDisplayComplete : false
|
|
76
|
+
);
|
|
116
77
|
</script>
|
|
117
78
|
|
|
118
79
|
<div class="incremark">
|
|
119
80
|
<!-- 主要内容块 -->
|
|
120
|
-
{#if incremark
|
|
81
|
+
{#if incremark}
|
|
121
82
|
<!-- 使用 incremark 的 blocks store -->
|
|
122
|
-
{#each
|
|
123
|
-
{#if block.node.type !== 'definition' && block.node.type !== 'footnoteDefinition'}
|
|
83
|
+
{#each $incremarkBlocks as block (block.stableId)}
|
|
84
|
+
{#if (block as ParsedBlock).node.type !== 'definition' && (block as ParsedBlock).node.type !== 'footnoteDefinition'}
|
|
124
85
|
<div
|
|
125
|
-
class="incremark-block {block.status === 'completed' ? completedClass : pendingClass} {showBlockStatus ? 'incremark-show-status' : ''} {(block as BlockWithStableId).isLastPending ? 'incremark-last-pending' : ''}"
|
|
86
|
+
class="incremark-block {(block as ParsedBlock).status === 'completed' ? completedClass : pendingClass} {showBlockStatus ? 'incremark-show-status' : ''} {(block as BlockWithStableId).isLastPending ? 'incremark-last-pending' : ''}"
|
|
126
87
|
>
|
|
127
88
|
<!-- 使用 IncremarkRenderer,传递 customContainers 和 customCodeBlocks -->
|
|
128
|
-
<IncremarkRenderer
|
|
129
|
-
node={block.node}
|
|
89
|
+
<IncremarkRenderer
|
|
90
|
+
node={(block as ParsedBlock).node}
|
|
130
91
|
customContainers={customContainers}
|
|
131
92
|
customCodeBlocks={customCodeBlocks}
|
|
132
|
-
|
|
93
|
+
codeBlockConfigs={codeBlockConfigs}
|
|
94
|
+
blockStatus={(block as ParsedBlock).status}
|
|
133
95
|
/>
|
|
134
96
|
</div>
|
|
135
97
|
{/if}
|
|
136
98
|
{/each}
|
|
137
99
|
{:else}
|
|
138
100
|
<!-- 使用传入的 blocks 数组 -->
|
|
139
|
-
{#each
|
|
140
|
-
{#if block.node.type !== 'definition' && block.node.type !== 'footnoteDefinition'}
|
|
101
|
+
{#each (Array.isArray(blocks) ? blocks : []) as block (block.stableId)}
|
|
102
|
+
{#if (block as ParsedBlock).node.type !== 'definition' && (block as ParsedBlock).node.type !== 'footnoteDefinition'}
|
|
141
103
|
<div
|
|
142
|
-
class="incremark-block {block.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.isLastPending ? 'incremark-last-pending' : ''}"
|
|
143
105
|
>
|
|
144
106
|
<!-- 使用 IncremarkRenderer,传递 customContainers 和 customCodeBlocks -->
|
|
145
|
-
<IncremarkRenderer
|
|
146
|
-
node={block.node}
|
|
107
|
+
<IncremarkRenderer
|
|
108
|
+
node={(block as ParsedBlock).node}
|
|
147
109
|
customContainers={customContainers}
|
|
148
110
|
customCodeBlocks={customCodeBlocks}
|
|
149
|
-
|
|
111
|
+
codeBlockConfigs={codeBlockConfigs}
|
|
112
|
+
blockStatus={(block as ParsedBlock).status}
|
|
150
113
|
/>
|
|
151
114
|
</div>
|
|
152
115
|
{/if}
|
|
@@ -154,12 +117,12 @@
|
|
|
154
117
|
{/if}
|
|
155
118
|
|
|
156
119
|
<!-- 脚注列表(仅在内容完全显示后显示) -->
|
|
157
|
-
{#if incremark && incremarkIsDisplayComplete && footnoteReferenceOrder
|
|
120
|
+
{#if incremark && $incremarkIsDisplayComplete && $footnoteReferenceOrder}
|
|
158
121
|
{@const footnoteOrder = $footnoteReferenceOrder ?? []}
|
|
159
122
|
{#if footnoteOrder.length > 0}
|
|
160
123
|
<IncremarkFootnotes />
|
|
161
124
|
{/if}
|
|
162
|
-
{:else if !incremark &&
|
|
125
|
+
{:else if !incremark && isDisplayComplete && $footnoteReferenceOrder}
|
|
163
126
|
{@const footnoteOrder = $footnoteReferenceOrder ?? []}
|
|
164
127
|
{#if footnoteOrder.length > 0}
|
|
165
128
|
<IncremarkFootnotes />
|
|
@@ -8,12 +8,19 @@ import type { ComponentMap, BlockWithStableId } from './types';
|
|
|
8
8
|
interface Props {
|
|
9
9
|
/** 要渲染的块列表(来自 useIncremark 的 blocks) */
|
|
10
10
|
blocks?: BlockWithStableId[] | Readable<BlockWithStableId[]>;
|
|
11
|
+
/** 内容是否完全显示完成(用于控制脚注等需要在内容完全显示后才出现的元素)
|
|
12
|
+
* 如果传入了 incremark,则会自动使用 incremark.isDisplayComplete,此 prop 被忽略 */
|
|
13
|
+
isDisplayComplete?: boolean;
|
|
11
14
|
/** 自定义组件映射,key 为节点类型 */
|
|
12
15
|
components?: ComponentMap;
|
|
13
16
|
/** 自定义容器组件映射,key 为容器名称(如 'warning', 'info') */
|
|
14
17
|
customContainers?: Record<string, Component<any>>;
|
|
15
18
|
/** 自定义代码块组件映射,key 为代码语言名称(如 'echart', 'mermaid') */
|
|
16
19
|
customCodeBlocks?: Record<string, Component<any>>;
|
|
20
|
+
/** 代码块配置映射,key 为代码语言名称 */
|
|
21
|
+
codeBlockConfigs?: Record<string, {
|
|
22
|
+
takeOver?: boolean;
|
|
23
|
+
}>;
|
|
17
24
|
/** 待处理块的样式类名 */
|
|
18
25
|
pendingClass?: string;
|
|
19
26
|
/** 已完成块的样式类名 */
|
|
@@ -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,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;AAM5D;;GAEG;AACH,UAAU,KAAK;IACb,wCAAwC;IACxC,MAAM,CAAC,EAAE,iBAAiB,EAAE,GAAG,QAAQ,CAAC,iBAAiB,EAAE,CAAC,CAAA;IAC5D;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,11 @@
|
|
|
1
1
|
<!--
|
|
2
2
|
@file IncremarkBlockquote.svelte - 引用组件
|
|
3
|
-
@description 渲染 Markdown
|
|
3
|
+
@description 渲染 Markdown 引用块,支持所有块级内容
|
|
4
4
|
-->
|
|
5
5
|
|
|
6
6
|
<script lang="ts">
|
|
7
7
|
import type { Blockquote } from 'mdast'
|
|
8
|
-
import
|
|
8
|
+
import IncremarkRenderer from './IncremarkRenderer.svelte'
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* 组件 Props
|
|
@@ -20,11 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
<blockquote class="incremark-blockquote">
|
|
22
22
|
{#each node.children as child, index (index)}
|
|
23
|
-
{
|
|
24
|
-
<IncremarkParagraph node={child} />
|
|
25
|
-
{:else}
|
|
26
|
-
<div class="unknown-child">{child.type}</div>
|
|
27
|
-
{/if}
|
|
23
|
+
<IncremarkRenderer node={child} />
|
|
28
24
|
{/each}
|
|
29
25
|
</blockquote>
|
|
30
26
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IncremarkBlockquote.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkBlockquote.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAIrC;;GAEG;AACH,UAAU,KAAK;IACb,WAAW;IACX,IAAI,EAAE,UAAU,CAAA;CACjB;
|
|
1
|
+
{"version":3,"file":"IncremarkBlockquote.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkBlockquote.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAIrC;;GAEG;AACH,UAAU,KAAK;IACb,WAAW;IACX,IAAI,EAAE,UAAU,CAAA;CACjB;AAoBH,QAAA,MAAM,mBAAmB,2CAAwC,CAAC;AAClE,KAAK,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAClE,eAAe,mBAAmB,CAAC"}
|
|
@@ -15,12 +15,16 @@
|
|
|
15
15
|
node: Code
|
|
16
16
|
/** Shiki 主题,默认 github-dark */
|
|
17
17
|
theme?: string
|
|
18
|
+
/** 默认回退主题(当指定主题加载失败时使用),默认 github-dark */
|
|
19
|
+
fallbackTheme?: string
|
|
18
20
|
/** 是否禁用代码高亮 */
|
|
19
21
|
disableHighlight?: boolean
|
|
20
22
|
/** Mermaid 渲染延迟(毫秒),用于流式输入时防抖 */
|
|
21
23
|
mermaidDelay?: number
|
|
22
24
|
/** 自定义代码块组件映射,key 为代码语言名称 */
|
|
23
25
|
customCodeBlocks?: Record<string, any>
|
|
26
|
+
/** 代码块配置映射,key 为代码语言名称 */
|
|
27
|
+
codeBlockConfigs?: Record<string, { takeOver?: boolean }>
|
|
24
28
|
/** 块状态,用于判断是否使用自定义组件 */
|
|
25
29
|
blockStatus?: 'pending' | 'stable' | 'completed'
|
|
26
30
|
}
|
|
@@ -28,9 +32,11 @@
|
|
|
28
32
|
let {
|
|
29
33
|
node,
|
|
30
34
|
theme = 'github-dark',
|
|
35
|
+
fallbackTheme = 'github-dark',
|
|
31
36
|
disableHighlight = false,
|
|
32
37
|
mermaidDelay = 500,
|
|
33
38
|
customCodeBlocks,
|
|
39
|
+
codeBlockConfigs,
|
|
34
40
|
blockStatus = 'completed'
|
|
35
41
|
}: Props = $props()
|
|
36
42
|
|
|
@@ -63,15 +69,24 @@
|
|
|
63
69
|
|
|
64
70
|
// 检查是否有自定义代码块组件
|
|
65
71
|
const CustomCodeBlock = $derived.by(() => {
|
|
66
|
-
|
|
67
|
-
if (
|
|
72
|
+
const component = customCodeBlocks?.[language]
|
|
73
|
+
if (!component) return null
|
|
74
|
+
|
|
75
|
+
// 检查该语言的配置
|
|
76
|
+
const config = codeBlockConfigs?.[language]
|
|
77
|
+
|
|
78
|
+
// 如果配置了 takeOver 为 true,则从一开始就使用
|
|
79
|
+
if (config?.takeOver) {
|
|
80
|
+
return component
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// 否则,默认行为:只在 completed 状态使用
|
|
84
|
+
if (blockStatus !== 'completed') {
|
|
68
85
|
return null
|
|
69
86
|
}
|
|
70
|
-
return customCodeBlocks?.[language] || null
|
|
71
|
-
})
|
|
72
87
|
|
|
73
|
-
|
|
74
|
-
|
|
88
|
+
return component
|
|
89
|
+
})
|
|
75
90
|
|
|
76
91
|
/**
|
|
77
92
|
* 切换 Mermaid 视图模式
|
|
@@ -188,7 +203,7 @@
|
|
|
188
203
|
|
|
189
204
|
const html = highlighter.codeToHtml(code, {
|
|
190
205
|
lang: loadedLanguages.has(lang) ? lang : 'text',
|
|
191
|
-
theme: loadedThemes.has(theme) ? theme :
|
|
206
|
+
theme: loadedThemes.has(theme) ? theme : fallbackTheme
|
|
192
207
|
})
|
|
193
208
|
highlightedHtml = html
|
|
194
209
|
} catch (e) {
|
|
@@ -229,13 +244,9 @@
|
|
|
229
244
|
</script>
|
|
230
245
|
|
|
231
246
|
<!-- 自定义代码块组件 -->
|
|
232
|
-
{#if
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
codeStr={code}
|
|
236
|
-
lang={language}
|
|
237
|
-
/>
|
|
238
|
-
<!-- Mermaid 图表 -->
|
|
247
|
+
{#if CustomCodeBlock}
|
|
248
|
+
{@const Component = CustomCodeBlock}
|
|
249
|
+
<Component codeStr={code} lang={language} completed={blockStatus === 'completed'} takeOver={codeBlockConfigs?.[language]?.takeOver} />
|
|
239
250
|
{:else if isMermaid}
|
|
240
251
|
<div class="incremark-mermaid">
|
|
241
252
|
<div class="mermaid-header">
|
|
@@ -7,12 +7,18 @@ interface Props {
|
|
|
7
7
|
node: Code;
|
|
8
8
|
/** Shiki 主题,默认 github-dark */
|
|
9
9
|
theme?: string;
|
|
10
|
+
/** 默认回退主题(当指定主题加载失败时使用),默认 github-dark */
|
|
11
|
+
fallbackTheme?: string;
|
|
10
12
|
/** 是否禁用代码高亮 */
|
|
11
13
|
disableHighlight?: boolean;
|
|
12
14
|
/** Mermaid 渲染延迟(毫秒),用于流式输入时防抖 */
|
|
13
15
|
mermaidDelay?: number;
|
|
14
16
|
/** 自定义代码块组件映射,key 为代码语言名称 */
|
|
15
17
|
customCodeBlocks?: Record<string, any>;
|
|
18
|
+
/** 代码块配置映射,key 为代码语言名称 */
|
|
19
|
+
codeBlockConfigs?: Record<string, {
|
|
20
|
+
takeOver?: boolean;
|
|
21
|
+
}>;
|
|
16
22
|
/** 块状态,用于判断是否使用自定义组件 */
|
|
17
23
|
blockStatus?: 'pending' | 'stable' | 'completed';
|
|
18
24
|
}
|
|
@@ -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;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;
|
|
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;AA8RH,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
|
|
@@ -1,12 +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,
|
|
7
|
+
import type { List, ListItem, RootContent } from 'mdast'
|
|
8
8
|
import IncremarkInline from './IncremarkInline.svelte'
|
|
9
|
-
import
|
|
9
|
+
import IncremarkRenderer from './IncremarkRenderer.svelte'
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* 组件 Props
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
* @param item - 列表项节点
|
|
37
37
|
* @returns 行内内容数组
|
|
38
38
|
*/
|
|
39
|
-
function getItemInlineContent(item: ListItem)
|
|
39
|
+
function getItemInlineContent(item: ListItem) {
|
|
40
40
|
const firstChild = item.children[0]
|
|
41
41
|
if (firstChild?.type === 'paragraph') {
|
|
42
|
-
return firstChild.children
|
|
42
|
+
return firstChild.children
|
|
43
43
|
}
|
|
44
44
|
return []
|
|
45
45
|
}
|
|
@@ -51,14 +51,14 @@
|
|
|
51
51
|
* @param item - 列表项节点
|
|
52
52
|
* @returns 块级子节点数组
|
|
53
53
|
*/
|
|
54
|
-
function getItemBlockChildren(item: ListItem):
|
|
54
|
+
function getItemBlockChildren(item: ListItem): RootContent[] {
|
|
55
55
|
return item.children.filter((child, index) => {
|
|
56
56
|
// 第一个 paragraph 已经被处理为内联内容
|
|
57
57
|
if (index === 0 && child.type === 'paragraph') {
|
|
58
58
|
return false
|
|
59
59
|
}
|
|
60
60
|
return true
|
|
61
|
-
})
|
|
61
|
+
})
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
/**
|
|
@@ -96,12 +96,9 @@
|
|
|
96
96
|
</label>
|
|
97
97
|
{:else}
|
|
98
98
|
<IncremarkInline nodes={getItemInlineContent(item)} />
|
|
99
|
-
<!--
|
|
99
|
+
<!-- 递归渲染所有块级内容(嵌套列表、heading、blockquote、code、table 等) -->
|
|
100
100
|
{#each getItemBlockChildren(item) as child, childIndex (childIndex)}
|
|
101
|
-
{
|
|
102
|
-
<IncremarkList node={child} />
|
|
103
|
-
{/if}
|
|
104
|
-
<!-- 其他块级内容可以在这里扩展 -->
|
|
101
|
+
<IncremarkRenderer node={child} />
|
|
105
102
|
{/each}
|
|
106
103
|
{/if}
|
|
107
104
|
</li>
|
|
@@ -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,EAAyB,MAAM,OAAO,CAAA;AAKtD;;GAEG;AACH,UAAU,KAAK;IACb,WAAW;IACX,IAAI,EAAE,IAAI,CAAA;CACX;AAyFH,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
import type { RootContent, HTML } from 'mdast'
|
|
8
8
|
import IncremarkHeading from './IncremarkHeading.svelte'
|
|
9
9
|
import IncremarkParagraph from './IncremarkParagraph.svelte'
|
|
10
|
-
import IncremarkCode from './IncremarkCode.svelte'
|
|
11
10
|
import IncremarkList from './IncremarkList.svelte'
|
|
12
11
|
import IncremarkTable from './IncremarkTable.svelte'
|
|
13
12
|
import IncremarkBlockquote from './IncremarkBlockquote.svelte'
|
|
@@ -15,6 +14,7 @@
|
|
|
15
14
|
import IncremarkMath from './IncremarkMath.svelte'
|
|
16
15
|
import IncremarkHtmlElement from './IncremarkHtmlElement.svelte'
|
|
17
16
|
import IncremarkDefault from './IncremarkDefault.svelte'
|
|
17
|
+
import IncremarkCode from './IncremarkCode.svelte'
|
|
18
18
|
import IncremarkContainer, { type ContainerNode } from './IncremarkContainer.svelte'
|
|
19
19
|
|
|
20
20
|
/**
|
|
@@ -25,23 +25,24 @@
|
|
|
25
25
|
node: RootContent | ContainerNode
|
|
26
26
|
customContainers?: Record<string, any>
|
|
27
27
|
customCodeBlocks?: Record<string, any>
|
|
28
|
+
codeBlockConfigs?: Record<string, { takeOver?: boolean }>
|
|
28
29
|
blockStatus?: 'pending' | 'stable' | 'completed'
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
let {
|
|
32
|
-
node,
|
|
32
|
+
let {
|
|
33
|
+
node,
|
|
33
34
|
customContainers,
|
|
34
35
|
customCodeBlocks,
|
|
36
|
+
codeBlockConfigs,
|
|
35
37
|
blockStatus
|
|
36
38
|
}: Props = $props()
|
|
37
39
|
|
|
38
40
|
/**
|
|
39
|
-
*
|
|
41
|
+
* 默认组件映射
|
|
40
42
|
*/
|
|
41
|
-
const
|
|
43
|
+
const defaultComponentMap: Record<string, any> = {
|
|
42
44
|
heading: IncremarkHeading,
|
|
43
45
|
paragraph: IncremarkParagraph,
|
|
44
|
-
code: IncremarkCode,
|
|
45
46
|
list: IncremarkList,
|
|
46
47
|
table: IncremarkTable,
|
|
47
48
|
blockquote: IncremarkBlockquote,
|
|
@@ -49,13 +50,16 @@
|
|
|
49
50
|
math: IncremarkMath,
|
|
50
51
|
inlineMath: IncremarkMath,
|
|
51
52
|
htmlElement: IncremarkHtmlElement,
|
|
53
|
+
containerDirective: IncremarkContainer,
|
|
54
|
+
leafDirective: IncremarkContainer,
|
|
55
|
+
textDirective: IncremarkContainer,
|
|
52
56
|
}
|
|
53
57
|
|
|
54
58
|
/**
|
|
55
59
|
* 获取组件
|
|
56
60
|
*/
|
|
57
61
|
function getComponent(type: string): any {
|
|
58
|
-
return
|
|
62
|
+
return defaultComponentMap[type] || IncremarkDefault
|
|
59
63
|
}
|
|
60
64
|
|
|
61
65
|
/**
|
|
@@ -84,16 +88,14 @@
|
|
|
84
88
|
node={node}
|
|
85
89
|
customContainers={customContainers}
|
|
86
90
|
/>
|
|
87
|
-
<!-- 代码节点:特殊处理,传递 customCodeBlocks 和 blockStatus -->
|
|
91
|
+
<!-- 代码节点:特殊处理,传递 customCodeBlocks、codeBlockConfigs 和 blockStatus -->
|
|
88
92
|
{:else if node.type === 'code'}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
/>
|
|
96
|
-
{/if}
|
|
93
|
+
<IncremarkCode
|
|
94
|
+
node={node}
|
|
95
|
+
customCodeBlocks={customCodeBlocks}
|
|
96
|
+
codeBlockConfigs={codeBlockConfigs}
|
|
97
|
+
blockStatus={blockStatus}
|
|
98
|
+
/>
|
|
97
99
|
{:else}
|
|
98
100
|
<!-- 其他节点:使用对应组件 -->
|
|
99
101
|
{@const Component = getComponent(node.type)}
|
|
@@ -8,6 +8,9 @@ interface Props {
|
|
|
8
8
|
node: RootContent | ContainerNode;
|
|
9
9
|
customContainers?: Record<string, any>;
|
|
10
10
|
customCodeBlocks?: Record<string, any>;
|
|
11
|
+
codeBlockConfigs?: Record<string, {
|
|
12
|
+
takeOver?: boolean;
|
|
13
|
+
}>;
|
|
11
14
|
blockStatus?: 'pending' | 'stable' | 'completed';
|
|
12
15
|
}
|
|
13
16
|
declare const IncremarkRenderer: import("svelte").Component<Props, {}, "">;
|
|
@@ -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;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"}
|
|
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,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;IACzD,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"}
|
|
@@ -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;AAED;;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,WAAW,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"useIncremark.d.ts","sourceRoot":"","sources":["../../src/stores/useIncremark.ts"],"names":[],"mappings":"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"}
|
|
@@ -60,6 +60,29 @@ export function useIncremark(options = {}) {
|
|
|
60
60
|
const markdown = writable('');
|
|
61
61
|
const isFinalized = writable(false);
|
|
62
62
|
const footnoteReferenceOrder = writable([]);
|
|
63
|
+
/**
|
|
64
|
+
* 处理解析器更新结果(统一 append 和 finalize 的更新逻辑)
|
|
65
|
+
*/
|
|
66
|
+
function handleUpdate(update, isFinalize) {
|
|
67
|
+
markdown.set(parser.getBuffer());
|
|
68
|
+
if (update.completed.length > 0) {
|
|
69
|
+
completedBlocks.update((blocks) => [
|
|
70
|
+
...blocks,
|
|
71
|
+
...update.completed
|
|
72
|
+
]);
|
|
73
|
+
}
|
|
74
|
+
pendingBlocks.set(update.pending);
|
|
75
|
+
if (isFinalize) {
|
|
76
|
+
isLoading.set(false);
|
|
77
|
+
isFinalized.set(true);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
isLoading.set(true);
|
|
81
|
+
}
|
|
82
|
+
// 更新脚注引用顺序
|
|
83
|
+
footnoteReferenceOrder.set(update.footnoteReferenceOrder);
|
|
84
|
+
setFootnoteReferenceOrder(update.footnoteReferenceOrder);
|
|
85
|
+
}
|
|
63
86
|
// 使用 useTypewriter store 管理打字机效果
|
|
64
87
|
const { blocks, typewriter, transformer, isAnimationComplete } = useTypewriter({
|
|
65
88
|
typewriter: options.typewriter,
|
|
@@ -67,9 +90,16 @@ export function useIncremark(options = {}) {
|
|
|
67
90
|
pendingBlocks
|
|
68
91
|
});
|
|
69
92
|
// 内容是否完全显示完成
|
|
70
|
-
//
|
|
93
|
+
// 如果没有配置打字机或未启用打字机:解析完成即显示完成
|
|
71
94
|
// 如果启用打字机:解析完成 + 动画完成
|
|
72
|
-
const isDisplayComplete = derived([isFinalized, isAnimationComplete], ([$isFinalized, $isAnimationComplete]) =>
|
|
95
|
+
const isDisplayComplete = derived([isFinalized, isAnimationComplete, typewriter.enabled], ([$isFinalized, $isAnimationComplete, $typewriterEnabled]) => {
|
|
96
|
+
// 没有配置打字机,或者打字机未启用:只需判断是否 finalized
|
|
97
|
+
if (!options.typewriter || !$typewriterEnabled) {
|
|
98
|
+
return $isFinalized;
|
|
99
|
+
}
|
|
100
|
+
// 启用了打字机:需要 finalize + 动画完成
|
|
101
|
+
return $isFinalized && $isAnimationComplete;
|
|
102
|
+
});
|
|
73
103
|
// AST
|
|
74
104
|
const ast = derived([completedBlocks, pendingBlocks], ([$completedBlocks, $pendingBlocks]) => ({
|
|
75
105
|
type: 'root',
|
|
@@ -85,19 +115,8 @@ export function useIncremark(options = {}) {
|
|
|
85
115
|
* @returns 增量更新结果
|
|
86
116
|
*/
|
|
87
117
|
function append(chunk) {
|
|
88
|
-
isLoading.set(true);
|
|
89
118
|
const update = parser.append(chunk);
|
|
90
|
-
|
|
91
|
-
if (update.completed.length > 0) {
|
|
92
|
-
completedBlocks.update((blocks) => [
|
|
93
|
-
...blocks,
|
|
94
|
-
...update.completed
|
|
95
|
-
]);
|
|
96
|
-
}
|
|
97
|
-
pendingBlocks.set(update.pending);
|
|
98
|
-
// 更新脚注引用顺序
|
|
99
|
-
footnoteReferenceOrder.set(update.footnoteReferenceOrder);
|
|
100
|
-
setFootnoteReferenceOrder(update.footnoteReferenceOrder);
|
|
119
|
+
handleUpdate(update, false);
|
|
101
120
|
return update;
|
|
102
121
|
}
|
|
103
122
|
/**
|
|
@@ -107,19 +126,7 @@ export function useIncremark(options = {}) {
|
|
|
107
126
|
*/
|
|
108
127
|
function finalize() {
|
|
109
128
|
const update = parser.finalize();
|
|
110
|
-
|
|
111
|
-
if (update.completed.length > 0) {
|
|
112
|
-
completedBlocks.update((blocks) => [
|
|
113
|
-
...blocks,
|
|
114
|
-
...update.completed
|
|
115
|
-
]);
|
|
116
|
-
}
|
|
117
|
-
pendingBlocks.set([]);
|
|
118
|
-
isLoading.set(false);
|
|
119
|
-
isFinalized.set(true);
|
|
120
|
-
// 更新脚注引用顺序
|
|
121
|
-
footnoteReferenceOrder.set(update.footnoteReferenceOrder);
|
|
122
|
-
setFootnoteReferenceOrder(update.footnoteReferenceOrder);
|
|
129
|
+
handleUpdate(update, true);
|
|
123
130
|
return update;
|
|
124
131
|
}
|
|
125
132
|
/**
|
|
@@ -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;
|
|
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,CAAC;QAAC,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC,CAAA;IACpF,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,CA8KhF"}
|
|
@@ -82,9 +82,11 @@ export function useTypewriter(options) {
|
|
|
82
82
|
result.push({ ...block, stableId: block.id });
|
|
83
83
|
}
|
|
84
84
|
for (let i = 0; i < $pendingBlocks.length; i++) {
|
|
85
|
+
const isLastPending = i === $pendingBlocks.length - 1;
|
|
85
86
|
result.push({
|
|
86
87
|
...$pendingBlocks[i],
|
|
87
|
-
stableId: `pending-${i}
|
|
88
|
+
stableId: `pending-${i}`,
|
|
89
|
+
isLastPending
|
|
88
90
|
});
|
|
89
91
|
}
|
|
90
92
|
return result;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@incremark/svelte",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
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/
|
|
28
|
-
"@incremark/
|
|
29
|
-
"@incremark/
|
|
30
|
-
"@incremark/
|
|
27
|
+
"@incremark/devtools": "0.2.6",
|
|
28
|
+
"@incremark/core": "0.2.6",
|
|
29
|
+
"@incremark/theme": "0.2.6",
|
|
30
|
+
"@incremark/shared": "0.2.6"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"svelte": "^5.0.0",
|