svelte-streamdown 1.0.8 → 2.0.0
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/README.md +155 -140
- package/dist/Block.svelte +17 -41
- package/dist/Elements/Alert.svelte +1 -2
- package/dist/Elements/Code.svelte +3 -5
- package/dist/Elements/Code.svelte.d.ts +0 -2
- package/dist/Elements/Element.svelte +170 -42
- package/dist/Elements/FootnoteRef.svelte +126 -0
- package/dist/Elements/FootnoteRef.svelte.d.ts +7 -0
- package/dist/Elements/Image.svelte +4 -4
- package/dist/Elements/{A.svelte → Link.svelte} +4 -4
- package/dist/Elements/{A.svelte.d.ts → Link.svelte.d.ts} +3 -3
- package/dist/Elements/Math.svelte +13 -24
- package/dist/Elements/Math.svelte.d.ts +0 -2
- package/dist/Elements/Mermaid.svelte +105 -115
- package/dist/Elements/Mermaid.svelte.d.ts +0 -2
- package/dist/Elements/Table.svelte +1 -1
- package/dist/Elements/index.d.ts +5 -24
- package/dist/Elements/index.js +5 -24
- package/dist/Streamdown.d.ts +52 -10
- package/dist/Streamdown.js +19 -1
- package/dist/Streamdown.svelte +2 -34
- package/dist/Streamdown.svelte.d.ts +1 -14
- package/dist/marked/index.d.ts +6 -10
- package/dist/marked/index.js +29 -17
- package/dist/marked/marked-alert.d.ts +2 -2
- package/dist/marked/marked-alert.js +11 -24
- package/dist/marked/marked-footnotes.d.ts +1 -0
- package/dist/marked/marked-footnotes.js +27 -8
- package/dist/marked/marked-list.d.ts +36 -0
- package/dist/marked/marked-list.js +232 -0
- package/dist/marked/marked-math.js +1 -4
- package/dist/marked/marked-subsup.d.ts +28 -0
- package/dist/marked/marked-subsup.js +45 -0
- package/dist/marked/marked-table.d.ts +59 -0
- package/dist/marked/marked-table.js +495 -0
- package/dist/theme.d.ts +54 -30
- package/dist/theme.js +51 -35
- package/dist/utils/panzoom.svelte.d.ts +17 -18
- package/dist/utils/panzoom.svelte.js +0 -2
- package/dist/utils/parse-incomplete-markdown.js +157 -0
- package/dist/utils/useClickOutside.svelte.d.ts +8 -0
- package/dist/utils/useClickOutside.svelte.js +41 -0
- package/dist/utils/useKeyDown.svelte.d.ts +5 -0
- package/dist/utils/useKeyDown.svelte.js +23 -0
- package/package.json +2 -1
- package/dist/Elements/Blockquote.svelte +0 -28
- package/dist/Elements/Blockquote.svelte.d.ts +0 -9
- package/dist/Elements/Del.svelte +0 -28
- package/dist/Elements/Del.svelte.d.ts +0 -9
- package/dist/Elements/Em.svelte +0 -28
- package/dist/Elements/Em.svelte.d.ts +0 -9
- package/dist/Elements/Heading.svelte +0 -25
- package/dist/Elements/Heading.svelte.d.ts +0 -9
- package/dist/Elements/Hr.svelte +0 -26
- package/dist/Elements/Hr.svelte.d.ts +0 -9
- package/dist/Elements/InlineCode.svelte +0 -28
- package/dist/Elements/InlineCode.svelte.d.ts +0 -9
- package/dist/Elements/Li.svelte +0 -28
- package/dist/Elements/Li.svelte.d.ts +0 -9
- package/dist/Elements/Ol.svelte +0 -30
- package/dist/Elements/Ol.svelte.d.ts +0 -9
- package/dist/Elements/P.svelte +0 -28
- package/dist/Elements/P.svelte.d.ts +0 -9
- package/dist/Elements/Strong.svelte +0 -28
- package/dist/Elements/Strong.svelte.d.ts +0 -9
- package/dist/Elements/Sub.svelte +0 -27
- package/dist/Elements/Sub.svelte.d.ts +0 -8
- package/dist/Elements/Sup.svelte +0 -28
- package/dist/Elements/Sup.svelte.d.ts +0 -8
- package/dist/Elements/Tbody.svelte +0 -24
- package/dist/Elements/Tbody.svelte.d.ts +0 -7
- package/dist/Elements/Td.svelte +0 -28
- package/dist/Elements/Td.svelte.d.ts +0 -9
- package/dist/Elements/Th.svelte +0 -28
- package/dist/Elements/Th.svelte.d.ts +0 -9
- package/dist/Elements/Thead.svelte +0 -27
- package/dist/Elements/Thead.svelte.d.ts +0 -9
- package/dist/Elements/Tr.svelte +0 -27
- package/dist/Elements/Tr.svelte.d.ts +0 -9
- package/dist/Elements/Ul.svelte +0 -28
- package/dist/Elements/Ul.svelte.d.ts +0 -9
- /package/dist/{hightlighter.svelte.d.ts → utils/hightlighter.svelte.d.ts} +0 -0
- /package/dist/{hightlighter.svelte.js → utils/hightlighter.svelte.js} +0 -0
package/dist/theme.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ClassValue } from 'clsx';
|
|
2
2
|
export declare const cn: (...inputs: ClassValue[]) => string;
|
|
3
3
|
export declare const theme: {
|
|
4
|
-
|
|
4
|
+
link: {
|
|
5
5
|
base: string;
|
|
6
6
|
blocked: string;
|
|
7
7
|
};
|
|
@@ -34,6 +34,7 @@ export declare const theme: {
|
|
|
34
34
|
};
|
|
35
35
|
li: {
|
|
36
36
|
base: string;
|
|
37
|
+
checkbox: string;
|
|
37
38
|
};
|
|
38
39
|
code: {
|
|
39
40
|
base: string;
|
|
@@ -44,17 +45,14 @@ export declare const theme: {
|
|
|
44
45
|
skeleton: string;
|
|
45
46
|
pre: string;
|
|
46
47
|
};
|
|
47
|
-
|
|
48
|
+
codespan: {
|
|
48
49
|
base: string;
|
|
49
50
|
};
|
|
50
|
-
|
|
51
|
+
image: {
|
|
51
52
|
base: string;
|
|
52
53
|
image: string;
|
|
53
54
|
downloadButton: string;
|
|
54
55
|
};
|
|
55
|
-
pre: {
|
|
56
|
-
base: string;
|
|
57
|
-
};
|
|
58
56
|
blockquote: {
|
|
59
57
|
base: string;
|
|
60
58
|
};
|
|
@@ -78,15 +76,18 @@ export declare const theme: {
|
|
|
78
76
|
tbody: {
|
|
79
77
|
base: string;
|
|
80
78
|
};
|
|
81
|
-
|
|
79
|
+
tfoot: {
|
|
82
80
|
base: string;
|
|
83
81
|
};
|
|
84
|
-
|
|
82
|
+
tr: {
|
|
85
83
|
base: string;
|
|
86
84
|
};
|
|
87
85
|
td: {
|
|
88
86
|
base: string;
|
|
89
87
|
};
|
|
88
|
+
th: {
|
|
89
|
+
base: string;
|
|
90
|
+
};
|
|
90
91
|
sup: {
|
|
91
92
|
base: string;
|
|
92
93
|
};
|
|
@@ -107,9 +108,10 @@ export declare const theme: {
|
|
|
107
108
|
buttons: string;
|
|
108
109
|
};
|
|
109
110
|
math: {
|
|
110
|
-
|
|
111
|
+
block: string;
|
|
112
|
+
inline: string;
|
|
111
113
|
};
|
|
112
|
-
|
|
114
|
+
br: {
|
|
113
115
|
base: string;
|
|
114
116
|
};
|
|
115
117
|
em: {
|
|
@@ -118,9 +120,15 @@ export declare const theme: {
|
|
|
118
120
|
del: {
|
|
119
121
|
base: string;
|
|
120
122
|
};
|
|
123
|
+
footnoteRef: {
|
|
124
|
+
base: string;
|
|
125
|
+
};
|
|
126
|
+
footnotePopover: {
|
|
127
|
+
base: string;
|
|
128
|
+
};
|
|
121
129
|
};
|
|
122
130
|
export declare const shadcnTheme: {
|
|
123
|
-
|
|
131
|
+
link: {
|
|
124
132
|
base: string;
|
|
125
133
|
blocked: string;
|
|
126
134
|
};
|
|
@@ -153,6 +161,7 @@ export declare const shadcnTheme: {
|
|
|
153
161
|
};
|
|
154
162
|
li: {
|
|
155
163
|
base: string;
|
|
164
|
+
checkbox: string;
|
|
156
165
|
};
|
|
157
166
|
code: {
|
|
158
167
|
base: string;
|
|
@@ -163,17 +172,14 @@ export declare const shadcnTheme: {
|
|
|
163
172
|
skeleton: string;
|
|
164
173
|
pre: string;
|
|
165
174
|
};
|
|
166
|
-
|
|
175
|
+
codespan: {
|
|
167
176
|
base: string;
|
|
168
177
|
};
|
|
169
|
-
|
|
178
|
+
image: {
|
|
170
179
|
base: string;
|
|
171
180
|
image: string;
|
|
172
181
|
downloadButton: string;
|
|
173
182
|
};
|
|
174
|
-
pre: {
|
|
175
|
-
base: string;
|
|
176
|
-
};
|
|
177
183
|
blockquote: {
|
|
178
184
|
base: string;
|
|
179
185
|
};
|
|
@@ -197,15 +203,18 @@ export declare const shadcnTheme: {
|
|
|
197
203
|
tbody: {
|
|
198
204
|
base: string;
|
|
199
205
|
};
|
|
200
|
-
|
|
206
|
+
tfoot: {
|
|
201
207
|
base: string;
|
|
202
208
|
};
|
|
203
|
-
|
|
209
|
+
tr: {
|
|
204
210
|
base: string;
|
|
205
211
|
};
|
|
206
212
|
td: {
|
|
207
213
|
base: string;
|
|
208
214
|
};
|
|
215
|
+
th: {
|
|
216
|
+
base: string;
|
|
217
|
+
};
|
|
209
218
|
sup: {
|
|
210
219
|
base: string;
|
|
211
220
|
};
|
|
@@ -226,9 +235,10 @@ export declare const shadcnTheme: {
|
|
|
226
235
|
buttons: string;
|
|
227
236
|
};
|
|
228
237
|
math: {
|
|
229
|
-
|
|
238
|
+
block: string;
|
|
239
|
+
inline: string;
|
|
230
240
|
};
|
|
231
|
-
|
|
241
|
+
br: {
|
|
232
242
|
base: string;
|
|
233
243
|
};
|
|
234
244
|
em: {
|
|
@@ -237,10 +247,16 @@ export declare const shadcnTheme: {
|
|
|
237
247
|
del: {
|
|
238
248
|
base: string;
|
|
239
249
|
};
|
|
250
|
+
footnoteRef: {
|
|
251
|
+
base: string;
|
|
252
|
+
};
|
|
253
|
+
footnotePopover: {
|
|
254
|
+
base: string;
|
|
255
|
+
};
|
|
240
256
|
};
|
|
241
257
|
export type Theme = typeof theme;
|
|
242
258
|
export declare const mergeTheme: (customTheme?: Partial<Theme>, baseTheme?: "tailwind" | "shadcn") => {
|
|
243
|
-
|
|
259
|
+
link: {
|
|
244
260
|
base: string;
|
|
245
261
|
blocked: string;
|
|
246
262
|
};
|
|
@@ -273,6 +289,7 @@ export declare const mergeTheme: (customTheme?: Partial<Theme>, baseTheme?: "tai
|
|
|
273
289
|
};
|
|
274
290
|
li: {
|
|
275
291
|
base: string;
|
|
292
|
+
checkbox: string;
|
|
276
293
|
};
|
|
277
294
|
code: {
|
|
278
295
|
base: string;
|
|
@@ -283,17 +300,14 @@ export declare const mergeTheme: (customTheme?: Partial<Theme>, baseTheme?: "tai
|
|
|
283
300
|
skeleton: string;
|
|
284
301
|
pre: string;
|
|
285
302
|
};
|
|
286
|
-
|
|
303
|
+
codespan: {
|
|
287
304
|
base: string;
|
|
288
305
|
};
|
|
289
|
-
|
|
306
|
+
image: {
|
|
290
307
|
base: string;
|
|
291
308
|
image: string;
|
|
292
309
|
downloadButton: string;
|
|
293
310
|
};
|
|
294
|
-
pre: {
|
|
295
|
-
base: string;
|
|
296
|
-
};
|
|
297
311
|
blockquote: {
|
|
298
312
|
base: string;
|
|
299
313
|
};
|
|
@@ -317,15 +331,18 @@ export declare const mergeTheme: (customTheme?: Partial<Theme>, baseTheme?: "tai
|
|
|
317
331
|
tbody: {
|
|
318
332
|
base: string;
|
|
319
333
|
};
|
|
320
|
-
|
|
334
|
+
tfoot: {
|
|
321
335
|
base: string;
|
|
322
336
|
};
|
|
323
|
-
|
|
337
|
+
tr: {
|
|
324
338
|
base: string;
|
|
325
339
|
};
|
|
326
340
|
td: {
|
|
327
341
|
base: string;
|
|
328
342
|
};
|
|
343
|
+
th: {
|
|
344
|
+
base: string;
|
|
345
|
+
};
|
|
329
346
|
sup: {
|
|
330
347
|
base: string;
|
|
331
348
|
};
|
|
@@ -346,9 +363,10 @@ export declare const mergeTheme: (customTheme?: Partial<Theme>, baseTheme?: "tai
|
|
|
346
363
|
buttons: string;
|
|
347
364
|
};
|
|
348
365
|
math: {
|
|
349
|
-
|
|
366
|
+
block: string;
|
|
367
|
+
inline: string;
|
|
350
368
|
};
|
|
351
|
-
|
|
369
|
+
br: {
|
|
352
370
|
base: string;
|
|
353
371
|
};
|
|
354
372
|
em: {
|
|
@@ -357,4 +375,10 @@ export declare const mergeTheme: (customTheme?: Partial<Theme>, baseTheme?: "tai
|
|
|
357
375
|
del: {
|
|
358
376
|
base: string;
|
|
359
377
|
};
|
|
378
|
+
footnoteRef: {
|
|
379
|
+
base: string;
|
|
380
|
+
};
|
|
381
|
+
footnotePopover: {
|
|
382
|
+
base: string;
|
|
383
|
+
};
|
|
360
384
|
};
|
package/dist/theme.js
CHANGED
|
@@ -2,7 +2,7 @@ import { clsx } from 'clsx';
|
|
|
2
2
|
import { twMerge } from 'tailwind-merge';
|
|
3
3
|
export const cn = (...inputs) => twMerge(clsx(inputs));
|
|
4
4
|
export const theme = {
|
|
5
|
-
|
|
5
|
+
link: {
|
|
6
6
|
base: 'text-blue-600 font-medium underline',
|
|
7
7
|
blocked: 'text-gray-500'
|
|
8
8
|
},
|
|
@@ -28,13 +28,14 @@ export const theme = {
|
|
|
28
28
|
base: ''
|
|
29
29
|
},
|
|
30
30
|
ul: {
|
|
31
|
-
base: 'ml-4 list-
|
|
31
|
+
base: 'ml-4 list-inside list-disc whitespace-normal'
|
|
32
32
|
},
|
|
33
33
|
ol: {
|
|
34
|
-
base: 'ml-4 list-
|
|
34
|
+
base: 'ml-4 list-inside whitespace-normal'
|
|
35
35
|
},
|
|
36
36
|
li: {
|
|
37
|
-
base: 'py-1'
|
|
37
|
+
base: 'py-1 marker:hidden',
|
|
38
|
+
checkbox: '-ml-2'
|
|
38
39
|
},
|
|
39
40
|
code: {
|
|
40
41
|
base: 'my-4 w-full overflow-hidden rounded-xl border border-gray-200 flex flex-col',
|
|
@@ -45,17 +46,14 @@ export const theme = {
|
|
|
45
46
|
skeleton: 'rounded-md font-mono text-transparent bg-gray-200 whitespace-nowrap inline-block',
|
|
46
47
|
pre: 'overflow-x-auto font-mono p-0 bg-gray-100/40'
|
|
47
48
|
},
|
|
48
|
-
|
|
49
|
-
base: 'bg-gray-100 rounded px-1.5 py-0.5 font-mono'
|
|
49
|
+
codespan: {
|
|
50
|
+
base: 'bg-gray-100 rounded px-1.5 py-0.5 font-mono text-[0.9em]'
|
|
50
51
|
},
|
|
51
|
-
|
|
52
|
+
image: {
|
|
52
53
|
base: 'group relative my-4 mx-auto w-fit block',
|
|
53
54
|
image: 'max-w-full rounded-lg',
|
|
54
55
|
downloadButton: 'absolute right-2 bottom-2 flex h-8 w-8 cursor-pointer items-center justify-center rounded-md border border-gray-200 bg-white/90 shadow-sm backdrop-blur-sm transition-all duration-200 hover:bg-white opacity-0 group-hover:opacity-100'
|
|
55
56
|
},
|
|
56
|
-
pre: {
|
|
57
|
-
base: 'overflow-x-auto font-mono text-xs p-4 bg-gray-100/40'
|
|
58
|
-
},
|
|
59
57
|
blockquote: {
|
|
60
58
|
base: 'border-gray-600/30 text-gray-600 my-4 border-l-4 pl-4 italic'
|
|
61
59
|
},
|
|
@@ -74,20 +72,23 @@ export const theme = {
|
|
|
74
72
|
table: 'w-full border-collapse min-w-full'
|
|
75
73
|
},
|
|
76
74
|
thead: {
|
|
77
|
-
base: 'bg-gray-
|
|
75
|
+
base: 'bg-gray-200/80'
|
|
78
76
|
},
|
|
79
77
|
tbody: {
|
|
80
|
-
base: '
|
|
78
|
+
base: ''
|
|
79
|
+
},
|
|
80
|
+
tfoot: {
|
|
81
|
+
base: 'bg-gray-100/50 border-t border-gray-300'
|
|
81
82
|
},
|
|
82
83
|
tr: {
|
|
83
84
|
base: 'border-gray-200 border-b hover:bg-gray-100/50 transition-colors'
|
|
84
85
|
},
|
|
85
|
-
th: {
|
|
86
|
-
base: 'px-4 py-3 text-left text-sm font-semibold whitespace-nowrap min-w-[200px]'
|
|
87
|
-
},
|
|
88
86
|
td: {
|
|
89
87
|
base: 'px-4 py-3 text-sm min-w-[200px] max-w-[400px] break-words'
|
|
90
88
|
},
|
|
89
|
+
th: {
|
|
90
|
+
base: 'px-4 py-3 text-sm text-foreground min-w-[200px] max-w-[400px] break-words'
|
|
91
|
+
},
|
|
91
92
|
sup: {
|
|
92
93
|
base: 'text-sm'
|
|
93
94
|
},
|
|
@@ -108,9 +109,10 @@ export const theme = {
|
|
|
108
109
|
buttons: 'absolute right-1 top-1 z-10 flex h-fit w-fit items-center gap-1'
|
|
109
110
|
},
|
|
110
111
|
math: {
|
|
111
|
-
|
|
112
|
+
block: '',
|
|
113
|
+
inline: ''
|
|
112
114
|
},
|
|
113
|
-
|
|
115
|
+
br: {
|
|
114
116
|
base: ''
|
|
115
117
|
},
|
|
116
118
|
em: {
|
|
@@ -118,10 +120,16 @@ export const theme = {
|
|
|
118
120
|
},
|
|
119
121
|
del: {
|
|
120
122
|
base: 'line-through'
|
|
123
|
+
},
|
|
124
|
+
footnoteRef: {
|
|
125
|
+
base: 'text-gray-600 px-1 py-0.5 rounded-md bg-gray-100/80'
|
|
126
|
+
},
|
|
127
|
+
footnotePopover: {
|
|
128
|
+
base: 'fixed z-50 max-h-[30vh] max-w-3xl overflow-y-auto rounded-lg bg-background p-4 shadow'
|
|
121
129
|
}
|
|
122
130
|
};
|
|
123
131
|
export const shadcnTheme = {
|
|
124
|
-
|
|
132
|
+
link: {
|
|
125
133
|
base: 'text-primary font-medium underline hover:text-primary/80',
|
|
126
134
|
blocked: 'text-muted-foreground'
|
|
127
135
|
},
|
|
@@ -147,13 +155,14 @@ export const shadcnTheme = {
|
|
|
147
155
|
base: 'text-foreground'
|
|
148
156
|
},
|
|
149
157
|
ul: {
|
|
150
|
-
base: 'ml-4 list-
|
|
158
|
+
base: 'ml-4 list-inside list-disc whitespace-normal text-foreground'
|
|
151
159
|
},
|
|
152
160
|
ol: {
|
|
153
|
-
base: 'ml-4 list-
|
|
161
|
+
base: 'ml-4 list-inside whitespace-normal text-foreground'
|
|
154
162
|
},
|
|
155
163
|
li: {
|
|
156
|
-
base: 'py-1'
|
|
164
|
+
base: 'py-1',
|
|
165
|
+
checkbox: '-ml-2'
|
|
157
166
|
},
|
|
158
167
|
code: {
|
|
159
168
|
base: 'my-4 w-full overflow-hidden rounded-lg border border-border flex flex-col',
|
|
@@ -164,17 +173,14 @@ export const shadcnTheme = {
|
|
|
164
173
|
skeleton: 'rounded-md font-mono text-transparent bg-muted whitespace-nowrap inline-block',
|
|
165
174
|
pre: 'overflow-x-auto font-mono p-0 bg-muted/40'
|
|
166
175
|
},
|
|
167
|
-
|
|
168
|
-
base: 'bg-muted rounded px-1.5 py-0.5 font-mono text-foreground'
|
|
176
|
+
codespan: {
|
|
177
|
+
base: 'bg-muted rounded px-1.5 py-0.5 font-mono text-foreground text-[0.9em]'
|
|
169
178
|
},
|
|
170
|
-
|
|
179
|
+
image: {
|
|
171
180
|
base: 'group relative my-4 mx-auto w-fit block',
|
|
172
181
|
image: 'max-w-full rounded-lg',
|
|
173
182
|
downloadButton: 'absolute right-2 bottom-2 flex h-8 w-8 cursor-pointer items-center justify-center rounded-md border border-border bg-background/90 shadow-sm backdrop-blur-sm transition-all duration-200 hover:bg-background opacity-0 group-hover:opacity-100'
|
|
174
183
|
},
|
|
175
|
-
pre: {
|
|
176
|
-
base: 'overflow-x-auto font-mono text-xs p-4 bg-muted/40'
|
|
177
|
-
},
|
|
178
184
|
blockquote: {
|
|
179
185
|
base: 'border-muted-foreground/30 text-muted-foreground my-4 border-l-4 pl-4 italic'
|
|
180
186
|
},
|
|
@@ -193,20 +199,23 @@ export const shadcnTheme = {
|
|
|
193
199
|
table: 'w-full border-collapse min-w-full'
|
|
194
200
|
},
|
|
195
201
|
thead: {
|
|
196
|
-
base: 'bg-muted/
|
|
202
|
+
base: 'bg-muted/80'
|
|
197
203
|
},
|
|
198
204
|
tbody: {
|
|
199
|
-
base: '
|
|
205
|
+
base: ''
|
|
206
|
+
},
|
|
207
|
+
tfoot: {
|
|
208
|
+
base: 'bg-muted/50 border-t border-border'
|
|
200
209
|
},
|
|
201
210
|
tr: {
|
|
202
211
|
base: 'border-border border-b hover:bg-muted/50 transition-colors'
|
|
203
212
|
},
|
|
204
|
-
th: {
|
|
205
|
-
base: 'px-4 py-3 text-left text-sm font-semibold whitespace-nowrap text-foreground min-w-[200px]'
|
|
206
|
-
},
|
|
207
213
|
td: {
|
|
208
214
|
base: 'px-4 py-3 text-sm text-foreground min-w-[200px] max-w-[400px] break-words'
|
|
209
215
|
},
|
|
216
|
+
th: {
|
|
217
|
+
base: 'px-4 py-3 text-sm text-foreground min-w-[200px] max-w-[400px] break-words'
|
|
218
|
+
},
|
|
210
219
|
sup: {
|
|
211
220
|
base: 'text-sm'
|
|
212
221
|
},
|
|
@@ -227,16 +236,23 @@ export const shadcnTheme = {
|
|
|
227
236
|
buttons: 'absolute right-1 top-1 z-10 flex h-fit w-fit items-center gap-1'
|
|
228
237
|
},
|
|
229
238
|
math: {
|
|
230
|
-
|
|
239
|
+
block: 'text-foreground',
|
|
240
|
+
inline: 'text-foreground'
|
|
231
241
|
},
|
|
232
|
-
|
|
233
|
-
base: '
|
|
242
|
+
br: {
|
|
243
|
+
base: ''
|
|
234
244
|
},
|
|
235
245
|
em: {
|
|
236
246
|
base: 'italic text-foreground'
|
|
237
247
|
},
|
|
238
248
|
del: {
|
|
239
249
|
base: 'line-through text-muted-foreground'
|
|
250
|
+
},
|
|
251
|
+
footnoteRef: {
|
|
252
|
+
base: 'text-muted-foreground px-1 text-sm inline-block rounded-full bg-muted/80 aspect-square border border-border'
|
|
253
|
+
},
|
|
254
|
+
footnotePopover: {
|
|
255
|
+
base: 'fixed z-50 max-h-[30vh] shadow max-w-3xl overflow-y-auto rounded-lg bg-background p-4'
|
|
240
256
|
}
|
|
241
257
|
};
|
|
242
258
|
export const mergeTheme = (customTheme, baseTheme) => {
|
|
@@ -8,29 +8,28 @@ export interface PanzoomOptions {
|
|
|
8
8
|
initialY?: number;
|
|
9
9
|
activateMouseWheel?: boolean;
|
|
10
10
|
}
|
|
11
|
-
export interface
|
|
12
|
-
|
|
11
|
+
export interface ExpandOptions {
|
|
12
|
+
padding?: number;
|
|
13
|
+
duration?: number;
|
|
14
|
+
easing?: string;
|
|
15
|
+
zIndex?: number;
|
|
16
|
+
fitRatio?: number;
|
|
17
|
+
}
|
|
18
|
+
export declare const usePanzoom: (opts?: PanzoomOptions) => {
|
|
19
|
+
attach: (target: HTMLElement | SVGSVGElement) => () => void;
|
|
13
20
|
zoomToFit: (padding?: number) => void;
|
|
14
21
|
zoomBy: (factor: number) => void;
|
|
15
22
|
zoomIn: (factor?: number) => void;
|
|
16
23
|
zoomOut: (factor?: number) => void;
|
|
17
24
|
moveBy: (dx: number, dy: number) => void;
|
|
18
|
-
setTransform: (
|
|
25
|
+
setTransform: (nx: number, ny: number, ns: number) => void;
|
|
19
26
|
expand: () => void;
|
|
20
27
|
collapse: () => void;
|
|
21
|
-
toggleExpand: (
|
|
28
|
+
toggleExpand: () => Promise<void>;
|
|
29
|
+
readonly transform: {
|
|
30
|
+
readonly x: number;
|
|
31
|
+
readonly y: number;
|
|
32
|
+
readonly scale: number;
|
|
33
|
+
};
|
|
22
34
|
readonly expanded: boolean;
|
|
23
|
-
|
|
24
|
-
x: number;
|
|
25
|
-
y: number;
|
|
26
|
-
scale: number;
|
|
27
|
-
}>;
|
|
28
|
-
}
|
|
29
|
-
export interface ExpandOptions {
|
|
30
|
-
padding?: number;
|
|
31
|
-
duration?: number;
|
|
32
|
-
easing?: string;
|
|
33
|
-
zIndex?: number;
|
|
34
|
-
fitRatio?: number;
|
|
35
|
-
}
|
|
36
|
-
export declare const usePanzoom: (opts?: PanzoomOptions) => PanzoomInstance;
|
|
35
|
+
};
|
|
@@ -429,7 +429,6 @@ export const usePanzoom = (opts = {}) => {
|
|
|
429
429
|
apply();
|
|
430
430
|
}
|
|
431
431
|
function zoomBy(factor) {
|
|
432
|
-
console.log('zoomBy', factor);
|
|
433
432
|
if (!node)
|
|
434
433
|
return;
|
|
435
434
|
// Use zoomAt with the center of the container for consistent behavior
|
|
@@ -448,7 +447,6 @@ export const usePanzoom = (opts = {}) => {
|
|
|
448
447
|
zoomBy(factor);
|
|
449
448
|
}
|
|
450
449
|
function zoomOut(factor = 1.25) {
|
|
451
|
-
console.log('zoomOut', factor);
|
|
452
450
|
// zoom out by inverse multiplier
|
|
453
451
|
if (factor <= 0)
|
|
454
452
|
return;
|
|
@@ -6,6 +6,8 @@ const singleAsteriskPattern = /(\*)([^*]*?)$/;
|
|
|
6
6
|
const singleUnderscorePattern = /(_)([^_]*?)$/;
|
|
7
7
|
const inlineCodePattern = /(`)([^`]*?)$/;
|
|
8
8
|
const strikethroughPattern = /(~~)([^~]*?)$/;
|
|
9
|
+
const subPattern = /(~)([^~]*?)$/;
|
|
10
|
+
const supPattern = /(\^)([^\^]*?)$/;
|
|
9
11
|
// Helper function to check if we have a complete code block
|
|
10
12
|
const hasCompleteCodeBlock = (text) => {
|
|
11
13
|
const tripleBackticks = (text.match(/```/g) || []).length;
|
|
@@ -196,6 +198,38 @@ const isWithinMathBlock = (text, position) => {
|
|
|
196
198
|
}
|
|
197
199
|
return inInlineMath || inBlockMath;
|
|
198
200
|
};
|
|
201
|
+
// Check if a position is within a footnote reference pattern [^label]
|
|
202
|
+
const isWithinFootnoteRef = (text, position) => {
|
|
203
|
+
// Look backwards from position to find if we're inside [^...]
|
|
204
|
+
let openBracketPos = -1;
|
|
205
|
+
let caretPos = -1;
|
|
206
|
+
for (let i = position; i >= 0; i--) {
|
|
207
|
+
if (text[i] === ']') {
|
|
208
|
+
// Found closing bracket before our position, not in footnote
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
if (text[i] === '^' && caretPos === -1) {
|
|
212
|
+
caretPos = i;
|
|
213
|
+
}
|
|
214
|
+
if (text[i] === '[') {
|
|
215
|
+
openBracketPos = i;
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// Check if we have the pattern [^ and our position is after the caret
|
|
220
|
+
if (openBracketPos !== -1 && caretPos === openBracketPos + 1 && position >= caretPos) {
|
|
221
|
+
// Look forward to see if there's a closing bracket
|
|
222
|
+
for (let i = position + 1; i < text.length; i++) {
|
|
223
|
+
if (text[i] === ']') {
|
|
224
|
+
return true; // We're inside [^...] pattern
|
|
225
|
+
}
|
|
226
|
+
if (text[i] === '[' || text[i] === '\n') {
|
|
227
|
+
break; // Invalid pattern
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return false;
|
|
232
|
+
};
|
|
199
233
|
// Counts single underscores that are not part of double underscores, not escaped, and not in math blocks
|
|
200
234
|
const countSingleUnderscores = (text) => {
|
|
201
235
|
return text.split('').reduce((acc, char, index) => {
|
|
@@ -335,6 +369,127 @@ const handleIncompleteStrikethrough = (text) => {
|
|
|
335
369
|
}
|
|
336
370
|
return text;
|
|
337
371
|
};
|
|
372
|
+
// Counts single tildes that are not part of double tildes and not escaped
|
|
373
|
+
const countSingleTildes = (text) => {
|
|
374
|
+
return text.split('').reduce((acc, char, index) => {
|
|
375
|
+
if (char === '~') {
|
|
376
|
+
const prevChar = text[index - 1];
|
|
377
|
+
const nextChar = text[index + 1];
|
|
378
|
+
// Skip if escaped with backslash
|
|
379
|
+
if (prevChar === '\\') {
|
|
380
|
+
return acc;
|
|
381
|
+
}
|
|
382
|
+
if (prevChar !== '~' && nextChar !== '~') {
|
|
383
|
+
return acc + 1;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
return acc;
|
|
387
|
+
}, 0);
|
|
388
|
+
};
|
|
389
|
+
// Completes incomplete subscript formatting (~)
|
|
390
|
+
const handleIncompleteSub = (text) => {
|
|
391
|
+
// Don't process if inside a complete code block
|
|
392
|
+
if (hasCompleteCodeBlock(text)) {
|
|
393
|
+
return text;
|
|
394
|
+
}
|
|
395
|
+
const singleTildes = countSingleTildes(text);
|
|
396
|
+
if (singleTildes % 2 === 1) {
|
|
397
|
+
// Find the last unmatched tilde and add content until we find a good place to close
|
|
398
|
+
const lastTildeIndex = text.lastIndexOf('~');
|
|
399
|
+
if (lastTildeIndex !== -1) {
|
|
400
|
+
// Check if the tilde is within a math block - if so, don't process
|
|
401
|
+
if (isWithinMathBlock(text, lastTildeIndex)) {
|
|
402
|
+
return text;
|
|
403
|
+
}
|
|
404
|
+
const afterTilde = text.substring(lastTildeIndex + 1);
|
|
405
|
+
// Don't close if there's no meaningful content after the opening marker
|
|
406
|
+
if (!afterTilde || /^[\s_~*`^]*$/.test(afterTilde)) {
|
|
407
|
+
return text;
|
|
408
|
+
}
|
|
409
|
+
// Find the end of the subscript content
|
|
410
|
+
// For typical sub/sup patterns, look for single numbers, letters, or simple expressions
|
|
411
|
+
const endMatch = afterTilde.match(/^([0-9]+|[a-zA-Z]|[a-zA-Z0-9]{1,3})(?=\s|[^a-zA-Z0-9]|$)/);
|
|
412
|
+
if (endMatch) {
|
|
413
|
+
const contentLength = endMatch[1].length;
|
|
414
|
+
const insertPosition = lastTildeIndex + 1 + contentLength;
|
|
415
|
+
return text.substring(0, insertPosition) + '~' + text.substring(insertPosition);
|
|
416
|
+
}
|
|
417
|
+
else {
|
|
418
|
+
// Fallback: if no clear boundary, treat everything until space as content
|
|
419
|
+
const spaceMatch = afterTilde.match(/^([^\s]+)/);
|
|
420
|
+
if (spaceMatch) {
|
|
421
|
+
const contentLength = spaceMatch[1].length;
|
|
422
|
+
const insertPosition = lastTildeIndex + 1 + contentLength;
|
|
423
|
+
return text.substring(0, insertPosition) + '~' + text.substring(insertPosition);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
return text;
|
|
429
|
+
};
|
|
430
|
+
// Counts single carets that are not escaped and not in footnote references
|
|
431
|
+
const countSingleCarets = (text) => {
|
|
432
|
+
return text.split('').reduce((acc, char, index) => {
|
|
433
|
+
if (char === '^') {
|
|
434
|
+
const prevChar = text[index - 1];
|
|
435
|
+
// Skip if escaped with backslash
|
|
436
|
+
if (prevChar === '\\') {
|
|
437
|
+
return acc;
|
|
438
|
+
}
|
|
439
|
+
// Skip if within footnote reference
|
|
440
|
+
if (isWithinFootnoteRef(text, index)) {
|
|
441
|
+
return acc;
|
|
442
|
+
}
|
|
443
|
+
return acc + 1;
|
|
444
|
+
}
|
|
445
|
+
return acc;
|
|
446
|
+
}, 0);
|
|
447
|
+
};
|
|
448
|
+
// Completes incomplete superscript formatting (^)
|
|
449
|
+
const handleIncompleteSup = (text) => {
|
|
450
|
+
// Don't process if inside a complete code block
|
|
451
|
+
if (hasCompleteCodeBlock(text)) {
|
|
452
|
+
return text;
|
|
453
|
+
}
|
|
454
|
+
const singleCarets = countSingleCarets(text);
|
|
455
|
+
if (singleCarets % 2 === 1) {
|
|
456
|
+
// Find the last unmatched caret and add content until we find a good place to close
|
|
457
|
+
const lastCaretIndex = text.lastIndexOf('^');
|
|
458
|
+
if (lastCaretIndex !== -1) {
|
|
459
|
+
// Check if the caret is within a math block - if so, don't process
|
|
460
|
+
if (isWithinMathBlock(text, lastCaretIndex)) {
|
|
461
|
+
return text;
|
|
462
|
+
}
|
|
463
|
+
// Check if the caret is within a footnote reference - if so, don't process
|
|
464
|
+
if (isWithinFootnoteRef(text, lastCaretIndex)) {
|
|
465
|
+
return text;
|
|
466
|
+
}
|
|
467
|
+
const afterCaret = text.substring(lastCaretIndex + 1);
|
|
468
|
+
// Don't close if there's no meaningful content after the opening marker
|
|
469
|
+
if (!afterCaret || /^[\s_~*`^]*$/.test(afterCaret)) {
|
|
470
|
+
return text;
|
|
471
|
+
}
|
|
472
|
+
// Find the end of the superscript content
|
|
473
|
+
// For typical sub/sup patterns, look for single numbers, letters, or simple expressions
|
|
474
|
+
const endMatch = afterCaret.match(/^([0-9]+|[a-zA-Z]|[a-zA-Z0-9]{1,3})(?=\s|[^a-zA-Z0-9]|$)/);
|
|
475
|
+
if (endMatch) {
|
|
476
|
+
const contentLength = endMatch[1].length;
|
|
477
|
+
const insertPosition = lastCaretIndex + 1 + contentLength;
|
|
478
|
+
return text.substring(0, insertPosition) + '^' + text.substring(insertPosition);
|
|
479
|
+
}
|
|
480
|
+
else {
|
|
481
|
+
// Fallback: if no clear boundary, treat everything until space as content
|
|
482
|
+
const spaceMatch = afterCaret.match(/^([^\s]+)/);
|
|
483
|
+
if (spaceMatch) {
|
|
484
|
+
const contentLength = spaceMatch[1].length;
|
|
485
|
+
const insertPosition = lastCaretIndex + 1 + contentLength;
|
|
486
|
+
return text.substring(0, insertPosition) + '^' + text.substring(insertPosition);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return text;
|
|
492
|
+
};
|
|
338
493
|
// Counts single dollar signs that are not part of double dollar signs and not escaped
|
|
339
494
|
const _countSingleDollarSigns = (text) => {
|
|
340
495
|
return text.split('').reduce((acc, char, index) => {
|
|
@@ -435,6 +590,8 @@ export const parseIncompleteMarkdown = (text) => {
|
|
|
435
590
|
result = handleIncompleteSingleUnderscoreItalic(result);
|
|
436
591
|
result = handleIncompleteInlineCode(result);
|
|
437
592
|
result = handleIncompleteStrikethrough(result);
|
|
593
|
+
result = handleIncompleteSub(result);
|
|
594
|
+
result = handleIncompleteSup(result);
|
|
438
595
|
// Handle KaTeX formatting (only block math with $$)
|
|
439
596
|
result = handleIncompleteBlockKatex(result);
|
|
440
597
|
// Note: We don't handle inline KaTeX with single $ as they're likely currency symbols
|