@incremark/solid 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.
- package/LICENSE +22 -0
- package/README.en.md +278 -0
- package/README.md +278 -0
- package/dist/components/AutoScrollContainer.d.ts +17 -0
- package/dist/components/AutoScrollContainer.d.ts.map +1 -0
- package/dist/components/CachedCodeRenderer.d.ts +12 -0
- package/dist/components/CachedCodeRenderer.d.ts.map +1 -0
- package/dist/components/ConfigProvider.d.ts +17 -0
- package/dist/components/ConfigProvider.d.ts.map +1 -0
- package/dist/components/Incremark.d.ts +35 -0
- package/dist/components/Incremark.d.ts.map +1 -0
- package/dist/components/IncremarkBlockquote.d.ts +7 -0
- package/dist/components/IncremarkBlockquote.d.ts.map +1 -0
- package/dist/components/IncremarkCode.d.ts +26 -0
- package/dist/components/IncremarkCode.d.ts.map +1 -0
- package/dist/components/IncremarkCodeDefault.d.ts +15 -0
- package/dist/components/IncremarkCodeDefault.d.ts.map +1 -0
- package/dist/components/IncremarkCodeMermaid.d.ts +14 -0
- package/dist/components/IncremarkCodeMermaid.d.ts.map +1 -0
- package/dist/components/IncremarkContainer.d.ts +22 -0
- package/dist/components/IncremarkContainer.d.ts.map +1 -0
- package/dist/components/IncremarkContent.d.ts +10 -0
- package/dist/components/IncremarkContent.d.ts.map +1 -0
- package/dist/components/IncremarkDefault.d.ts +11 -0
- package/dist/components/IncremarkDefault.d.ts.map +1 -0
- package/dist/components/IncremarkFootnotes.d.ts +10 -0
- package/dist/components/IncremarkFootnotes.d.ts.map +1 -0
- package/dist/components/IncremarkHeading.d.ts +7 -0
- package/dist/components/IncremarkHeading.d.ts.map +1 -0
- package/dist/components/IncremarkHtmlElement.d.ts +26 -0
- package/dist/components/IncremarkHtmlElement.d.ts.map +1 -0
- package/dist/components/IncremarkInline.d.ts +7 -0
- package/dist/components/IncremarkInline.d.ts.map +1 -0
- package/dist/components/IncremarkList.d.ts +7 -0
- package/dist/components/IncremarkList.d.ts.map +1 -0
- package/dist/components/IncremarkMath.d.ts +16 -0
- package/dist/components/IncremarkMath.d.ts.map +1 -0
- package/dist/components/IncremarkParagraph.d.ts +7 -0
- package/dist/components/IncremarkParagraph.d.ts.map +1 -0
- package/dist/components/IncremarkRenderer.d.ts +20 -0
- package/dist/components/IncremarkRenderer.d.ts.map +1 -0
- package/dist/components/IncremarkTable.d.ts +7 -0
- package/dist/components/IncremarkTable.d.ts.map +1 -0
- package/dist/components/IncremarkThematicBreak.d.ts +7 -0
- package/dist/components/IncremarkThematicBreak.d.ts.map +1 -0
- package/dist/components/SvgIcon.d.ts +14 -0
- package/dist/components/SvgIcon.d.ts.map +1 -0
- package/dist/components/ThemeProvider.d.ts +17 -0
- package/dist/components/ThemeProvider.d.ts.map +1 -0
- package/dist/components/index.d.ts +47 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/composables/index.d.ts +10 -0
- package/dist/composables/index.d.ts.map +1 -0
- package/dist/composables/useBlockTransformer.d.ts +33 -0
- package/dist/composables/useBlockTransformer.d.ts.map +1 -0
- package/dist/composables/useDefinationsContext.d.ts +7 -0
- package/dist/composables/useDefinationsContext.d.ts.map +1 -0
- package/dist/composables/useDevTools.d.ts +35 -0
- package/dist/composables/useDevTools.d.ts.map +1 -0
- package/dist/composables/useIncremark.d.ts +84 -0
- package/dist/composables/useIncremark.d.ts.map +1 -0
- package/dist/composables/useLocale.d.ts +2 -0
- package/dist/composables/useLocale.d.ts.map +1 -0
- package/dist/composables/useProvideDefinations.d.ts +36 -0
- package/dist/composables/useProvideDefinations.d.ts.map +1 -0
- package/dist/composables/useShiki.d.ts +71 -0
- package/dist/composables/useShiki.d.ts.map +1 -0
- package/dist/composables/useStreamRenderer.d.ts +25 -0
- package/dist/composables/useStreamRenderer.d.ts.map +1 -0
- package/dist/composables/useTypewriter.d.ts +48 -0
- package/dist/composables/useTypewriter.d.ts.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2123 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +27 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/animatedChunks.d.ts +20 -0
- package/dist/utils/animatedChunks.d.ts.map +1 -0
- package/dist/utils/cursor.d.ts +9 -0
- package/dist/utils/cursor.d.ts.map +1 -0
- package/package.json +74 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,2123 @@
|
|
|
1
|
+
// src/composables/useIncremark.ts
|
|
2
|
+
import {
|
|
3
|
+
createSignal as createSignal3,
|
|
4
|
+
createEffect as createEffect2
|
|
5
|
+
} from "solid-js";
|
|
6
|
+
import {
|
|
7
|
+
createIncremarkParser
|
|
8
|
+
} from "@incremark/core";
|
|
9
|
+
|
|
10
|
+
// src/composables/useProvideDefinations.tsx
|
|
11
|
+
import { createSignal } from "solid-js";
|
|
12
|
+
import { createContext } from "solid-js";
|
|
13
|
+
import { jsx } from "solid-js/jsx-runtime";
|
|
14
|
+
var DefinationsContext = createContext();
|
|
15
|
+
function DefinationsProvider(props) {
|
|
16
|
+
return /* @__PURE__ */ jsx(DefinationsContext.Provider, { value: props.value, children: props.children });
|
|
17
|
+
}
|
|
18
|
+
function useProvideDefinations() {
|
|
19
|
+
const [definations, setDefinations] = createSignal({});
|
|
20
|
+
const [footnoteDefinitions, setFootnoteDefinitions] = createSignal({});
|
|
21
|
+
const [footnoteReferenceOrder, setFootnoteReferenceOrder] = createSignal([]);
|
|
22
|
+
function clearDefinations() {
|
|
23
|
+
setDefinations({});
|
|
24
|
+
}
|
|
25
|
+
function clearFootnoteDefinitions() {
|
|
26
|
+
setFootnoteDefinitions({});
|
|
27
|
+
}
|
|
28
|
+
function clearFootnoteReferenceOrder() {
|
|
29
|
+
setFootnoteReferenceOrder([]);
|
|
30
|
+
}
|
|
31
|
+
function clearAllDefinations() {
|
|
32
|
+
clearDefinations();
|
|
33
|
+
clearFootnoteDefinitions();
|
|
34
|
+
clearFootnoteReferenceOrder();
|
|
35
|
+
}
|
|
36
|
+
const contextValue = {
|
|
37
|
+
definations,
|
|
38
|
+
setDefinations,
|
|
39
|
+
footnoteDefinitions,
|
|
40
|
+
setFootnoteDefinitions,
|
|
41
|
+
footnoteReferenceOrder,
|
|
42
|
+
setFootnoteReferenceOrder,
|
|
43
|
+
clearAllDefinations
|
|
44
|
+
};
|
|
45
|
+
return {
|
|
46
|
+
definations,
|
|
47
|
+
setDefinations,
|
|
48
|
+
footnoteDefinitions,
|
|
49
|
+
setFootnoteDefinitions,
|
|
50
|
+
footnoteReferenceOrder,
|
|
51
|
+
setFootnoteReferenceOrder,
|
|
52
|
+
clearDefinations,
|
|
53
|
+
clearFootnoteDefinitions,
|
|
54
|
+
clearFootnoteReferenceOrder,
|
|
55
|
+
clearAllDefinations,
|
|
56
|
+
DefinationsProvider,
|
|
57
|
+
contextValue
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// src/composables/useTypewriter.ts
|
|
62
|
+
import {
|
|
63
|
+
createSignal as createSignal2,
|
|
64
|
+
createEffect,
|
|
65
|
+
onCleanup
|
|
66
|
+
} from "solid-js";
|
|
67
|
+
import { createStore, reconcile } from "solid-js/store";
|
|
68
|
+
import {
|
|
69
|
+
createBlockTransformer,
|
|
70
|
+
defaultPlugins,
|
|
71
|
+
mathPlugin,
|
|
72
|
+
collectFootnoteReferences
|
|
73
|
+
} from "@incremark/core";
|
|
74
|
+
|
|
75
|
+
// src/utils/cursor.ts
|
|
76
|
+
function addCursorToNode(node, cursor) {
|
|
77
|
+
if (node.type === "code") {
|
|
78
|
+
return node;
|
|
79
|
+
}
|
|
80
|
+
const cloned = JSON.parse(JSON.stringify(node));
|
|
81
|
+
function addToLast(n) {
|
|
82
|
+
if (n.type === "code") {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
if (n.children && n.children.length > 0) {
|
|
86
|
+
for (let i = n.children.length - 1; i >= 0; i--) {
|
|
87
|
+
if (addToLast(n.children[i])) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
n.children.push({ type: "text", value: cursor });
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
if (n.type === "text" && typeof n.value === "string") {
|
|
95
|
+
n.value += cursor;
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
if (typeof n.value === "string") {
|
|
99
|
+
n.value += cursor;
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
addToLast(cloned);
|
|
105
|
+
return cloned;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// src/composables/useTypewriter.ts
|
|
109
|
+
function useTypewriter(options) {
|
|
110
|
+
const { typewriter: typewriterInput, completedBlocks, pendingBlocks } = options;
|
|
111
|
+
const initialConfig = typewriterInput();
|
|
112
|
+
const [typewriterEnabled, setTypewriterEnabled] = createSignal2(initialConfig?.enabled ?? !!initialConfig);
|
|
113
|
+
const [isTypewriterProcessing, setIsTypewriterProcessing] = createSignal2(false);
|
|
114
|
+
const [isTypewriterPaused, setIsTypewriterPaused] = createSignal2(false);
|
|
115
|
+
const [typewriterEffect, setTypewriterEffect] = createSignal2(initialConfig?.effect ?? "none");
|
|
116
|
+
const [typewriterCursor, setTypewriterCursor] = createSignal2(initialConfig?.cursor ?? "|");
|
|
117
|
+
const [isAnimationComplete, setIsAnimationComplete] = createSignal2(true);
|
|
118
|
+
const [blocksStore, setBlocksStore] = createStore({ items: [] });
|
|
119
|
+
let transformer = null;
|
|
120
|
+
let displayBlocksCache = [];
|
|
121
|
+
function convertToRenderBlocks(displayBlocks) {
|
|
122
|
+
return displayBlocks.map((db, index) => {
|
|
123
|
+
const isPending = !db.isDisplayComplete;
|
|
124
|
+
const isLastPending = isPending && index === displayBlocks.length - 1;
|
|
125
|
+
let node = db.displayNode;
|
|
126
|
+
if (typewriterEffect() === "typing" && isLastPending) {
|
|
127
|
+
node = addCursorToNode(db.displayNode, typewriterCursor());
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
id: db.id,
|
|
131
|
+
status: db.status,
|
|
132
|
+
node,
|
|
133
|
+
startOffset: 0,
|
|
134
|
+
endOffset: 0,
|
|
135
|
+
rawText: "",
|
|
136
|
+
isLastPending
|
|
137
|
+
};
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
if (initialConfig) {
|
|
141
|
+
transformer = createBlockTransformer({
|
|
142
|
+
charsPerTick: initialConfig.charsPerTick ?? [1, 3],
|
|
143
|
+
tickInterval: initialConfig.tickInterval ?? 30,
|
|
144
|
+
effect: initialConfig.effect ?? "none",
|
|
145
|
+
pauseOnHidden: initialConfig.pauseOnHidden ?? true,
|
|
146
|
+
// 默认插件 + 数学公式插件(数学公式应该整体显示,不参与打字机逐字符效果)
|
|
147
|
+
plugins: initialConfig.plugins ?? [...defaultPlugins, mathPlugin],
|
|
148
|
+
onChange: (blocks) => {
|
|
149
|
+
displayBlocksCache = blocks;
|
|
150
|
+
const newRenderBlocks = convertToRenderBlocks(displayBlocksCache);
|
|
151
|
+
setBlocksStore("items", reconcile(newRenderBlocks, { key: "id", merge: true }));
|
|
152
|
+
setIsTypewriterProcessing(transformer?.isProcessing() ?? false);
|
|
153
|
+
setIsTypewriterPaused(transformer?.isPausedState() ?? false);
|
|
154
|
+
if (transformer?.isProcessing() ?? false) {
|
|
155
|
+
setIsAnimationComplete(false);
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
onAllComplete: () => {
|
|
159
|
+
setIsAnimationComplete(true);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
createEffect(() => {
|
|
164
|
+
const newConfig = typewriterInput();
|
|
165
|
+
if (!newConfig) return;
|
|
166
|
+
if (newConfig.enabled !== void 0) {
|
|
167
|
+
setTypewriterEnabled(newConfig.enabled);
|
|
168
|
+
}
|
|
169
|
+
if (newConfig.effect !== void 0) {
|
|
170
|
+
setTypewriterEffect(newConfig.effect);
|
|
171
|
+
}
|
|
172
|
+
if (newConfig.cursor !== void 0) {
|
|
173
|
+
setTypewriterCursor(newConfig.cursor);
|
|
174
|
+
}
|
|
175
|
+
transformer?.setOptions({
|
|
176
|
+
charsPerTick: newConfig.charsPerTick,
|
|
177
|
+
tickInterval: newConfig.tickInterval,
|
|
178
|
+
effect: newConfig.effect,
|
|
179
|
+
pauseOnHidden: newConfig.pauseOnHidden
|
|
180
|
+
});
|
|
181
|
+
if (newConfig.enabled === false && transformer) {
|
|
182
|
+
transformer.reset();
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
if (transformer) {
|
|
186
|
+
createEffect(() => {
|
|
187
|
+
if (!typewriterEnabled()) return;
|
|
188
|
+
const allBlocks = [...completedBlocks(), ...pendingBlocks()];
|
|
189
|
+
transformer.push(allBlocks);
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
const rawBlocks = () => [...completedBlocks(), ...pendingBlocks()];
|
|
193
|
+
createEffect(() => {
|
|
194
|
+
const enabled = typewriterEnabled();
|
|
195
|
+
const blocks = rawBlocks();
|
|
196
|
+
if (!enabled || !transformer) {
|
|
197
|
+
setBlocksStore("items", reconcile(blocks, { key: "id", merge: true }));
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
const displayedFootnoteReferenceOrder = () => {
|
|
201
|
+
if (!typewriterEnabled() || !transformer) {
|
|
202
|
+
const references2 = [];
|
|
203
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
204
|
+
for (const block of rawBlocks()) {
|
|
205
|
+
const blockRefs = collectFootnoteReferences(block.node);
|
|
206
|
+
for (const ref of blockRefs) {
|
|
207
|
+
if (!seen2.has(ref)) {
|
|
208
|
+
seen2.add(ref);
|
|
209
|
+
references2.push(ref);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return references2;
|
|
214
|
+
}
|
|
215
|
+
if (!isAnimationComplete()) {
|
|
216
|
+
return [];
|
|
217
|
+
}
|
|
218
|
+
const references = [];
|
|
219
|
+
const seen = /* @__PURE__ */ new Set();
|
|
220
|
+
for (const db of displayBlocksCache) {
|
|
221
|
+
const blockRefs = collectFootnoteReferences(db.displayNode);
|
|
222
|
+
for (const ref of blockRefs) {
|
|
223
|
+
if (!seen.has(ref)) {
|
|
224
|
+
seen.add(ref);
|
|
225
|
+
references.push(ref);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return references;
|
|
230
|
+
};
|
|
231
|
+
const typewriterControls = {
|
|
232
|
+
enabled: () => typewriterEnabled(),
|
|
233
|
+
setEnabled: (value) => {
|
|
234
|
+
setTypewriterEnabled(value);
|
|
235
|
+
},
|
|
236
|
+
isProcessing: () => isTypewriterProcessing(),
|
|
237
|
+
isPaused: () => isTypewriterPaused(),
|
|
238
|
+
effect: () => typewriterEffect(),
|
|
239
|
+
skip: () => transformer?.skip(),
|
|
240
|
+
pause: () => {
|
|
241
|
+
transformer?.pause();
|
|
242
|
+
setIsTypewriterPaused(true);
|
|
243
|
+
},
|
|
244
|
+
resume: () => {
|
|
245
|
+
transformer?.resume();
|
|
246
|
+
setIsTypewriterPaused(false);
|
|
247
|
+
},
|
|
248
|
+
setOptions: (opts) => {
|
|
249
|
+
if (opts.enabled !== void 0) {
|
|
250
|
+
setTypewriterEnabled(opts.enabled);
|
|
251
|
+
}
|
|
252
|
+
if (opts.charsPerTick !== void 0 || opts.tickInterval !== void 0 || opts.effect !== void 0 || opts.pauseOnHidden !== void 0) {
|
|
253
|
+
transformer?.setOptions({
|
|
254
|
+
charsPerTick: opts.charsPerTick,
|
|
255
|
+
tickInterval: opts.tickInterval,
|
|
256
|
+
effect: opts.effect,
|
|
257
|
+
pauseOnHidden: opts.pauseOnHidden
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
if (opts.effect !== void 0) {
|
|
261
|
+
setTypewriterEffect(opts.effect);
|
|
262
|
+
}
|
|
263
|
+
if (opts.cursor !== void 0) {
|
|
264
|
+
setTypewriterCursor(opts.cursor);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
onCleanup(() => {
|
|
269
|
+
transformer?.destroy();
|
|
270
|
+
});
|
|
271
|
+
return {
|
|
272
|
+
blocks: blocksStore.items,
|
|
273
|
+
typewriter: typewriterControls,
|
|
274
|
+
transformer,
|
|
275
|
+
isAnimationComplete: () => isAnimationComplete(),
|
|
276
|
+
displayedFootnoteReferenceOrder: () => displayedFootnoteReferenceOrder()
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// src/utils/animatedChunks.ts
|
|
281
|
+
var animatedChunks = /* @__PURE__ */ new Set();
|
|
282
|
+
function shouldAnimateChunk(createdAt) {
|
|
283
|
+
if (animatedChunks.has(createdAt)) {
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
animatedChunks.add(createdAt);
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
function clearAnimatedChunks() {
|
|
290
|
+
animatedChunks.clear();
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// src/composables/useIncremark.ts
|
|
294
|
+
function useIncremark(optionsInput = () => ({})) {
|
|
295
|
+
const { setDefinations, setFootnoteDefinitions, footnoteReferenceOrder, setFootnoteReferenceOrder, contextValue, DefinationsProvider: DefinationsProvider2 } = useProvideDefinations();
|
|
296
|
+
function createParser(options) {
|
|
297
|
+
return createIncremarkParser({
|
|
298
|
+
...options,
|
|
299
|
+
onChange: (state) => {
|
|
300
|
+
setDefinations(state.definitions);
|
|
301
|
+
setFootnoteDefinitions(state.footnoteDefinitions);
|
|
302
|
+
options.onChange?.(state);
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
let parser = createParser(optionsInput());
|
|
307
|
+
const [completedBlocks, setCompletedBlocks] = createSignal3([]);
|
|
308
|
+
const [pendingBlocks, setPendingBlocks] = createSignal3([]);
|
|
309
|
+
const [isLoading, setIsLoading] = createSignal3(false);
|
|
310
|
+
const [markdown, setMarkdown] = createSignal3("");
|
|
311
|
+
const [isFinalized, setIsFinalized] = createSignal3(false);
|
|
312
|
+
const { blocks, typewriter, transformer, isAnimationComplete, displayedFootnoteReferenceOrder } = useTypewriter({
|
|
313
|
+
typewriter: () => optionsInput().typewriter,
|
|
314
|
+
completedBlocks,
|
|
315
|
+
pendingBlocks
|
|
316
|
+
});
|
|
317
|
+
const isDisplayComplete = () => {
|
|
318
|
+
if (!optionsInput().typewriter || !typewriter.enabled()) {
|
|
319
|
+
return isFinalized();
|
|
320
|
+
}
|
|
321
|
+
return isFinalized() && isAnimationComplete();
|
|
322
|
+
};
|
|
323
|
+
const [ast, setAst] = createSignal3({
|
|
324
|
+
type: "root",
|
|
325
|
+
children: []
|
|
326
|
+
});
|
|
327
|
+
function handleUpdate(update, isFinalize = false) {
|
|
328
|
+
setMarkdown(parser.getBuffer());
|
|
329
|
+
if (update.updated.length > 0) {
|
|
330
|
+
const idsToRemove = new Set(update.updated.map((b) => b.id));
|
|
331
|
+
setCompletedBlocks((prev) => prev.filter((b) => !idsToRemove.has(b.id)));
|
|
332
|
+
}
|
|
333
|
+
if (update.completed.length > 0) {
|
|
334
|
+
setCompletedBlocks((prev) => [...prev, ...update.completed]);
|
|
335
|
+
}
|
|
336
|
+
setPendingBlocks(update.pending);
|
|
337
|
+
if (isFinalize) {
|
|
338
|
+
if (update.pending.length > 0) {
|
|
339
|
+
setCompletedBlocks((prev) => [...prev, ...update.pending]);
|
|
340
|
+
setPendingBlocks([]);
|
|
341
|
+
}
|
|
342
|
+
setIsLoading(false);
|
|
343
|
+
setIsFinalized(true);
|
|
344
|
+
} else {
|
|
345
|
+
setIsLoading(true);
|
|
346
|
+
}
|
|
347
|
+
setFootnoteReferenceOrder(update.footnoteReferenceOrder);
|
|
348
|
+
}
|
|
349
|
+
function append(chunk) {
|
|
350
|
+
const update = parser.append(chunk);
|
|
351
|
+
setAst(update.ast);
|
|
352
|
+
handleUpdate(update, false);
|
|
353
|
+
return update;
|
|
354
|
+
}
|
|
355
|
+
function finalize() {
|
|
356
|
+
const update = parser.finalize();
|
|
357
|
+
handleUpdate(update, true);
|
|
358
|
+
return update;
|
|
359
|
+
}
|
|
360
|
+
function abort() {
|
|
361
|
+
return finalize();
|
|
362
|
+
}
|
|
363
|
+
function reset() {
|
|
364
|
+
parser.reset();
|
|
365
|
+
setCompletedBlocks([]);
|
|
366
|
+
setPendingBlocks([]);
|
|
367
|
+
setMarkdown("");
|
|
368
|
+
setIsLoading(false);
|
|
369
|
+
setIsFinalized(false);
|
|
370
|
+
setFootnoteReferenceOrder([]);
|
|
371
|
+
transformer?.reset();
|
|
372
|
+
clearAnimatedChunks();
|
|
373
|
+
}
|
|
374
|
+
let lastOptionsStr = "";
|
|
375
|
+
createEffect2(() => {
|
|
376
|
+
const opts = optionsInput();
|
|
377
|
+
const { typewriter: _, astBuilder, ...parserOptions } = opts;
|
|
378
|
+
const optionsStr = JSON.stringify(parserOptions) + "|" + (astBuilder?.name ?? "default");
|
|
379
|
+
if (optionsStr !== lastOptionsStr) {
|
|
380
|
+
lastOptionsStr = optionsStr;
|
|
381
|
+
const { typewriter: _2, ...parserOptions2 } = opts;
|
|
382
|
+
parser.updateOptions(parserOptions2);
|
|
383
|
+
setCompletedBlocks([]);
|
|
384
|
+
setPendingBlocks([]);
|
|
385
|
+
setMarkdown("");
|
|
386
|
+
setIsLoading(false);
|
|
387
|
+
setIsFinalized(false);
|
|
388
|
+
setFootnoteReferenceOrder([]);
|
|
389
|
+
transformer?.reset();
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
createEffect2(() => {
|
|
393
|
+
const newOrder = displayedFootnoteReferenceOrder();
|
|
394
|
+
setFootnoteReferenceOrder(newOrder);
|
|
395
|
+
});
|
|
396
|
+
function render(content) {
|
|
397
|
+
const update = parser.render(content);
|
|
398
|
+
setMarkdown(parser.getBuffer());
|
|
399
|
+
setCompletedBlocks(parser.getCompletedBlocks());
|
|
400
|
+
setPendingBlocks([]);
|
|
401
|
+
setIsLoading(false);
|
|
402
|
+
setIsFinalized(true);
|
|
403
|
+
setFootnoteReferenceOrder(update.footnoteReferenceOrder);
|
|
404
|
+
setFootnoteReferenceOrder(update.footnoteReferenceOrder);
|
|
405
|
+
return update;
|
|
406
|
+
}
|
|
407
|
+
const result = {
|
|
408
|
+
/** 已收集的完整 Markdown 字符串 */
|
|
409
|
+
markdown,
|
|
410
|
+
/** 已完成的块列表 */
|
|
411
|
+
completedBlocks,
|
|
412
|
+
/** 待处理的块列表 */
|
|
413
|
+
pendingBlocks,
|
|
414
|
+
/** 当前完整的 AST */
|
|
415
|
+
ast,
|
|
416
|
+
/** 用于渲染的 blocks(根据打字机设置自动处理) */
|
|
417
|
+
blocks,
|
|
418
|
+
/** 是否正在加载 */
|
|
419
|
+
isLoading,
|
|
420
|
+
/** 是否已完成(finalize) */
|
|
421
|
+
isFinalized,
|
|
422
|
+
/**
|
|
423
|
+
* 内容是否完全显示完成
|
|
424
|
+
* - 无打字机:等于 isFinalized
|
|
425
|
+
* - 有打字机:isFinalized + 动画播放完成
|
|
426
|
+
* 适用于控制 footnote 等需要在内容完全显示后才出现的元素
|
|
427
|
+
*/
|
|
428
|
+
isDisplayComplete,
|
|
429
|
+
/** 脚注引用的出现顺序 */
|
|
430
|
+
footnoteReferenceOrder,
|
|
431
|
+
/** 追加内容 */
|
|
432
|
+
append,
|
|
433
|
+
/** 完成解析 */
|
|
434
|
+
finalize,
|
|
435
|
+
/** 强制中断 */
|
|
436
|
+
abort,
|
|
437
|
+
/** 重置解析器和打字机 */
|
|
438
|
+
reset,
|
|
439
|
+
/** 一次性渲染(reset + append + finalize) */
|
|
440
|
+
render,
|
|
441
|
+
/** 解析器实例 */
|
|
442
|
+
parser,
|
|
443
|
+
/** 打字机控制 */
|
|
444
|
+
typewriter,
|
|
445
|
+
/** Context value for DefinationsProvider */
|
|
446
|
+
contextValue,
|
|
447
|
+
/** DefinationsProvider component */
|
|
448
|
+
DefinationsProvider: DefinationsProvider2
|
|
449
|
+
};
|
|
450
|
+
return result;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// src/composables/useShiki.ts
|
|
454
|
+
import { createSignal as createSignal4 } from "solid-js";
|
|
455
|
+
var _ShikiManager = class _ShikiManager {
|
|
456
|
+
constructor() {
|
|
457
|
+
/** 存储 highlighter 实例,key 为主题名称 */
|
|
458
|
+
this.highlighters = /* @__PURE__ */ new Map();
|
|
459
|
+
}
|
|
460
|
+
static getInstance() {
|
|
461
|
+
if (!_ShikiManager.instance) {
|
|
462
|
+
_ShikiManager.instance = new _ShikiManager();
|
|
463
|
+
}
|
|
464
|
+
return _ShikiManager.instance;
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* 获取或创建 highlighter
|
|
468
|
+
* @param theme 主题名称
|
|
469
|
+
* @returns highlighter 实例
|
|
470
|
+
*/
|
|
471
|
+
async getHighlighter(theme) {
|
|
472
|
+
if (this.highlighters.has(theme)) {
|
|
473
|
+
return this.highlighters.get(theme);
|
|
474
|
+
}
|
|
475
|
+
const { createHighlighter } = await import("shiki");
|
|
476
|
+
const highlighter = await createHighlighter({
|
|
477
|
+
themes: [theme],
|
|
478
|
+
langs: []
|
|
479
|
+
});
|
|
480
|
+
const info = {
|
|
481
|
+
highlighter,
|
|
482
|
+
loadedLanguages: /* @__PURE__ */ new Set(),
|
|
483
|
+
loadedThemes: /* @__PURE__ */ new Set([theme])
|
|
484
|
+
};
|
|
485
|
+
this.highlighters.set(theme, info);
|
|
486
|
+
return info;
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* 加载语言(按需)
|
|
490
|
+
* @param theme 主题名称
|
|
491
|
+
* @param lang 语言名称
|
|
492
|
+
*/
|
|
493
|
+
async loadLanguage(theme, lang) {
|
|
494
|
+
const info = this.highlighters.get(theme);
|
|
495
|
+
if (!info || info.loadedLanguages.has(lang)) return;
|
|
496
|
+
try {
|
|
497
|
+
await info.highlighter.loadLanguage(lang);
|
|
498
|
+
info.loadedLanguages.add(lang);
|
|
499
|
+
} catch {
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* 加载主题(按需)
|
|
504
|
+
* @param theme 主题名称
|
|
505
|
+
*/
|
|
506
|
+
async loadTheme(theme) {
|
|
507
|
+
const info = this.highlighters.get(theme);
|
|
508
|
+
if (!info || info.loadedThemes.has(theme)) return;
|
|
509
|
+
try {
|
|
510
|
+
await info.highlighter.loadTheme(theme);
|
|
511
|
+
info.loadedThemes.add(theme);
|
|
512
|
+
} catch {
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* 高亮代码
|
|
517
|
+
* @param theme 主题名称
|
|
518
|
+
* @param code 代码内容
|
|
519
|
+
* @param lang 语言名称
|
|
520
|
+
* @param fallbackTheme 回退主题
|
|
521
|
+
* @returns 高亮后的 HTML
|
|
522
|
+
*/
|
|
523
|
+
async codeToHtml(theme, code, lang, fallbackTheme) {
|
|
524
|
+
const info = this.highlighters.get(theme);
|
|
525
|
+
if (!info) throw new Error("Highlighter not found");
|
|
526
|
+
const actualLang = info.loadedLanguages.has(lang) ? lang : "text";
|
|
527
|
+
const actualTheme = info.loadedThemes.has(theme) ? theme : fallbackTheme;
|
|
528
|
+
return info.highlighter.codeToHtml(code, {
|
|
529
|
+
lang: actualLang,
|
|
530
|
+
theme: actualTheme
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* 清理所有 highlighter(应用退出或需要重置时调用)
|
|
535
|
+
*/
|
|
536
|
+
disposeAll() {
|
|
537
|
+
for (const [, info] of this.highlighters) {
|
|
538
|
+
if (info.highlighter?.dispose) {
|
|
539
|
+
info.highlighter.dispose();
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
this.highlighters.clear();
|
|
543
|
+
}
|
|
544
|
+
};
|
|
545
|
+
_ShikiManager.instance = null;
|
|
546
|
+
var ShikiManager = _ShikiManager;
|
|
547
|
+
var shikiManagerInstance = null;
|
|
548
|
+
function getShikiManager() {
|
|
549
|
+
if (!shikiManagerInstance) {
|
|
550
|
+
shikiManagerInstance = ShikiManager.getInstance();
|
|
551
|
+
}
|
|
552
|
+
return shikiManagerInstance;
|
|
553
|
+
}
|
|
554
|
+
function useShiki(theme) {
|
|
555
|
+
const [highlighterInfo, setHighlighterInfo] = createSignal4(null);
|
|
556
|
+
const [isHighlighting, setIsHighlighting] = createSignal4(false);
|
|
557
|
+
const [isReady, setIsReady] = createSignal4(false);
|
|
558
|
+
async function initHighlighter() {
|
|
559
|
+
if (isReady()) return;
|
|
560
|
+
try {
|
|
561
|
+
const info = await getShikiManager().getHighlighter(theme);
|
|
562
|
+
setHighlighterInfo(info);
|
|
563
|
+
setIsReady(true);
|
|
564
|
+
} catch (e) {
|
|
565
|
+
console.warn("Failed to initialize Shiki highlighter:", e);
|
|
566
|
+
throw e;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
async function getHighlighter() {
|
|
570
|
+
if (!highlighterInfo()) {
|
|
571
|
+
const info = await getShikiManager().getHighlighter(theme);
|
|
572
|
+
setHighlighterInfo(info);
|
|
573
|
+
setIsReady(true);
|
|
574
|
+
return info;
|
|
575
|
+
}
|
|
576
|
+
return highlighterInfo();
|
|
577
|
+
}
|
|
578
|
+
async function highlight(code, lang, fallbackTheme) {
|
|
579
|
+
setIsHighlighting(true);
|
|
580
|
+
try {
|
|
581
|
+
const info = await getHighlighter();
|
|
582
|
+
const manager = getShikiManager();
|
|
583
|
+
if (!info.loadedLanguages.has(lang) && lang !== "text") {
|
|
584
|
+
await manager.loadLanguage(theme, lang);
|
|
585
|
+
}
|
|
586
|
+
if (!info.loadedThemes.has(theme)) {
|
|
587
|
+
await manager.loadTheme(theme);
|
|
588
|
+
}
|
|
589
|
+
return await manager.codeToHtml(
|
|
590
|
+
theme,
|
|
591
|
+
code,
|
|
592
|
+
lang,
|
|
593
|
+
fallbackTheme
|
|
594
|
+
);
|
|
595
|
+
} catch (e) {
|
|
596
|
+
throw e;
|
|
597
|
+
} finally {
|
|
598
|
+
setIsHighlighting(false);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
return {
|
|
602
|
+
highlighterInfo,
|
|
603
|
+
isHighlighting,
|
|
604
|
+
isReady,
|
|
605
|
+
initHighlighter,
|
|
606
|
+
highlight
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// src/components/ConfigProvider.tsx
|
|
611
|
+
import { createContext as createContext2, useContext, createSignal as createSignal5, createMemo } from "solid-js";
|
|
612
|
+
import { zhCN } from "@incremark/shared";
|
|
613
|
+
import { jsx as jsx2 } from "solid-js/jsx-runtime";
|
|
614
|
+
var LocaleContext = createContext2();
|
|
615
|
+
var ConfigProvider = (props) => {
|
|
616
|
+
const [locale, setLocale] = createSignal5(props.locale || zhCN);
|
|
617
|
+
createMemo(() => {
|
|
618
|
+
setLocale(props.locale || zhCN);
|
|
619
|
+
});
|
|
620
|
+
return /* @__PURE__ */ jsx2(LocaleContext.Provider, { value: { locale }, children: props.children });
|
|
621
|
+
};
|
|
622
|
+
function useLocale() {
|
|
623
|
+
const context = useContext(LocaleContext);
|
|
624
|
+
const locale = context?.locale || (() => zhCN);
|
|
625
|
+
return (key) => {
|
|
626
|
+
const keys = key.split(".");
|
|
627
|
+
let value = locale();
|
|
628
|
+
for (const k of keys) {
|
|
629
|
+
value = value?.[k];
|
|
630
|
+
}
|
|
631
|
+
return value || key;
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// src/composables/useDefinationsContext.ts
|
|
636
|
+
import { useContext as useContext2 } from "solid-js";
|
|
637
|
+
function useDefinationsContext() {
|
|
638
|
+
const context = useContext2(DefinationsContext);
|
|
639
|
+
if (!context) {
|
|
640
|
+
throw new Error("DefinationsContext not found. Make sure you are using this within a component that provides DefinationsContext.");
|
|
641
|
+
}
|
|
642
|
+
return context;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
// src/composables/useDevTools.ts
|
|
646
|
+
import { createSignal as createSignal6 } from "solid-js";
|
|
647
|
+
function useDevTools(options = {}) {
|
|
648
|
+
const [enabled, setEnabled] = createSignal6(options.enabled ?? false);
|
|
649
|
+
const [blocks, setBlocks] = createSignal6([]);
|
|
650
|
+
const [ast, setAst] = createSignal6(null);
|
|
651
|
+
const stats = () => ({
|
|
652
|
+
blockCount: blocks().length,
|
|
653
|
+
completedCount: blocks().filter((b) => b.status === "completed").length,
|
|
654
|
+
pendingCount: blocks().filter((b) => b.status !== "completed").length
|
|
655
|
+
});
|
|
656
|
+
function toggle() {
|
|
657
|
+
setEnabled((prev) => !prev);
|
|
658
|
+
}
|
|
659
|
+
return {
|
|
660
|
+
enabled,
|
|
661
|
+
toggle,
|
|
662
|
+
setEnabled,
|
|
663
|
+
blocks,
|
|
664
|
+
setBlocks,
|
|
665
|
+
ast,
|
|
666
|
+
setAst,
|
|
667
|
+
stats
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// src/composables/useStreamRenderer.ts
|
|
672
|
+
import { createSignal as createSignal7 } from "solid-js";
|
|
673
|
+
function useStreamRenderer(options = {}) {
|
|
674
|
+
const [blocks, setBlocks] = createSignal7(options.initialBlocks ?? []);
|
|
675
|
+
function addBlocks(newBlocks) {
|
|
676
|
+
setBlocks((prev) => [...prev, ...newBlocks]);
|
|
677
|
+
}
|
|
678
|
+
function clearBlocks() {
|
|
679
|
+
setBlocks([]);
|
|
680
|
+
}
|
|
681
|
+
const blockCount = () => blocks().length;
|
|
682
|
+
return {
|
|
683
|
+
blocks,
|
|
684
|
+
setBlocks,
|
|
685
|
+
addBlocks,
|
|
686
|
+
clearBlocks,
|
|
687
|
+
blockCount
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// src/composables/useBlockTransformer.ts
|
|
692
|
+
import { createSignal as createSignal8 } from "solid-js";
|
|
693
|
+
import {
|
|
694
|
+
createBlockTransformer as createBlockTransformer2
|
|
695
|
+
} from "@incremark/core";
|
|
696
|
+
function useBlockTransformer(options = {}) {
|
|
697
|
+
const [displayBlocks, setDisplayBlocks] = createSignal8([]);
|
|
698
|
+
const [isProcessing, setIsProcessing] = createSignal8(false);
|
|
699
|
+
const [isPaused, setIsPaused] = createSignal8(false);
|
|
700
|
+
const transformer = createBlockTransformer2({
|
|
701
|
+
charsPerTick: options.charsPerTick ?? [1, 3],
|
|
702
|
+
tickInterval: options.tickInterval ?? 30,
|
|
703
|
+
effect: options.effect ?? "none",
|
|
704
|
+
pauseOnHidden: options.pauseOnHidden ?? true,
|
|
705
|
+
plugins: options.plugins,
|
|
706
|
+
onChange: (blocks) => {
|
|
707
|
+
setDisplayBlocks(blocks);
|
|
708
|
+
setIsProcessing(transformer?.isProcessing() ?? false);
|
|
709
|
+
setIsPaused(transformer?.isPausedState() ?? false);
|
|
710
|
+
}
|
|
711
|
+
});
|
|
712
|
+
function push(blocks) {
|
|
713
|
+
transformer.push(blocks);
|
|
714
|
+
}
|
|
715
|
+
function skip() {
|
|
716
|
+
transformer.skip();
|
|
717
|
+
}
|
|
718
|
+
function pause() {
|
|
719
|
+
transformer.pause();
|
|
720
|
+
}
|
|
721
|
+
function resume() {
|
|
722
|
+
transformer.resume();
|
|
723
|
+
}
|
|
724
|
+
function reset() {
|
|
725
|
+
transformer.reset();
|
|
726
|
+
}
|
|
727
|
+
function destroy() {
|
|
728
|
+
transformer.destroy();
|
|
729
|
+
}
|
|
730
|
+
function setOptions(opts) {
|
|
731
|
+
transformer.setOptions(opts);
|
|
732
|
+
}
|
|
733
|
+
return {
|
|
734
|
+
displayBlocks,
|
|
735
|
+
isProcessing,
|
|
736
|
+
isPaused,
|
|
737
|
+
push,
|
|
738
|
+
skip,
|
|
739
|
+
pause,
|
|
740
|
+
resume,
|
|
741
|
+
reset,
|
|
742
|
+
destroy,
|
|
743
|
+
setOptions
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
// src/components/Incremark.tsx
|
|
748
|
+
import { For as For9, Show as Show13, mergeProps } from "solid-js";
|
|
749
|
+
|
|
750
|
+
// src/components/IncremarkRenderer.tsx
|
|
751
|
+
import { Show as Show11 } from "solid-js";
|
|
752
|
+
import { Dynamic as Dynamic5 } from "solid-js/web";
|
|
753
|
+
|
|
754
|
+
// src/components/IncremarkHeading.tsx
|
|
755
|
+
import { Dynamic as Dynamic2 } from "solid-js/web";
|
|
756
|
+
|
|
757
|
+
// src/components/IncremarkInline.tsx
|
|
758
|
+
import { hasChunks, getStableText, isHtmlNode } from "@incremark/shared";
|
|
759
|
+
import { For as For2, Index, Show as Show3 } from "solid-js";
|
|
760
|
+
|
|
761
|
+
// src/components/IncremarkMath.tsx
|
|
762
|
+
import { createSignal as createSignal9, createEffect as createEffect4, onCleanup as onCleanup3, Show } from "solid-js";
|
|
763
|
+
import { jsx as jsx3, jsxs } from "solid-js/jsx-runtime";
|
|
764
|
+
var IncremarkMath = (props) => {
|
|
765
|
+
const [renderedHtml, setRenderedHtml] = createSignal9("");
|
|
766
|
+
const [isLoading, setIsLoading] = createSignal9(false);
|
|
767
|
+
const isInline = () => props.node.type === "inlineMath";
|
|
768
|
+
const formula = () => props.node.value;
|
|
769
|
+
let renderTimer = null;
|
|
770
|
+
let katexRef = null;
|
|
771
|
+
function scheduleRender() {
|
|
772
|
+
if (!formula()) {
|
|
773
|
+
setRenderedHtml("");
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
if (renderTimer) {
|
|
777
|
+
clearTimeout(renderTimer);
|
|
778
|
+
}
|
|
779
|
+
setIsLoading(true);
|
|
780
|
+
renderTimer = setTimeout(() => {
|
|
781
|
+
doRender();
|
|
782
|
+
}, props.renderDelay ?? 0);
|
|
783
|
+
}
|
|
784
|
+
async function doRender() {
|
|
785
|
+
if (!formula()) return;
|
|
786
|
+
try {
|
|
787
|
+
if (!katexRef) {
|
|
788
|
+
const katexModule = await import("katex");
|
|
789
|
+
katexRef = katexModule.default;
|
|
790
|
+
}
|
|
791
|
+
const katex = katexRef;
|
|
792
|
+
setRenderedHtml(katex.renderToString(formula(), {
|
|
793
|
+
displayMode: !isInline(),
|
|
794
|
+
throwOnError: false,
|
|
795
|
+
strict: false
|
|
796
|
+
}));
|
|
797
|
+
} catch {
|
|
798
|
+
setRenderedHtml("");
|
|
799
|
+
} finally {
|
|
800
|
+
setIsLoading(false);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
createEffect4(() => {
|
|
804
|
+
scheduleRender();
|
|
805
|
+
});
|
|
806
|
+
onCleanup3(() => {
|
|
807
|
+
if (renderTimer) {
|
|
808
|
+
clearTimeout(renderTimer);
|
|
809
|
+
}
|
|
810
|
+
});
|
|
811
|
+
if (isInline()) {
|
|
812
|
+
return /* @__PURE__ */ jsxs("span", { class: "incremark-math-inline", children: [
|
|
813
|
+
/* @__PURE__ */ jsx3(Show, { when: renderedHtml() && !isLoading(), children: /* @__PURE__ */ jsx3("span", { innerHTML: renderedHtml() }) }),
|
|
814
|
+
/* @__PURE__ */ jsx3(Show, { when: !renderedHtml() || isLoading(), children: /* @__PURE__ */ jsx3("code", { class: "math-source", children: formula() }) })
|
|
815
|
+
] });
|
|
816
|
+
}
|
|
817
|
+
return /* @__PURE__ */ jsxs("div", { class: "incremark-math-block", children: [
|
|
818
|
+
/* @__PURE__ */ jsx3(Show, { when: renderedHtml() && !isLoading(), children: /* @__PURE__ */ jsx3("div", { innerHTML: renderedHtml(), class: "math-rendered" }) }),
|
|
819
|
+
/* @__PURE__ */ jsx3(Show, { when: !renderedHtml() || isLoading(), children: /* @__PURE__ */ jsx3("pre", { class: "math-source-block", children: /* @__PURE__ */ jsx3("code", { children: formula() }) }) })
|
|
820
|
+
] });
|
|
821
|
+
};
|
|
822
|
+
|
|
823
|
+
// src/components/IncremarkHtmlElement.tsx
|
|
824
|
+
import { For, Show as Show2 } from "solid-js";
|
|
825
|
+
import { Dynamic } from "solid-js/web";
|
|
826
|
+
import { Fragment, jsx as jsx4 } from "solid-js/jsx-runtime";
|
|
827
|
+
var INLINE_ELEMENTS = [
|
|
828
|
+
"a",
|
|
829
|
+
"abbr",
|
|
830
|
+
"acronym",
|
|
831
|
+
"b",
|
|
832
|
+
"bdo",
|
|
833
|
+
"big",
|
|
834
|
+
"br",
|
|
835
|
+
"button",
|
|
836
|
+
"cite",
|
|
837
|
+
"code",
|
|
838
|
+
"dfn",
|
|
839
|
+
"em",
|
|
840
|
+
"i",
|
|
841
|
+
"img",
|
|
842
|
+
"input",
|
|
843
|
+
"kbd",
|
|
844
|
+
"label",
|
|
845
|
+
"map",
|
|
846
|
+
"object",
|
|
847
|
+
"output",
|
|
848
|
+
"q",
|
|
849
|
+
"samp",
|
|
850
|
+
"script",
|
|
851
|
+
"select",
|
|
852
|
+
"small",
|
|
853
|
+
"span",
|
|
854
|
+
"strong",
|
|
855
|
+
"sub",
|
|
856
|
+
"sup",
|
|
857
|
+
"textarea",
|
|
858
|
+
"time",
|
|
859
|
+
"tt",
|
|
860
|
+
"var"
|
|
861
|
+
];
|
|
862
|
+
var VOID_ELEMENTS = [
|
|
863
|
+
"area",
|
|
864
|
+
"base",
|
|
865
|
+
"br",
|
|
866
|
+
"col",
|
|
867
|
+
"embed",
|
|
868
|
+
"hr",
|
|
869
|
+
"img",
|
|
870
|
+
"input",
|
|
871
|
+
"link",
|
|
872
|
+
"meta",
|
|
873
|
+
"param",
|
|
874
|
+
"source",
|
|
875
|
+
"track",
|
|
876
|
+
"wbr"
|
|
877
|
+
];
|
|
878
|
+
function isInlineElement(tagName) {
|
|
879
|
+
return INLINE_ELEMENTS.includes(tagName.toLowerCase());
|
|
880
|
+
}
|
|
881
|
+
function isVoidElement(tagName) {
|
|
882
|
+
return VOID_ELEMENTS.includes(tagName.toLowerCase());
|
|
883
|
+
}
|
|
884
|
+
function hasOnlyInlineChildren(children) {
|
|
885
|
+
if (!children || children.length === 0) return true;
|
|
886
|
+
return children.every((child) => {
|
|
887
|
+
const type = child.type;
|
|
888
|
+
const inlineTypes = ["text", "strong", "emphasis", "inlineCode", "link", "image", "break", "html", "htmlElement"];
|
|
889
|
+
if (inlineTypes.includes(type)) {
|
|
890
|
+
if (type === "htmlElement") {
|
|
891
|
+
return isInlineElement(child.tagName);
|
|
892
|
+
}
|
|
893
|
+
return true;
|
|
894
|
+
}
|
|
895
|
+
return false;
|
|
896
|
+
});
|
|
897
|
+
}
|
|
898
|
+
function renderChildren(children) {
|
|
899
|
+
if (!children || children.length === 0) return null;
|
|
900
|
+
if (hasOnlyInlineChildren(children)) {
|
|
901
|
+
return /* @__PURE__ */ jsx4(IncremarkInline, { nodes: children });
|
|
902
|
+
}
|
|
903
|
+
return /* @__PURE__ */ jsx4(For, { each: children, children: (child, idx) => {
|
|
904
|
+
if (child.type === "htmlElement") {
|
|
905
|
+
return /* @__PURE__ */ jsx4(IncremarkHtmlElement, { node: child });
|
|
906
|
+
}
|
|
907
|
+
if (child.type === "text") {
|
|
908
|
+
return /* @__PURE__ */ jsx4(Fragment, { children: child.value });
|
|
909
|
+
}
|
|
910
|
+
if (["strong", "emphasis", "inlineCode", "link", "image", "break"].includes(child.type)) {
|
|
911
|
+
return /* @__PURE__ */ jsx4(IncremarkInline, { nodes: [child] });
|
|
912
|
+
}
|
|
913
|
+
if (child.type === "paragraph") {
|
|
914
|
+
return /* @__PURE__ */ jsx4("p", { children: /* @__PURE__ */ jsx4(IncremarkInline, { nodes: child.children }) });
|
|
915
|
+
}
|
|
916
|
+
return /* @__PURE__ */ jsx4(IncremarkRenderer, { node: child });
|
|
917
|
+
} });
|
|
918
|
+
}
|
|
919
|
+
var IncremarkHtmlElement = (props) => {
|
|
920
|
+
const tagName = () => props.node.tagName;
|
|
921
|
+
const attrs = () => props.node.attrs || {};
|
|
922
|
+
const children = () => props.node.children || [];
|
|
923
|
+
const isVoid = () => isVoidElement(tagName());
|
|
924
|
+
return /* @__PURE__ */ jsx4(
|
|
925
|
+
Dynamic,
|
|
926
|
+
{
|
|
927
|
+
component: tagName(),
|
|
928
|
+
...attrs(),
|
|
929
|
+
class: `incremark-html-element incremark-${tagName()}`,
|
|
930
|
+
children: /* @__PURE__ */ jsx4(Show2, { when: !isVoid(), children: renderChildren(children()) })
|
|
931
|
+
}
|
|
932
|
+
);
|
|
933
|
+
};
|
|
934
|
+
|
|
935
|
+
// src/components/IncremarkInline.tsx
|
|
936
|
+
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs2 } from "solid-js/jsx-runtime";
|
|
937
|
+
function isHtmlElementNode(node) {
|
|
938
|
+
return node.type === "htmlElement";
|
|
939
|
+
}
|
|
940
|
+
function isImageReference(node) {
|
|
941
|
+
return node.type === "imageReference";
|
|
942
|
+
}
|
|
943
|
+
function isLinkReference(node) {
|
|
944
|
+
return node.type === "linkReference";
|
|
945
|
+
}
|
|
946
|
+
var IncremarkInline = (props) => {
|
|
947
|
+
const { definations, footnoteDefinitions } = useDefinationsContext();
|
|
948
|
+
function getChunks(node) {
|
|
949
|
+
if (hasChunks(node)) {
|
|
950
|
+
return node.chunks;
|
|
951
|
+
}
|
|
952
|
+
return void 0;
|
|
953
|
+
}
|
|
954
|
+
function isInlineMath(node) {
|
|
955
|
+
return node.type === "inlineMath";
|
|
956
|
+
}
|
|
957
|
+
return /* @__PURE__ */ jsx5(Fragment2, { children: /* @__PURE__ */ jsx5(For2, { each: props.nodes, children: (node, idx) => /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
958
|
+
/* @__PURE__ */ jsxs2(Show3, { when: node.type === "text", children: [
|
|
959
|
+
getStableText(node),
|
|
960
|
+
/* @__PURE__ */ jsx5(Index, { each: getChunks(node) || [], children: (chunk, idx2) => /* @__PURE__ */ jsx5(
|
|
961
|
+
"span",
|
|
962
|
+
{
|
|
963
|
+
class: "incremark-fade-in",
|
|
964
|
+
"data-chunk-key": chunk().createdAt,
|
|
965
|
+
children: chunk().text
|
|
966
|
+
}
|
|
967
|
+
) })
|
|
968
|
+
] }),
|
|
969
|
+
/* @__PURE__ */ jsx5(Show3, { when: isInlineMath(node), children: /* @__PURE__ */ jsx5(IncremarkMath, { node }) }),
|
|
970
|
+
/* @__PURE__ */ jsx5(Show3, { when: isHtmlElementNode(node), children: /* @__PURE__ */ jsx5(IncremarkHtmlElement, { node }) }),
|
|
971
|
+
/* @__PURE__ */ jsx5(Show3, { when: isHtmlNode(node), children: /* @__PURE__ */ jsx5("span", { class: "incremark-inline-html", innerHTML: node.value }) }),
|
|
972
|
+
/* @__PURE__ */ jsx5(Show3, { when: node.type === "strong", children: /* @__PURE__ */ jsx5("strong", { children: /* @__PURE__ */ jsx5(IncremarkInline, { nodes: node.children }) }) }),
|
|
973
|
+
/* @__PURE__ */ jsx5(Show3, { when: node.type === "emphasis", children: /* @__PURE__ */ jsx5("em", { children: /* @__PURE__ */ jsx5(IncremarkInline, { nodes: node.children }) }) }),
|
|
974
|
+
/* @__PURE__ */ jsx5(Show3, { when: node.type === "inlineCode", children: /* @__PURE__ */ jsx5("code", { class: "incremark-inline-code", children: node.value }) }),
|
|
975
|
+
/* @__PURE__ */ jsx5(Show3, { when: node.type === "link", children: /* @__PURE__ */ jsx5(
|
|
976
|
+
"a",
|
|
977
|
+
{
|
|
978
|
+
class: "incremark-link",
|
|
979
|
+
href: node.url,
|
|
980
|
+
target: "_blank",
|
|
981
|
+
rel: "noopener noreferrer",
|
|
982
|
+
children: /* @__PURE__ */ jsx5(IncremarkInline, { nodes: node.children })
|
|
983
|
+
}
|
|
984
|
+
) }),
|
|
985
|
+
/* @__PURE__ */ jsx5(Show3, { when: node.type === "image", children: /* @__PURE__ */ jsx5(
|
|
986
|
+
"img",
|
|
987
|
+
{
|
|
988
|
+
class: "incremark-image",
|
|
989
|
+
src: node.url,
|
|
990
|
+
alt: node.alt || "",
|
|
991
|
+
title: node.title || void 0,
|
|
992
|
+
loading: "lazy"
|
|
993
|
+
}
|
|
994
|
+
) }),
|
|
995
|
+
/* @__PURE__ */ jsx5(Show3, { when: isImageReference(node), children: /* @__PURE__ */ jsx5(
|
|
996
|
+
Show3,
|
|
997
|
+
{
|
|
998
|
+
when: definations()[node.identifier],
|
|
999
|
+
fallback: /* @__PURE__ */ jsxs2("span", { class: "incremark-image-ref-missing", children: [
|
|
1000
|
+
"![",
|
|
1001
|
+
node.alt,
|
|
1002
|
+
"][",
|
|
1003
|
+
node.identifier || node.label,
|
|
1004
|
+
"]"
|
|
1005
|
+
] }),
|
|
1006
|
+
children: /* @__PURE__ */ jsx5(
|
|
1007
|
+
"img",
|
|
1008
|
+
{
|
|
1009
|
+
class: "incremark-image incremark-reference-image",
|
|
1010
|
+
src: definations()[node.identifier].url,
|
|
1011
|
+
alt: node.alt || "",
|
|
1012
|
+
title: definations()[node.identifier].title || void 0,
|
|
1013
|
+
loading: "lazy"
|
|
1014
|
+
}
|
|
1015
|
+
)
|
|
1016
|
+
}
|
|
1017
|
+
) }),
|
|
1018
|
+
/* @__PURE__ */ jsx5(Show3, { when: isLinkReference(node), children: /* @__PURE__ */ jsx5(
|
|
1019
|
+
Show3,
|
|
1020
|
+
{
|
|
1021
|
+
when: definations()[node.identifier],
|
|
1022
|
+
fallback: /* @__PURE__ */ jsxs2("span", { class: "incremark-link-ref-missing", children: [
|
|
1023
|
+
"[",
|
|
1024
|
+
node.children.map((c) => c.value).join(""),
|
|
1025
|
+
"][",
|
|
1026
|
+
node.identifier || node.label,
|
|
1027
|
+
"]"
|
|
1028
|
+
] }),
|
|
1029
|
+
children: /* @__PURE__ */ jsx5(
|
|
1030
|
+
"a",
|
|
1031
|
+
{
|
|
1032
|
+
class: "incremark-link incremark-reference-link",
|
|
1033
|
+
href: definations()[node.identifier].url,
|
|
1034
|
+
title: definations()[node.identifier].title || void 0,
|
|
1035
|
+
target: "_blank",
|
|
1036
|
+
rel: "noopener noreferrer",
|
|
1037
|
+
children: /* @__PURE__ */ jsx5(IncremarkInline, { nodes: node.children })
|
|
1038
|
+
}
|
|
1039
|
+
)
|
|
1040
|
+
}
|
|
1041
|
+
) }),
|
|
1042
|
+
/* @__PURE__ */ jsx5(Show3, { when: node.type === "footnoteReference", children: /* @__PURE__ */ jsx5("sup", { class: "incremark-footnote-ref", children: /* @__PURE__ */ jsxs2("a", { href: `#fn-${node.identifier}`, id: `fnref-${node.identifier}`, children: [
|
|
1043
|
+
"[",
|
|
1044
|
+
node.identifier,
|
|
1045
|
+
"]"
|
|
1046
|
+
] }) }) }),
|
|
1047
|
+
/* @__PURE__ */ jsx5(Show3, { when: node.type === "break", children: /* @__PURE__ */ jsx5("br", {}) }),
|
|
1048
|
+
/* @__PURE__ */ jsx5(Show3, { when: node.type === "delete", children: /* @__PURE__ */ jsx5("del", { children: /* @__PURE__ */ jsx5(IncremarkInline, { nodes: node.children }) }) })
|
|
1049
|
+
] }) }) });
|
|
1050
|
+
};
|
|
1051
|
+
|
|
1052
|
+
// src/components/IncremarkHeading.tsx
|
|
1053
|
+
import { jsx as jsx6 } from "solid-js/jsx-runtime";
|
|
1054
|
+
var IncremarkHeading = (props) => {
|
|
1055
|
+
const tag = () => `h${props.node.depth}`;
|
|
1056
|
+
return /* @__PURE__ */ jsx6(Dynamic2, { component: tag(), class: `incremark-heading h${props.node.depth}`, children: /* @__PURE__ */ jsx6(IncremarkInline, { nodes: props.node.children }) });
|
|
1057
|
+
};
|
|
1058
|
+
|
|
1059
|
+
// src/components/IncremarkParagraph.tsx
|
|
1060
|
+
import { jsx as jsx7 } from "solid-js/jsx-runtime";
|
|
1061
|
+
var IncremarkParagraph = (props) => {
|
|
1062
|
+
return /* @__PURE__ */ jsx7("p", { class: "incremark-paragraph", children: /* @__PURE__ */ jsx7(IncremarkInline, { nodes: props.node.children }) });
|
|
1063
|
+
};
|
|
1064
|
+
|
|
1065
|
+
// src/components/IncremarkCode.tsx
|
|
1066
|
+
import { Show as Show7 } from "solid-js";
|
|
1067
|
+
import { Dynamic as Dynamic3 } from "solid-js/web";
|
|
1068
|
+
|
|
1069
|
+
// src/components/IncremarkCodeMermaid.tsx
|
|
1070
|
+
import { createEffect as createEffect5, createSignal as createSignal10, onCleanup as onCleanup4, onMount, Show as Show4 } from "solid-js";
|
|
1071
|
+
import { GravityMermaid, LucideCode, LucideEye, LucideCopy, LucideCopyCheck } from "@incremark/icons";
|
|
1072
|
+
import { isClipboardAvailable } from "@incremark/shared";
|
|
1073
|
+
|
|
1074
|
+
// src/components/SvgIcon.tsx
|
|
1075
|
+
import { jsx as jsx8 } from "solid-js/jsx-runtime";
|
|
1076
|
+
var SvgIcon = (props) => {
|
|
1077
|
+
return /* @__PURE__ */ jsx8(
|
|
1078
|
+
"span",
|
|
1079
|
+
{
|
|
1080
|
+
classList: {
|
|
1081
|
+
"incremark-icon": true,
|
|
1082
|
+
[props.sizeClass || ""]: !!props.sizeClass
|
|
1083
|
+
},
|
|
1084
|
+
innerHTML: props.svg,
|
|
1085
|
+
"aria-hidden": "true"
|
|
1086
|
+
}
|
|
1087
|
+
);
|
|
1088
|
+
};
|
|
1089
|
+
|
|
1090
|
+
// src/components/IncremarkCodeMermaid.tsx
|
|
1091
|
+
import { jsx as jsx9, jsxs as jsxs3 } from "solid-js/jsx-runtime";
|
|
1092
|
+
var IncremarkCodeMermaid = (props) => {
|
|
1093
|
+
const [mermaidSvg, setMermaidSvg] = createSignal10("");
|
|
1094
|
+
const [mermaidError, setMermaidError] = createSignal10("");
|
|
1095
|
+
const [mermaidLoading, setMermaidLoading] = createSignal10(false);
|
|
1096
|
+
const [copied, setCopied] = createSignal10(false);
|
|
1097
|
+
const [mermaidViewMode, setMermaidViewMode] = createSignal10("preview");
|
|
1098
|
+
let mermaidInstance = null;
|
|
1099
|
+
let renderTimer = null;
|
|
1100
|
+
let copyTimeoutId = null;
|
|
1101
|
+
let chartId = `mermaid-${Math.random().toString(36).substr(2, 9)}`;
|
|
1102
|
+
const code = () => props.node.value;
|
|
1103
|
+
const t = useLocale();
|
|
1104
|
+
function toggleMermaidView() {
|
|
1105
|
+
setMermaidViewMode((prev) => prev === "preview" ? "source" : "preview");
|
|
1106
|
+
}
|
|
1107
|
+
onMount(async () => {
|
|
1108
|
+
try {
|
|
1109
|
+
const mermaidModule = await import("mermaid");
|
|
1110
|
+
const mermaid = mermaidModule.default;
|
|
1111
|
+
mermaid.initialize({
|
|
1112
|
+
startOnLoad: false,
|
|
1113
|
+
theme: "dark",
|
|
1114
|
+
securityLevel: "loose",
|
|
1115
|
+
suppressErrorRendering: true
|
|
1116
|
+
});
|
|
1117
|
+
mermaidInstance = mermaid;
|
|
1118
|
+
} catch (e) {
|
|
1119
|
+
console.warn("Failed to initialize Mermaid:", e);
|
|
1120
|
+
setMermaidError("Failed to initialize");
|
|
1121
|
+
}
|
|
1122
|
+
});
|
|
1123
|
+
function scheduleRender() {
|
|
1124
|
+
if (!code()) {
|
|
1125
|
+
return;
|
|
1126
|
+
}
|
|
1127
|
+
if (renderTimer) {
|
|
1128
|
+
clearTimeout(renderTimer);
|
|
1129
|
+
}
|
|
1130
|
+
setMermaidLoading(true);
|
|
1131
|
+
setMermaidError("");
|
|
1132
|
+
renderTimer = setTimeout(() => {
|
|
1133
|
+
doRender();
|
|
1134
|
+
}, props.mermaidDelay ?? 500);
|
|
1135
|
+
}
|
|
1136
|
+
async function doRender() {
|
|
1137
|
+
if (!code() || !mermaidInstance) return;
|
|
1138
|
+
try {
|
|
1139
|
+
const { svg } = await mermaidInstance.render(chartId, code());
|
|
1140
|
+
setMermaidSvg(svg);
|
|
1141
|
+
setMermaidError("");
|
|
1142
|
+
} catch (e) {
|
|
1143
|
+
setMermaidError("");
|
|
1144
|
+
setMermaidSvg("");
|
|
1145
|
+
} finally {
|
|
1146
|
+
setMermaidLoading(false);
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
createEffect5(() => {
|
|
1150
|
+
scheduleRender();
|
|
1151
|
+
});
|
|
1152
|
+
onCleanup4(() => {
|
|
1153
|
+
if (renderTimer) {
|
|
1154
|
+
clearTimeout(renderTimer);
|
|
1155
|
+
}
|
|
1156
|
+
if (copyTimeoutId) {
|
|
1157
|
+
clearTimeout(copyTimeoutId);
|
|
1158
|
+
}
|
|
1159
|
+
});
|
|
1160
|
+
async function copyCode() {
|
|
1161
|
+
if (!isClipboardAvailable()) return;
|
|
1162
|
+
try {
|
|
1163
|
+
await navigator.clipboard.writeText(code());
|
|
1164
|
+
setCopied(true);
|
|
1165
|
+
if (copyTimeoutId) {
|
|
1166
|
+
clearTimeout(copyTimeoutId);
|
|
1167
|
+
}
|
|
1168
|
+
copyTimeoutId = setTimeout(() => {
|
|
1169
|
+
setCopied(false);
|
|
1170
|
+
}, 2e3);
|
|
1171
|
+
} catch {
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
return /* @__PURE__ */ jsxs3("div", { class: "incremark-mermaid", children: [
|
|
1175
|
+
/* @__PURE__ */ jsxs3("div", { class: "mermaid-header", children: [
|
|
1176
|
+
/* @__PURE__ */ jsxs3("span", { class: "language", children: [
|
|
1177
|
+
/* @__PURE__ */ jsx9(SvgIcon, { svg: GravityMermaid, sizeClass: "language-icon" }),
|
|
1178
|
+
"MERMAID"
|
|
1179
|
+
] }),
|
|
1180
|
+
/* @__PURE__ */ jsxs3("div", { class: "mermaid-actions", children: [
|
|
1181
|
+
/* @__PURE__ */ jsx9(
|
|
1182
|
+
"button",
|
|
1183
|
+
{
|
|
1184
|
+
class: "code-btn",
|
|
1185
|
+
onClick: toggleMermaidView,
|
|
1186
|
+
type: "button",
|
|
1187
|
+
disabled: !mermaidSvg(),
|
|
1188
|
+
"aria-label": mermaidViewMode() === "preview" ? t("mermaid.viewSource") : t("mermaid.preview"),
|
|
1189
|
+
title: mermaidViewMode() === "preview" ? "View Source" : "Preview",
|
|
1190
|
+
children: /* @__PURE__ */ jsx9(SvgIcon, { svg: mermaidViewMode() === "preview" ? LucideCode : LucideEye })
|
|
1191
|
+
}
|
|
1192
|
+
),
|
|
1193
|
+
/* @__PURE__ */ jsx9(
|
|
1194
|
+
"button",
|
|
1195
|
+
{
|
|
1196
|
+
class: "code-btn",
|
|
1197
|
+
onClick: copyCode,
|
|
1198
|
+
type: "button",
|
|
1199
|
+
"aria-label": copied() ? t("mermaid.copied") : t("mermaid.copy"),
|
|
1200
|
+
title: copied() ? "Copied!" : "Copy",
|
|
1201
|
+
children: /* @__PURE__ */ jsx9(SvgIcon, { svg: copied() ? LucideCopyCheck : LucideCopy })
|
|
1202
|
+
}
|
|
1203
|
+
)
|
|
1204
|
+
] })
|
|
1205
|
+
] }),
|
|
1206
|
+
/* @__PURE__ */ jsxs3("div", { class: "mermaid-content", children: [
|
|
1207
|
+
/* @__PURE__ */ jsx9(Show4, { when: mermaidLoading() && !mermaidSvg(), children: /* @__PURE__ */ jsx9("div", { class: "mermaid-loading", children: /* @__PURE__ */ jsx9("pre", { class: "mermaid-source-code", children: code() }) }) }),
|
|
1208
|
+
/* @__PURE__ */ jsx9(Show4, { when: mermaidViewMode() === "source" && !mermaidLoading(), children: /* @__PURE__ */ jsx9("pre", { class: "mermaid-source-code", children: code() }) }),
|
|
1209
|
+
/* @__PURE__ */ jsx9(Show4, { when: mermaidViewMode() === "preview" && mermaidSvg() && !mermaidLoading(), children: /* @__PURE__ */ jsx9("div", { innerHTML: mermaidSvg(), class: "mermaid-svg" }) }),
|
|
1210
|
+
/* @__PURE__ */ jsx9(Show4, { when: !mermaidSvg() && !mermaidLoading() && mermaidViewMode() === "preview", children: /* @__PURE__ */ jsx9("pre", { class: "mermaid-source-code", children: code() }) })
|
|
1211
|
+
] })
|
|
1212
|
+
] });
|
|
1213
|
+
};
|
|
1214
|
+
|
|
1215
|
+
// src/components/IncremarkCodeDefault.tsx
|
|
1216
|
+
import { createEffect as createEffect7, createSignal as createSignal12, onCleanup as onCleanup6, Show as Show6 } from "solid-js";
|
|
1217
|
+
import { LucideCopy as LucideCopy2, LucideCopyCheck as LucideCopyCheck2 } from "@incremark/icons";
|
|
1218
|
+
import { isClipboardAvailable as isClipboardAvailable2 } from "@incremark/shared";
|
|
1219
|
+
|
|
1220
|
+
// src/components/CachedCodeRenderer.tsx
|
|
1221
|
+
import { CodeToTokenTransformStream } from "shiki-stream";
|
|
1222
|
+
import { getTokenStyleObject } from "@shikijs/core";
|
|
1223
|
+
import { createEffect as createEffect6, createSignal as createSignal11, on, onCleanup as onCleanup5, onMount as onMount2, For as For3, Show as Show5 } from "solid-js";
|
|
1224
|
+
import { batch } from "solid-js";
|
|
1225
|
+
import { jsx as jsx10 } from "solid-js/jsx-runtime";
|
|
1226
|
+
var isBrowser = typeof window !== "undefined";
|
|
1227
|
+
var CachedCodeRenderer = (props) => {
|
|
1228
|
+
const [hasStreamError, setHasStreamError] = createSignal11(false);
|
|
1229
|
+
const [tokens, setTokens] = createSignal11([]);
|
|
1230
|
+
const [index, setIndex] = createSignal11(0);
|
|
1231
|
+
let controller = null;
|
|
1232
|
+
let abortController = null;
|
|
1233
|
+
onMount2(() => {
|
|
1234
|
+
if (!isBrowser) return;
|
|
1235
|
+
const textStream = new ReadableStream({
|
|
1236
|
+
start(_controller) {
|
|
1237
|
+
controller = _controller;
|
|
1238
|
+
}
|
|
1239
|
+
});
|
|
1240
|
+
try {
|
|
1241
|
+
const tokenStream = textStream.pipeThrough(
|
|
1242
|
+
new CodeToTokenTransformStream({
|
|
1243
|
+
highlighter: props.highlighter,
|
|
1244
|
+
lang: props.lang,
|
|
1245
|
+
theme: props.theme,
|
|
1246
|
+
allowRecalls: true
|
|
1247
|
+
})
|
|
1248
|
+
);
|
|
1249
|
+
let started = false;
|
|
1250
|
+
abortController = new AbortController();
|
|
1251
|
+
tokenStream.pipeTo(new WritableStream({
|
|
1252
|
+
write(token) {
|
|
1253
|
+
if (abortController?.signal.aborted) return;
|
|
1254
|
+
if (!started) {
|
|
1255
|
+
started = true;
|
|
1256
|
+
props.onStreamStart?.();
|
|
1257
|
+
}
|
|
1258
|
+
batch(() => {
|
|
1259
|
+
if ("recall" in token) {
|
|
1260
|
+
setTokens((ts) => ts.slice(0, -token.recall));
|
|
1261
|
+
} else {
|
|
1262
|
+
setTokens((ts) => [...ts, token]);
|
|
1263
|
+
}
|
|
1264
|
+
});
|
|
1265
|
+
},
|
|
1266
|
+
close: () => {
|
|
1267
|
+
if (!abortController?.signal.aborted) {
|
|
1268
|
+
props.onStreamEnd?.();
|
|
1269
|
+
}
|
|
1270
|
+
},
|
|
1271
|
+
abort: () => {
|
|
1272
|
+
if (!abortController?.signal.aborted) {
|
|
1273
|
+
props.onStreamEnd?.();
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
}), { signal: abortController.signal }).catch((error) => {
|
|
1277
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
1278
|
+
return;
|
|
1279
|
+
}
|
|
1280
|
+
if (error instanceof Error && error.message.includes("not found")) {
|
|
1281
|
+
setHasStreamError(true);
|
|
1282
|
+
return;
|
|
1283
|
+
}
|
|
1284
|
+
console.error("Stream error:", error);
|
|
1285
|
+
setHasStreamError(true);
|
|
1286
|
+
});
|
|
1287
|
+
} catch (error) {
|
|
1288
|
+
if (error instanceof Error && error.message.includes("not found")) {
|
|
1289
|
+
setHasStreamError(true);
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1292
|
+
console.error("Failed to create token stream:", error);
|
|
1293
|
+
setHasStreamError(true);
|
|
1294
|
+
}
|
|
1295
|
+
});
|
|
1296
|
+
createEffect6(on(
|
|
1297
|
+
() => props.code,
|
|
1298
|
+
(newCode) => {
|
|
1299
|
+
if (!isBrowser || !controller || abortController?.signal.aborted) return;
|
|
1300
|
+
const currentIndex = index();
|
|
1301
|
+
if (newCode.length > currentIndex && !hasStreamError()) {
|
|
1302
|
+
const incremental = newCode.slice(currentIndex);
|
|
1303
|
+
controller.enqueue(incremental);
|
|
1304
|
+
setIndex(newCode.length);
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
));
|
|
1308
|
+
onCleanup5(() => {
|
|
1309
|
+
abortController?.abort();
|
|
1310
|
+
controller = null;
|
|
1311
|
+
setHasStreamError(false);
|
|
1312
|
+
setTokens([]);
|
|
1313
|
+
setIndex(0);
|
|
1314
|
+
});
|
|
1315
|
+
return /* @__PURE__ */ jsx10(
|
|
1316
|
+
Show5,
|
|
1317
|
+
{
|
|
1318
|
+
when: !(hasStreamError() || !isBrowser || tokens().length === 0),
|
|
1319
|
+
fallback: (
|
|
1320
|
+
// SSR 或错误时渲染原始代码
|
|
1321
|
+
/* @__PURE__ */ jsx10("pre", { class: "shiki incremark-code-stream", children: /* @__PURE__ */ jsx10("code", { children: props.code }) })
|
|
1322
|
+
),
|
|
1323
|
+
children: /* @__PURE__ */ jsx10("pre", { class: "shiki incremark-code-stream", children: /* @__PURE__ */ jsx10("code", { children: /* @__PURE__ */ jsx10(For3, { each: tokens(), children: (token) => /* @__PURE__ */ jsx10("span", { style: token.htmlStyle ?? getTokenStyleObject(token), children: token.content }) }) }) })
|
|
1324
|
+
}
|
|
1325
|
+
);
|
|
1326
|
+
};
|
|
1327
|
+
|
|
1328
|
+
// src/components/IncremarkCodeDefault.tsx
|
|
1329
|
+
import { jsx as jsx11, jsxs as jsxs4 } from "solid-js/jsx-runtime";
|
|
1330
|
+
var IncremarkCodeDefault = (props) => {
|
|
1331
|
+
const [copied, setCopied] = createSignal12(false);
|
|
1332
|
+
const language = () => props.node.lang || "text";
|
|
1333
|
+
const code = () => props.node.value;
|
|
1334
|
+
const t = useLocale();
|
|
1335
|
+
const { highlighterInfo, initHighlighter } = useShiki(props.theme ?? "github-dark");
|
|
1336
|
+
const [isLanguageLoaded, setIsLanguageLoaded] = createSignal12(false);
|
|
1337
|
+
const shouldEnableHighlight = () => {
|
|
1338
|
+
return !props.disableHighlight && code() && code().length > 0;
|
|
1339
|
+
};
|
|
1340
|
+
createEffect7(async () => {
|
|
1341
|
+
const info = highlighterInfo();
|
|
1342
|
+
const lang = language();
|
|
1343
|
+
const shouldHighlight = shouldEnableHighlight();
|
|
1344
|
+
if (!shouldHighlight) {
|
|
1345
|
+
return;
|
|
1346
|
+
}
|
|
1347
|
+
if (!info) {
|
|
1348
|
+
await initHighlighter();
|
|
1349
|
+
} else if (lang && lang !== "text") {
|
|
1350
|
+
if (!info.loadedLanguages.has(lang)) {
|
|
1351
|
+
try {
|
|
1352
|
+
setIsLanguageLoaded(false);
|
|
1353
|
+
const supportedLangs = info.highlighter.getLoadedLanguages();
|
|
1354
|
+
const bundledLangs = await import("shiki").then((m) => Object.keys(m.bundledLanguages || {}));
|
|
1355
|
+
const isSupported = supportedLangs.includes(lang) || bundledLangs.includes(lang);
|
|
1356
|
+
if (isSupported) {
|
|
1357
|
+
await info.highlighter.loadLanguage(lang);
|
|
1358
|
+
info.loadedLanguages.add(lang);
|
|
1359
|
+
}
|
|
1360
|
+
setIsLanguageLoaded(true);
|
|
1361
|
+
} catch {
|
|
1362
|
+
setIsLanguageLoaded(true);
|
|
1363
|
+
}
|
|
1364
|
+
} else {
|
|
1365
|
+
setIsLanguageLoaded(true);
|
|
1366
|
+
}
|
|
1367
|
+
} else {
|
|
1368
|
+
setIsLanguageLoaded(true);
|
|
1369
|
+
}
|
|
1370
|
+
});
|
|
1371
|
+
let copyTimeoutId = null;
|
|
1372
|
+
onCleanup6(() => {
|
|
1373
|
+
if (copyTimeoutId) {
|
|
1374
|
+
clearTimeout(copyTimeoutId);
|
|
1375
|
+
}
|
|
1376
|
+
});
|
|
1377
|
+
async function copyCode() {
|
|
1378
|
+
if (!isClipboardAvailable2()) return;
|
|
1379
|
+
try {
|
|
1380
|
+
await navigator.clipboard.writeText(code());
|
|
1381
|
+
setCopied(true);
|
|
1382
|
+
if (copyTimeoutId) {
|
|
1383
|
+
clearTimeout(copyTimeoutId);
|
|
1384
|
+
}
|
|
1385
|
+
copyTimeoutId = setTimeout(() => {
|
|
1386
|
+
setCopied(false);
|
|
1387
|
+
}, 2e3);
|
|
1388
|
+
} catch {
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
return /* @__PURE__ */ jsxs4("div", { class: "incremark-code", children: [
|
|
1392
|
+
/* @__PURE__ */ jsxs4("div", { class: "code-header", children: [
|
|
1393
|
+
/* @__PURE__ */ jsx11("span", { class: "language", children: language() }),
|
|
1394
|
+
/* @__PURE__ */ jsx11(
|
|
1395
|
+
"button",
|
|
1396
|
+
{
|
|
1397
|
+
class: "code-btn",
|
|
1398
|
+
onClick: copyCode,
|
|
1399
|
+
type: "button",
|
|
1400
|
+
"aria-label": copied() ? t("code.copied") : t("code.copy"),
|
|
1401
|
+
title: copied() ? "Copied!" : "Copy",
|
|
1402
|
+
children: /* @__PURE__ */ jsx11(SvgIcon, { svg: copied() ? LucideCopyCheck2 : LucideCopy2 })
|
|
1403
|
+
}
|
|
1404
|
+
)
|
|
1405
|
+
] }),
|
|
1406
|
+
/* @__PURE__ */ jsx11("div", { class: "code-content", children: /* @__PURE__ */ jsx11("div", { class: "shiki-wrapper", children: /* @__PURE__ */ jsx11(
|
|
1407
|
+
Show6,
|
|
1408
|
+
{
|
|
1409
|
+
when: shouldEnableHighlight() && highlighterInfo() && isLanguageLoaded(),
|
|
1410
|
+
fallback: (
|
|
1411
|
+
// 无高亮模式(禁用高亮、无代码内容、或语言未加载完成时显示)
|
|
1412
|
+
/* @__PURE__ */ jsx11("pre", { class: "code-fallback", children: /* @__PURE__ */ jsx11("code", { children: code() }) })
|
|
1413
|
+
),
|
|
1414
|
+
children: /* @__PURE__ */ jsx11(
|
|
1415
|
+
CachedCodeRenderer,
|
|
1416
|
+
{
|
|
1417
|
+
code: code(),
|
|
1418
|
+
lang: language(),
|
|
1419
|
+
theme: props.theme ?? "github-dark",
|
|
1420
|
+
highlighter: highlighterInfo().highlighter
|
|
1421
|
+
}
|
|
1422
|
+
)
|
|
1423
|
+
}
|
|
1424
|
+
) }) })
|
|
1425
|
+
] });
|
|
1426
|
+
};
|
|
1427
|
+
|
|
1428
|
+
// src/components/IncremarkCode.tsx
|
|
1429
|
+
import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs5 } from "solid-js/jsx-runtime";
|
|
1430
|
+
var IncremarkCode = (props) => {
|
|
1431
|
+
const language = () => props.node.lang || "text";
|
|
1432
|
+
const CustomCodeBlock = () => props.customCodeBlocks?.[language()];
|
|
1433
|
+
const shouldUseCustomCodeBlock = () => {
|
|
1434
|
+
const component = props.customCodeBlocks?.[language()];
|
|
1435
|
+
if (!component) return false;
|
|
1436
|
+
const config = props.codeBlockConfigs?.[language()];
|
|
1437
|
+
if (config?.takeOver) {
|
|
1438
|
+
return true;
|
|
1439
|
+
}
|
|
1440
|
+
return props.blockStatus === "completed";
|
|
1441
|
+
};
|
|
1442
|
+
const isMermaid = () => language() === "mermaid";
|
|
1443
|
+
const DefaultCodeComponent = () => props.defaultCodeComponent ?? IncremarkCodeDefault;
|
|
1444
|
+
const customProps = () => ({
|
|
1445
|
+
codeStr: props.node.value,
|
|
1446
|
+
lang: language(),
|
|
1447
|
+
completed: props.blockStatus === "completed",
|
|
1448
|
+
takeOver: props.codeBlockConfigs?.[language()]?.takeOver
|
|
1449
|
+
});
|
|
1450
|
+
const defaultProps = () => ({
|
|
1451
|
+
node: props.node,
|
|
1452
|
+
theme: props.theme,
|
|
1453
|
+
fallbackTheme: props.fallbackTheme,
|
|
1454
|
+
disableHighlight: props.disableHighlight,
|
|
1455
|
+
blockStatus: props.blockStatus
|
|
1456
|
+
});
|
|
1457
|
+
const mermaidProps = () => ({
|
|
1458
|
+
node: props.node,
|
|
1459
|
+
mermaidDelay: props.mermaidDelay
|
|
1460
|
+
});
|
|
1461
|
+
return /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1462
|
+
/* @__PURE__ */ jsx12(Show7, { when: CustomCodeBlock() && shouldUseCustomCodeBlock(), children: /* @__PURE__ */ jsx12(
|
|
1463
|
+
Dynamic3,
|
|
1464
|
+
{
|
|
1465
|
+
component: CustomCodeBlock(),
|
|
1466
|
+
...customProps()
|
|
1467
|
+
}
|
|
1468
|
+
) }),
|
|
1469
|
+
/* @__PURE__ */ jsx12(Show7, { when: isMermaid() && !shouldUseCustomCodeBlock(), children: /* @__PURE__ */ jsx12(
|
|
1470
|
+
IncremarkCodeMermaid,
|
|
1471
|
+
{
|
|
1472
|
+
node: props.node,
|
|
1473
|
+
mermaidDelay: props.mermaidDelay
|
|
1474
|
+
}
|
|
1475
|
+
) }),
|
|
1476
|
+
/* @__PURE__ */ jsx12(Show7, { when: !isMermaid() && !shouldUseCustomCodeBlock(), children: /* @__PURE__ */ jsx12(
|
|
1477
|
+
Dynamic3,
|
|
1478
|
+
{
|
|
1479
|
+
component: DefaultCodeComponent(),
|
|
1480
|
+
...defaultProps()
|
|
1481
|
+
}
|
|
1482
|
+
) })
|
|
1483
|
+
] });
|
|
1484
|
+
};
|
|
1485
|
+
var IncremarkCode_default = IncremarkCode;
|
|
1486
|
+
|
|
1487
|
+
// src/components/IncremarkList.tsx
|
|
1488
|
+
import { Show as Show8, Index as Index2 } from "solid-js";
|
|
1489
|
+
import { jsx as jsx13, jsxs as jsxs6 } from "solid-js/jsx-runtime";
|
|
1490
|
+
var IncremarkList = (props) => {
|
|
1491
|
+
const ordered = () => props.node.ordered;
|
|
1492
|
+
const start = () => props.node.start || void 0;
|
|
1493
|
+
function getItemInlineContent(item) {
|
|
1494
|
+
const firstChild = item.children[0];
|
|
1495
|
+
if (firstChild?.type === "paragraph") {
|
|
1496
|
+
return firstChild.children;
|
|
1497
|
+
}
|
|
1498
|
+
return [];
|
|
1499
|
+
}
|
|
1500
|
+
function getItemBlockChildren(item) {
|
|
1501
|
+
return item.children.filter((child, index) => {
|
|
1502
|
+
if (index === 0 && child.type === "paragraph") {
|
|
1503
|
+
return false;
|
|
1504
|
+
}
|
|
1505
|
+
return true;
|
|
1506
|
+
});
|
|
1507
|
+
}
|
|
1508
|
+
function hasBlockChildren(item) {
|
|
1509
|
+
return getItemBlockChildren(item).length > 0;
|
|
1510
|
+
}
|
|
1511
|
+
const hasTaskList = () => props.node.children.some((item) => item.checked !== null && item.checked !== void 0);
|
|
1512
|
+
return /* @__PURE__ */ jsx13(
|
|
1513
|
+
Show8,
|
|
1514
|
+
{
|
|
1515
|
+
when: ordered(),
|
|
1516
|
+
fallback: /* @__PURE__ */ jsx13(
|
|
1517
|
+
"ul",
|
|
1518
|
+
{
|
|
1519
|
+
class: `incremark-list${hasTaskList() ? " task-list" : ""}`,
|
|
1520
|
+
children: /* @__PURE__ */ jsx13(Index2, { each: props.node.children, children: (item, index) => {
|
|
1521
|
+
const itemData = item();
|
|
1522
|
+
const isTaskItem = itemData.checked !== null && itemData.checked !== void 0;
|
|
1523
|
+
return /* @__PURE__ */ jsxs6(
|
|
1524
|
+
"li",
|
|
1525
|
+
{
|
|
1526
|
+
class: `incremark-list-item${isTaskItem ? " task-item" : ""}`,
|
|
1527
|
+
children: [
|
|
1528
|
+
/* @__PURE__ */ jsx13(Show8, { when: isTaskItem, children: /* @__PURE__ */ jsxs6("label", { class: "task-label", children: [
|
|
1529
|
+
/* @__PURE__ */ jsx13(
|
|
1530
|
+
"input",
|
|
1531
|
+
{
|
|
1532
|
+
type: "checkbox",
|
|
1533
|
+
checked: itemData.checked ?? false,
|
|
1534
|
+
disabled: true,
|
|
1535
|
+
class: "checkbox"
|
|
1536
|
+
}
|
|
1537
|
+
),
|
|
1538
|
+
/* @__PURE__ */ jsx13("span", { class: "task-content", children: /* @__PURE__ */ jsx13(IncremarkInline, { nodes: getItemInlineContent(itemData) }) })
|
|
1539
|
+
] }) }),
|
|
1540
|
+
/* @__PURE__ */ jsxs6(Show8, { when: !isTaskItem, children: [
|
|
1541
|
+
/* @__PURE__ */ jsx13(IncremarkInline, { nodes: getItemInlineContent(itemData) }),
|
|
1542
|
+
/* @__PURE__ */ jsx13(Show8, { when: hasBlockChildren(itemData), children: /* @__PURE__ */ jsx13(Index2, { each: getItemBlockChildren(itemData), children: (child) => /* @__PURE__ */ jsx13(IncremarkRenderer, { node: child() }) }) })
|
|
1543
|
+
] })
|
|
1544
|
+
]
|
|
1545
|
+
}
|
|
1546
|
+
);
|
|
1547
|
+
} })
|
|
1548
|
+
}
|
|
1549
|
+
),
|
|
1550
|
+
children: /* @__PURE__ */ jsx13(
|
|
1551
|
+
"ol",
|
|
1552
|
+
{
|
|
1553
|
+
class: `incremark-list${hasTaskList() ? " task-list" : ""}`,
|
|
1554
|
+
start: start(),
|
|
1555
|
+
children: /* @__PURE__ */ jsx13(Index2, { each: props.node.children, children: (item, index) => {
|
|
1556
|
+
const itemData = item();
|
|
1557
|
+
const isTaskItem = itemData.checked !== null && itemData.checked !== void 0;
|
|
1558
|
+
return /* @__PURE__ */ jsxs6(
|
|
1559
|
+
"li",
|
|
1560
|
+
{
|
|
1561
|
+
class: `incremark-list-item${isTaskItem ? " task-item" : ""}`,
|
|
1562
|
+
children: [
|
|
1563
|
+
/* @__PURE__ */ jsx13(Show8, { when: isTaskItem, children: /* @__PURE__ */ jsxs6("label", { class: "task-label", children: [
|
|
1564
|
+
/* @__PURE__ */ jsx13(
|
|
1565
|
+
"input",
|
|
1566
|
+
{
|
|
1567
|
+
type: "checkbox",
|
|
1568
|
+
checked: itemData.checked ?? false,
|
|
1569
|
+
disabled: true,
|
|
1570
|
+
class: "checkbox"
|
|
1571
|
+
}
|
|
1572
|
+
),
|
|
1573
|
+
/* @__PURE__ */ jsx13("span", { class: "task-content", children: /* @__PURE__ */ jsx13(IncremarkInline, { nodes: getItemInlineContent(itemData) }) })
|
|
1574
|
+
] }) }),
|
|
1575
|
+
/* @__PURE__ */ jsxs6(Show8, { when: !isTaskItem, children: [
|
|
1576
|
+
/* @__PURE__ */ jsx13(IncremarkInline, { nodes: getItemInlineContent(itemData) }),
|
|
1577
|
+
/* @__PURE__ */ jsx13(Show8, { when: hasBlockChildren(itemData), children: /* @__PURE__ */ jsx13(Index2, { each: getItemBlockChildren(itemData), children: (child) => /* @__PURE__ */ jsx13(IncremarkRenderer, { node: child() }) }) })
|
|
1578
|
+
] })
|
|
1579
|
+
]
|
|
1580
|
+
}
|
|
1581
|
+
);
|
|
1582
|
+
} })
|
|
1583
|
+
}
|
|
1584
|
+
)
|
|
1585
|
+
}
|
|
1586
|
+
);
|
|
1587
|
+
};
|
|
1588
|
+
|
|
1589
|
+
// src/components/IncremarkTable.tsx
|
|
1590
|
+
import { For as For5, Show as Show9 } from "solid-js";
|
|
1591
|
+
import { jsx as jsx14, jsxs as jsxs7 } from "solid-js/jsx-runtime";
|
|
1592
|
+
var IncremarkTable = (props) => {
|
|
1593
|
+
function getCellContent(cell) {
|
|
1594
|
+
return cell.children;
|
|
1595
|
+
}
|
|
1596
|
+
const firstRow = () => props.node.children[0];
|
|
1597
|
+
const remainingRows = () => props.node.children.slice(1);
|
|
1598
|
+
const getAlignClass = (cellIndex) => {
|
|
1599
|
+
return `incremark-table-align-${props.node.align?.[cellIndex] || "left"}`;
|
|
1600
|
+
};
|
|
1601
|
+
return /* @__PURE__ */ jsx14("div", { class: "incremark-table-wrapper", children: /* @__PURE__ */ jsxs7("table", { class: "incremark-table", children: [
|
|
1602
|
+
/* @__PURE__ */ jsx14(Show9, { when: firstRow(), children: /* @__PURE__ */ jsx14("thead", { children: /* @__PURE__ */ jsx14("tr", { children: /* @__PURE__ */ jsx14(For5, { each: firstRow().children, children: (cell, cellIndex) => /* @__PURE__ */ jsx14("th", { class: getAlignClass(cellIndex()), children: /* @__PURE__ */ jsx14(IncremarkInline, { nodes: getCellContent(cell) }) }) }) }) }) }),
|
|
1603
|
+
/* @__PURE__ */ jsx14("tbody", { children: /* @__PURE__ */ jsx14(For5, { each: remainingRows(), children: (row) => /* @__PURE__ */ jsx14("tr", { children: /* @__PURE__ */ jsx14(For5, { each: row.children, children: (cell, cellIndex) => /* @__PURE__ */ jsx14("td", { class: getAlignClass(cellIndex()), children: /* @__PURE__ */ jsx14(IncremarkInline, { nodes: getCellContent(cell) }) }) }) }) }) })
|
|
1604
|
+
] }) });
|
|
1605
|
+
};
|
|
1606
|
+
|
|
1607
|
+
// src/components/IncremarkBlockquote.tsx
|
|
1608
|
+
import { For as For6 } from "solid-js";
|
|
1609
|
+
import { jsx as jsx15 } from "solid-js/jsx-runtime";
|
|
1610
|
+
var IncremarkBlockquote = (props) => {
|
|
1611
|
+
return /* @__PURE__ */ jsx15("blockquote", { class: "incremark-blockquote", children: /* @__PURE__ */ jsx15(For6, { each: props.node.children, children: (child) => /* @__PURE__ */ jsx15(IncremarkRenderer, { node: child }) }) });
|
|
1612
|
+
};
|
|
1613
|
+
|
|
1614
|
+
// src/components/IncremarkThematicBreak.tsx
|
|
1615
|
+
import { jsx as jsx16 } from "solid-js/jsx-runtime";
|
|
1616
|
+
var IncremarkThematicBreak = () => {
|
|
1617
|
+
return /* @__PURE__ */ jsx16("hr", { class: "incremark-thematic-break" });
|
|
1618
|
+
};
|
|
1619
|
+
|
|
1620
|
+
// src/components/IncremarkContainer.tsx
|
|
1621
|
+
import { For as For7, Show as Show10 } from "solid-js";
|
|
1622
|
+
import { Dynamic as Dynamic4 } from "solid-js/web";
|
|
1623
|
+
import { jsx as jsx17 } from "solid-js/jsx-runtime";
|
|
1624
|
+
function parseOptions(attributes) {
|
|
1625
|
+
if (!attributes) return {};
|
|
1626
|
+
const options = {};
|
|
1627
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
1628
|
+
try {
|
|
1629
|
+
options[key] = JSON.parse(value);
|
|
1630
|
+
} catch {
|
|
1631
|
+
options[key] = value;
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
return options;
|
|
1635
|
+
}
|
|
1636
|
+
var IncremarkContainer = (props) => {
|
|
1637
|
+
const containerName = () => props.node.name;
|
|
1638
|
+
const options = () => parseOptions(props.node.attributes);
|
|
1639
|
+
const CustomContainer = () => props.customContainers?.[containerName()];
|
|
1640
|
+
const hasCustomContainer = () => !!props.customContainers?.[containerName()];
|
|
1641
|
+
return /* @__PURE__ */ jsx17(
|
|
1642
|
+
Show10,
|
|
1643
|
+
{
|
|
1644
|
+
when: hasCustomContainer(),
|
|
1645
|
+
fallback: /* @__PURE__ */ jsx17("div", { class: `incremark-container incremark-container-${containerName()}`, children: /* @__PURE__ */ jsx17(Show10, { when: props.node.children && props.node.children.length > 0, children: /* @__PURE__ */ jsx17("div", { class: "incremark-container-content", children: /* @__PURE__ */ jsx17(For7, { each: props.node.children, children: (child) => /* @__PURE__ */ jsx17(IncremarkRenderer, { node: child }) }) }) }) }),
|
|
1646
|
+
children: /* @__PURE__ */ jsx17(
|
|
1647
|
+
Dynamic4,
|
|
1648
|
+
{
|
|
1649
|
+
component: CustomContainer(),
|
|
1650
|
+
name: containerName(),
|
|
1651
|
+
options: options(),
|
|
1652
|
+
children: /* @__PURE__ */ jsx17(Show10, { when: props.node.children && props.node.children.length > 0, children: /* @__PURE__ */ jsx17(For7, { each: props.node.children, children: (child) => /* @__PURE__ */ jsx17(IncremarkRenderer, { node: child }) }) })
|
|
1653
|
+
}
|
|
1654
|
+
)
|
|
1655
|
+
}
|
|
1656
|
+
);
|
|
1657
|
+
};
|
|
1658
|
+
|
|
1659
|
+
// src/components/IncremarkDefault.tsx
|
|
1660
|
+
import { jsx as jsx18 } from "solid-js/jsx-runtime";
|
|
1661
|
+
var IncremarkDefault = (props) => {
|
|
1662
|
+
return /* @__PURE__ */ jsx18("pre", { class: "incremark-debug", children: /* @__PURE__ */ jsx18("code", { children: JSON.stringify(props.node, null, 2) }) });
|
|
1663
|
+
};
|
|
1664
|
+
|
|
1665
|
+
// src/components/IncremarkRenderer.tsx
|
|
1666
|
+
import { Fragment as Fragment4, jsx as jsx19, jsxs as jsxs8 } from "solid-js/jsx-runtime";
|
|
1667
|
+
var defaultComponentMap = {
|
|
1668
|
+
heading: IncremarkHeading,
|
|
1669
|
+
paragraph: IncremarkParagraph,
|
|
1670
|
+
code: IncremarkCode_default,
|
|
1671
|
+
list: IncremarkList,
|
|
1672
|
+
table: IncremarkTable,
|
|
1673
|
+
blockquote: IncremarkBlockquote,
|
|
1674
|
+
thematicBreak: IncremarkThematicBreak,
|
|
1675
|
+
math: IncremarkMath,
|
|
1676
|
+
inlineMath: IncremarkMath,
|
|
1677
|
+
htmlElement: IncremarkHtmlElement,
|
|
1678
|
+
containerDirective: IncremarkContainer,
|
|
1679
|
+
leafDirective: IncremarkContainer,
|
|
1680
|
+
textDirective: IncremarkContainer
|
|
1681
|
+
};
|
|
1682
|
+
function getComponent(type, customComponents) {
|
|
1683
|
+
const map = { ...defaultComponentMap, ...customComponents };
|
|
1684
|
+
return map[type] || IncremarkDefault;
|
|
1685
|
+
}
|
|
1686
|
+
function isContainerNode(node) {
|
|
1687
|
+
const type = node.type;
|
|
1688
|
+
return type === "containerDirective" || type === "leafDirective" || type === "textDirective";
|
|
1689
|
+
}
|
|
1690
|
+
function isHtmlNode2(node) {
|
|
1691
|
+
return node.type === "html";
|
|
1692
|
+
}
|
|
1693
|
+
var IncremarkRenderer = (props) => {
|
|
1694
|
+
return /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
1695
|
+
/* @__PURE__ */ jsx19(Show11, { when: isHtmlNode2(props.node), children: /* @__PURE__ */ jsx19("pre", { class: "incremark-html-code", children: /* @__PURE__ */ jsx19("code", { children: props.node.value }) }) }),
|
|
1696
|
+
/* @__PURE__ */ jsx19(Show11, { when: isContainerNode(props.node) && !isHtmlNode2(props.node), children: /* @__PURE__ */ jsx19(
|
|
1697
|
+
IncremarkContainer,
|
|
1698
|
+
{
|
|
1699
|
+
node: props.node,
|
|
1700
|
+
customContainers: props.customContainers
|
|
1701
|
+
}
|
|
1702
|
+
) }),
|
|
1703
|
+
/* @__PURE__ */ jsx19(
|
|
1704
|
+
Show11,
|
|
1705
|
+
{
|
|
1706
|
+
when: props.node.type === "code" && !isHtmlNode2(props.node) && !isContainerNode(props.node),
|
|
1707
|
+
children: /* @__PURE__ */ jsx19(
|
|
1708
|
+
IncremarkCode_default,
|
|
1709
|
+
{
|
|
1710
|
+
node: props.node,
|
|
1711
|
+
customCodeBlocks: props.customCodeBlocks,
|
|
1712
|
+
codeBlockConfigs: props.codeBlockConfigs,
|
|
1713
|
+
blockStatus: props.blockStatus,
|
|
1714
|
+
defaultCodeComponent: props.components?.["code"]
|
|
1715
|
+
}
|
|
1716
|
+
)
|
|
1717
|
+
}
|
|
1718
|
+
),
|
|
1719
|
+
/* @__PURE__ */ jsx19(
|
|
1720
|
+
Show11,
|
|
1721
|
+
{
|
|
1722
|
+
when: props.node.type !== "code" && !isHtmlNode2(props.node) && !isContainerNode(props.node),
|
|
1723
|
+
children: /* @__PURE__ */ jsx19(
|
|
1724
|
+
Dynamic5,
|
|
1725
|
+
{
|
|
1726
|
+
component: getComponent(props.node.type, props.components),
|
|
1727
|
+
node: props.node
|
|
1728
|
+
}
|
|
1729
|
+
)
|
|
1730
|
+
}
|
|
1731
|
+
)
|
|
1732
|
+
] });
|
|
1733
|
+
};
|
|
1734
|
+
var IncremarkRenderer_default = IncremarkRenderer;
|
|
1735
|
+
|
|
1736
|
+
// src/components/IncremarkFootnotes.tsx
|
|
1737
|
+
import { For as For8, Show as Show12 } from "solid-js";
|
|
1738
|
+
import { jsx as jsx20, jsxs as jsxs9 } from "solid-js/jsx-runtime";
|
|
1739
|
+
var IncremarkFootnotes = () => {
|
|
1740
|
+
const { footnoteDefinitions, footnoteReferenceOrder } = useDefinationsContext();
|
|
1741
|
+
const orderedFootnotes = () => {
|
|
1742
|
+
return footnoteReferenceOrder().map((identifier) => ({
|
|
1743
|
+
identifier,
|
|
1744
|
+
definition: footnoteDefinitions()[identifier]
|
|
1745
|
+
})).filter((item) => item.definition !== void 0);
|
|
1746
|
+
};
|
|
1747
|
+
const hasFootnotes = () => orderedFootnotes().length > 0;
|
|
1748
|
+
return /* @__PURE__ */ jsx20(Show12, { when: hasFootnotes(), children: /* @__PURE__ */ jsxs9("section", { class: "incremark-footnotes", children: [
|
|
1749
|
+
/* @__PURE__ */ jsx20("hr", { class: "incremark-footnotes-divider" }),
|
|
1750
|
+
/* @__PURE__ */ jsx20("ol", { class: "incremark-footnotes-list", children: /* @__PURE__ */ jsx20(For8, { each: orderedFootnotes(), children: (item, index) => /* @__PURE__ */ jsxs9(
|
|
1751
|
+
"li",
|
|
1752
|
+
{
|
|
1753
|
+
id: `fn-${item.identifier}`,
|
|
1754
|
+
class: "incremark-footnote-item",
|
|
1755
|
+
children: [
|
|
1756
|
+
/* @__PURE__ */ jsxs9("div", { class: "incremark-footnote-content", children: [
|
|
1757
|
+
/* @__PURE__ */ jsxs9("span", { class: "incremark-footnote-number", children: [
|
|
1758
|
+
index() + 1,
|
|
1759
|
+
"."
|
|
1760
|
+
] }),
|
|
1761
|
+
/* @__PURE__ */ jsx20("div", { class: "incremark-footnote-body", children: /* @__PURE__ */ jsx20(For8, { each: item.definition.children, children: (child) => /* @__PURE__ */ jsx20(
|
|
1762
|
+
IncremarkRenderer_default,
|
|
1763
|
+
{
|
|
1764
|
+
node: child
|
|
1765
|
+
}
|
|
1766
|
+
) }) })
|
|
1767
|
+
] }),
|
|
1768
|
+
/* @__PURE__ */ jsx20(
|
|
1769
|
+
"a",
|
|
1770
|
+
{
|
|
1771
|
+
href: `#fnref-${item.identifier}`,
|
|
1772
|
+
class: "incremark-footnote-backref",
|
|
1773
|
+
"aria-label": "\u8FD4\u56DE\u5F15\u7528\u4F4D\u7F6E",
|
|
1774
|
+
children: "\u21A9"
|
|
1775
|
+
}
|
|
1776
|
+
)
|
|
1777
|
+
]
|
|
1778
|
+
}
|
|
1779
|
+
) }) })
|
|
1780
|
+
] }) });
|
|
1781
|
+
};
|
|
1782
|
+
|
|
1783
|
+
// src/components/Incremark.tsx
|
|
1784
|
+
import { jsx as jsx21, jsxs as jsxs10 } from "solid-js/jsx-runtime";
|
|
1785
|
+
function IncremarkInner(props) {
|
|
1786
|
+
const mergedProps = mergeProps({
|
|
1787
|
+
isDisplayComplete: false,
|
|
1788
|
+
pendingClass: "incremark-pending",
|
|
1789
|
+
completedClass: "incremark-completed",
|
|
1790
|
+
showBlockStatus: false
|
|
1791
|
+
}, props);
|
|
1792
|
+
const components = () => mergedProps.components || {};
|
|
1793
|
+
const customContainers = () => mergedProps.customContainers || {};
|
|
1794
|
+
const customCodeBlocks = () => mergedProps.customCodeBlocks || {};
|
|
1795
|
+
const codeBlockConfigs = () => mergedProps.codeBlockConfigs || {};
|
|
1796
|
+
const {
|
|
1797
|
+
footnoteReferenceOrder
|
|
1798
|
+
} = useDefinationsContext();
|
|
1799
|
+
const actualBlocks = () => {
|
|
1800
|
+
if (mergedProps.incremark) {
|
|
1801
|
+
return mergedProps.incremark.blocks;
|
|
1802
|
+
}
|
|
1803
|
+
return typeof mergedProps.blocks === "function" ? mergedProps.blocks() : mergedProps.blocks;
|
|
1804
|
+
};
|
|
1805
|
+
const actualIsDisplayComplete = () => {
|
|
1806
|
+
if (mergedProps.incremark) {
|
|
1807
|
+
return mergedProps.incremark.isDisplayComplete();
|
|
1808
|
+
}
|
|
1809
|
+
return typeof mergedProps.isDisplayComplete === "function" ? mergedProps.isDisplayComplete() : mergedProps.isDisplayComplete;
|
|
1810
|
+
};
|
|
1811
|
+
return /* @__PURE__ */ jsxs10("div", { class: "incremark", children: [
|
|
1812
|
+
/* @__PURE__ */ jsx21(For9, { each: actualBlocks(), children: (block) => /* @__PURE__ */ jsx21(
|
|
1813
|
+
Show13,
|
|
1814
|
+
{
|
|
1815
|
+
when: block.node.type !== "definition" && block.node.type !== "footnoteDefinition",
|
|
1816
|
+
children: /* @__PURE__ */ jsx21(
|
|
1817
|
+
"div",
|
|
1818
|
+
{
|
|
1819
|
+
class: `incremark-block ${block.status === "completed" ? mergedProps.completedClass : mergedProps.pendingClass}${mergedProps.showBlockStatus ? " incremark-show-status" : ""}${block.isLastPending ? " incremark-last-pending" : ""}`,
|
|
1820
|
+
children: /* @__PURE__ */ jsx21(
|
|
1821
|
+
IncremarkRenderer_default,
|
|
1822
|
+
{
|
|
1823
|
+
node: block.node,
|
|
1824
|
+
customContainers: customContainers(),
|
|
1825
|
+
customCodeBlocks: customCodeBlocks(),
|
|
1826
|
+
codeBlockConfigs: codeBlockConfigs(),
|
|
1827
|
+
components: components(),
|
|
1828
|
+
blockStatus: block.status
|
|
1829
|
+
}
|
|
1830
|
+
)
|
|
1831
|
+
}
|
|
1832
|
+
)
|
|
1833
|
+
}
|
|
1834
|
+
) }),
|
|
1835
|
+
/* @__PURE__ */ jsx21(Show13, { when: actualIsDisplayComplete() && footnoteReferenceOrder().length > 0, children: /* @__PURE__ */ jsx21(IncremarkFootnotes, {}) })
|
|
1836
|
+
] });
|
|
1837
|
+
}
|
|
1838
|
+
var Incremark = (props) => {
|
|
1839
|
+
return /* @__PURE__ */ jsx21(IncremarkInner, { ...props });
|
|
1840
|
+
};
|
|
1841
|
+
var Incremark_default = Incremark;
|
|
1842
|
+
|
|
1843
|
+
// src/components/IncremarkContent.tsx
|
|
1844
|
+
import { createEffect as createEffect8 } from "solid-js";
|
|
1845
|
+
import { jsx as jsx22 } from "solid-js/jsx-runtime";
|
|
1846
|
+
var IncremarkContent = (props) => {
|
|
1847
|
+
const incremarkOptions = () => ({
|
|
1848
|
+
gfm: true,
|
|
1849
|
+
htmlTree: true,
|
|
1850
|
+
containers: true,
|
|
1851
|
+
math: true,
|
|
1852
|
+
...props.incremarkOptions
|
|
1853
|
+
});
|
|
1854
|
+
const { blocks, append, finalize, render, reset, isDisplayComplete, markdown, contextValue, DefinationsProvider: DefinationsProvider2 } = useIncremark(incremarkOptions);
|
|
1855
|
+
const isStreamMode = () => typeof props.stream === "function";
|
|
1856
|
+
async function handleStreamInput() {
|
|
1857
|
+
if (!props.stream) return;
|
|
1858
|
+
try {
|
|
1859
|
+
const stream = props.stream();
|
|
1860
|
+
for await (const chunk of stream) {
|
|
1861
|
+
append(chunk);
|
|
1862
|
+
}
|
|
1863
|
+
finalize();
|
|
1864
|
+
} catch (error) {
|
|
1865
|
+
console.error("Stream error: ", error);
|
|
1866
|
+
finalize();
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
function handleContentInput(newContent, oldContent) {
|
|
1870
|
+
if (!newContent) {
|
|
1871
|
+
if (oldContent) {
|
|
1872
|
+
reset();
|
|
1873
|
+
}
|
|
1874
|
+
return;
|
|
1875
|
+
}
|
|
1876
|
+
if (newContent?.startsWith(oldContent ?? "")) {
|
|
1877
|
+
const delta = newContent.slice((oldContent || "").length);
|
|
1878
|
+
append(delta);
|
|
1879
|
+
} else {
|
|
1880
|
+
render(newContent);
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
createEffect8(() => {
|
|
1884
|
+
const newContent = props.content;
|
|
1885
|
+
if (isStreamMode()) {
|
|
1886
|
+
handleStreamInput();
|
|
1887
|
+
} else {
|
|
1888
|
+
handleContentInput(newContent, markdown());
|
|
1889
|
+
}
|
|
1890
|
+
});
|
|
1891
|
+
createEffect8(() => {
|
|
1892
|
+
const newIsFinished = props.isFinished;
|
|
1893
|
+
if (newIsFinished && props.content === markdown()) {
|
|
1894
|
+
finalize();
|
|
1895
|
+
}
|
|
1896
|
+
});
|
|
1897
|
+
return /* @__PURE__ */ jsx22(DefinationsProvider2, { value: contextValue, children: /* @__PURE__ */ jsx22(
|
|
1898
|
+
Incremark_default,
|
|
1899
|
+
{
|
|
1900
|
+
blocks,
|
|
1901
|
+
pendingClass: props.pendingClass,
|
|
1902
|
+
isDisplayComplete: isDisplayComplete(),
|
|
1903
|
+
showBlockStatus: props.showBlockStatus,
|
|
1904
|
+
components: props.components,
|
|
1905
|
+
customContainers: props.customContainers,
|
|
1906
|
+
customCodeBlocks: props.customCodeBlocks,
|
|
1907
|
+
codeBlockConfigs: props.codeBlockConfigs
|
|
1908
|
+
}
|
|
1909
|
+
) });
|
|
1910
|
+
};
|
|
1911
|
+
|
|
1912
|
+
// src/components/AutoScrollContainer.tsx
|
|
1913
|
+
import { createSignal as createSignal13, onCleanup as onCleanup7, onMount as onMount4 } from "solid-js";
|
|
1914
|
+
import { jsx as jsx23 } from "solid-js/jsx-runtime";
|
|
1915
|
+
var AutoScrollContainer = (props) => {
|
|
1916
|
+
let containerRef;
|
|
1917
|
+
const [isUserScrolledUp, setIsUserScrolledUp] = createSignal13(false);
|
|
1918
|
+
let lastScrollTop = 0;
|
|
1919
|
+
let lastScrollHeight = 0;
|
|
1920
|
+
const enabled = () => typeof props.enabled === "function" ? props.enabled() : props.enabled ?? true;
|
|
1921
|
+
const threshold = () => props.threshold ?? 50;
|
|
1922
|
+
const scrollBehavior = () => props.behavior ?? "instant";
|
|
1923
|
+
function isNearBottom() {
|
|
1924
|
+
if (!containerRef) return true;
|
|
1925
|
+
const { scrollTop, scrollHeight, clientHeight } = containerRef;
|
|
1926
|
+
return scrollHeight - scrollTop - clientHeight <= threshold();
|
|
1927
|
+
}
|
|
1928
|
+
function scrollToBottom(force = false) {
|
|
1929
|
+
if (!containerRef) return;
|
|
1930
|
+
if (isUserScrolledUp() && !force) return;
|
|
1931
|
+
containerRef.scrollTo({
|
|
1932
|
+
top: containerRef.scrollHeight,
|
|
1933
|
+
behavior: scrollBehavior()
|
|
1934
|
+
});
|
|
1935
|
+
}
|
|
1936
|
+
function hasScrollbar() {
|
|
1937
|
+
if (!containerRef) return false;
|
|
1938
|
+
return containerRef.scrollHeight > containerRef.clientHeight;
|
|
1939
|
+
}
|
|
1940
|
+
function handleScroll() {
|
|
1941
|
+
if (!containerRef) return;
|
|
1942
|
+
const { scrollTop, scrollHeight, clientHeight } = containerRef;
|
|
1943
|
+
if (scrollHeight <= clientHeight) {
|
|
1944
|
+
setIsUserScrolledUp(false);
|
|
1945
|
+
lastScrollTop = 0;
|
|
1946
|
+
lastScrollHeight = scrollHeight;
|
|
1947
|
+
return;
|
|
1948
|
+
}
|
|
1949
|
+
if (isNearBottom()) {
|
|
1950
|
+
setIsUserScrolledUp(false);
|
|
1951
|
+
} else {
|
|
1952
|
+
const isScrollingUp = scrollTop < lastScrollTop;
|
|
1953
|
+
const isContentUnchanged = scrollHeight === lastScrollHeight;
|
|
1954
|
+
if (isScrollingUp && isContentUnchanged) {
|
|
1955
|
+
setIsUserScrolledUp(true);
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
lastScrollTop = scrollTop;
|
|
1959
|
+
lastScrollHeight = scrollHeight;
|
|
1960
|
+
}
|
|
1961
|
+
let observer = null;
|
|
1962
|
+
onMount4(() => {
|
|
1963
|
+
if (!containerRef) return;
|
|
1964
|
+
lastScrollTop = containerRef.scrollTop;
|
|
1965
|
+
lastScrollHeight = containerRef.scrollHeight;
|
|
1966
|
+
observer = new MutationObserver(() => {
|
|
1967
|
+
requestAnimationFrame(() => {
|
|
1968
|
+
if (!containerRef) return;
|
|
1969
|
+
if (!hasScrollbar()) {
|
|
1970
|
+
setIsUserScrolledUp(false);
|
|
1971
|
+
}
|
|
1972
|
+
lastScrollHeight = containerRef.scrollHeight;
|
|
1973
|
+
if (enabled() && !isUserScrolledUp()) {
|
|
1974
|
+
scrollToBottom();
|
|
1975
|
+
}
|
|
1976
|
+
});
|
|
1977
|
+
});
|
|
1978
|
+
observer.observe(containerRef, {
|
|
1979
|
+
childList: true,
|
|
1980
|
+
subtree: true,
|
|
1981
|
+
characterData: true
|
|
1982
|
+
});
|
|
1983
|
+
});
|
|
1984
|
+
onCleanup7(() => {
|
|
1985
|
+
observer?.disconnect();
|
|
1986
|
+
});
|
|
1987
|
+
return /* @__PURE__ */ jsx23(
|
|
1988
|
+
"div",
|
|
1989
|
+
{
|
|
1990
|
+
ref: containerRef,
|
|
1991
|
+
class: "auto-scroll-container",
|
|
1992
|
+
onScroll: handleScroll,
|
|
1993
|
+
children: props.children
|
|
1994
|
+
}
|
|
1995
|
+
);
|
|
1996
|
+
};
|
|
1997
|
+
|
|
1998
|
+
// src/components/ThemeProvider.tsx
|
|
1999
|
+
import { createContext as createContext3, useContext as useContext3, createMemo as createMemo4, createSignal as createSignal14 } from "solid-js";
|
|
2000
|
+
import { applyTheme } from "@incremark/theme";
|
|
2001
|
+
import { jsx as jsx24 } from "solid-js/jsx-runtime";
|
|
2002
|
+
var ThemeContext = createContext3();
|
|
2003
|
+
var ThemeProvider = (props) => {
|
|
2004
|
+
let containerRef;
|
|
2005
|
+
const [theme, setTheme] = createSignal14(props.theme || "default");
|
|
2006
|
+
createMemo4(() => {
|
|
2007
|
+
const currentTheme = props.theme || "default";
|
|
2008
|
+
setTheme(currentTheme);
|
|
2009
|
+
if (typeof document !== "undefined" && containerRef) {
|
|
2010
|
+
applyTheme(containerRef, currentTheme);
|
|
2011
|
+
}
|
|
2012
|
+
});
|
|
2013
|
+
return /* @__PURE__ */ jsx24(ThemeContext.Provider, { value: { theme, setTheme }, children: /* @__PURE__ */ jsx24("div", { ref: containerRef, class: "incremark-theme-provider", children: props.children }) });
|
|
2014
|
+
};
|
|
2015
|
+
function useTheme() {
|
|
2016
|
+
const context = useContext3(ThemeContext);
|
|
2017
|
+
if (!context) {
|
|
2018
|
+
throw new Error("useTheme must be used within a ThemeProvider");
|
|
2019
|
+
}
|
|
2020
|
+
return context;
|
|
2021
|
+
}
|
|
2022
|
+
|
|
2023
|
+
// src/index.ts
|
|
2024
|
+
import {
|
|
2025
|
+
BlockTransformer,
|
|
2026
|
+
createBlockTransformer as createBlockTransformer3,
|
|
2027
|
+
countChars,
|
|
2028
|
+
sliceAst,
|
|
2029
|
+
cloneNode,
|
|
2030
|
+
codeBlockPlugin,
|
|
2031
|
+
mermaidPlugin,
|
|
2032
|
+
imagePlugin,
|
|
2033
|
+
mathPlugin as mathPlugin2,
|
|
2034
|
+
thematicBreakPlugin,
|
|
2035
|
+
defaultPlugins as defaultPlugins2,
|
|
2036
|
+
allPlugins,
|
|
2037
|
+
createPlugin
|
|
2038
|
+
} from "@incremark/core";
|
|
2039
|
+
import {
|
|
2040
|
+
defaultTheme,
|
|
2041
|
+
darkTheme,
|
|
2042
|
+
generateCSSVars,
|
|
2043
|
+
mergeTheme,
|
|
2044
|
+
applyTheme as applyTheme2
|
|
2045
|
+
} from "@incremark/theme";
|
|
2046
|
+
import { en as enShared, zhCN as zhCNShared } from "@incremark/shared";
|
|
2047
|
+
export {
|
|
2048
|
+
AutoScrollContainer,
|
|
2049
|
+
BlockTransformer,
|
|
2050
|
+
CachedCodeRenderer,
|
|
2051
|
+
ConfigProvider,
|
|
2052
|
+
ConfigProvider as ConfigProviderExport,
|
|
2053
|
+
Incremark,
|
|
2054
|
+
IncremarkBlockquote,
|
|
2055
|
+
IncremarkCode,
|
|
2056
|
+
IncremarkCode_default as IncremarkCodeAlias,
|
|
2057
|
+
IncremarkCodeDefault,
|
|
2058
|
+
IncremarkCodeMermaid,
|
|
2059
|
+
IncremarkContainer,
|
|
2060
|
+
IncremarkContent,
|
|
2061
|
+
IncremarkDefault,
|
|
2062
|
+
IncremarkFootnotes,
|
|
2063
|
+
IncremarkHeading,
|
|
2064
|
+
IncremarkHtmlElement,
|
|
2065
|
+
IncremarkInline,
|
|
2066
|
+
IncremarkList,
|
|
2067
|
+
IncremarkMath,
|
|
2068
|
+
IncremarkParagraph,
|
|
2069
|
+
IncremarkRenderer,
|
|
2070
|
+
IncremarkTable,
|
|
2071
|
+
IncremarkThematicBreak,
|
|
2072
|
+
SvgIcon,
|
|
2073
|
+
ThemeProvider,
|
|
2074
|
+
ThemeProvider as ThemeProviderExport,
|
|
2075
|
+
allPlugins,
|
|
2076
|
+
applyTheme2 as applyTheme,
|
|
2077
|
+
clearAnimatedChunks,
|
|
2078
|
+
cloneNode,
|
|
2079
|
+
codeBlockPlugin,
|
|
2080
|
+
countChars,
|
|
2081
|
+
createBlockTransformer3 as createBlockTransformer,
|
|
2082
|
+
createPlugin,
|
|
2083
|
+
darkTheme,
|
|
2084
|
+
defaultPlugins2 as defaultPlugins,
|
|
2085
|
+
defaultTheme,
|
|
2086
|
+
enShared as en,
|
|
2087
|
+
generateCSSVars,
|
|
2088
|
+
imagePlugin,
|
|
2089
|
+
mathPlugin2 as mathPlugin,
|
|
2090
|
+
mergeTheme,
|
|
2091
|
+
mermaidPlugin,
|
|
2092
|
+
shouldAnimateChunk,
|
|
2093
|
+
sliceAst,
|
|
2094
|
+
thematicBreakPlugin,
|
|
2095
|
+
useBlockTransformer,
|
|
2096
|
+
useDefinationsContext,
|
|
2097
|
+
useDevTools,
|
|
2098
|
+
useIncremark,
|
|
2099
|
+
useLocale,
|
|
2100
|
+
useProvideDefinations,
|
|
2101
|
+
useStreamRenderer,
|
|
2102
|
+
useTheme,
|
|
2103
|
+
zhCNShared as zhCN
|
|
2104
|
+
};
|
|
2105
|
+
/**
|
|
2106
|
+
* @file useTypewriter Composable - 打字机效果管理
|
|
2107
|
+
*
|
|
2108
|
+
* @description
|
|
2109
|
+
* 管理打字机效果的状态和控制逻辑。
|
|
2110
|
+
*
|
|
2111
|
+
* @author Incremark Team
|
|
2112
|
+
* @license MIT
|
|
2113
|
+
*/
|
|
2114
|
+
/**
|
|
2115
|
+
* @file Animated Chunks Tracker
|
|
2116
|
+
*
|
|
2117
|
+
* @description
|
|
2118
|
+
* 跟踪已播放过动画的 chunk,避免重复播放动画导致闪烁
|
|
2119
|
+
*
|
|
2120
|
+
* @author Incremark Team
|
|
2121
|
+
* @license MIT
|
|
2122
|
+
*/
|
|
2123
|
+
//# sourceMappingURL=index.js.map
|