@incremark/svelte 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist/components/CachedCodeRenderer.svelte +125 -0
  2. package/dist/components/CachedCodeRenderer.svelte.d.ts +10 -0
  3. package/dist/components/CachedCodeRenderer.svelte.d.ts.map +1 -0
  4. package/dist/components/ConfigProvider.svelte +5 -4
  5. package/dist/components/ConfigProvider.svelte.d.ts +1 -1
  6. package/dist/components/ConfigProvider.svelte.d.ts.map +1 -1
  7. package/dist/components/Incremark.svelte +10 -37
  8. package/dist/components/Incremark.svelte.d.ts +1 -1
  9. package/dist/components/Incremark.svelte.d.ts.map +1 -1
  10. package/dist/components/IncremarkCode.svelte +8 -6
  11. package/dist/components/IncremarkCode.svelte.d.ts.map +1 -1
  12. package/dist/components/IncremarkCodeDefault.svelte +60 -31
  13. package/dist/components/IncremarkCodeDefault.svelte.d.ts +2 -0
  14. package/dist/components/IncremarkCodeDefault.svelte.d.ts.map +1 -1
  15. package/dist/components/IncremarkContent.svelte +14 -18
  16. package/dist/components/IncremarkContent.svelte.d.ts.map +1 -1
  17. package/dist/components/IncremarkFootnotes.svelte +3 -6
  18. package/dist/components/IncremarkFootnotes.svelte.d.ts.map +1 -1
  19. package/dist/components/IncremarkInline.svelte +9 -10
  20. package/dist/components/IncremarkInline.svelte.d.ts.map +1 -1
  21. package/dist/components/IncremarkMath.svelte +1 -1
  22. package/dist/components/types.d.ts +1 -1
  23. package/dist/components/types.d.ts.map +1 -1
  24. package/dist/context/{definitionsContext.d.ts → definitionsContext.svelte.d.ts} +13 -11
  25. package/dist/context/definitionsContext.svelte.d.ts.map +1 -0
  26. package/dist/context/{definitionsContext.js → definitionsContext.svelte.js} +18 -15
  27. package/dist/index.d.ts +6 -5
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +5 -5
  30. package/dist/stores/{useBlockTransformer.d.ts → useBlockTransformer.svelte.d.ts} +33 -35
  31. package/dist/stores/useBlockTransformer.svelte.d.ts.map +1 -0
  32. package/dist/stores/useBlockTransformer.svelte.js +106 -0
  33. package/dist/stores/useDevTools.svelte.d.ts +1 -1
  34. package/dist/stores/useDevTools.svelte.d.ts.map +1 -1
  35. package/dist/stores/{useIncremark.d.ts → useIncremark.svelte.d.ts} +31 -34
  36. package/dist/stores/useIncremark.svelte.d.ts.map +1 -0
  37. package/dist/stores/useIncremark.svelte.js +226 -0
  38. package/dist/stores/useLocale.svelte.d.ts.map +1 -1
  39. package/dist/stores/useLocale.svelte.js +3 -2
  40. package/dist/stores/useShiki.svelte.d.ts +26 -0
  41. package/dist/stores/useShiki.svelte.d.ts.map +1 -1
  42. package/dist/stores/useShiki.svelte.js +27 -0
  43. package/dist/stores/useTypewriter.svelte.d.ts +49 -0
  44. package/dist/stores/useTypewriter.svelte.d.ts.map +1 -0
  45. package/dist/stores/useTypewriter.svelte.js +212 -0
  46. package/dist/utils/cursor.d.ts.map +1 -1
  47. package/dist/utils/cursor.js +8 -0
  48. package/package.json +9 -6
  49. package/dist/context/definitionsContext.d.ts.map +0 -1
  50. package/dist/stores/useBlockTransformer.d.ts.map +0 -1
  51. package/dist/stores/useBlockTransformer.js +0 -110
  52. package/dist/stores/useIncremark.d.ts.map +0 -1
  53. package/dist/stores/useIncremark.js +0 -208
  54. package/dist/stores/useTypewriter.d.ts +0 -44
  55. package/dist/stores/useTypewriter.d.ts.map +0 -1
  56. 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
- }