File size: 1,973 Bytes
b94860a 671ee32 ec5d85c 671ee32 6ee391c ec5d85c 0c9aa36 b94860a 21b8785 4331e77 21b8785 4331e77 0c7ea0d 671ee32 ec5d85c b94860a ec5d85c b94860a 6ee391c 671ee32 ec5d85c 0c9aa36 ec5d85c 6ee391c ec5d85c b3383d5 0c9aa36 ec5d85c 0c9aa36 ec5d85c b94860a 3027088 5bb6125 4e7334f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
<script lang="ts">
import { processBlocks, processBlocksSync, type BlockToken } from "$lib/utils/marked";
import MarkdownWorker from "$lib/workers/markdownWorker?worker";
import MarkdownBlock from "./MarkdownBlock.svelte";
import { browser } from "$app/environment";
import { onMount, onDestroy } from "svelte";
import { updateDebouncer } from "$lib/utils/updates";
interface Props {
content: string;
sources?: { title?: string; link: string }[];
loading?: boolean;
}
let { content, sources = [], loading = false }: Props = $props();
let blocks: BlockToken[] = $state(processBlocksSync(content, sources));
let worker: Worker | null = null;
let latestRequestId = 0;
function handleBlocks(result: BlockToken[], requestId: number) {
if (requestId !== latestRequestId) return;
blocks = result;
updateDebouncer.endRender();
}
$effect(() => {
if (!browser) {
blocks = processBlocksSync(content, sources);
return;
}
const requestId = ++latestRequestId;
if (worker) {
updateDebouncer.startRender();
worker.postMessage({ type: "process", content, sources, requestId });
return;
}
(async () => {
updateDebouncer.startRender();
const processed = await processBlocks(content, sources);
// Only apply if this is still the latest request
handleBlocks(processed, requestId);
})();
});
onMount(() => {
if (typeof Worker !== "undefined") {
worker = new MarkdownWorker();
worker.onmessage = (event: MessageEvent) => {
const data = event.data as { type?: string; blocks?: BlockToken[]; requestId?: number };
if (data?.type !== "processed" || !data.blocks || data.requestId === undefined) return;
handleBlocks(data.blocks, data.requestId);
};
}
});
onDestroy(() => {
worker?.terminate();
worker = null;
});
</script>
{#each blocks as block, index (loading && index === blocks.length - 1 ? `stream-${index}` : block.id)}
<MarkdownBlock tokens={block.tokens} {loading} />
{/each}
|