HTML and CSS
Comfit renders source code as an escaped HTML fragment. The default structure is <pre><code>, with a span around each line. Choose how the fragment represents token styles:
| Mode | Use it when | What you supply |
|---|---|---|
| Inline | You want theme colors in the returned HTML. | A bundled theme ID or theme object, depending on the package. |
| Classes | You want a shared stylesheet. | CSS rules for capture classes, or an @comfit/css theme. |
| Variables | You want your application's CSS to define the colors. | --comfit-* CSS variables. |
The default is classes in the libraries and inline styles in the CLI. None of these modes sets your font, padding, or line-number layout.
Inline styles
Embed theme colors in the returned fragment.
import { renderHtml, RenderHtmlConfig, RenderHtmlStyle } from "@comfit/node";
const config = new RenderHtmlConfig();
config.style = RenderHtmlStyle.Inline;
const html = renderHtml(
"const answer = 42;",
"javascript",
"catppuccin-mocha",
config,
);
Use an initialized browser highlighter with JavaScript loaded. Inline output takes a theme object, not a bundled theme ID.
const html = highlighter.renderHtml("const answer = 42;", "javascript", {
style: "inline",
theme: {
default: { fg: "#cdd6f4", bg: "#1e1e2e" },
styles: {
keyword: { fg: "#cba6f7" },
number: { fg: "#fab387" },
},
},
});
Enable the javascript and render-html features on comfit. Also enable catppuccin-mocha on comfit-themes.
let mut highlighter = comfit::Highlighter::new()?;
let highlighted = highlighter.highlight(
"const answer = 42;",
"javascript",
&comfit::HighlightConfig::default(),
)?;
let config = comfit::RenderHtmlConfig {
style: comfit::RenderHtmlStyle::Inline,
..Default::default()
};
let html = highlighted.render_html(comfit_themes::catppuccin_mocha::theme(), &config);
import comfit
config = comfit.RenderHtmlConfig(style=comfit.RenderHtmlStyle.Inline)
html = comfit.render_html(
"const answer = 42;", "javascript", "catppuccin-mocha", config
)
Add this configuration to your framework's rehypePlugins. See the Markdown and MDX to set up a pipeline.
import rehypeComfit from "@comfit/rehype";
const rehypePlugins = [
[rehypeComfit, { style: "inline", theme: "catppuccin-mocha" }],
];
comfit html main.js --theme catppuccin-mocha --style inline
Classes
Use class-based output when several code blocks should share a stylesheet instead of embedding colors in every fragment. @comfit/css styles HTML generated by any Comfit package.
This example uses Catppuccin Mocha. The theme catalog lists the other stylesheets and their matching outer classes.
Install a stylesheet
pnpm add @comfit/css
npm install @comfit/css
bun add @comfit/css
Load a theme
Load the stylesheet on the web page that displays the generated HTML, regardless of which Comfit package renders it.
Import the stylesheet in your frontend entry point with a build tool that supports CSS imports.
import "@comfit/css/catppuccin-mocha.css";
For a page without a bundler, use a link element.
<link
rel="stylesheet"
href="https://esm.sh/@comfit/[email protected]/dist/catppuccin-mocha.css"
>
Match the HTML class
Generate a fragment with the matching outer class:
import { renderHtmlClasses, RenderHtmlConfig } from "@comfit/node";
const config = new RenderHtmlConfig();
config.preClass = "comfit-catppuccin-mocha";
const html = renderHtmlClasses("const answer = 42;", "javascript", config);
Use an initialized browser highlighter with JavaScript loaded.
import "@comfit/css/catppuccin-mocha.css";
const html = highlighter.renderHtml("const answer = 42;", "javascript", {
style: "class",
preClass: "comfit-catppuccin-mocha",
});
Enable the javascript and render-html features on comfit.
let mut highlighter = comfit::Highlighter::new()?;
let highlighted = highlighter.highlight(
"const answer = 42;",
"javascript",
&comfit::HighlightConfig::default(),
)?;
let config = comfit::RenderHtmlConfig {
pre_class: Some("comfit-catppuccin-mocha".into()),
..Default::default()
};
let html = highlighted.render_html_classes(&config);
Pass a valid bundled theme ID even in class mode.
import comfit
config = comfit.RenderHtmlConfig(
style=comfit.RenderHtmlStyle.Class,
pre_class="comfit-catppuccin-mocha",
)
html = comfit.render_html(
"const answer = 42;", "javascript", "catppuccin-mocha", config
)
Add this configuration to your framework's rehypePlugins. See the Markdown and MDX to set up a pipeline.
import rehypeComfit from "@comfit/rehype";
const rehypePlugins = [
[rehypeComfit, { style: "class", preClass: "comfit-catppuccin-mocha" }],
];
comfit html main.js --theme catppuccin-mocha --style class \
--pre-class comfit-catppuccin-mocha
The stylesheet's scope must match the outer pre class: catppuccin-mocha.css expects comfit-catppuccin-mocha. You can serve the stylesheet through an HTML link element instead of importing it.
A function.call capture produces both function and function-call classes. Lines have line and, when selected, line-highlight classes. Brackets can have rainbow and rainbow-N classes.
The class-prefix option changes these names. Bundled CSS expects no prefix. A custom prefix needs a matching stylesheet.
CSS variables
Render CSS variable references instead of theme colors.
import {
renderHtmlClasses,
RenderHtmlConfig,
RenderHtmlStyle,
} from "@comfit/node";
const config = new RenderHtmlConfig();
config.style = RenderHtmlStyle.Variables;
config.preClass = "code-block";
const html = renderHtmlClasses("const answer = 42;", "javascript", config);
Use an initialized browser highlighter with JavaScript loaded.
const html = highlighter.renderHtml("const answer = 42;", "javascript", {
style: "variables",
preClass: "code-block",
});
Enable the javascript and render-html features on comfit.
let mut highlighter = comfit::Highlighter::new()?;
let highlighted = highlighter.highlight(
"const answer = 42;",
"javascript",
&comfit::HighlightConfig::default(),
)?;
let config = comfit::RenderHtmlConfig {
style: comfit::RenderHtmlStyle::Variables,
pre_class: Some("code-block".into()),
..Default::default()
};
let html = highlighted.render_html_classes(&config);
A valid theme ID is required, although variable mode does not use its palette.
import comfit
config = comfit.RenderHtmlConfig(
style=comfit.RenderHtmlStyle.Variables,
pre_class="code-block",
)
html = comfit.render_html(
"const answer = 42;", "javascript", "catppuccin-mocha", config
)
Add this configuration to your framework's rehypePlugins. See the Markdown and MDX to set up a pipeline.
import rehypeComfit from "@comfit/rehype";
const rehypePlugins = [
[rehypeComfit, { style: "variables", preClass: "code-block" }],
];
A valid theme ID is required, although variable mode does not use its palette.
comfit html main.js --theme catppuccin-mocha --style variables \
--pre-class code-block
Define colors in your CSS:
.code-block {
--comfit-fg: #cdd6f4;
--comfit-bg: #1e1e2e;
--comfit-keyword-fg: #cba6f7;
--comfit-number-fg: #fab387;
}
Capture variables fall back from the full name to its parents, then to the default. For example, --comfit-function-call-fg falls back to --comfit-function-fg, then --comfit-fg. The class-prefix option does not rename these variables.
@comfit/css provides class rules, not variable-mode palettes. Set the variables yourself.
Add layout styles
Use your outer class to set the font, padding, and overflow. The generated .line elements do not add visible line numbers. Give them display: block if you want selected-line backgrounds to fill the available width.
Comfit escapes source text and generated attribute values. When building your own renderer from tokens, escape token text yourself. A syntax highlighter is not a sanitizer for arbitrary HTML documents.
Element tags
Choose the outer container and line wrapper elements. Their defaults are pre and span.
The inner code element and token span elements stay unchanged. Classes and inline styles remain on the selected wrappers.
import { RenderHtmlConfig } from "@comfit/node";
const config = new RenderHtmlConfig();
config.preTag = "div";
config.lineTag = "div";
Use an initialized browser highlighter with JavaScript loaded.
const html = highlighter.renderHtml("const answer = 42;", "javascript", {
preTag: "div",
lineTag: "div",
});
Enable the render-html feature on comfit.
let config = comfit::RenderHtmlConfig {
pre_tag: "div".into(),
line_tag: "div".into(),
..Default::default()
};
import comfit
config = comfit.RenderHtmlConfig(pre_tag="div", line_tag="div")
Add this configuration to your framework's rehypePlugins. See the Markdown and MDX to set up a pipeline.
import rehypeComfit from "@comfit/rehype";
const rehypePlugins = [
[rehypeComfit, { preTag: "div", lineTag: "div" }],
];
Rehype assigns these names to its HAST wrappers after rendering, so its HTML parser does not normalize them.
comfit html main.js --theme catppuccin-mocha \
--pre-tag div --line-tag div
Bundled @comfit/css stylesheets target pre.comfit-<theme>. A different outer tag needs a stylesheet with a matching selector.