Skip to main content

Code

Info:Display html svelte astro Success: coverage 36/36

A read-only, syntax-highlighted code block themed entirely from the code-token family.

Live demo

live · @xoji/astro

Code

Themed highlighting, three languages

Every block colors itself from the --code-* family the algorithm derives, so it re-themes with the rest of the chrome.

type Theme = { bg: string; accent: string };

const derive = (theme: Theme): string =>
	`--bg-0: ${theme.bg}; --accent: ${theme.accent};`;

console.log(derive({ bg: "#0f1115", accent: "#5b8cff" }));
fn main() {
	let accent = "#5b8cff";
	println!("derive from {accent}");
}
.xoji-code {
	color: var(--code-fg);
	background: var(--code-bg);
}

Line numbers & highlights

line-numbers adds a counter gutter; highlight tints the lines that matter (here 2,4 ) with the derived --code-line-highlight .

function total(items) {	let sum = 0;	for (const n of items) sum += n;	return sum;}

Soft-wrap

wrap folds a long line instead of scrolling it sideways: purely declarative, no JavaScript.

const message = "a deliberately long single line that would otherwise scroll sideways, but soft-wraps instead so the whole statement stays readable in a narrow column";

Code is a turnkey, read-only code block with the tokenizer built in; it's the first component to read the --code-* family. It tokenizes with Prism, whose output is class-based, so the block re-themes live the moment the theme changes: the colors are just cascading CSS variables, never baked inline.

The lang prop names the language with aliases resolved (tstypescript), and the source is the element's text content (or, for Astro, a code prop). Grammar loading is fully lazy and per-language. A page with no code block loads nothing; a page with a few languages loads Prism core once plus only those grammar chunks, walking each grammar's dependencies first. At runtime the block paints immediately as plain-but-themed text and recolors in place once the grammar resolves, so there is no flash and no layout shift; the Astro binding tokenizes at build and ships pre-colored with zero browser JS. preload warms a block's grammar eagerly to kill even the minor recolor flash, sharing one warm path with the page-level XojiCode.warm() static. An unknown language falls back to plain-but-themed text rather than erroring.

When to use

How this component composes with the rest of the set.

Set lang to the source's language; use an alias (ts, html, js) and it resolves to the canonical grammar.
On a code-heavy page, call XojiCode.warm(["ts", "rust"]) once at startup, or mark individual blocks preload, to load grammars before first paint.
For a language Prism does not ship, register it with XojiCode.registerLanguage(name, grammar) and use that name as lang.
Reach for the Astro binding when the code is known at build time; it ships pre-colored with zero grammar bytes in the browser.

Props

7 props, straight from the manifest.

PropTypeDefaultBindingsDescription
lang string
html svelte astro
The language id, with aliases resolved (`ts` → `typescript`). An unknown id falls back to plain-but-themed text.
code string
html svelte astro
The source to highlight. Optional for html/svelte (the text content is used); the canonical input for Astro's build-time tokenization.
preload boolean false
html svelte astro
Warm this block's grammar eagerly and emit a `modulepreload` hint, killing the minor recolor flash on known code-heavy pages.
copy boolean true
html svelte astro
The copy-to-clipboard button. On by default; set `copy="false"` to drop it. It only paints where it can work — hidden in an insecure context (no Clipboard API) and on the zero-JS Astro path.
wrap boolean false
html svelte astro
Soft-wrap long lines instead of scrolling them horizontally. Purely declarative — the host attribute drives a CSS rule, so it needs no JavaScript and works on the zero-JS Astro path.
line-numbers boolean false
html svelte astro
Number each line in a gutter that stays put while the code scrolls sideways. Tag-aware, so a token spanning lines (a block comment, a multi-line string) still numbers cleanly, and it co-operates with `wrap` — a wrapped line keeps a single number at its top. The gutter is pure derived chrome — it borrows `--code-comment` and `--field-border`, adding no tokens — and renders on the zero-JS Astro path too.
highlight string
html svelte astro
Tint chosen lines with `--code-line-highlight` to call out the ones that matter — a 1-based spec like `2`, `2,4`, or `4-6`, mixable as `1,3-5,8`. Pairs with `line-numbers`, works under `wrap`, and renders on the zero-JS Astro path; it reuses a token the algorithm already derives, so it adds none.

