A component for rendering code.
A CodeSnippet component has the following properties:
| Prop | Required | Description |
|---|---|---|
src | yes | The source code to render. |
lang | yes | The language for syntax highlighting. |
// This is the `default` entry point for the package (not including Svelte components).
export * from '$lib/schemas/index.js';
export * from '$lib/utils/index.js';
export * from '$lib/types.js'; // Export types.
<script lang="ts">
import { CodeSnippet } from '$lib/components/index.js';
import src from '$lib/index.ts?raw';
</script>
<CodeSnippet {src} lang="typescript" />
<script module lang="ts">
import { createHighlighterCore } from 'shiki/core';
import { createJavaScriptRegexEngine } from 'shiki/engine/javascript';
export const highlighter = await createHighlighterCore({
langs: [
import('@shikijs/langs/bash'),
import('@shikijs/langs/html'),
import('@shikijs/langs/javascript'),
import('@shikijs/langs/json'),
import('@shikijs/langs/markdown'),
import('@shikijs/langs/svelte'),
import('@shikijs/langs/typescript'),
import('@shikijs/langs/yaml'),
import('@shikijs/langs/xml')
],
themes: [import('@shikijs/themes/github-light'), import('@shikijs/themes/github-dark')],
engine: createJavaScriptRegexEngine()
});
</script>
<script lang="ts">
import { Check, Copy } from '@lucide/svelte';
import Button from './Button.svelte';
interface Props {
src: string;
lang: string;
}
const { src, lang = 'txt' }: Props = $props();
let copied = $state(false);
let timeoutId: ReturnType<typeof setTimeout> | null = null;
const generatedHtml = $derived(
highlighter.codeToHtml(src, {
lang,
themes: {
light: 'github-light',
dark: 'github-dark'
}
})
);
async function handleCopy() {
// Clear existing timeout.
if (timeoutId !== null) {
clearTimeout(timeoutId);
}
await navigator.clipboard.writeText(src);
copied = true;
timeoutId = setTimeout(() => {
copied = false;
timeoutId = null;
}, 2000);
}
// Cleanup timeout on unmount.
$effect(() => {
return () => {
if (timeoutId !== null) {
clearTimeout(timeoutId);
}
};
});
</script>
<div
data-component="CodeSnippet"
class="relative overflow-hidden rounded-container [&>pre]:overflow-x-auto [&>pre]:p-4 [&>pre]:text-sm"
>
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html generatedHtml}
<Button
onclick={handleCopy}
aria-label={copied ? 'Copied!' : 'Copy code'}
class="absolute right-4 bottom-4"
>
{#snippet icon()}
{#if copied}
<Check />
{:else}
<Copy />
{/if}
{/snippet}
</Button>
</div>
<style>
:global([data-component='Example'] [data-component='CodeSnippet']) {
border-start-start-radius: 0;
border-start-end-radius: 0;
}
</style>
<script lang="ts">
import src from '$lib/components/CodeSnippet.svelte?raw';
import { CodeSnippet } from '$lib/components/index.js';
</script>
<CodeSnippet {src} lang="svelte" />