markstream-svelte 0.0.1-beta.3 → 0.0.1-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/InlineCodeNode.svelte +60 -8
- package/dist/components/InlineCodeNode.svelte.d.ts +3 -1
- package/dist/components/MermaidBlockNode.svelte +3 -2
- package/dist/components/NodeOutlet.svelte +2 -1
- package/dist/components/NodeRenderer.svelte +254 -12
- package/dist/components/TextNode.svelte +12 -14
- package/dist/components/shared/node-helpers.d.ts +77 -9
- package/dist/components/shared/node-helpers.js +1 -0
- package/dist/components/shared/node-outlet-helpers.d.ts +3 -1
- package/dist/composables/useSmoothMarkdownStream.svelte.d.ts +19 -0
- package/dist/composables/useSmoothMarkdownStream.svelte.js +40 -0
- package/dist/context/smoothStreaming.d.ts +15 -0
- package/dist/context/smoothStreaming.js +14 -0
- package/dist/customComponents.d.ts +1 -1
- package/dist/enhanceRenderedHtml.d.ts +7 -5
- package/dist/enhanceRenderedHtml.js +2 -1
- package/dist/hydrateCustomTagContent.js +6 -3
- package/dist/index.css +38 -4
- package/dist/index.d.ts +5 -1
- package/dist/index.js +2 -0
- package/dist/index.px.css +38 -4
- package/dist/index.tailwind.css +38 -4
- package/dist/optional/d2.d.ts +13 -2
- package/dist/optional/infographic.d.ts +13 -1
- package/dist/optional/katex.d.ts +5 -2
- package/dist/optional/mermaid.d.ts +23 -2
- package/dist/optional/monaco.d.ts +18 -1
- package/dist/parseNestedMarkdownToNodes.d.ts +6 -1
- package/dist/types/monaco.d.ts +3 -3
- package/package.json +6 -4
|
@@ -1,13 +1,65 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type { SvelteRenderableNode } from './shared/node-helpers'
|
|
2
|
+
import type { SvelteRenderableNode, SvelteRenderContext } from './shared/node-helpers'
|
|
3
|
+
import { resolveStreamingTextState } from 'markstream-core'
|
|
3
4
|
import { getString } from './shared/node-helpers'
|
|
4
|
-
|
|
5
|
+
|
|
5
6
|
interface Props {
|
|
6
|
-
node: SvelteRenderableNode
|
|
7
|
+
node: SvelteRenderableNode
|
|
8
|
+
context?: SvelteRenderContext
|
|
9
|
+
indexKey?: string | number
|
|
7
10
|
}
|
|
8
|
-
|
|
9
|
-
let {
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
let {
|
|
13
|
+
node,
|
|
14
|
+
context = undefined,
|
|
15
|
+
indexKey = undefined,
|
|
16
|
+
}: Props = $props()
|
|
17
|
+
|
|
18
|
+
let previousKey = ''
|
|
19
|
+
let previousCode = ''
|
|
20
|
+
let deltaClass = 'markstream-svelte-text__stream-delta--a'
|
|
21
|
+
|
|
22
|
+
const code = $derived(getString((node as any)?.code ?? (node as any)?.content ?? (node as any)?.raw))
|
|
23
|
+
const streamKey = $derived(
|
|
24
|
+
`${String(context?.customId ?? 'global')}:${String(context?.streamRenderVersion ?? 0)}:${String(indexKey ?? 'inline-code')}`,
|
|
25
|
+
)
|
|
26
|
+
const fadeEnabled = $derived(context?.fade !== false)
|
|
27
|
+
|
|
28
|
+
const streamInfo = $derived.by(() => {
|
|
29
|
+
const state = context?.textStreamState
|
|
30
|
+
const previous = streamKey === previousKey
|
|
31
|
+
? previousCode
|
|
32
|
+
: (state?.get(streamKey) ?? '')
|
|
33
|
+
|
|
34
|
+
const result = resolveStreamingTextState({
|
|
35
|
+
nextContent: code,
|
|
36
|
+
previousContent: previous,
|
|
37
|
+
typewriterEnabled: fadeEnabled,
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
if (result.appended) {
|
|
41
|
+
deltaClass = deltaClass.endsWith('--a')
|
|
42
|
+
? 'markstream-svelte-text__stream-delta--b'
|
|
43
|
+
: 'markstream-svelte-text__stream-delta--a'
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
previousKey = streamKey
|
|
47
|
+
previousCode = code
|
|
48
|
+
state?.set(streamKey, code)
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
stableCode: result.settledContent,
|
|
52
|
+
deltaCode: result.streamedDelta,
|
|
53
|
+
deltaClass,
|
|
54
|
+
}
|
|
55
|
+
})
|
|
12
56
|
</script>
|
|
13
|
-
|
|
57
|
+
|
|
58
|
+
<code class="inline-code-node">
|
|
59
|
+
{streamInfo.stableCode}
|
|
60
|
+
{#if streamInfo.deltaCode}
|
|
61
|
+
<span class="markstream-svelte-text__stream-delta text-node-stream-delta {streamInfo.deltaClass}">
|
|
62
|
+
{streamInfo.deltaCode}
|
|
63
|
+
</span>
|
|
64
|
+
{/if}
|
|
65
|
+
</code>
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import type { SvelteRenderableNode } from './shared/node-helpers';
|
|
1
|
+
import type { SvelteRenderableNode, SvelteRenderContext } from './shared/node-helpers';
|
|
2
2
|
interface Props {
|
|
3
3
|
node: SvelteRenderableNode;
|
|
4
|
+
context?: SvelteRenderContext;
|
|
5
|
+
indexKey?: string | number;
|
|
4
6
|
}
|
|
5
7
|
declare const InlineCodeNode: import("svelte").Component<Props, {}, "">;
|
|
6
8
|
type InlineCodeNode = ReturnType<typeof InlineCodeNode>;
|
|
@@ -250,7 +250,8 @@
|
|
|
250
250
|
lastRenderedCode = normalized
|
|
251
251
|
svgCache[theme] = safeSvg
|
|
252
252
|
}
|
|
253
|
-
rendered
|
|
253
|
+
if (typeof rendered !== 'string')
|
|
254
|
+
rendered?.bindFunctions?.(document.createElement('div'))
|
|
254
255
|
}
|
|
255
256
|
catch (error) {
|
|
256
257
|
if (token === renderToken) {
|
|
@@ -582,4 +583,4 @@
|
|
|
582
583
|
</div>
|
|
583
584
|
{/if}
|
|
584
585
|
</div>
|
|
585
|
-
{/if}
|
|
586
|
+
{/if}
|
|
@@ -103,6 +103,7 @@
|
|
|
103
103
|
isDark={context?.isDark}
|
|
104
104
|
indexKey={indexKey}
|
|
105
105
|
typewriter={context?.typewriter}
|
|
106
|
+
fade={context?.fade}
|
|
106
107
|
{...customInputs}
|
|
107
108
|
/>
|
|
108
109
|
{:else if resolvedType === 'text' || resolvedType === 'text_special'}
|
|
@@ -136,7 +137,7 @@
|
|
|
136
137
|
{:else if resolvedType === 'image'}
|
|
137
138
|
<ImageNode {node} />
|
|
138
139
|
{:else if resolvedType === 'inline_code'}
|
|
139
|
-
<InlineCodeNode {node} />
|
|
140
|
+
<InlineCodeNode {node} {context} {indexKey} />
|
|
140
141
|
{:else if resolvedType === 'strong'}
|
|
141
142
|
<StrongNode {node} {context} {indexKey} />
|
|
142
143
|
{:else if resolvedType === 'emphasis'}
|
|
@@ -5,11 +5,14 @@
|
|
|
5
5
|
SvelteRenderableNode,
|
|
6
6
|
SvelteRenderContext,
|
|
7
7
|
} from './shared/node-helpers'
|
|
8
|
-
import { onDestroy, onMount, tick } from 'svelte'
|
|
8
|
+
import { getContext, onDestroy, onMount, setContext, tick } from 'svelte'
|
|
9
9
|
import { getCustomNodeComponents, subscribeCustomComponents } from '../customComponents'
|
|
10
10
|
import { disposeRenderedHtmlEnhancements, enhanceRenderedHtml } from '../enhanceRenderedHtml'
|
|
11
11
|
import NodeOutlet from './NodeOutlet.svelte'
|
|
12
12
|
import { buildRenderContext, resolveParsedNodes } from './shared/node-helpers'
|
|
13
|
+
import { useSmoothMarkdownStream } from '../composables/useSmoothMarkdownStream.svelte'
|
|
14
|
+
import { SMOOTH_STREAMING_CONTEXT } from '../context/smoothStreaming'
|
|
15
|
+
import type { SmoothStreamingContextValue } from '../context/smoothStreaming'
|
|
13
16
|
|
|
14
17
|
type NodeRendererComponentProps = NodeRendererProps & NodeRendererEvents & {
|
|
15
18
|
className?: string
|
|
@@ -45,7 +48,8 @@
|
|
|
45
48
|
isDark = false,
|
|
46
49
|
customId = undefined,
|
|
47
50
|
indexKey = undefined,
|
|
48
|
-
typewriter =
|
|
51
|
+
typewriter = false,
|
|
52
|
+
fade = true,
|
|
49
53
|
batchRendering = true,
|
|
50
54
|
initialRenderBatchSize = 40,
|
|
51
55
|
renderBatchSize = 80,
|
|
@@ -56,6 +60,8 @@
|
|
|
56
60
|
maxLiveNodes = 320,
|
|
57
61
|
liveNodeBuffer = 60,
|
|
58
62
|
allowHtml = true,
|
|
63
|
+
smoothStreaming = 'auto' as boolean | 'auto',
|
|
64
|
+
smoothStreamingOptions = undefined,
|
|
59
65
|
className = '',
|
|
60
66
|
onCopy = undefined,
|
|
61
67
|
onHandleArtifactClick = undefined,
|
|
@@ -78,10 +84,91 @@
|
|
|
78
84
|
let renderBatchToken = 0
|
|
79
85
|
const textStreamState = new Map<string, string>()
|
|
80
86
|
|
|
87
|
+
const smoothStream = useSmoothMarkdownStream(smoothStreamingOptions)
|
|
88
|
+
let hasMountedForSmoothStreaming = $state(typeof window === 'undefined' || smoothStreaming === true)
|
|
89
|
+
const hasNodes = $derived(Array.isArray(nodes))
|
|
90
|
+
const parentSmoothStreaming = getContext<SmoothStreamingContextValue | undefined>(
|
|
91
|
+
SMOOTH_STREAMING_CONTEXT,
|
|
92
|
+
)
|
|
93
|
+
const smoothStreamingEligible = $derived.by(() => {
|
|
94
|
+
if (smoothStreaming === false)
|
|
95
|
+
return false
|
|
96
|
+
if (hasNodes)
|
|
97
|
+
return false
|
|
98
|
+
// When the parent renderer is already pacing content, avoid double-pacing
|
|
99
|
+
// in nested renderers (e.g. thinking blocks, custom tag content).
|
|
100
|
+
// Only applies in 'auto' mode — smoothStreaming === true explicitly opts in.
|
|
101
|
+
if (smoothStreaming !== true && parentSmoothStreaming?.())
|
|
102
|
+
return false
|
|
103
|
+
if (smoothStreaming === true)
|
|
104
|
+
return true
|
|
105
|
+
return typewriter === true || (maxLiveNodes ?? 0) <= 0
|
|
106
|
+
})
|
|
107
|
+
const smoothStreamingEnabled = $derived(hasMountedForSmoothStreaming && smoothStreamingEligible)
|
|
108
|
+
setContext(SMOOTH_STREAMING_CONTEXT, () => smoothStreamingEnabled)
|
|
109
|
+
|
|
110
|
+
// Baseline sync: in auto mode with initial static content, ensure the smooth
|
|
111
|
+
// stream source/visible is already synced before smooth streaming activates.
|
|
112
|
+
// This prevents a blank flash when the mount gate opens and renderContent
|
|
113
|
+
// switches from raw content to smoothStream.visible (which would be empty).
|
|
114
|
+
if (
|
|
115
|
+
smoothStreaming !== true
|
|
116
|
+
&& !Array.isArray(nodes)
|
|
117
|
+
&& content
|
|
118
|
+
) {
|
|
119
|
+
smoothStream.reset(content)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const renderContent = $derived(smoothStreamingEnabled ? smoothStream.visible : (content ?? ''))
|
|
123
|
+
const rawContent = $derived(content ?? '')
|
|
124
|
+
const smoothSourceSynced = $derived(hasNodes || smoothStream.source === rawContent)
|
|
125
|
+
const requestedFinal = $derived.by(() => {
|
|
126
|
+
const base = parseOptions ?? {}
|
|
127
|
+
return final ?? (base as any).final
|
|
128
|
+
})
|
|
129
|
+
const effectiveFinal = $derived.by(() => {
|
|
130
|
+
if (smoothStreamingEnabled && requestedFinal != null)
|
|
131
|
+
return Boolean(requestedFinal && smoothSourceSynced && smoothStream.caughtUp)
|
|
132
|
+
return requestedFinal
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
onMount(() => {
|
|
136
|
+
hasMountedForSmoothStreaming = true
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
$effect(() => {
|
|
140
|
+
const nextContent = content ?? ''
|
|
141
|
+
if (hasNodes) {
|
|
142
|
+
smoothStream.reset('')
|
|
143
|
+
return
|
|
144
|
+
}
|
|
145
|
+
if (!smoothStreamingEnabled) {
|
|
146
|
+
smoothStream.reset(nextContent)
|
|
147
|
+
if (requestedFinal)
|
|
148
|
+
smoothStream.finish({ flush: true })
|
|
149
|
+
return
|
|
150
|
+
}
|
|
151
|
+
const source = smoothStream.source
|
|
152
|
+
if (!nextContent) {
|
|
153
|
+
smoothStream.reset('')
|
|
154
|
+
}
|
|
155
|
+
else if (nextContent === source) {
|
|
156
|
+
// no-op
|
|
157
|
+
}
|
|
158
|
+
else if (nextContent.startsWith(source)) {
|
|
159
|
+
smoothStream.enqueue(nextContent.slice(source.length))
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
smoothStream.reset(nextContent)
|
|
163
|
+
}
|
|
164
|
+
if (requestedFinal)
|
|
165
|
+
smoothStream.finish()
|
|
166
|
+
})
|
|
167
|
+
|
|
81
168
|
let rendererProps = $derived({
|
|
82
|
-
content,
|
|
169
|
+
content: renderContent,
|
|
83
170
|
nodes,
|
|
84
|
-
final,
|
|
171
|
+
final: effectiveFinal,
|
|
85
172
|
parseOptions,
|
|
86
173
|
customMarkdownIt,
|
|
87
174
|
debugPerformance,
|
|
@@ -106,6 +193,7 @@
|
|
|
106
193
|
customId,
|
|
107
194
|
indexKey,
|
|
108
195
|
typewriter,
|
|
196
|
+
fade,
|
|
109
197
|
batchRendering,
|
|
110
198
|
initialRenderBatchSize,
|
|
111
199
|
renderBatchSize,
|
|
@@ -116,12 +204,14 @@
|
|
|
116
204
|
maxLiveNodes,
|
|
117
205
|
liveNodeBuffer,
|
|
118
206
|
allowHtml,
|
|
207
|
+
smoothStreaming,
|
|
208
|
+
smoothStreamingOptions,
|
|
119
209
|
} satisfies NodeRendererProps)
|
|
120
210
|
|
|
121
211
|
$effect.pre(() => {
|
|
122
|
-
if (previousContent !==
|
|
212
|
+
if (previousContent !== renderContent || previousNodes !== nodes) {
|
|
123
213
|
streamRenderVersion += 1
|
|
124
|
-
previousContent =
|
|
214
|
+
previousContent = renderContent
|
|
125
215
|
previousNodes = nodes
|
|
126
216
|
}
|
|
127
217
|
})
|
|
@@ -133,7 +223,7 @@
|
|
|
133
223
|
console.info('[markstream-svelte][perf] parse(sync)', {
|
|
134
224
|
ms: Math.round(performance.now() - start),
|
|
135
225
|
nodes: nextParsedNodes.length,
|
|
136
|
-
contentLength:
|
|
226
|
+
contentLength: renderContent?.length ?? 0,
|
|
137
227
|
})
|
|
138
228
|
}
|
|
139
229
|
return nextParsedNodes
|
|
@@ -167,7 +257,7 @@
|
|
|
167
257
|
void renderBatchDelay
|
|
168
258
|
void renderBatchBudgetMs
|
|
169
259
|
void renderBatchIdleTimeoutMs
|
|
170
|
-
void
|
|
260
|
+
void effectiveFinal
|
|
171
261
|
void renderedNodeCount
|
|
172
262
|
syncRenderedNodeWindow()
|
|
173
263
|
})
|
|
@@ -175,7 +265,7 @@
|
|
|
175
265
|
|
|
176
266
|
$effect(() => {
|
|
177
267
|
void rootEl
|
|
178
|
-
void
|
|
268
|
+
void effectiveFinal
|
|
179
269
|
void parsedNodes
|
|
180
270
|
void renderedNodes
|
|
181
271
|
void isDark
|
|
@@ -203,6 +293,7 @@
|
|
|
203
293
|
enhancementHandle?.dispose()
|
|
204
294
|
enhancementHandle = null
|
|
205
295
|
disposeRenderedHtmlEnhancements(rootEl)
|
|
296
|
+
clearTypewriterCursorTimeout()
|
|
206
297
|
})
|
|
207
298
|
|
|
208
299
|
function toPositiveInteger(value: unknown, fallback: number) {
|
|
@@ -213,7 +304,7 @@
|
|
|
213
304
|
function syncRenderedNodeWindow() {
|
|
214
305
|
const total = parsedNodes.length
|
|
215
306
|
const initialCount = Math.min(total, toPositiveInteger(initialRenderBatchSize, 40))
|
|
216
|
-
const shouldBatch =
|
|
307
|
+
const shouldBatch = effectiveFinal !== false && batchRendering !== false && total > initialCount
|
|
217
308
|
|
|
218
309
|
if (!shouldBatch) {
|
|
219
310
|
cancelRenderBatch()
|
|
@@ -296,7 +387,7 @@
|
|
|
296
387
|
async function scheduleEnhancement() {
|
|
297
388
|
if (!rootEl || typeof window === 'undefined')
|
|
298
389
|
return
|
|
299
|
-
const enhancementFinal = typeof
|
|
390
|
+
const enhancementFinal = typeof effectiveFinal === 'boolean' ? effectiveFinal : !hasLoadingNodes(parsedNodes)
|
|
300
391
|
if (!enhancementFinal) {
|
|
301
392
|
enhancementToken += 1
|
|
302
393
|
enhancementHandle?.dispose()
|
|
@@ -335,6 +426,156 @@
|
|
|
335
426
|
return false
|
|
336
427
|
}
|
|
337
428
|
|
|
429
|
+
// ── Typewriter cursor ──
|
|
430
|
+
let typewriterCursorEl: HTMLSpanElement | null = $state(null)
|
|
431
|
+
let showTypewriterCursor = $state(false)
|
|
432
|
+
let typewriterCursorTimeout: ReturnType<typeof setTimeout> | undefined
|
|
433
|
+
let lastTypewriterContentLength = 0
|
|
434
|
+
const TYPEWRITER_CURSOR_EXCLUDED_NODE_TYPES = new Set(['code_block', 'admonition', 'table', 'math_block', 'html_block', 'image'])
|
|
435
|
+
|
|
436
|
+
function shouldSkipTypewriterCursorForNode(node: unknown) {
|
|
437
|
+
if (!node || typeof node !== 'object')
|
|
438
|
+
return false
|
|
439
|
+
const type = (node as Record<string, unknown>).type
|
|
440
|
+
return typeof type === 'string' && TYPEWRITER_CURSOR_EXCLUDED_NODE_TYPES.has(type)
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
function shouldShowTypewriterCursorForCurrentNodes() {
|
|
444
|
+
const lastNode = parsedNodes[parsedNodes.length - 1]
|
|
445
|
+
return !shouldSkipTypewriterCursorForNode(lastNode)
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function getNodeTextLength(node: unknown): number {
|
|
449
|
+
if (!node || typeof node !== 'object')
|
|
450
|
+
return 0
|
|
451
|
+
const record = node as Record<string, unknown>
|
|
452
|
+
const direct = record.raw ?? record.content ?? record.code
|
|
453
|
+
if (typeof direct === 'string')
|
|
454
|
+
return direct.length
|
|
455
|
+
const children = record.children
|
|
456
|
+
if (Array.isArray(children))
|
|
457
|
+
return children.reduce((total: number, child: unknown) => total + getNodeTextLength(child), 0)
|
|
458
|
+
const items = record.items
|
|
459
|
+
if (Array.isArray(items))
|
|
460
|
+
return items.reduce((total: number, item: unknown) => total + getNodeTextLength(item), 0)
|
|
461
|
+
return 0
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
function getTypewriterContentLength() {
|
|
465
|
+
if (nodes?.length)
|
|
466
|
+
return nodes.reduce((total: number, node: unknown) => total + getNodeTextLength(node), 0)
|
|
467
|
+
// Use raw content length, not renderContent (which may be the paced-out
|
|
468
|
+
// visible portion when smooth streaming is active).
|
|
469
|
+
return (content ?? '').length
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
function clearTypewriterCursorTimeout() {
|
|
473
|
+
if (!typewriterCursorTimeout)
|
|
474
|
+
return
|
|
475
|
+
clearTimeout(typewriterCursorTimeout)
|
|
476
|
+
typewriterCursorTimeout = undefined
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
function getLastTextNode(root: HTMLElement) {
|
|
480
|
+
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
|
|
481
|
+
acceptNode(node) {
|
|
482
|
+
const text = node.textContent ?? ''
|
|
483
|
+
if (!text.trim())
|
|
484
|
+
return NodeFilter.FILTER_REJECT
|
|
485
|
+
const parent = node.parentElement
|
|
486
|
+
if (!parent)
|
|
487
|
+
return NodeFilter.FILTER_REJECT
|
|
488
|
+
if (parent.closest('.typewriter-cursor, .height-estimation-probes, [data-node-type="code_block"], [data-node-type="admonition"], [data-node-type="table"], [data-node-type="math_block"], [data-node-type="html_block"], [data-node-type="image"], script, style'))
|
|
489
|
+
return NodeFilter.FILTER_REJECT
|
|
490
|
+
return NodeFilter.FILTER_ACCEPT
|
|
491
|
+
},
|
|
492
|
+
})
|
|
493
|
+
let last: Text | null = null
|
|
494
|
+
let current = walker.nextNode()
|
|
495
|
+
while (current) {
|
|
496
|
+
last = current as Text
|
|
497
|
+
current = walker.nextNode()
|
|
498
|
+
}
|
|
499
|
+
return last
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
function updateTypewriterCursorPosition() {
|
|
503
|
+
if (typeof window === 'undefined' || !showTypewriterCursor || !rootEl || !typewriterCursorEl)
|
|
504
|
+
return
|
|
505
|
+
const root = rootEl
|
|
506
|
+
const cursor = typewriterCursorEl
|
|
507
|
+
const lastText = getLastTextNode(root)
|
|
508
|
+
const rootRect = root.getBoundingClientRect()
|
|
509
|
+
let left = 0
|
|
510
|
+
let top = 0
|
|
511
|
+
let height = 20
|
|
512
|
+
|
|
513
|
+
if (lastText?.textContent) {
|
|
514
|
+
const range = document.createRange()
|
|
515
|
+
const end = lastText.textContent.length
|
|
516
|
+
range.setStart(lastText, Math.max(0, end - 1))
|
|
517
|
+
range.setEnd(lastText, end)
|
|
518
|
+
const rects = typeof range.getClientRects === 'function'
|
|
519
|
+
? range.getClientRects()
|
|
520
|
+
: undefined
|
|
521
|
+
const rect = rects?.[rects.length - 1] ?? lastText.parentElement?.getBoundingClientRect()
|
|
522
|
+
if (rect) {
|
|
523
|
+
left = rect.right - rootRect.left + root.scrollLeft
|
|
524
|
+
top = rect.top - rootRect.top + root.scrollTop
|
|
525
|
+
height = rect.height || height
|
|
526
|
+
}
|
|
527
|
+
range.detach()
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
cursor.style.transform = `translate(${Math.max(0, left)}px, ${Math.max(0, top)}px)`
|
|
531
|
+
cursor.style.height = `${height}px`
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
$effect(() => {
|
|
535
|
+
void renderContent
|
|
536
|
+
void nodes
|
|
537
|
+
void typewriter
|
|
538
|
+
void parsedNodes.length
|
|
539
|
+
void effectiveFinal
|
|
540
|
+
if (typeof window === 'undefined' || hasNodes)
|
|
541
|
+
return
|
|
542
|
+
|
|
543
|
+
// When the stream is final (and effective — smooth streaming has caught up),
|
|
544
|
+
// hide the cursor immediately.
|
|
545
|
+
if (effectiveFinal) {
|
|
546
|
+
showTypewriterCursor = false
|
|
547
|
+
clearTypewriterCursorTimeout()
|
|
548
|
+
return
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
const nextLength = getTypewriterContentLength()
|
|
552
|
+
const cursorAllowed = shouldShowTypewriterCursorForCurrentNodes()
|
|
553
|
+
if (typewriter === false || !cursorAllowed || nextLength <= lastTypewriterContentLength) {
|
|
554
|
+
if (typewriter === false || !cursorAllowed)
|
|
555
|
+
showTypewriterCursor = false
|
|
556
|
+
lastTypewriterContentLength = nextLength
|
|
557
|
+
return
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
lastTypewriterContentLength = nextLength
|
|
561
|
+
showTypewriterCursor = true
|
|
562
|
+
clearTypewriterCursorTimeout()
|
|
563
|
+
tick().then(() => {
|
|
564
|
+
updateTypewriterCursorPosition()
|
|
565
|
+
})
|
|
566
|
+
typewriterCursorTimeout = setTimeout(() => {
|
|
567
|
+
showTypewriterCursor = false
|
|
568
|
+
}, 3000)
|
|
569
|
+
})
|
|
570
|
+
|
|
571
|
+
$effect(() => {
|
|
572
|
+
if (!showTypewriterCursor)
|
|
573
|
+
return
|
|
574
|
+
tick().then(() => {
|
|
575
|
+
updateTypewriterCursorPosition()
|
|
576
|
+
})
|
|
577
|
+
})
|
|
578
|
+
|
|
338
579
|
function handleMouseover(event: MouseEvent) {
|
|
339
580
|
const target = event.target as HTMLElement | null
|
|
340
581
|
if (target?.closest('[data-node-index]'))
|
|
@@ -362,9 +603,10 @@
|
|
|
362
603
|
>
|
|
363
604
|
{#each renderedNodes as node, index ((indexKey != null ? String(indexKey) : 'markdown-renderer') + '-' + index)}
|
|
364
605
|
<div class="node-slot" data-node-index={index} data-node-type={(node as any)?.type}>
|
|
365
|
-
<div class:typewriter-node={
|
|
606
|
+
<div class:fade-node={fade !== false && String((node as any)?.type || '') !== 'code_block'} class:typewriter-node={fade !== false && String((node as any)?.type || '') !== 'code_block'} class="node-content" data-node-index={index}>
|
|
366
607
|
<NodeOutlet node={node} context={renderContext} indexKey={(indexKey != null ? String(indexKey) : 'markdown-renderer') + '-' + index} />
|
|
367
608
|
</div>
|
|
368
609
|
</div>
|
|
369
610
|
{/each}
|
|
611
|
+
{#if showTypewriterCursor}<span bind:this={typewriterCursorEl} class="typewriter-cursor" aria-hidden="true"></span>{/if}
|
|
370
612
|
</div>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { SvelteRenderableNode, SvelteRenderContext } from './shared/node-helpers'
|
|
3
|
+
import { resolveStreamingTextState } from 'markstream-core'
|
|
3
4
|
import { getString } from './shared/node-helpers'
|
|
4
5
|
|
|
5
6
|
interface Props {
|
|
@@ -23,30 +24,27 @@
|
|
|
23
24
|
const content = $derived(getString((node as any)?.content ?? (node as any)?.raw))
|
|
24
25
|
const centered = $derived(Boolean((node as any)?.center))
|
|
25
26
|
const streamKey = $derived(String(context?.customId ?? 'global') + ':' + String(context?.streamRenderVersion ?? 0) + ':' + String(indexKey ?? 'node'))
|
|
27
|
+
const fadeEnabled = $derived(context?.fade !== false)
|
|
26
28
|
|
|
27
29
|
const streamInfo = $derived.by(() => {
|
|
28
30
|
const state = context?.textStreamState
|
|
29
31
|
const previous = streamKey === previousKey ? previousContent : (state?.get(streamKey) ?? '')
|
|
30
|
-
|
|
31
|
-
let stableContent = ''
|
|
32
|
-
let deltaContent = ''
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
const result = resolveStreamingTextState({
|
|
34
|
+
nextContent: content,
|
|
35
|
+
previousContent: previous,
|
|
36
|
+
typewriterEnabled: fadeEnabled,
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
if (result.appended)
|
|
37
40
|
deltaClass = deltaClass.endsWith('--a') ? 'markstream-svelte-text__stream-delta--b' : 'markstream-svelte-text__stream-delta--a'
|
|
38
|
-
|
|
39
|
-
else {
|
|
40
|
-
stableContent = content
|
|
41
|
-
deltaContent = ''
|
|
42
|
-
}
|
|
43
|
-
|
|
41
|
+
|
|
44
42
|
previousKey = streamKey
|
|
45
43
|
previousContent = content
|
|
46
44
|
state?.set(streamKey, content)
|
|
47
45
|
|
|
48
|
-
return { stableContent, deltaContent, deltaClass }
|
|
46
|
+
return { stableContent: result.settledContent, deltaContent: result.streamedDelta, deltaClass }
|
|
49
47
|
})
|
|
50
48
|
</script>
|
|
51
49
|
|
|
52
|
-
<span data-typewriter={typewriter
|
|
50
|
+
<span data-typewriter={context?.typewriter === true ? '1' : undefined} class:markstream-svelte-text--centered={centered} class="markstream-svelte-text-node text-node">{streamInfo.stableContent}{#if streamInfo.deltaContent}<span class="markstream-svelte-text__stream-delta text-node-stream-delta {streamInfo.deltaClass}">{streamInfo.deltaContent}</span>{/if}</span>
|
|
@@ -1,12 +1,76 @@
|
|
|
1
|
+
import type { SmoothMarkdownStreamOptions } from 'markstream-core';
|
|
1
2
|
import type { BaseNode, HtmlPolicy, MarkdownIt, ParsedNode, ParseOptions } from 'stream-markdown-parser';
|
|
2
3
|
import type { CustomComponentMap } from '../../customComponents';
|
|
3
4
|
import type { CodeBlockMonacoOptions, CodeBlockMonacoTheme } from '../../types/monaco';
|
|
4
5
|
import { getHtmlTagFromContent, hasCompleteHtmlTagContent, normalizeCustomHtmlTags, normalizeCustomHtmlTagName as normalizeTagName, stripCustomHtmlWrapper } from 'stream-markdown-parser';
|
|
5
6
|
export { getHtmlTagFromContent, hasCompleteHtmlTagContent, normalizeCustomHtmlTags, normalizeTagName, stripCustomHtmlWrapper, };
|
|
6
7
|
export type SvelteRenderableNode = (ParsedNode | BaseNode) & Record<string, unknown>;
|
|
8
|
+
export interface CodeBlockPreviewPayload {
|
|
9
|
+
node: SvelteRenderableNode;
|
|
10
|
+
artifactType: 'text/html' | 'image/svg+xml';
|
|
11
|
+
artifactTitle: string;
|
|
12
|
+
id: string;
|
|
13
|
+
}
|
|
14
|
+
export type NodeRendererCodeBlockProps = Partial<{
|
|
15
|
+
stream: boolean;
|
|
16
|
+
darkTheme: CodeBlockMonacoTheme;
|
|
17
|
+
lightTheme: CodeBlockMonacoTheme;
|
|
18
|
+
themes: CodeBlockMonacoTheme[];
|
|
19
|
+
monacoOptions: CodeBlockMonacoOptions;
|
|
20
|
+
minWidth: string | number;
|
|
21
|
+
maxWidth: string | number;
|
|
22
|
+
isShowPreview: boolean;
|
|
23
|
+
enableFontSizeControl: boolean;
|
|
24
|
+
showHeader: boolean;
|
|
25
|
+
showCopyButton: boolean;
|
|
26
|
+
showExpandButton: boolean;
|
|
27
|
+
showPreviewButton: boolean;
|
|
28
|
+
showCollapseButton: boolean;
|
|
29
|
+
showFontSizeButtons: boolean;
|
|
30
|
+
htmlPreviewAllowScripts: boolean;
|
|
31
|
+
htmlPreviewSandbox: string;
|
|
32
|
+
}> & Record<string, unknown>;
|
|
33
|
+
export type NodeRendererMermaidProps = Partial<{
|
|
34
|
+
maxHeight: string | null;
|
|
35
|
+
estimatedPreviewHeightPx: number;
|
|
36
|
+
workerTimeoutMs: number;
|
|
37
|
+
parseTimeoutMs: number;
|
|
38
|
+
renderTimeoutMs: number;
|
|
39
|
+
fullRenderTimeoutMs: number;
|
|
40
|
+
renderDebounceMs: number;
|
|
41
|
+
showHeader: boolean;
|
|
42
|
+
showModeToggle: boolean;
|
|
43
|
+
showCopyButton: boolean;
|
|
44
|
+
showExportButton: boolean;
|
|
45
|
+
showFullscreenButton: boolean;
|
|
46
|
+
showCollapseButton: boolean;
|
|
47
|
+
showZoomControls: boolean;
|
|
48
|
+
isStrict: boolean;
|
|
49
|
+
}> & Record<string, unknown>;
|
|
50
|
+
export type NodeRendererD2Props = Partial<{
|
|
51
|
+
maxHeight: string | null;
|
|
52
|
+
themeId: number | null;
|
|
53
|
+
darkThemeId: number | null;
|
|
54
|
+
showHeader: boolean;
|
|
55
|
+
showModeToggle: boolean;
|
|
56
|
+
showCopyButton: boolean;
|
|
57
|
+
showExportButton: boolean;
|
|
58
|
+
showCollapseButton: boolean;
|
|
59
|
+
}> & Record<string, unknown>;
|
|
60
|
+
export type NodeRendererInfographicProps = Partial<{
|
|
61
|
+
maxHeight: string | null;
|
|
62
|
+
estimatedPreviewHeightPx: number;
|
|
63
|
+
showHeader: boolean;
|
|
64
|
+
showModeToggle: boolean;
|
|
65
|
+
showCopyButton: boolean;
|
|
66
|
+
showCollapseButton: boolean;
|
|
67
|
+
showExportButton: boolean;
|
|
68
|
+
showFullscreenButton: boolean;
|
|
69
|
+
showZoomControls: boolean;
|
|
70
|
+
}> & Record<string, unknown>;
|
|
7
71
|
export interface NodeRendererEvents {
|
|
8
72
|
onCopy?: (code: string) => void;
|
|
9
|
-
onHandleArtifactClick?: (payload:
|
|
73
|
+
onHandleArtifactClick?: (payload: CodeBlockPreviewPayload) => void;
|
|
10
74
|
}
|
|
11
75
|
export interface NodeRendererProps {
|
|
12
76
|
content?: string;
|
|
@@ -25,10 +89,10 @@ export interface NodeRendererProps {
|
|
|
25
89
|
renderCodeBlocksAsPre?: boolean;
|
|
26
90
|
codeBlockMinWidth?: string | number;
|
|
27
91
|
codeBlockMaxWidth?: string | number;
|
|
28
|
-
codeBlockProps?:
|
|
29
|
-
mermaidProps?:
|
|
30
|
-
d2Props?:
|
|
31
|
-
infographicProps?:
|
|
92
|
+
codeBlockProps?: NodeRendererCodeBlockProps;
|
|
93
|
+
mermaidProps?: NodeRendererMermaidProps;
|
|
94
|
+
d2Props?: NodeRendererD2Props;
|
|
95
|
+
infographicProps?: NodeRendererInfographicProps;
|
|
32
96
|
customComponents?: CustomComponentMap;
|
|
33
97
|
showTooltips?: boolean;
|
|
34
98
|
themes?: CodeBlockMonacoTheme[];
|
|
@@ -36,6 +100,7 @@ export interface NodeRendererProps {
|
|
|
36
100
|
customId?: string;
|
|
37
101
|
indexKey?: number | string;
|
|
38
102
|
typewriter?: boolean;
|
|
103
|
+
fade?: boolean;
|
|
39
104
|
batchRendering?: boolean;
|
|
40
105
|
initialRenderBatchSize?: number;
|
|
41
106
|
renderBatchSize?: number;
|
|
@@ -46,6 +111,8 @@ export interface NodeRendererProps {
|
|
|
46
111
|
maxLiveNodes?: number;
|
|
47
112
|
liveNodeBuffer?: number;
|
|
48
113
|
allowHtml?: boolean;
|
|
114
|
+
smoothStreaming?: boolean | 'auto';
|
|
115
|
+
smoothStreamingOptions?: SmoothMarkdownStreamOptions;
|
|
49
116
|
}
|
|
50
117
|
export interface SvelteRenderContext {
|
|
51
118
|
customId?: string;
|
|
@@ -53,6 +120,7 @@ export interface SvelteRenderContext {
|
|
|
53
120
|
indexKey?: string;
|
|
54
121
|
final?: boolean;
|
|
55
122
|
typewriter?: boolean;
|
|
123
|
+
fade?: boolean;
|
|
56
124
|
textStreamState?: Map<string, string>;
|
|
57
125
|
streamRenderVersion?: number;
|
|
58
126
|
showTooltips?: boolean;
|
|
@@ -63,10 +131,10 @@ export interface SvelteRenderContext {
|
|
|
63
131
|
customHtmlTags?: readonly string[];
|
|
64
132
|
parseOptions?: ParseOptions;
|
|
65
133
|
customMarkdownIt?: (md: MarkdownIt) => MarkdownIt;
|
|
66
|
-
codeBlockProps?:
|
|
67
|
-
mermaidProps?:
|
|
68
|
-
d2Props?:
|
|
69
|
-
infographicProps?:
|
|
134
|
+
codeBlockProps?: NodeRendererCodeBlockProps;
|
|
135
|
+
mermaidProps?: NodeRendererMermaidProps;
|
|
136
|
+
d2Props?: NodeRendererD2Props;
|
|
137
|
+
infographicProps?: NodeRendererInfographicProps;
|
|
70
138
|
customComponents?: CustomComponentMap;
|
|
71
139
|
codeBlockThemes?: {
|
|
72
140
|
themes?: CodeBlockMonacoTheme[];
|
|
@@ -29,6 +29,7 @@ export function buildRenderContext(props, events = {}, textStreamState, streamRe
|
|
|
29
29
|
indexKey: props.indexKey != null ? String(props.indexKey) : undefined,
|
|
30
30
|
final: props.final,
|
|
31
31
|
typewriter: props.typewriter,
|
|
32
|
+
fade: props.fade,
|
|
32
33
|
textStreamState,
|
|
33
34
|
streamRenderVersion,
|
|
34
35
|
showTooltips: props.showTooltips,
|
|
@@ -4,5 +4,7 @@ export declare function resolveNodeOutletCodeMode(node: SvelteRenderableNode, co
|
|
|
4
4
|
export declare function resolveHtmlTag(node: SvelteRenderableNode): string;
|
|
5
5
|
export declare function coerceCustomHtmlNode(node: SvelteRenderableNode): SvelteRenderableNode;
|
|
6
6
|
export declare function coerceBuiltinHtmlNode(node: SvelteRenderableNode, resolvedType: string): SvelteRenderableNode;
|
|
7
|
-
export declare function resolveNodeOutletCustomInputs(node: SvelteRenderableNode, context?: SvelteRenderContext):
|
|
7
|
+
export declare function resolveNodeOutletCustomInputs(node: SvelteRenderableNode, context?: SvelteRenderContext): {
|
|
8
|
+
[x: string]: any;
|
|
9
|
+
};
|
|
8
10
|
export declare function resolveNodeOutletCustomComponent(node: SvelteRenderableNode, context?: SvelteRenderContext, customComponents?: Record<string, any> | null): any;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { SmoothMarkdownStreamOptions } from 'markstream-core';
|
|
2
|
+
export type { SmoothMarkdownStreamOptions };
|
|
3
|
+
export interface SmoothMarkdownStreamControllerSvelte {
|
|
4
|
+
source: string;
|
|
5
|
+
visible: string;
|
|
6
|
+
done: boolean;
|
|
7
|
+
caughtUp: boolean;
|
|
8
|
+
final: boolean;
|
|
9
|
+
pendingChars: number;
|
|
10
|
+
enqueue: (chunk: string) => void;
|
|
11
|
+
finish: (options?: {
|
|
12
|
+
flush?: boolean;
|
|
13
|
+
}) => void;
|
|
14
|
+
flush: () => void;
|
|
15
|
+
reset: (initialMarkdown?: string) => void;
|
|
16
|
+
pause: () => void;
|
|
17
|
+
resume: () => void;
|
|
18
|
+
}
|
|
19
|
+
export declare function useSmoothMarkdownStream(options?: SmoothMarkdownStreamOptions): SmoothMarkdownStreamControllerSvelte;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { createSmoothMarkdownStream } from 'markstream-core';
|
|
2
|
+
import { onDestroy } from 'svelte';
|
|
3
|
+
export function useSmoothMarkdownStream(options = {}) {
|
|
4
|
+
let source = $state('');
|
|
5
|
+
let visible = $state('');
|
|
6
|
+
let done = $state(false);
|
|
7
|
+
let pendingChars = $state(0);
|
|
8
|
+
let caughtUp = $state(false);
|
|
9
|
+
let final = $state(false);
|
|
10
|
+
const controller = createSmoothMarkdownStream(options);
|
|
11
|
+
const sync = () => {
|
|
12
|
+
const snapshot = controller.getSnapshot();
|
|
13
|
+
source = snapshot.source;
|
|
14
|
+
visible = snapshot.visible;
|
|
15
|
+
done = snapshot.done;
|
|
16
|
+
pendingChars = snapshot.pendingChars;
|
|
17
|
+
caughtUp = snapshot.caughtUp;
|
|
18
|
+
final = snapshot.final;
|
|
19
|
+
};
|
|
20
|
+
const unsubscribe = controller.subscribe(sync);
|
|
21
|
+
sync();
|
|
22
|
+
onDestroy(() => {
|
|
23
|
+
unsubscribe();
|
|
24
|
+
controller.destroy();
|
|
25
|
+
});
|
|
26
|
+
return {
|
|
27
|
+
get source() { return source; },
|
|
28
|
+
get visible() { return visible; },
|
|
29
|
+
get done() { return done; },
|
|
30
|
+
get caughtUp() { return caughtUp; },
|
|
31
|
+
get final() { return final; },
|
|
32
|
+
get pendingChars() { return pendingChars; },
|
|
33
|
+
enqueue: chunk => controller.enqueue(chunk),
|
|
34
|
+
finish: opts => controller.finish(opts),
|
|
35
|
+
flush: () => controller.flush(),
|
|
36
|
+
reset: initialMarkdown => controller.reset(initialMarkdown),
|
|
37
|
+
pause: () => controller.pause(),
|
|
38
|
+
resume: () => controller.resume(),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context key and types for Svelte smooth streaming parent suppression.
|
|
3
|
+
*
|
|
4
|
+
* When a parent NodeRenderer is already pacing content via smooth streaming,
|
|
5
|
+
* nested renderers (e.g. thinking blocks, custom tag content) should suppress
|
|
6
|
+
* their own smooth streaming to avoid double-pacing.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* const parentSmoothStreaming = getContext<SmoothStreamingContextValue | undefined>(
|
|
10
|
+
* SMOOTH_STREAMING_CONTEXT,
|
|
11
|
+
* )
|
|
12
|
+
* setContext(SMOOTH_STREAMING_CONTEXT, () => smoothStreamingEnabled)
|
|
13
|
+
*/
|
|
14
|
+
export declare const SMOOTH_STREAMING_CONTEXT = "markstreamSmoothStreaming";
|
|
15
|
+
export type SmoothStreamingContextValue = () => boolean;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context key and types for Svelte smooth streaming parent suppression.
|
|
3
|
+
*
|
|
4
|
+
* When a parent NodeRenderer is already pacing content via smooth streaming,
|
|
5
|
+
* nested renderers (e.g. thinking blocks, custom tag content) should suppress
|
|
6
|
+
* their own smooth streaming to avoid double-pacing.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* const parentSmoothStreaming = getContext<SmoothStreamingContextValue | undefined>(
|
|
10
|
+
* SMOOTH_STREAMING_CONTEXT,
|
|
11
|
+
* )
|
|
12
|
+
* setContext(SMOOTH_STREAMING_CONTEXT, () => smoothStreamingEnabled)
|
|
13
|
+
*/
|
|
14
|
+
export const SMOOTH_STREAMING_CONTEXT = 'markstreamSmoothStreaming';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Component } from 'svelte';
|
|
2
|
-
export type MarkstreamSvelteComponent = Component<
|
|
2
|
+
export type MarkstreamSvelteComponent = Component<never>;
|
|
3
3
|
export type CustomComponentMap = Record<string, MarkstreamSvelteComponent>;
|
|
4
4
|
export declare function subscribeCustomComponents(listener: () => void): () => void;
|
|
5
5
|
export declare function getCustomComponentsRevision(): number;
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
import type { NodeRendererCodeBlockProps, NodeRendererD2Props, NodeRendererInfographicProps, NodeRendererMermaidProps } from './components/shared/node-helpers';
|
|
2
|
+
import type { CodeBlockMonacoOptions } from './types/monaco';
|
|
1
3
|
export interface EnhanceRenderedHtmlOptions {
|
|
2
4
|
final?: boolean;
|
|
3
5
|
isDark?: boolean;
|
|
4
6
|
renderCodeBlocksAsPre?: boolean;
|
|
5
|
-
monacoOptions?:
|
|
7
|
+
monacoOptions?: CodeBlockMonacoOptions;
|
|
6
8
|
d2ThemeId?: number | null;
|
|
7
9
|
d2DarkThemeId?: number | null;
|
|
8
10
|
showTooltips?: boolean;
|
|
9
|
-
codeBlockProps?:
|
|
10
|
-
mermaidProps?:
|
|
11
|
-
d2Props?:
|
|
12
|
-
infographicProps?:
|
|
11
|
+
codeBlockProps?: NodeRendererCodeBlockProps;
|
|
12
|
+
mermaidProps?: NodeRendererMermaidProps;
|
|
13
|
+
d2Props?: NodeRendererD2Props;
|
|
14
|
+
infographicProps?: NodeRendererInfographicProps;
|
|
13
15
|
onCopy?: (code: string) => void;
|
|
14
16
|
isCancelled?: () => boolean;
|
|
15
17
|
}
|
|
@@ -270,7 +270,8 @@ async function renderMermaid(root, cleanupFns, options, isActive) {
|
|
|
270
270
|
shell.body.innerHTML = safeSvg;
|
|
271
271
|
shell.body.classList.add('markstream-svelte-mermaid');
|
|
272
272
|
shell.wrapper.dataset.markstreamMermaid = '1';
|
|
273
|
-
(
|
|
273
|
+
if (typeof rendered !== 'string')
|
|
274
|
+
(_g = rendered === null || rendered === void 0 ? void 0 : rendered.bindFunctions) === null || _g === void 0 ? void 0 : _g.call(rendered, shell.body);
|
|
274
275
|
cleanupFns.push(() => {
|
|
275
276
|
if (shell.wrapper.isConnected)
|
|
276
277
|
shell.wrapper.replaceWith(originalPre.cloneNode(true));
|
|
@@ -28,8 +28,10 @@ export function hydrateCustomTagContent(nodes, source, customHtmlTags) {
|
|
|
28
28
|
for (const value of Object.values(node)) {
|
|
29
29
|
if (!Array.isArray(value))
|
|
30
30
|
continue;
|
|
31
|
-
for (const child of value)
|
|
32
|
-
|
|
31
|
+
for (const child of value) {
|
|
32
|
+
if (child && typeof child === 'object')
|
|
33
|
+
visitNode(child);
|
|
34
|
+
}
|
|
33
35
|
}
|
|
34
36
|
};
|
|
35
37
|
for (const node of cloned)
|
|
@@ -122,8 +124,9 @@ function cloneNodeTree(node) {
|
|
|
122
124
|
: { ...node };
|
|
123
125
|
if (!Array.isArray(cloned)) {
|
|
124
126
|
for (const [key, value] of Object.entries(cloned)) {
|
|
125
|
-
if (Array.isArray(value))
|
|
127
|
+
if (Array.isArray(value)) {
|
|
126
128
|
cloned[key] = value.map(item => cloneNodeTree(item));
|
|
129
|
+
}
|
|
127
130
|
}
|
|
128
131
|
}
|
|
129
132
|
return cloned;
|
package/dist/index.css
CHANGED
|
@@ -130,9 +130,10 @@ markstream-svelte {
|
|
|
130
130
|
width: 100%;
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
.markstream-svelte .typewriter-node
|
|
133
|
+
.markstream-svelte .typewriter-node,
|
|
134
|
+
.markstream-svelte .fade-node {
|
|
134
135
|
opacity: 0;
|
|
135
|
-
animation: typewriter-fade var(--typewriter-fade-duration,
|
|
136
|
+
animation: typewriter-fade var(--fade-duration, var(--typewriter-fade-duration, 280ms)) var(--fade-ease, var(--typewriter-fade-ease, cubic-bezier(0.33, 0, 0.67, 1))) both;
|
|
136
137
|
will-change: opacity;
|
|
137
138
|
}
|
|
138
139
|
|
|
@@ -151,8 +152,8 @@ markstream-svelte {
|
|
|
151
152
|
}
|
|
152
153
|
|
|
153
154
|
.markstream-svelte .markstream-svelte-text__stream-delta {
|
|
154
|
-
animation-duration: var(--stream-update-fade-duration, var(--typewriter-fade-duration,
|
|
155
|
-
animation-timing-function: var(--stream-update-fade-ease, var(--typewriter-fade-ease,
|
|
155
|
+
animation-duration: var(--stream-update-fade-duration, var(--fade-duration, var(--typewriter-fade-duration, 280ms)));
|
|
156
|
+
animation-timing-function: var(--stream-update-fade-ease, var(--fade-ease, var(--typewriter-fade-ease, cubic-bezier(0.33, 0, 0.67, 1))));
|
|
156
157
|
animation-fill-mode: both;
|
|
157
158
|
will-change: opacity;
|
|
158
159
|
}
|
|
@@ -278,6 +279,29 @@ markstream-svelte {
|
|
|
278
279
|
to { opacity: 1; }
|
|
279
280
|
}
|
|
280
281
|
|
|
282
|
+
.markstream-svelte .typewriter-cursor {
|
|
283
|
+
position: absolute;
|
|
284
|
+
left: 0;
|
|
285
|
+
top: 0;
|
|
286
|
+
display: inline-block;
|
|
287
|
+
width: 0.55em;
|
|
288
|
+
height: 1em;
|
|
289
|
+
margin-left: 0.08em;
|
|
290
|
+
vertical-align: -0.12em;
|
|
291
|
+
border-right: 2px solid currentColor;
|
|
292
|
+
pointer-events: none;
|
|
293
|
+
animation: typewriter-cursor-blink 1s steps(1, end) infinite;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
@keyframes typewriter-cursor-blink {
|
|
297
|
+
0%, 49% {
|
|
298
|
+
opacity: 1;
|
|
299
|
+
}
|
|
300
|
+
50%, 100% {
|
|
301
|
+
opacity: 0;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
281
305
|
@media (prefers-reduced-motion: reduce) {
|
|
282
306
|
.markstream-svelte .link-loading-indicator {
|
|
283
307
|
animation: none !important;
|
|
@@ -287,6 +311,16 @@ markstream-svelte {
|
|
|
287
311
|
.markstream-svelte .markstream-svelte-text__stream-delta {
|
|
288
312
|
animation: none !important;
|
|
289
313
|
}
|
|
314
|
+
|
|
315
|
+
.markstream-svelte .typewriter-node,
|
|
316
|
+
.markstream-svelte .fade-node {
|
|
317
|
+
animation: none !important;
|
|
318
|
+
opacity: 1;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.markstream-svelte .typewriter-cursor {
|
|
322
|
+
animation: none !important;
|
|
323
|
+
}
|
|
290
324
|
}
|
|
291
325
|
|
|
292
326
|
.markstream-svelte strong {
|
package/dist/index.d.ts
CHANGED
|
@@ -39,7 +39,7 @@ export { default as PreCodeNode } from './components/PreCodeNode.svelte';
|
|
|
39
39
|
export { default as ReferenceNode } from './components/ReferenceNode.svelte';
|
|
40
40
|
export { default as RenderChildren } from './components/RenderChildren.svelte';
|
|
41
41
|
export { buildRenderContext, resolveParsedNodes, } from './components/shared/node-helpers';
|
|
42
|
-
export type { NodeRendererEvents, NodeRendererProps, SvelteRenderableNode, SvelteRenderContext, } from './components/shared/node-helpers';
|
|
42
|
+
export type { CodeBlockPreviewPayload, NodeRendererCodeBlockProps, NodeRendererD2Props, NodeRendererEvents, NodeRendererInfographicProps, NodeRendererMermaidProps, NodeRendererProps, SvelteRenderableNode, SvelteRenderContext, } from './components/shared/node-helpers';
|
|
43
43
|
export { default as StrikethroughNode } from './components/StrikethroughNode.svelte';
|
|
44
44
|
export { default as StrongNode } from './components/StrongNode.svelte';
|
|
45
45
|
export { default as SubscriptNode } from './components/SubscriptNode.svelte';
|
|
@@ -49,6 +49,10 @@ export { default as TextNode } from './components/TextNode.svelte';
|
|
|
49
49
|
export { default as ThematicBreakNode } from './components/ThematicBreakNode.svelte';
|
|
50
50
|
export { default as Tooltip } from './components/Tooltip.svelte';
|
|
51
51
|
export { default as VmrContainerNode } from './components/VmrContainerNode.svelte';
|
|
52
|
+
export type { SmoothMarkdownStreamControllerSvelte, SmoothMarkdownStreamOptions, } from './composables/useSmoothMarkdownStream.svelte';
|
|
53
|
+
export { useSmoothMarkdownStream, } from './composables/useSmoothMarkdownStream.svelte';
|
|
54
|
+
export { SMOOTH_STREAMING_CONTEXT, } from './context/smoothStreaming';
|
|
55
|
+
export type { SmoothStreamingContextValue, } from './context/smoothStreaming';
|
|
52
56
|
export { clearGlobalCustomComponents, getCustomComponentsRevision, getCustomNodeComponents, removeCustomComponents, setCustomComponents, subscribeCustomComponents, } from './customComponents';
|
|
53
57
|
export type { CustomComponentMap, MarkstreamSvelteComponent } from './customComponents';
|
|
54
58
|
export { disposeRenderedHtmlEnhancements, enhanceRenderedHtml, } from './enhanceRenderedHtml';
|
package/dist/index.js
CHANGED
|
@@ -48,6 +48,8 @@ export { default as TextNode } from './components/TextNode.svelte';
|
|
|
48
48
|
export { default as ThematicBreakNode } from './components/ThematicBreakNode.svelte';
|
|
49
49
|
export { default as Tooltip } from './components/Tooltip.svelte';
|
|
50
50
|
export { default as VmrContainerNode } from './components/VmrContainerNode.svelte';
|
|
51
|
+
export { useSmoothMarkdownStream, } from './composables/useSmoothMarkdownStream.svelte';
|
|
52
|
+
export { SMOOTH_STREAMING_CONTEXT, } from './context/smoothStreaming';
|
|
51
53
|
export { clearGlobalCustomComponents, getCustomComponentsRevision, getCustomNodeComponents, removeCustomComponents, setCustomComponents, subscribeCustomComponents, } from './customComponents';
|
|
52
54
|
export { disposeRenderedHtmlEnhancements, enhanceRenderedHtml, } from './enhanceRenderedHtml';
|
|
53
55
|
export { setDefaultI18nMap, useSafeI18n } from './i18n/useSafeI18n';
|
package/dist/index.px.css
CHANGED
|
@@ -130,9 +130,10 @@ markstream-svelte {
|
|
|
130
130
|
width: 100%;
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
.markstream-svelte .typewriter-node
|
|
133
|
+
.markstream-svelte .typewriter-node,
|
|
134
|
+
.markstream-svelte .fade-node {
|
|
134
135
|
opacity: 0;
|
|
135
|
-
animation: typewriter-fade var(--typewriter-fade-duration,
|
|
136
|
+
animation: typewriter-fade var(--fade-duration, var(--typewriter-fade-duration, 280ms)) var(--fade-ease, var(--typewriter-fade-ease, cubic-bezier(0.33, 0, 0.67, 1))) both;
|
|
136
137
|
will-change: opacity;
|
|
137
138
|
}
|
|
138
139
|
|
|
@@ -151,8 +152,8 @@ markstream-svelte {
|
|
|
151
152
|
}
|
|
152
153
|
|
|
153
154
|
.markstream-svelte .markstream-svelte-text__stream-delta {
|
|
154
|
-
animation-duration: var(--stream-update-fade-duration, var(--typewriter-fade-duration,
|
|
155
|
-
animation-timing-function: var(--stream-update-fade-ease, var(--typewriter-fade-ease,
|
|
155
|
+
animation-duration: var(--stream-update-fade-duration, var(--fade-duration, var(--typewriter-fade-duration, 280ms)));
|
|
156
|
+
animation-timing-function: var(--stream-update-fade-ease, var(--fade-ease, var(--typewriter-fade-ease, cubic-bezier(0.33, 0, 0.67, 1))));
|
|
156
157
|
animation-fill-mode: both;
|
|
157
158
|
will-change: opacity;
|
|
158
159
|
}
|
|
@@ -278,6 +279,29 @@ markstream-svelte {
|
|
|
278
279
|
to { opacity: 1; }
|
|
279
280
|
}
|
|
280
281
|
|
|
282
|
+
.markstream-svelte .typewriter-cursor {
|
|
283
|
+
position: absolute;
|
|
284
|
+
left: 0;
|
|
285
|
+
top: 0;
|
|
286
|
+
display: inline-block;
|
|
287
|
+
width: 0.55em;
|
|
288
|
+
height: 1em;
|
|
289
|
+
margin-left: 0.08em;
|
|
290
|
+
vertical-align: -0.12em;
|
|
291
|
+
border-right: 2px solid currentColor;
|
|
292
|
+
pointer-events: none;
|
|
293
|
+
animation: typewriter-cursor-blink 1s steps(1, end) infinite;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
@keyframes typewriter-cursor-blink {
|
|
297
|
+
0%, 49% {
|
|
298
|
+
opacity: 1;
|
|
299
|
+
}
|
|
300
|
+
50%, 100% {
|
|
301
|
+
opacity: 0;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
281
305
|
@media (prefers-reduced-motion: reduce) {
|
|
282
306
|
.markstream-svelte .link-loading-indicator {
|
|
283
307
|
animation: none !important;
|
|
@@ -287,6 +311,16 @@ markstream-svelte {
|
|
|
287
311
|
.markstream-svelte .markstream-svelte-text__stream-delta {
|
|
288
312
|
animation: none !important;
|
|
289
313
|
}
|
|
314
|
+
|
|
315
|
+
.markstream-svelte .typewriter-node,
|
|
316
|
+
.markstream-svelte .fade-node {
|
|
317
|
+
animation: none !important;
|
|
318
|
+
opacity: 1;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.markstream-svelte .typewriter-cursor {
|
|
322
|
+
animation: none !important;
|
|
323
|
+
}
|
|
290
324
|
}
|
|
291
325
|
|
|
292
326
|
.markstream-svelte strong {
|
package/dist/index.tailwind.css
CHANGED
|
@@ -130,9 +130,10 @@ markstream-svelte {
|
|
|
130
130
|
width: 100%;
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
.markstream-svelte .typewriter-node
|
|
133
|
+
.markstream-svelte .typewriter-node,
|
|
134
|
+
.markstream-svelte .fade-node {
|
|
134
135
|
opacity: 0;
|
|
135
|
-
animation: typewriter-fade var(--typewriter-fade-duration,
|
|
136
|
+
animation: typewriter-fade var(--fade-duration, var(--typewriter-fade-duration, 280ms)) var(--fade-ease, var(--typewriter-fade-ease, cubic-bezier(0.33, 0, 0.67, 1))) both;
|
|
136
137
|
will-change: opacity;
|
|
137
138
|
}
|
|
138
139
|
|
|
@@ -151,8 +152,8 @@ markstream-svelte {
|
|
|
151
152
|
}
|
|
152
153
|
|
|
153
154
|
.markstream-svelte .markstream-svelte-text__stream-delta {
|
|
154
|
-
animation-duration: var(--stream-update-fade-duration, var(--typewriter-fade-duration,
|
|
155
|
-
animation-timing-function: var(--stream-update-fade-ease, var(--typewriter-fade-ease,
|
|
155
|
+
animation-duration: var(--stream-update-fade-duration, var(--fade-duration, var(--typewriter-fade-duration, 280ms)));
|
|
156
|
+
animation-timing-function: var(--stream-update-fade-ease, var(--fade-ease, var(--typewriter-fade-ease, cubic-bezier(0.33, 0, 0.67, 1))));
|
|
156
157
|
animation-fill-mode: both;
|
|
157
158
|
will-change: opacity;
|
|
158
159
|
}
|
|
@@ -278,6 +279,29 @@ markstream-svelte {
|
|
|
278
279
|
to { opacity: 1; }
|
|
279
280
|
}
|
|
280
281
|
|
|
282
|
+
.markstream-svelte .typewriter-cursor {
|
|
283
|
+
position: absolute;
|
|
284
|
+
left: 0;
|
|
285
|
+
top: 0;
|
|
286
|
+
display: inline-block;
|
|
287
|
+
width: 0.55em;
|
|
288
|
+
height: 1em;
|
|
289
|
+
margin-left: 0.08em;
|
|
290
|
+
vertical-align: -0.12em;
|
|
291
|
+
border-right: 2px solid currentColor;
|
|
292
|
+
pointer-events: none;
|
|
293
|
+
animation: typewriter-cursor-blink 1s steps(1, end) infinite;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
@keyframes typewriter-cursor-blink {
|
|
297
|
+
0%, 49% {
|
|
298
|
+
opacity: 1;
|
|
299
|
+
}
|
|
300
|
+
50%, 100% {
|
|
301
|
+
opacity: 0;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
281
305
|
@media (prefers-reduced-motion: reduce) {
|
|
282
306
|
.markstream-svelte .link-loading-indicator {
|
|
283
307
|
animation: none !important;
|
|
@@ -287,6 +311,16 @@ markstream-svelte {
|
|
|
287
311
|
.markstream-svelte .markstream-svelte-text__stream-delta {
|
|
288
312
|
animation: none !important;
|
|
289
313
|
}
|
|
314
|
+
|
|
315
|
+
.markstream-svelte .typewriter-node,
|
|
316
|
+
.markstream-svelte .fade-node {
|
|
317
|
+
animation: none !important;
|
|
318
|
+
opacity: 1;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.markstream-svelte .typewriter-cursor {
|
|
322
|
+
animation: none !important;
|
|
323
|
+
}
|
|
290
324
|
}
|
|
291
325
|
|
|
292
326
|
.markstream-svelte strong {
|
package/dist/optional/d2.d.ts
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface D2Instance {
|
|
2
|
+
D2?: D2Constructor;
|
|
3
|
+
compile?: (source: string, options?: Record<string, unknown>) => Promise<unknown> | unknown;
|
|
4
|
+
render?: (input: unknown, options?: Record<string, unknown>) => Promise<unknown> | unknown;
|
|
5
|
+
}
|
|
6
|
+
export interface D2Constructor {
|
|
7
|
+
new (): D2Instance;
|
|
8
|
+
D2?: D2Constructor;
|
|
9
|
+
compile?: D2Instance['compile'];
|
|
10
|
+
}
|
|
11
|
+
export type D2Module = D2Constructor | D2Instance;
|
|
12
|
+
export type D2Loader = () => Promise<unknown> | unknown;
|
|
2
13
|
export declare function setD2Loader(loader: D2Loader | null): void;
|
|
3
14
|
export declare function enableD2(loader?: D2Loader): void;
|
|
4
15
|
export declare function disableD2(): void;
|
|
5
16
|
export declare function isD2Enabled(): boolean;
|
|
6
|
-
export declare function getD2(): Promise<
|
|
17
|
+
export declare function getD2(): Promise<D2Module | null>;
|
|
@@ -1 +1,13 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface InfographicInstance {
|
|
2
|
+
render: (source: string) => unknown;
|
|
3
|
+
destroy?: () => unknown;
|
|
4
|
+
on?: (event: string, handler: (payload: unknown) => void) => unknown;
|
|
5
|
+
}
|
|
6
|
+
export interface InfographicConstructor {
|
|
7
|
+
new (options: {
|
|
8
|
+
container: HTMLElement;
|
|
9
|
+
width?: string | number;
|
|
10
|
+
height?: string | number;
|
|
11
|
+
}): InfographicInstance;
|
|
12
|
+
}
|
|
13
|
+
export declare function getInfographic(): Promise<InfographicConstructor | null>;
|
package/dist/optional/katex.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface KatexModule {
|
|
2
|
+
renderToString: (content: string, options?: Record<string, unknown>) => string;
|
|
3
|
+
}
|
|
4
|
+
export type KatexLoader = () => Promise<unknown> | unknown;
|
|
2
5
|
export declare function setKatexLoader(loader: KatexLoader | null): void;
|
|
3
6
|
export declare function enableKatex(loader?: KatexLoader): void;
|
|
4
7
|
export declare function disableKatex(): void;
|
|
5
8
|
export declare function isKatexEnabled(): boolean;
|
|
6
|
-
export declare function getKatex(): Promise<
|
|
9
|
+
export declare function getKatex(): Promise<KatexModule | null>;
|
|
@@ -1,6 +1,27 @@
|
|
|
1
|
-
export type MermaidLoader = () => Promise<
|
|
1
|
+
export type MermaidLoader = () => Promise<unknown> | unknown;
|
|
2
|
+
export interface MermaidModule {
|
|
3
|
+
render: (id: string, source: string) => Promise<MermaidRenderResult> | MermaidRenderResult;
|
|
4
|
+
parse?: (source: string) => Promise<unknown> | unknown;
|
|
5
|
+
initialize?: (config?: Record<string, unknown>) => unknown;
|
|
6
|
+
mermaidAPI?: {
|
|
7
|
+
render?: MermaidModule['render'];
|
|
8
|
+
parse?: MermaidModule['parse'];
|
|
9
|
+
initialize?: MermaidModule['initialize'];
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export type MermaidRenderResult = string | {
|
|
13
|
+
svg?: string;
|
|
14
|
+
bindFunctions?: (element: Element) => unknown;
|
|
15
|
+
};
|
|
16
|
+
interface MermaidInitConfig extends Record<string, unknown> {
|
|
17
|
+
securityLevel?: unknown;
|
|
18
|
+
flowchart?: {
|
|
19
|
+
htmlLabels?: unknown;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
2
22
|
export declare function setMermaidLoader(loader: MermaidLoader | null): void;
|
|
3
23
|
export declare function enableMermaid(loader?: MermaidLoader): void;
|
|
4
24
|
export declare function disableMermaid(): void;
|
|
5
25
|
export declare function isMermaidEnabled(): boolean;
|
|
6
|
-
export declare function getMermaid(initConfig?:
|
|
26
|
+
export declare function getMermaid(initConfig?: MermaidInitConfig): Promise<MermaidModule | null>;
|
|
27
|
+
export {};
|
|
@@ -1,4 +1,21 @@
|
|
|
1
|
+
export interface MonacoRuntimeHelpers {
|
|
2
|
+
createEditor?: (container: HTMLElement, code: string, language: string) => Promise<unknown> | unknown;
|
|
3
|
+
createDiffEditor?: (container: HTMLElement, original: string, modified: string, language: string) => Promise<unknown> | unknown;
|
|
4
|
+
updateCode?: (code: string, language?: string) => Promise<unknown> | unknown;
|
|
5
|
+
updateDiff?: (original: string, modified: string, language?: string) => Promise<unknown> | unknown;
|
|
6
|
+
cleanupEditor?: () => unknown;
|
|
7
|
+
safeClean?: () => unknown;
|
|
8
|
+
setTheme?: (theme?: string | Record<string, unknown>) => Promise<unknown> | unknown;
|
|
9
|
+
getEditorView?: () => unknown;
|
|
10
|
+
getDiffEditorView?: () => unknown;
|
|
11
|
+
refreshDiffPresentation?: () => unknown;
|
|
12
|
+
}
|
|
13
|
+
export interface MonacoRuntimeModule {
|
|
14
|
+
useMonaco: (options?: Record<string, unknown>) => MonacoRuntimeHelpers;
|
|
15
|
+
preloadMonacoWorkers?: () => Promise<unknown> | unknown;
|
|
16
|
+
getOrCreateHighlighter?: (...args: unknown[]) => Promise<unknown> | unknown;
|
|
17
|
+
}
|
|
1
18
|
export declare function isCodeBlockRuntimeReady(): boolean;
|
|
2
19
|
export declare function resetCodeBlockRuntimeReadyForTest(): void;
|
|
3
20
|
export declare function preloadCodeBlockRuntime(): Promise<boolean>;
|
|
4
|
-
export declare function getUseMonaco(): Promise<
|
|
21
|
+
export declare function getUseMonaco(): Promise<MonacoRuntimeModule | null>;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { BaseNode, MarkdownIt, ParseOptions } from 'stream-markdown-parser';
|
|
2
|
+
type NestedMarkdownSourceNode = BaseNode & {
|
|
3
|
+
children?: BaseNode[];
|
|
4
|
+
content?: string;
|
|
5
|
+
};
|
|
2
6
|
export interface NestedMarkdownNodesInput {
|
|
3
|
-
node?:
|
|
7
|
+
node?: NestedMarkdownSourceNode | null;
|
|
4
8
|
nodes?: readonly BaseNode[] | null;
|
|
5
9
|
content?: string | null;
|
|
6
10
|
}
|
|
@@ -12,3 +16,4 @@ export interface NestedMarkdownNodesOptions {
|
|
|
12
16
|
customMarkdownIt?: (markdown: MarkdownIt) => MarkdownIt;
|
|
13
17
|
}
|
|
14
18
|
export declare function parseNestedMarkdownToNodes(input: NestedMarkdownNodesInput, options?: NestedMarkdownNodesOptions): BaseNode[];
|
|
19
|
+
export {};
|
package/dist/types/monaco.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export interface CodeBlockMonacoThemeObject {
|
|
|
7
7
|
[key: string]: unknown;
|
|
8
8
|
}
|
|
9
9
|
export type CodeBlockMonacoTheme = string | CodeBlockMonacoThemeObject;
|
|
10
|
-
export type CodeBlockMonacoLanguage = string | ((...args:
|
|
10
|
+
export type CodeBlockMonacoLanguage = string | ((...args: unknown[]) => unknown);
|
|
11
11
|
export interface CodeBlockDiffHideUnchangedRegionsOptions {
|
|
12
12
|
enabled?: boolean;
|
|
13
13
|
contextLineCount?: number;
|
|
@@ -60,6 +60,6 @@ export interface CodeBlockMonacoOptions {
|
|
|
60
60
|
diffHunkActionsOnHover?: boolean;
|
|
61
61
|
diffHunkHoverHideDelayMs?: number;
|
|
62
62
|
onDiffHunkAction?: (context: CodeBlockDiffHunkActionContext) => void | boolean | Promise<void | boolean>;
|
|
63
|
-
scrollbar?: Record<string,
|
|
64
|
-
[key: string]:
|
|
63
|
+
scrollbar?: Record<string, unknown>;
|
|
64
|
+
[key: string]: unknown;
|
|
65
65
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "markstream-svelte",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.1-beta.
|
|
4
|
+
"version": "0.0.1-beta.5",
|
|
5
5
|
"description": "Svelte Markdown renderer for Markstream, aligned with markstream-vue and markstream-react.",
|
|
6
6
|
"author": "Simon He",
|
|
7
7
|
"license": "MIT",
|
|
@@ -71,7 +71,8 @@
|
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
73
|
"@floating-ui/dom": "^1.7.6",
|
|
74
|
-
"
|
|
74
|
+
"markstream-core": "0.0.1",
|
|
75
|
+
"stream-markdown-parser": "0.0.95"
|
|
75
76
|
},
|
|
76
77
|
"devDependencies": {
|
|
77
78
|
"@sveltejs/package": "^2.5.7",
|
|
@@ -86,10 +87,11 @@
|
|
|
86
87
|
"vite": "^7.3.1"
|
|
87
88
|
},
|
|
88
89
|
"scripts": {
|
|
89
|
-
"build": "svelte-package -i src -o dist && postcss src/index.css -o dist/index.css && cp dist/index.css dist/index.tailwind.css && node ../../scripts/generate-px-css.mjs",
|
|
90
|
+
"build": "pnpm --dir ../markstream-core build && svelte-package -i src -o dist && postcss src/index.css -o dist/index.css && cp dist/index.css dist/index.tailwind.css && node ../../scripts/generate-px-css.mjs",
|
|
90
91
|
"dev": "vite dev",
|
|
91
92
|
"preview": "vite preview",
|
|
92
93
|
"typecheck": "svelte-check --tsconfig ./tsconfig.json",
|
|
93
|
-
"
|
|
94
|
+
"check:core-published": "node ../../scripts/check-core-published.mjs --package-json package.json --core-package-json ../markstream-core/package.json",
|
|
95
|
+
"release": "pnpm run check:core-published && bumpp --commit --no-tag --no-push && pnpm publish --access public && node ../../scripts/tag-package.mjs --package-json package.json --push"
|
|
94
96
|
}
|
|
95
97
|
}
|