Anatomy

The named parts that make up the component, with their selectors.

pre

.xoji-code

The block surface: the scroll container that carries the code background and padding.

--code-bg --code-fg --radius-md --font-mono --text-sm --space-4

code

.xoji-code code

The tokenized source: .token.* spans colored by the per-scope code tokens.

--code-keyword --code-string --code-comment --code-function

copy

.xoji-code-copy

The copy-to-clipboard button, anchored top-right; fades in on hover or focus and flashes a vivid Copied state on success.

--neutral-bg --field-border --radius-sm --success-vivid

line-number

.xoji-code-line::before

The per-line counter gutter, shown when line-numbers is set; it sticks to the left edge as the code scrolls sideways and reads dimmed, like a comment.

--code-comment --field-border --code-bg --space-4 --space-2

line-highlight

.xoji-code-line[data-line-highlight]

A line called out by highlight; the whole row is tinted with --code-line-highlight, the low-alpha accent the algorithm derives for exactly this.

--code-line-highlight

Tokens & coverage

What the component consumes, checked live against what the algorithm produces.

Success:fully covered 36/36 consumed tokens produced default register: 276 tokens

Live coverage check against the xoji-default register (derive(xojiDefault, { anchors })coverComponent(manifest, register)). Every token this component consumes must be a key the algorithm produces.

--border-thin --code-attr --code-bg --code-comment --code-fg --code-function --code-keyword --code-line-highlight --code-number --code-operator --code-punctuation --code-regexp --code-selection --code-string --code-tag --code-type --code-variable --duration-fast --ease-standard --field-border --font-mono --font-sans --leading-normal --neutral --neutral-bg --neutral-fg --neutral-text --radius-md --radius-sm --space-1 --space-2 --space-4 --success --success-vivid --text-sm --text-xs

Slots

default
html svelte

The source code as text content (html/svelte). For Astro, pass the source via the code prop instead.

Accessibility

Renders semantic <pre><code>, so assistive tech announces the block as preformatted code.
Coloring is presentational only: the token spans add no meaning, so the code reads identically with styles off.
The copy control is a real <button> with an accessible name, keyboard-operable, and reachable on touch where there is no hover; on a successful copy its name updates to Copied so the action is announced.

Code

Languages and preload

A TypeScript block and a preloaded Rust block, both colored from the code-token family.

<xoji-code lang="ts">const greet = (name: string) =&gt; `hi ${name}`;</xoji-code>

<xoji-code lang="rust" preload>fn main() { println!("hello"); }</xoji-code>
<script lang="ts">
	import { Code } from "@xoji/svelte";
</script>

<Code lang="ts">{`const greet = (name: string) => \`hi ${name}\`;`}</Code>
---
import Code from "@xoji/astro/Code.astro";
---

<Code lang="ts" code={`const greet = (name: string) => \`hi ${name}\`;`} />

Soft-wrap long lines

wrap folds long lines into the column instead of scrolling them sideways. It's a declarative host attribute, so it needs no JavaScript and works on the static Astro path.

<xoji-code lang="ts" wrap>const message = "a long line that soft-wraps in a narrow column instead of scrolling sideways";</xoji-code>
<script lang="ts">
	import { Code } from "@xoji/svelte";
</script>

<Code lang="ts" wrap>{`const message = "a long line that soft-wraps instead of scrolling";`}</Code>
---
import Code from "@xoji/astro/Code.astro";
---

<Code lang="ts" wrap code={`const message = "a long line that soft-wraps instead of scrolling";`} />

Line numbers

line-numbers adds a counter gutter that sticks to the left edge as the code scrolls and keeps a single number per logical line even under wrap.

<xoji-code lang="ts" line-numbers>function add(a: number, b: number) {
	return a + b;
}

const sum = add(2, 3);</xoji-code>
<script lang="ts">
	import { Code } from "@xoji/svelte";
</script>

