@celesta/code
Syntax-highlighted code, with themes and line highlights.
@celesta/code draws syntax-highlighted source code in a composition. It tokenizes with twinkleplop and draws each line as one of Celesta’s own Text layers with color runs, and line highlights as Rects, so code scales, fades, blurs, and exports like any other layer. It is optional: @celesta/react does not depend on it.
Your first code block
import { Assets, Composition, Font, Rect } from '@celesta/react';
import { Code, codeThemes } from '@celesta/code';
const source = `const message: string = 'Hello, Celesta.';
console.log(message);`;
const style = { fontFamily: 'IBM Plex Mono', fontSize: 40, lineHeight: 60 };
export default function Root() {
return (
<Composition width={1280} height={480} fps={30} durationInFrames={90}>
<Assets>
<Font src="./fonts/IBMPlexMono-Regular.ttf" />
</Assets>
<Rect width={1280} height={480} fill="#161418" />
<Code x={64} y={64} language="ts" style={style} theme={codeThemes.dark}>
{source}
</Code>
</Composition>
);
}
Code takes the source as its only child, as a string. Keep indentation and trailing newlines inside the string: they are part of the picture.
Fonts
Use a monospaced font. Code defaults to JetBrains Mono at 24 px with a line height of 1.5 × the font size. Load the font file with <Font src="…" />, as above, or install it on the machine that renders. If the font is missing, Celesta falls back as it does for any text.
Props
Code props
| API | Use it for |
|---|---|
children |
The source, as a string. |
language |
tsx, ts, json, bash, or text (the default, which applies no coloring). |
style |
A Celesta TextStyle: fontFamily, fontSize, lineHeight, and so on. Text is left aligned and never wraps, and the theme supplies each run’s fill color. Other align values throw. |
theme |
Token colors, a foreground fallback, and the line highlight color. codeThemes.dark by default. |
tabSize |
Width of a tab stop, counted in characters. Defaults to 2. |
highlightLines |
One-based line numbers to mark with a highlight band. |
highlightWidth |
Band width in pixels. Defaults to the width of the source; set it to reach the edge of a surrounding panel. |
visibleCharacters |
How much of the source to show, for typing effects. See code: typing, carets & tokens. |
x, y, scale, rotation, anchorX/anchorY, opacity, blendMode, blur, shadow, glow |
The usual layer props apply to the whole block. |
Line highlights
highlightLines draws a band behind the lines you name, full width and full line height, even while the code is still being typed:
<Code x={64} y={64} language="ts" style={style} highlightLines={[2]} highlightWidth={1152}>
{source}
</Code>
Animate the highlight by changing the list as the frame advances; each band is cheap, so highlighting a line per beat or per cue is fine.
Themes
codeThemes.dark and codeThemes.light are ready to use. A theme does not draw a panel background: place a Rect behind the code, sized to your design. To customize, spread a built-in theme and override what you need:
const theme = {
...codeThemes.dark,
highlightLine: '#a68bbf30',
tokens: { ...codeThemes.dark.tokens, keyword: '#e0b7ff' },
};
Token names are twinkleplop’s, such as keyword, string, comment, number, function, type, tag_name, attr_name, punctuation, and operator. In JSON, object keys are property; string values keep string and string_escape. A name your theme does not list uses foreground.
Continue with typing effects, carets, and tokens.