-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSourceView.svelte
More file actions
68 lines (61 loc) · 2.05 KB
/
SourceView.svelte
File metadata and controls
68 lines (61 loc) · 2.05 KB
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
<script lang="ts">
const {
url,
onLoadingChange,
}: {
url: keyof typeof sources;
onLoadingChange?: (loading: boolean) => void;
} = $props();
const sources = {
"./index.html": { lang: "html" },
"./App.svelte": { lang: "svelte" },
"./ReadmeView.svelte": { lang: "svelte" },
"./SourceView.svelte": { lang: "svelte" },
"./SourcesView.svelte": { lang: "svelte" },
} as const satisfies { [url: string]: { lang: string } };
let highlighterPromise: ReturnType<typeof createHighlighter> | undefined;
async function createHighlighter() {
const [
{ createBundledHighlighter, createSingletonShorthands },
{ createJavaScriptRegexEngine },
] = await Promise.all([
import("https://esm.sh/shiki@4.0.2/core"),
import("https://esm.sh/shiki@4.0.2/engine/javascript"),
]);
const bundledHighlighter = createBundledHighlighter({
langs: {
html: () => import("https://esm.sh/@shikijs/langs@4.0.2/html"),
svelte: () => import("https://esm.sh/@shikijs/langs@4.0.2/svelte"),
},
themes: {
nord: () => import("https://esm.sh/@shikijs/themes@4.0.2/nord"),
},
engine: () => createJavaScriptRegexEngine(),
});
return createSingletonShorthands(bundledHighlighter);
}
async function fetchSourceHTML(
url: keyof typeof sources,
signal?: AbortSignal,
) {
const { lang } = sources[url];
const [source, highlighter] = await Promise.all([
fetch(url, { signal }).then((res) => res.text()),
(highlighterPromise ??= createHighlighter()),
]);
const html = await highlighter.codeToHtml(source, { lang, theme: "nord" });
signal?.throwIfAborted();
return html;
}
let sourceHTML = $state<string | undefined>(undefined);
$effect(function updateSourceHTML() {
const ctrl = new AbortController();
onLoadingChange?.(true);
fetchSourceHTML(url, ctrl.signal).then((html) => {
sourceHTML = html;
onLoadingChange?.(false);
});
return () => ctrl.abort();
});
</script>
<section>{@html sourceHTML}</section>