<Code lang="ts" lineNumbers>{`function add(a, b) {
	return a + b;
}`}</Code>
---
import Code from "@xoji/astro/Code.astro";
---

<Code lang="ts" lineNumbers code={`function add(a, b) {
	return a + b;
}`} />

Highlighting lines

highlight tints the lines that matter, via a 1-based spec like 2,4 or 4-6, drawn from the --code-line-highlight token the algorithm already derives; it pairs with line-numbers.

<xoji-code lang="ts" line-numbers highlight="2,4">function total(items) {
	let sum = 0;
	for (const n of items) sum += n;
	return sum;
}</xoji-code>
<script lang="ts">
	import { Code } from "@xoji/svelte";
</script>

<Code lang="ts" lineNumbers highlight="2,4">{`function total(items) {
	let sum = 0;
	for (const n of items) sum += n;
	return sum;
}`}</Code>
---
import Code from "@xoji/astro/Code.astro";
---

<Code lang="ts" lineNumbers highlight="2,4" code={`function total(items) {
	let sum = 0;
	for (const n of items) sum += n;
	return sum;
}`} />

Languages

Every language the code block can highlight, 299 in all; each grammar lazy-loaded per block. An unknown language renders as plain, themed text rather than erroring.

Added by xoji

Info:astro Info:svelte

Prism ships neither; xoji adds them. Everything else is Prism's canonical set.

Aliases

adoc → asciidoc arm-asm → armasm art → arturo atom → markup avdl → avro-idl avs → avisynth cfc → cfscript cilk → cilkcpp
All 299 languages
abapabnfactionscriptadaagdaalantlr4apacheconfapexaplapplescriptaqlarduinoarffarmasmarturoasciidocasm6502asmatmelaspnetastroautohotkeyautoitavisynthavro-idlawkbashbasicbatchbbcodebbjbicepbirbbisonbnfbqnbrainfuckbrightscriptbrobslccfscriptchaiscriptcilcilkccilkcppclikeclojurecmakecobolcoffeescriptconcurnascooklangcoqcppcrystalcsharpcshtmlcspcsscss-extrascsvcuecypherddartdataweavedaxdhalldiffdjangodns-zone-filedockerdotebnfeditorconfigeiffelejselixirelmerberlangetluaexcel-formulafactorfalsefirestore-security-rulesflowfortranfsharpftlgapgcodegdscriptgedcomgettextgherkingitglslgmlgngogo-modulegradlegraphqlgroovyhamlhandlebarshaskellhaxehclhlslhoonhpkphstshttpichigojamiconicu-message-formatidrisiecstignoreinform7iniiojjavajavadocjavadoclikejavascriptjavastacktracejexljoliejqjs-extrasjs-templatesjsdocjsonjson5jsonpjsstacktracejsxjuliakeepalivedkeymankotlinkumirkustolatexlattelesslilypondlinker-scriptliquidlisplivescriptllvmloglolcodeluamagmamakefilemarkdownmarkupmarkup-templatingmatamatlabmaxscriptmelmermaidmetafontmizarmongodbmonkeymoonscriptn1qln4jsnand2tetris-hdlnaniscriptnasmneonnevodnginxnimnixnsisobjectivecocamlodinopenclopenqasmozparigpparserpascalpascaligopcaxispeoplecodeperlphpphp-extrasphpdocplant-umlplsqlpowerquerypowershellprocessingprologpromqlpropertiesprotobufpslpugpuppetpurepurebasicpurescriptpythonqqmlqoreqsharprracketreasonregexregorenpyrescriptrestriproboconfrobotframeworkrubyrustsassassscalaschemescssshell-sessionsmalismalltalksmartysmlsoliditysolution-filesoysparqlsplunk-splsqfsqlsquirrelstanstatastylussupercollidersvelteswiftsystemdt4-cst4-templatingt4-vbtaptcltextiletomltremortsxtt2turtletwigtypescripttyposcriptunrealscriptuorazorurivvalavbnetvelocityverilogvhdlvimvisual-basicwarpscriptwasmweb-idlwgslwikiwolframwrenxeoraxml-docxojoxqueryyamlyangzig