@incremark/svelte 0.3.1 → 0.3.2
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/CachedCodeRenderer.svelte +120 -0
- package/dist/components/CachedCodeRenderer.svelte.d.ts +10 -0
- package/dist/components/CachedCodeRenderer.svelte.d.ts.map +1 -0
- package/dist/components/ConfigProvider.svelte +5 -4
- package/dist/components/ConfigProvider.svelte.d.ts +1 -1
- package/dist/components/ConfigProvider.svelte.d.ts.map +1 -1
- package/dist/components/Incremark.svelte +10 -37
- package/dist/components/Incremark.svelte.d.ts +1 -1
- package/dist/components/Incremark.svelte.d.ts.map +1 -1
- package/dist/components/IncremarkCode.svelte +8 -6
- package/dist/components/IncremarkCode.svelte.d.ts.map +1 -1
- package/dist/components/IncremarkCodeDefault.svelte +60 -31
- package/dist/components/IncremarkCodeDefault.svelte.d.ts +2 -0
- package/dist/components/IncremarkCodeDefault.svelte.d.ts.map +1 -1
- package/dist/components/IncremarkContent.svelte +14 -18
- package/dist/components/IncremarkContent.svelte.d.ts.map +1 -1
- package/dist/components/IncremarkFootnotes.svelte +3 -6
- package/dist/components/IncremarkFootnotes.svelte.d.ts.map +1 -1
- package/dist/components/IncremarkInline.svelte +9 -10
- package/dist/components/IncremarkInline.svelte.d.ts.map +1 -1
- package/dist/components/types.d.ts +1 -1
- package/dist/components/types.d.ts.map +1 -1
- package/dist/context/{definitionsContext.d.ts → definitionsContext.svelte.d.ts} +13 -11
- package/dist/context/definitionsContext.svelte.d.ts.map +1 -0
- package/dist/context/{definitionsContext.js → definitionsContext.svelte.js} +18 -15
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -5
- package/dist/stores/{useBlockTransformer.d.ts → useBlockTransformer.svelte.d.ts} +33 -35
- package/dist/stores/useBlockTransformer.svelte.d.ts.map +1 -0
- package/dist/stores/useBlockTransformer.svelte.js +106 -0
- package/dist/stores/useDevTools.svelte.d.ts +1 -1
- package/dist/stores/useDevTools.svelte.d.ts.map +1 -1
- package/dist/stores/{useIncremark.d.ts → useIncremark.svelte.d.ts} +31 -34
- package/dist/stores/useIncremark.svelte.d.ts.map +1 -0
- package/dist/stores/useIncremark.svelte.js +226 -0
- package/dist/stores/useLocale.svelte.d.ts.map +1 -1
- package/dist/stores/useLocale.svelte.js +3 -2
- package/dist/stores/useShiki.svelte.d.ts +26 -0
- package/dist/stores/useShiki.svelte.d.ts.map +1 -1
- package/dist/stores/useShiki.svelte.js +27 -0
- package/dist/stores/useTypewriter.svelte.d.ts +49 -0
- package/dist/stores/useTypewriter.svelte.d.ts.map +1 -0
- package/dist/stores/useTypewriter.svelte.js +212 -0
- package/dist/utils/cursor.d.ts.map +1 -1
- package/dist/utils/cursor.js +8 -0
- package/package.json +9 -6
- package/dist/context/definitionsContext.d.ts.map +0 -1
- package/dist/stores/useBlockTransformer.d.ts.map +0 -1
- package/dist/stores/useBlockTransformer.js +0 -110
- package/dist/stores/useIncremark.d.ts.map +0 -1
- package/dist/stores/useIncremark.js +0 -208
- package/dist/stores/useTypewriter.d.ts +0 -44
- package/dist/stores/useTypewriter.d.ts.map +0 -1
- package/dist/stores/useTypewriter.js +0 -163
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useBlockTransformer.d.ts","sourceRoot":"","sources":["../../src/stores/useBlockTransformer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAoC,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC9E,OAAO,EACL,gBAAgB,EAEhB,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,eAAe,EACrB,MAAM,iBAAiB,CAAA;AAExB;;GAEG;AACH,MAAM,WAAW,0BAA2B,SAAQ,IAAI,CAAC,kBAAkB,EAAE,UAAU,CAAC;CAAG;AAE3F;;GAEG;AACH,MAAM,WAAW,yBAAyB,CAAC,CAAC,GAAG,OAAO;IACpD,2BAA2B;IAC3B,aAAa,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IAC1C,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,aAAa;IACb,IAAI,EAAE,MAAM,IAAI,CAAA;IAChB,WAAW;IACX,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,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,IAAI,CAAC,kBAAkB,EAAE,cAAc,GAAG,cAAc,GAAG,QAAQ,GAAG,eAAe,CAAC,CAAC,KAAK,IAAI,CAAA;IAC9H,6BAA6B;IAC7B,WAAW,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAA;CACjC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,GAAG,OAAO,EAC7C,YAAY,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EACxC,OAAO,GAAE,0BAA+B,GACvC,yBAAyB,CAAC,CAAC,CAAC,CAwD9B"}
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file useBlockTransformer Store - 块转换器
|
|
3
|
-
* @description 用于控制 blocks 的逐步显示(打字机效果)
|
|
4
|
-
*/
|
|
5
|
-
import { writable, derived } from 'svelte/store';
|
|
6
|
-
import { createBlockTransformer } from '@incremark/core';
|
|
7
|
-
/**
|
|
8
|
-
* Svelte 5 Store: Block Transformer
|
|
9
|
-
*
|
|
10
|
-
* @description
|
|
11
|
-
* 用于控制 blocks 的逐步显示(打字机效果)
|
|
12
|
-
* 作为解析器和渲染器之间的中间层
|
|
13
|
-
*
|
|
14
|
-
* 特性:
|
|
15
|
-
* - 使用 requestAnimationFrame 实现流畅动画
|
|
16
|
-
* - 支持随机步长 `charsPerTick: [1, 3]`
|
|
17
|
-
* - 支持动画效果 `effect: 'typing'`
|
|
18
|
-
* - 页面不可见时自动暂停
|
|
19
|
-
*
|
|
20
|
-
* @param sourceBlocks - 源 blocks store
|
|
21
|
-
* @param options - 转换器选项
|
|
22
|
-
* @returns 转换器状态和控制对象
|
|
23
|
-
*
|
|
24
|
-
* @example
|
|
25
|
-
* ```svelte
|
|
26
|
-
* <script>
|
|
27
|
-
* import { useIncremark, useBlockTransformer, defaultPlugins } from '@incremark/svelte'
|
|
28
|
-
* import { derived } from 'svelte/store'
|
|
29
|
-
*
|
|
30
|
-
* const { completedBlocks, append, finalize } = useIncremark()
|
|
31
|
-
*
|
|
32
|
-
* // 使用 completedBlocks 作为输入(ID 稳定)
|
|
33
|
-
* const sourceBlocks = derived(completedBlocks, ($blocks) =>
|
|
34
|
-
* $blocks.map(b => ({
|
|
35
|
-
* id: b.id,
|
|
36
|
-
* node: b.node,
|
|
37
|
-
* status: b.status
|
|
38
|
-
* }))
|
|
39
|
-
* )
|
|
40
|
-
*
|
|
41
|
-
* // 添加打字机效果
|
|
42
|
-
* const { displayBlocks, isProcessing, skip, effect } = useBlockTransformer(sourceBlocks, {
|
|
43
|
-
* charsPerTick: [1, 3],
|
|
44
|
-
* tickInterval: 30,
|
|
45
|
-
* effect: 'typing',
|
|
46
|
-
* plugins: defaultPlugins
|
|
47
|
-
* })
|
|
48
|
-
* </script>
|
|
49
|
-
*
|
|
50
|
-
* <template>
|
|
51
|
-
* <Incremark blocks={$displayBlocks} class:typing={$effect === 'typing'} />
|
|
52
|
-
* {#if $isProcessing}
|
|
53
|
-
* <button on:click={skip}>跳过</button>
|
|
54
|
-
* {/if}
|
|
55
|
-
* </template>
|
|
56
|
-
* ```
|
|
57
|
-
*/
|
|
58
|
-
export function useBlockTransformer(sourceBlocks, options = {}) {
|
|
59
|
-
const displayBlocks = writable([]);
|
|
60
|
-
const isProcessing = writable(false);
|
|
61
|
-
const isPaused = writable(false);
|
|
62
|
-
const effect = writable(options.effect ?? 'none');
|
|
63
|
-
const transformer = createBlockTransformer({
|
|
64
|
-
...options,
|
|
65
|
-
onChange: (blocks) => {
|
|
66
|
-
displayBlocks.set(blocks);
|
|
67
|
-
isProcessing.set(transformer.isProcessing());
|
|
68
|
-
isPaused.set(transformer.isPausedState());
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
// 监听源 blocks 变化
|
|
72
|
-
sourceBlocks.subscribe((blocks) => {
|
|
73
|
-
// 推入新 blocks
|
|
74
|
-
transformer.push(blocks);
|
|
75
|
-
// 处理正在显示的 block 内容更新
|
|
76
|
-
displayBlocks.update((displayBlocksValue) => {
|
|
77
|
-
const currentDisplaying = displayBlocksValue.find((b) => !b.isDisplayComplete);
|
|
78
|
-
if (currentDisplaying) {
|
|
79
|
-
const updated = blocks.find((b) => b.id === currentDisplaying.id);
|
|
80
|
-
if (updated) {
|
|
81
|
-
transformer.update(updated);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return displayBlocksValue;
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
return {
|
|
88
|
-
displayBlocks: derived(displayBlocks, ($blocks) => $blocks),
|
|
89
|
-
isProcessing: derived(isProcessing, ($processing) => $processing),
|
|
90
|
-
isPaused: derived(isPaused, ($paused) => $paused),
|
|
91
|
-
effect: derived(effect, ($effect) => $effect),
|
|
92
|
-
skip: () => transformer.skip(),
|
|
93
|
-
reset: () => transformer.reset(),
|
|
94
|
-
pause: () => {
|
|
95
|
-
transformer.pause();
|
|
96
|
-
isPaused.set(true);
|
|
97
|
-
},
|
|
98
|
-
resume: () => {
|
|
99
|
-
transformer.resume();
|
|
100
|
-
isPaused.set(false);
|
|
101
|
-
},
|
|
102
|
-
setOptions: (opts) => {
|
|
103
|
-
transformer.setOptions(opts);
|
|
104
|
-
if (opts.effect !== undefined) {
|
|
105
|
-
effect.set(opts.effect);
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
transformer
|
|
109
|
-
};
|
|
110
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useIncremark.d.ts","sourceRoot":"","sources":["../../src/stores/useIncremark.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file useIncremark Store - 核心 Store
|
|
3
|
-
* @description Svelte 5 Store: Incremark 流式 Markdown 解析器
|
|
4
|
-
*/
|
|
5
|
-
import { writable, derived } from 'svelte/store';
|
|
6
|
-
import { createIncremarkParser } from '@incremark/core';
|
|
7
|
-
import { setDefinitionsContext } from '../context/definitionsContext';
|
|
8
|
-
import { useTypewriter } from './useTypewriter';
|
|
9
|
-
/**
|
|
10
|
-
* Svelte 5 Store: Incremark 流式 Markdown 解析器
|
|
11
|
-
*
|
|
12
|
-
* @description
|
|
13
|
-
* 核心 store,管理解析器状态和操作
|
|
14
|
-
*
|
|
15
|
-
* @param options - 解析器选项
|
|
16
|
-
* @returns 解析器状态和控制对象
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```svelte
|
|
20
|
-
* <script>
|
|
21
|
-
* import { useIncremark, Incremark } from '@incremark/svelte'
|
|
22
|
-
*
|
|
23
|
-
* // 基础用法
|
|
24
|
-
* const { blocks, append, finalize } = useIncremark()
|
|
25
|
-
*
|
|
26
|
-
* // 启用打字机效果
|
|
27
|
-
* const { blocks, append, finalize, typewriter } = useIncremark({
|
|
28
|
-
* typewriter: {
|
|
29
|
-
* enabled: true,
|
|
30
|
-
* charsPerTick: [1, 3],
|
|
31
|
-
* tickInterval: 30,
|
|
32
|
-
* effect: 'typing',
|
|
33
|
-
* cursor: '|'
|
|
34
|
-
* }
|
|
35
|
-
* })
|
|
36
|
-
* </script>
|
|
37
|
-
*
|
|
38
|
-
* <template>
|
|
39
|
-
* <Incremark blocks={$blocks} />
|
|
40
|
-
* </template>
|
|
41
|
-
* ```
|
|
42
|
-
*/
|
|
43
|
-
export function useIncremark(options = {}) {
|
|
44
|
-
// 内部自动提供 definitions context
|
|
45
|
-
const { setDefinations, setFootnoteDefinitions, setFootnoteReferenceOrder } = setDefinitionsContext();
|
|
46
|
-
// 解析器
|
|
47
|
-
const parser = createIncremarkParser({
|
|
48
|
-
...options,
|
|
49
|
-
onChange: (state) => {
|
|
50
|
-
setDefinations(state.definitions);
|
|
51
|
-
setFootnoteDefinitions(state.footnoteDefinitions);
|
|
52
|
-
// 调用用户提供的 onChange
|
|
53
|
-
options.onChange?.(state);
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
// 状态 stores
|
|
57
|
-
const completedBlocks = writable([]);
|
|
58
|
-
const pendingBlocks = writable([]);
|
|
59
|
-
const isLoading = writable(false);
|
|
60
|
-
const markdown = writable('');
|
|
61
|
-
const isFinalized = writable(false);
|
|
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
|
-
}
|
|
86
|
-
// 使用 useTypewriter store 管理打字机效果
|
|
87
|
-
const { blocks, typewriter, transformer, isAnimationComplete } = useTypewriter({
|
|
88
|
-
typewriter: options.typewriter,
|
|
89
|
-
completedBlocks,
|
|
90
|
-
pendingBlocks
|
|
91
|
-
});
|
|
92
|
-
// 内容是否完全显示完成
|
|
93
|
-
// 如果没有配置打字机或未启用打字机:解析完成即显示完成
|
|
94
|
-
// 如果启用打字机:解析完成 + 动画完成
|
|
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
|
-
});
|
|
103
|
-
// AST
|
|
104
|
-
const ast = derived([completedBlocks, pendingBlocks], ([$completedBlocks, $pendingBlocks]) => ({
|
|
105
|
-
type: 'root',
|
|
106
|
-
children: [
|
|
107
|
-
...$completedBlocks.map((b) => b.node),
|
|
108
|
-
...$pendingBlocks.map((b) => b.node)
|
|
109
|
-
]
|
|
110
|
-
}));
|
|
111
|
-
/**
|
|
112
|
-
* 追加内容
|
|
113
|
-
*
|
|
114
|
-
* @param chunk - 要追加的 Markdown 文本块
|
|
115
|
-
* @returns 增量更新结果
|
|
116
|
-
*/
|
|
117
|
-
function append(chunk) {
|
|
118
|
-
const update = parser.append(chunk);
|
|
119
|
-
handleUpdate(update, false);
|
|
120
|
-
return update;
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* 完成解析
|
|
124
|
-
*
|
|
125
|
-
* @returns 增量更新结果
|
|
126
|
-
*/
|
|
127
|
-
function finalize() {
|
|
128
|
-
const update = parser.finalize();
|
|
129
|
-
handleUpdate(update, true);
|
|
130
|
-
return update;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* 强制中断
|
|
134
|
-
*
|
|
135
|
-
* @returns 增量更新结果
|
|
136
|
-
*/
|
|
137
|
-
function abort() {
|
|
138
|
-
return finalize();
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* 重置解析器和打字机
|
|
142
|
-
*/
|
|
143
|
-
function reset() {
|
|
144
|
-
parser.reset();
|
|
145
|
-
completedBlocks.set([]);
|
|
146
|
-
pendingBlocks.set([]);
|
|
147
|
-
markdown.set('');
|
|
148
|
-
isLoading.set(false);
|
|
149
|
-
isFinalized.set(false);
|
|
150
|
-
footnoteReferenceOrder.set([]);
|
|
151
|
-
// 重置 transformer
|
|
152
|
-
transformer?.reset();
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* 一次性渲染(reset + append + finalize)
|
|
156
|
-
*
|
|
157
|
-
* @param content - 完整的 Markdown 内容
|
|
158
|
-
* @returns 增量更新结果
|
|
159
|
-
*/
|
|
160
|
-
function render(content) {
|
|
161
|
-
const update = parser.render(content);
|
|
162
|
-
markdown.set(parser.getBuffer());
|
|
163
|
-
completedBlocks.set(parser.getCompletedBlocks());
|
|
164
|
-
pendingBlocks.set([]);
|
|
165
|
-
isLoading.set(false);
|
|
166
|
-
isFinalized.set(true);
|
|
167
|
-
footnoteReferenceOrder.set(update.footnoteReferenceOrder);
|
|
168
|
-
setFootnoteReferenceOrder(update.footnoteReferenceOrder);
|
|
169
|
-
return update;
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* 更新解析器配置(动态更新,不需要重建 parser 实例)
|
|
173
|
-
*
|
|
174
|
-
* 注意:更新配置后会自动重置状态
|
|
175
|
-
*
|
|
176
|
-
* @param newOptions - 部分配置选项(包括 astBuilder,可以动态切换引擎)
|
|
177
|
-
*/
|
|
178
|
-
function updateOptions(newOptions) {
|
|
179
|
-
parser.updateOptions(newOptions);
|
|
180
|
-
// 同步 Svelte 状态
|
|
181
|
-
completedBlocks.set([]);
|
|
182
|
-
pendingBlocks.set([]);
|
|
183
|
-
markdown.set('');
|
|
184
|
-
isLoading.set(false);
|
|
185
|
-
isFinalized.set(false);
|
|
186
|
-
footnoteReferenceOrder.set([]);
|
|
187
|
-
transformer?.reset();
|
|
188
|
-
}
|
|
189
|
-
return {
|
|
190
|
-
markdown,
|
|
191
|
-
completedBlocks,
|
|
192
|
-
pendingBlocks,
|
|
193
|
-
ast,
|
|
194
|
-
blocks,
|
|
195
|
-
isLoading,
|
|
196
|
-
isFinalized,
|
|
197
|
-
isDisplayComplete,
|
|
198
|
-
footnoteReferenceOrder,
|
|
199
|
-
append,
|
|
200
|
-
finalize,
|
|
201
|
-
abort,
|
|
202
|
-
reset,
|
|
203
|
-
render,
|
|
204
|
-
updateOptions,
|
|
205
|
-
parser,
|
|
206
|
-
typewriter
|
|
207
|
-
};
|
|
208
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file useTypewriter Store - 打字机效果管理
|
|
3
|
-
* @description 管理打字机效果的状态和控制逻辑,从 useIncremark 中拆分出来以简化代码
|
|
4
|
-
*/
|
|
5
|
-
import { type Writable, type Readable } from 'svelte/store';
|
|
6
|
-
import { type RootContent, type ParsedBlock, type BlockTransformer } from '@incremark/core';
|
|
7
|
-
import type { TypewriterOptions, TypewriterControls } from './useIncremark';
|
|
8
|
-
/**
|
|
9
|
-
* useTypewriter 选项
|
|
10
|
-
*/
|
|
11
|
-
export interface UseTypewriterOptions {
|
|
12
|
-
/** 打字机配置 */
|
|
13
|
-
typewriter?: TypewriterOptions;
|
|
14
|
-
/** 已完成的块列表 store */
|
|
15
|
-
completedBlocks: Writable<ParsedBlock[]>;
|
|
16
|
-
/** 待处理的块列表 store */
|
|
17
|
-
pendingBlocks: Writable<ParsedBlock[]>;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* useTypewriter 返回值
|
|
21
|
-
*/
|
|
22
|
-
export interface UseTypewriterReturn {
|
|
23
|
-
/** 用于渲染的 blocks(经过打字机处理或原始blocks) */
|
|
24
|
-
blocks: Readable<Array<ParsedBlock & {
|
|
25
|
-
isLastPending?: boolean;
|
|
26
|
-
}>>;
|
|
27
|
-
/** 打字机控制对象 */
|
|
28
|
-
typewriter: TypewriterControls;
|
|
29
|
-
/** transformer 实例 */
|
|
30
|
-
transformer: BlockTransformer<RootContent> | null;
|
|
31
|
-
/** 所有动画是否已完成(队列为空且没有正在处理的 block) */
|
|
32
|
-
isAnimationComplete: Readable<boolean>;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* useTypewriter Store
|
|
36
|
-
*
|
|
37
|
-
* @description
|
|
38
|
-
* 管理打字机效果的所有状态和逻辑
|
|
39
|
-
*
|
|
40
|
-
* @param options - 打字机配置和数据
|
|
41
|
-
* @returns 打字机状态和控制对象
|
|
42
|
-
*/
|
|
43
|
-
export declare function useTypewriter(options: UseTypewriterOptions): UseTypewriterReturn;
|
|
44
|
-
//# sourceMappingURL=useTypewriter.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file useTypewriter Store - 打字机效果管理
|
|
3
|
-
* @description 管理打字机效果的状态和控制逻辑,从 useIncremark 中拆分出来以简化代码
|
|
4
|
-
*/
|
|
5
|
-
import { writable, derived } from 'svelte/store';
|
|
6
|
-
import { createBlockTransformer, defaultPlugins } from '@incremark/core';
|
|
7
|
-
import { addCursorToNode } from '../utils/cursor';
|
|
8
|
-
/**
|
|
9
|
-
* useTypewriter Store
|
|
10
|
-
*
|
|
11
|
-
* @description
|
|
12
|
-
* 管理打字机效果的所有状态和逻辑
|
|
13
|
-
*
|
|
14
|
-
* @param options - 打字机配置和数据
|
|
15
|
-
* @returns 打字机状态和控制对象
|
|
16
|
-
*/
|
|
17
|
-
export function useTypewriter(options) {
|
|
18
|
-
const { typewriter: typewriterConfig, completedBlocks, pendingBlocks } = options;
|
|
19
|
-
// 打字机状态 stores
|
|
20
|
-
const typewriterEnabled = writable(typewriterConfig?.enabled ?? !!typewriterConfig);
|
|
21
|
-
const displayBlocks = writable([]);
|
|
22
|
-
const isTypewriterProcessing = writable(false);
|
|
23
|
-
const isTypewriterPaused = writable(false);
|
|
24
|
-
const typewriterEffect = writable(typewriterConfig?.effect ?? 'none');
|
|
25
|
-
const typewriterCursor = writable(typewriterConfig?.cursor ?? '|');
|
|
26
|
-
const isAnimationComplete = writable(true); // 初始为 true(没有动画时视为完成)
|
|
27
|
-
// 创建 transformer(如果有 typewriter 配置)
|
|
28
|
-
let transformer = null;
|
|
29
|
-
if (typewriterConfig) {
|
|
30
|
-
const twOptions = typewriterConfig;
|
|
31
|
-
transformer = createBlockTransformer({
|
|
32
|
-
charsPerTick: twOptions.charsPerTick ?? [1, 3],
|
|
33
|
-
tickInterval: twOptions.tickInterval ?? 30,
|
|
34
|
-
effect: twOptions.effect ?? 'none',
|
|
35
|
-
pauseOnHidden: twOptions.pauseOnHidden ?? true,
|
|
36
|
-
plugins: twOptions.plugins ?? defaultPlugins,
|
|
37
|
-
onChange: (blocks) => {
|
|
38
|
-
displayBlocks.set(blocks);
|
|
39
|
-
isTypewriterProcessing.set(transformer?.isProcessing() ?? false);
|
|
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);
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
// 将 completedBlocks 转换为 SourceBlock 格式
|
|
53
|
-
const sourceBlocks = derived(completedBlocks, ($completedBlocks) => {
|
|
54
|
-
return $completedBlocks.map(block => ({
|
|
55
|
-
id: block.id,
|
|
56
|
-
node: block.node,
|
|
57
|
-
status: block.status
|
|
58
|
-
}));
|
|
59
|
-
});
|
|
60
|
-
// 监听 sourceBlocks 变化,推送给 transformer
|
|
61
|
-
if (transformer) {
|
|
62
|
-
let unsubscribe = null;
|
|
63
|
-
unsubscribe = sourceBlocks.subscribe((blocks) => {
|
|
64
|
-
transformer.push(blocks);
|
|
65
|
-
// 更新正在显示的 block
|
|
66
|
-
displayBlocks.update((displayBlocksValue) => {
|
|
67
|
-
const currentDisplaying = displayBlocksValue.find((b) => !b.isDisplayComplete);
|
|
68
|
-
if (currentDisplaying) {
|
|
69
|
-
const updated = blocks.find((b) => b.id === currentDisplaying.id);
|
|
70
|
-
if (updated) {
|
|
71
|
-
transformer.update(updated);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return displayBlocksValue;
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
// 原始 blocks(不经过打字机)
|
|
79
|
-
const rawBlocks = derived([completedBlocks, pendingBlocks], ([$completedBlocks, $pendingBlocks]) => {
|
|
80
|
-
const result = [];
|
|
81
|
-
for (const block of $completedBlocks) {
|
|
82
|
-
result.push(block);
|
|
83
|
-
}
|
|
84
|
-
for (let i = 0; i < $pendingBlocks.length; i++) {
|
|
85
|
-
const isLastPending = i === $pendingBlocks.length - 1;
|
|
86
|
-
result.push({
|
|
87
|
-
...$pendingBlocks[i],
|
|
88
|
-
isLastPending
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
return result;
|
|
92
|
-
});
|
|
93
|
-
// 最终用于渲染的 blocks
|
|
94
|
-
const blocks = derived([typewriterEnabled, displayBlocks, rawBlocks, typewriterEffect, typewriterCursor], ([$enabled, $displayBlocks, $rawBlocks, $effect, $cursor]) => {
|
|
95
|
-
// 未启用打字机或没有 transformer:返回原始 blocks
|
|
96
|
-
if (!$enabled || !transformer) {
|
|
97
|
-
return $rawBlocks;
|
|
98
|
-
}
|
|
99
|
-
// 启用打字机:使用 displayBlocks
|
|
100
|
-
return $displayBlocks.map((db, index) => {
|
|
101
|
-
const isPending = !db.isDisplayComplete;
|
|
102
|
-
const isLastPending = isPending && index === $displayBlocks.length - 1;
|
|
103
|
-
// typing 效果时添加光标
|
|
104
|
-
let node = db.displayNode;
|
|
105
|
-
if ($effect === 'typing' && isLastPending) {
|
|
106
|
-
node = addCursorToNode(db.displayNode, $cursor);
|
|
107
|
-
}
|
|
108
|
-
return {
|
|
109
|
-
id: db.id,
|
|
110
|
-
status: (db.isDisplayComplete ? 'completed' : 'pending'),
|
|
111
|
-
isLastPending,
|
|
112
|
-
node,
|
|
113
|
-
startOffset: 0,
|
|
114
|
-
endOffset: 0,
|
|
115
|
-
rawText: ''
|
|
116
|
-
};
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
// 打字机控制对象
|
|
120
|
-
const typewriterControls = {
|
|
121
|
-
enabled: derived(typewriterEnabled, ($enabled) => $enabled),
|
|
122
|
-
setEnabled: (value) => {
|
|
123
|
-
typewriterEnabled.set(value);
|
|
124
|
-
},
|
|
125
|
-
isProcessing: derived(isTypewriterProcessing, ($processing) => $processing),
|
|
126
|
-
isPaused: derived(isTypewriterPaused, ($paused) => $paused),
|
|
127
|
-
effect: derived(typewriterEffect, ($effect) => $effect),
|
|
128
|
-
skip: () => transformer?.skip(),
|
|
129
|
-
pause: () => {
|
|
130
|
-
transformer?.pause();
|
|
131
|
-
isTypewriterPaused.set(true);
|
|
132
|
-
},
|
|
133
|
-
resume: () => {
|
|
134
|
-
transformer?.resume();
|
|
135
|
-
isTypewriterPaused.set(false);
|
|
136
|
-
},
|
|
137
|
-
setOptions: (opts) => {
|
|
138
|
-
if (opts.enabled !== undefined) {
|
|
139
|
-
typewriterEnabled.set(opts.enabled);
|
|
140
|
-
}
|
|
141
|
-
if (opts.charsPerTick !== undefined || opts.tickInterval !== undefined || opts.effect !== undefined || opts.pauseOnHidden !== undefined) {
|
|
142
|
-
transformer?.setOptions({
|
|
143
|
-
charsPerTick: opts.charsPerTick,
|
|
144
|
-
tickInterval: opts.tickInterval,
|
|
145
|
-
effect: opts.effect,
|
|
146
|
-
pauseOnHidden: opts.pauseOnHidden
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
if (opts.effect !== undefined) {
|
|
150
|
-
typewriterEffect.set(opts.effect);
|
|
151
|
-
}
|
|
152
|
-
if (opts.cursor !== undefined) {
|
|
153
|
-
typewriterCursor.set(opts.cursor);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
return {
|
|
158
|
-
blocks,
|
|
159
|
-
typewriter: typewriterControls,
|
|
160
|
-
transformer,
|
|
161
|
-
isAnimationComplete: derived(isAnimationComplete, ($v) => $v)
|
|
162
|
-
};
|
|
163
|
-
}
|