File size: 2,127 Bytes
fc69895
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
71
72
73
<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 DOMPurify from "isomorphic-dompurify";
	import { onMount } 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));

	async function processContent(
		content: string,
		sources: { title?: string; link: string }[]
	): Promise<BlockToken[]> {
		// Note: Worker support for blocks can be added later if needed
		// For now, use direct processing which is still efficient due to block memoization
		return processBlocks(content, sources);
	}

	$effect(() => {
		if (!browser) {
			blocks = processBlocksSync(content, sources);
		} else {
			(async () => {
				updateDebouncer.startRender();
				blocks = await processContent(content, sources).then(async (processedBlocks) =>
					Promise.all(
						processedBlocks.map(async (block) => ({
							...block,
							tokens: await Promise.all(
								block.tokens.map(async (token) => {
									if (token.type === "text") {
										token.html = DOMPurify.sanitize(await token.html);
									}
									return token;
								})
							),
						}))
					)
				);

				updateDebouncer.endRender();
			})();
		}
	});

	onMount(() => {
		// todo: fix worker, seems to be transmitting a lot of data
		// worker = browser && window.Worker ? new MarkdownWorker() : null;

		DOMPurify.addHook("afterSanitizeAttributes", (node) => {
			if (node.tagName === "A") {
				node.setAttribute("target", "_blank");
				node.setAttribute("rel", "noreferrer");
			}
		});
	});
</script>

{#each blocks as block, index (loading && index === blocks.length - 1 ? `stream-${index}` : block.id)}
	<MarkdownBlock tokens={block.tokens} {loading} />
{/each}