const greeting = "Hello, World!";
console.log(greeting); <script lang="ts">
import { CodeHighlighted } from "kumo-svelte/components/code";
import ShikiDemoProvider from "./shiki-demo-provider.svelte";
const code = `const greeting = "Hello, World!";
console.log(greeting);`;
</script>
<ShikiDemoProvider>
<CodeHighlighted {code} lang="typescript" />
</ShikiDemoProvider>
Overview
A Shiki-powered syntax highlighter. It supports a curated set of bundled languages with TextMate grammars, Kumo light/dark themes, lazy loading, line highlighting, line numbers, and copy buttons.
Import CodeHighlighted and ShikiProvider from kumo-svelte/components/code.
Import
Import the highlighting components from the code component subpath.
import { CodeHighlighted, ShikiProvider } from "kumo-svelte/components/code"; Basic Usage
Wrap the relevant part of your app with ShikiProvider to configure Shiki once. All CodeHighlighted components inside share the same Shiki instance.
<script lang="ts">
import { CodeHighlighted, ShikiProvider } from "kumo-svelte/components/code";
</script>
<ShikiProvider engine="javascript" languages={["typescript", "bash", "json"]}>
<CodeHighlighted code="const x = 1;" lang="typescript" />
</ShikiProvider> Examples
Languages
CodeHighlighted supports the languages listed in the API reference. Only load the languages you need in ShikiProvider.
TypeScript
interface User {
id: string;
name: string;
email: string;
}
async function fetchUser(id: string): Promise<User> {
const response = await fetch(`/api/users/${id}`);
return response.json();
} <script lang="ts">
import { CodeHighlighted } from "kumo-svelte/components/code";
import ShikiDemoProvider from "./shiki-demo-provider.svelte";
const code = `interface User {
id: string;
name: string;
email: string;
}
async function fetchUser(id: string): Promise<User> {
const response = await fetch(\`/api/users/\${id}\`);
return response.json();
}`;
</script>
<ShikiDemoProvider>
<CodeHighlighted {code} lang="typescript" />
</ShikiDemoProvider>
Svelte markup
Use lang="html" for Svelte snippets because the Svelte package exposes the curated Shiki language list in the API reference.
<script lang="ts">
let count = $state(0);
</script>
<button onclick={() => count += 1}>
Count: {count}
</button> <script lang="ts">
import { CodeHighlighted } from "kumo-svelte/components/code";
import ShikiDemoProvider from "./shiki-demo-provider.svelte";
const code = `<script lang="ts">
let count = $state(0);
<\/script>
<button onclick={() => count += 1}>
Count: {count}
</button>`;
</script>
<ShikiDemoProvider>
<CodeHighlighted {code} lang="html" />
</ShikiDemoProvider>
Bash / shell
# Install Kumo Svelte
pnpm add kumo-svelte
# Start development server
pnpm dev <script lang="ts">
import { CodeHighlighted } from "kumo-svelte/components/code";
import ShikiDemoProvider from "./shiki-demo-provider.svelte";
const code = `# Install Kumo Svelte
pnpm add kumo-svelte
# Start development server
pnpm dev`;
</script>
<ShikiDemoProvider>
<CodeHighlighted {code} lang="bash" />
</ShikiDemoProvider>
JSON
{
"name": "kumo-svelte-app",
"dependencies": {
"kumo-svelte": "latest",
"shiki": "^4.0.0"
}
} <script lang="ts">
import { CodeHighlighted } from "kumo-svelte/components/code";
import ShikiDemoProvider from "./shiki-demo-provider.svelte";
const code = `{
"name": "kumo-svelte-app",
"dependencies": {
"kumo-svelte": "latest",
"shiki": "^4.0.0"
}
}`;
</script>
<ShikiDemoProvider>
<CodeHighlighted {code} lang="json" />
</ShikiDemoProvider>
CSS
.button {
background: var(--color-brand);
border-radius: 0.5rem;
padding: 0.5rem 1rem;
&:hover {
background: var(--color-brand-hover);
}
} <script lang="ts">
import { CodeHighlighted } from "kumo-svelte/components/code";
import ShikiDemoProvider from "./shiki-demo-provider.svelte";
const code = `.button {
background: var(--color-brand);
border-radius: 0.5rem;
padding: 0.5rem 1rem;
&:hover {
background: var(--color-brand-hover);
}
}`;
</script>
<ShikiDemoProvider>
<CodeHighlighted {code} lang="css" />
</ShikiDemoProvider>
Highlight Lines
Emphasize specific lines with highlightLines. Line numbers are 1-indexed.
function processData(items: string[]) {
// Filter out empty items
const filtered = items.filter(Boolean);
// Transform to uppercase (highlighted)
const transformed = filtered.map((item) => item.toUpperCase());
// Return sorted result
return transformed.toSorted();
} <script lang="ts">
import { CodeHighlighted } from "kumo-svelte/components/code";
import ShikiDemoProvider from "./shiki-demo-provider.svelte";
const code = `function processData(items: string[]) {
// Filter out empty items
const filtered = items.filter(Boolean);
// Transform to uppercase (highlighted)
const transformed = filtered.map((item) => item.toUpperCase());
// Return sorted result
return transformed.toSorted();
}`;
</script>
<ShikiDemoProvider>
<CodeHighlighted {code} lang="typescript" highlightLines={[5, 6]} />
</ShikiDemoProvider>
Custom Highlight Color
Customize the highlight color with the --kumo-code-highlight-bg CSS variable.
function greet(name: string) {
// This line is highlighted
console.log(`Hello, ${name}!`);
return name.toUpperCase();
} --kumo-code-highlight-bg: hsla(220, 80%, 50%, 0.1)<script lang="ts">
import { CodeHighlighted } from "kumo-svelte/components/code";
import ShikiDemoProvider from "./shiki-demo-provider.svelte";
let hue = $state(220);
let opacity = $state(10);
let lightBg = $derived(`hsla(${hue}, 80%, 50%, ${opacity / 100})`);
let darkBg = $derived(`hsla(${hue}, 60%, 70%, ${(opacity + 5) / 100})`);
const code = `function greet(name: string) {
// This line is highlighted
console.log(\`Hello, \${name}!\`);
return name.toUpperCase();
}`;
let customHighlightStyles = $derived(`#custom-highlight-demo .kumo-shiki {
--kumo-code-highlight-bg: ${lightBg};
}
[data-mode="dark"] #custom-highlight-demo .kumo-shiki {
--kumo-code-highlight-bg: ${darkBg};
}`);
</script>
<ShikiDemoProvider>
<div class="space-y-4">
{@html `<style>${customHighlightStyles}</style>`}
<div id="custom-highlight-demo">
<CodeHighlighted {code} lang="typescript" highlightLines={[2, 3]} />
</div>
<div class="flex flex-wrap gap-6 rounded-md border border-kumo-hairline bg-kumo-elevated p-4">
<label class="flex flex-col gap-2">
<span class="text-sm text-kumo-subtle">Hue: {hue}°</span>
<input type="range" min="0" max="360" bind:value={hue} class="w-32" />
</label>
<label class="flex flex-col gap-2">
<span class="text-sm text-kumo-subtle">Opacity: {opacity}%</span>
<input type="range" min="2" max="30" bind:value={opacity} class="w-32" />
</label>
<div class="flex flex-col gap-2">
<span class="text-sm text-kumo-subtle">CSS Variable</span>
<code class="rounded bg-kumo-control px-2 py-1 font-mono text-xs">
--kumo-code-highlight-bg: {lightBg}
</code>
</div>
</div>
</div>
</ShikiDemoProvider>
Line Numbers
Display line numbers with showLineNumbers.
const statusLabels = {
active: "Active",
paused: "Paused",
errored: "Errored",
};
export function getStatusLabel(status: keyof typeof statusLabels) {
return statusLabels[status];
}<script lang="ts">
import { CodeHighlighted } from "kumo-svelte/components/code";
import ShikiDemoProvider from "./shiki-demo-provider.svelte";
const code = `const statusLabels = {
active: "Active",
paused: "Paused",
errored: "Errored",
};
export function getStatusLabel(status: keyof typeof statusLabels) {
return statusLabels[status];
}`;
</script>
<ShikiDemoProvider>
<CodeHighlighted {code} lang="typescript" showLineNumbers />
</ShikiDemoProvider>
Copy Button
Add a copy-to-clipboard button with showCopyButton.
pnpm add kumo-svelte <script lang="ts">
import { CodeHighlighted } from "kumo-svelte/components/code";
import ShikiDemoProvider from "./shiki-demo-provider.svelte";
const code = "pnpm add kumo-svelte";
</script>
<ShikiDemoProvider>
<CodeHighlighted {code} lang="bash" showCopyButton />
</ShikiDemoProvider>
Full Featured
Combine copy buttons and highlighted lines for a complete code display.
<script lang="ts">
import { CodeHighlighted, ShikiProvider } from "kumo-svelte/components/code";
const code = "const answer = 42;";
</script>
<ShikiProvider engine="javascript" languages={["typescript", "bash"]}>
<CodeHighlighted
{code}
lang="typescript"
showCopyButton
highlightLines={[1]}
/>
</ShikiProvider> <script lang="ts">
import { CodeHighlighted } from "kumo-svelte/components/code";
import ShikiDemoProvider from "./shiki-demo-provider.svelte";
const code = `<script lang="ts">
import { CodeHighlighted, ShikiProvider } from "kumo-svelte/components/code";
const code = "const answer = 42;";
<\/script>
<ShikiProvider engine="javascript" languages={["typescript", "bash"]}>
<CodeHighlighted
{code}
lang="typescript"
showCopyButton
highlightLines={[1]}
/>
</ShikiProvider>`;
</script>
<ShikiDemoProvider>
<CodeHighlighted {code} lang="html" showCopyButton highlightLines={[7, 8, 9, 10, 11, 12]} />
</ShikiDemoProvider>
Shared Provider
Multiple code blocks can share a single ShikiProvider. Shiki loads once and is reused for all blocks.
const config = { theme: "dark" }; pnpm run build { "success": true } <script lang="ts">
import { CodeHighlighted } from "kumo-svelte/components/code";
import ShikiDemoProvider from "./shiki-demo-provider.svelte";
</script>
<ShikiDemoProvider>
<div class="space-y-4">
<CodeHighlighted code={`const config = { theme: "dark" };`} lang="typescript" />
<CodeHighlighted code="pnpm run build" lang="bash" />
<CodeHighlighted code={`{ "success": true }`} lang="json" />
</div>
</ShikiDemoProvider>
Themes
CodeHighlighted uses the Kumo theme pair for consistent styling across applications:
- Light mode:
github-light - Dark mode:
vesper
Server-Side Usage
For SSR and static rendering, use the server utilities to highlight at build time.
One-off highlighting
import { highlightCode } from "kumo-svelte/components/code/server";
const html = await highlightCode(`const x = 1;`, "typescript"); Reusable highlighter
import { createServerHighlighter } from "kumo-svelte/components/code/server";
const highlighter = await createServerHighlighter({
languages: ["typescript", "bash", "json"],
});
const html1 = highlighter.highlight(code1, "typescript");
const html2 = highlighter.highlight(code2, "bash");
highlighter.dispose(); Custom Hook
Use useShikiHighlighter inside components rendered under a ShikiProvider when you need custom code block rendering.
<script lang="ts">
import { useShikiHighlighter } from "kumo-svelte/components/code";
let { code, lang } = $props();
const shiki = useShikiHighlighter();
let html = $derived(shiki.highlight(code, lang));
</script>
{#if shiki.error}
<p>Failed to load highlighter.</p>
{:else if shiki.isLoading || html === null}
<pre><code>{code}</code></pre>
{:else}
<pre>{@html html}</pre>
{/if} Internationalization
Customize copy button labels at the provider level for all code blocks, or override them per component.
<ShikiProvider
engine="javascript"
languages={["typescript", "bash"]}
labels={{ copy: "Copier", copied: "Copié!" }}
>
<CodeHighlighted
code={code}
lang="typescript"
showCopyButton
labels={{ copy: "Copy code", copied: "Done!" }}
/>
</ShikiProvider> SvelteKit Integration
Configure a shared provider in your root layout or in the route group that renders code examples.
<!-- src/routes/+layout.svelte -->
<script lang="ts">
import { ShikiProvider } from "kumo-svelte/components/code";
import type { Snippet } from "svelte";
let { children }: { children: Snippet } = $props();
</script>
<ShikiProvider engine="javascript" languages={["typescript", "bash", "json"]}>
{@render children()}
</ShikiProvider> API Reference
CodeHighlighted
| Prop | Type | Default |
|---|---|---|
| class | string | — |
| code* | string | — |
| highlightLines | number[] | — |
| labels | CodeHighlightedLabels | — |
| lang* | SupportedLanguage | — |
| showCopyButton | boolean | false |
| showLineNumbers | boolean | false |