Coflat exposes a stable set of cf-* class names plus documented CSS
custom properties. Hosts and applications own theme discovery,
persistence, user selection, CSS loading, and any theme-picker UI.
Coflat does not keep a theme registry or apply themes globally.
The package owns only the target contract:
- apply
cf-theme-scopeto the nearest root that should receive a theme - apply a theme class or data attribute chosen by the host
- render full-document reader HTML inside
cf-reader cf-doc-surface cf-doc-flow; document nodes carry canonicalcf-doc-*classes - mount editor instances inside the same scoped root when reader/editor should share a theme
This is intentionally scoped. A host can show two documents with two different themes on the same page.
<div class="cf-theme-scope cf-theme-blueprint-book" data-cf-theme="blueprint-book">
<div class="cf-reader-shell">
<aside class="cf-reader-toc">...</aside>
<main class="cf-reader-document">
<div class="cf-reader cf-doc-surface cf-doc-flow">
<!-- renderToHtml(...) output -->
</div>
</main>
</div>
</div>Plain renderToHtml callers should wrap the returned HTML themselves. Use the
full reader wrapper above for pages, long issue bodies, PR descriptions, and
exported documents. For compact snippets or comments, keep
cf-reader cf-doc-flow and add a host-owned compact class that overrides
width, padding, and rhythm locally.
The default stylesheet is @chaoxu/coflat/style.css. Optional
theme CSS is imported separately by hosts.
import "@chaoxu/coflat/style.css";
import "@chaoxu/coflat/themes/blueprint-book.css";This file is the contract. Changes to the class names or to the custom-property names below are breaking changes and bumped according to semver.
Hosts may represent internal, user-authored, or marketplace themes with
the exported CoflatThemeManifest type. The manifest is descriptive:
Coflat never loads css entries or writes variables for the host.
import type { CoflatThemeManifest } from "@chaoxu/coflat/reader";
const theme: CoflatThemeManifest = {
id: "my-lab-theme",
name: "My Lab Theme",
targets: ["reader", "editor"],
css: ["/themes/my-lab-theme.css"],
rootClass: "my-lab-theme",
dataTheme: "my-lab-theme",
variables: {
"--cf-content-max-width": "72ch",
},
};The bundled blueprint/book theme also has an exported manifest:
import { blueprintBookThemeManifest } from "@chaoxu/coflat/reader";| Class | Element |
|---|---|
cf-theme-scope |
scoped root for host/user-applied variables and theme classes |
cf-reader-shell |
optional single-document reader layout wrapper |
cf-reader-toc |
optional host-rendered table of contents |
cf-reader-document |
document column wrapper inside a shell |
cf-reader |
wrapper around renderToHtml output |
cf-doc-surface |
shared reader/editor document surface colors |
cf-doc-flow |
shared reader/editor document typography |
| Class | Element |
|---|---|
cf-doc-heading cf-doc-heading--h1 … --h6 |
canonical heading classes on <h1> … <h6> and editor heading lines |
cf-doc-paragraph |
canonical paragraph class |
cf-doc-list cf-doc-list--unordered |
canonical <ul> classes |
cf-doc-list cf-doc-list--ordered |
canonical <ol> classes |
cf-doc-list--tight / cf-doc-list--loose |
added to <ul> / <ol> for spacing |
cf-doc-list--check |
added to <ul> / <ol> when items are task items |
cf-doc-list-item |
canonical <li> class |
cf-doc-list-item cf-doc-list-item--check |
task <li> (carries `data-checked="true |
cf-doc-blockquote |
canonical <blockquote> class |
cf-doc-code-block |
canonical <pre> class (inner <code>; pre carries data-lang) |
cf-doc-block cf-doc-block--hr |
<hr> |
cf-doc-table-block |
canonical <table> class |
cf-doc-table-row |
<tr> |
cf-doc-table-cell |
<td> |
cf-doc-table-cell cf-doc-table-header |
<th> (header row cell) |
cf-doc-block cf-doc-block--{type} |
canonical semantic block classes |
cf-footnotes |
trailing <ol> listing footnote definitions |
cf-footnote-item |
each footnote <li> |
cf-doc-display-math |
block math placeholder |
| Class | Element |
|---|---|
cf-doc-code-token |
canonical inline-code class |
cf-highlight |
<mark> |
cf-image |
<img> |
cf-footnote-ref |
<sup> wrapping the ref <a> |
cf-footnote-backref |
<a> linking back from the definition |
cf-doc-inline-math |
inline math placeholder |
cf-katex-small-caps |
KaTeX HTML span emitted for \textsc{...} |
cf-citation |
explicitly formatted citation <span> |
cf-crossref-unresolved |
unresolved crossref <span> |
Full-document reader output and CM6 rich mode share the same document
semantics. Themes should style shared cf-doc-* classes, shared runtime
classes such as cf-math-*, cf-crossref-*, cf-citation-*, and the
--cf-* tokens on cf-theme-scope. Avoid reader-only or CM6-only overrides
for prose, lists, tables, math, cross-references, and semantic blocks unless
the visual difference is intentional.
Math placeholders carry both the document class and runtime class
(cf-doc-inline-math cf-math-inline,
cf-doc-display-math cf-math-display). Display math always contains
cf-math-display-content, so themes can center and size display math once for
both surfaces. Fenced semantic block references are derived from the block
manifest prefixes (thm, lem, prop, conj, def, prob, rem, ex,
and related figure/table/algorithm prefixes), so new block types should add a
manifest prefix instead of teaching the reader and editor separately.
KaTeX HTML output may also contain cf-katex-small-caps when the source uses
\textsc{...} in math. The default stylesheet renders that class with
font-variant-caps: small-caps; hosts that replace the Coflat stylesheet should
preserve equivalent styling.
| Attribute | Where |
|---|---|
data-lang |
<pre class="cf-doc-code-block"> (info string) |
data-checked |
task <li> ("true" or "false") |
data-math |
math placeholder (escaped raw source for hydration) |
data-align |
aligned table cells (also mirrored to inline style="text-align:…") |
data-ref-key |
citation / crossref placeholder |
data-ref-mode |
citation placeholder ("bracketed" or "narrative") |
data-source-line |
every block-level element (opt-in via renderToHtml(_, _, { sourceLineAttribution: true })) |
data-{key} |
fenced-div attribute key/value pairs flow through verbatim |
The library stylesheet defines the shared theming surface. Hosts should
prefer overriding these on a cf-theme-scope container. :root still
works for application-wide defaults.
| Variable | Default purpose |
|---|---|
--cf-bg |
Document/application background. |
--cf-fg |
Body text color. |
--cf-muted |
Muted text and secondary UI. |
--cf-border |
Default border color. |
--cf-subtle |
Subtle surface background. |
--cf-hover |
Hover surface background. |
--cf-active |
Active surface background. |
--cf-accent |
Accent/link fallback color. |
--cf-accent-fg |
Text on accent. |
--cf-color-link |
<a> text color. |
--cf-color-code-bg |
Background for cf-doc-code-block and cf-doc-code-token. |
--cf-ui-font |
UI font stack. |
--cf-content-font |
Document/prose font stack. |
--cf-code-font |
Monospace stack for code blocks and inline code. |
--cf-base-font-size |
Reader/editor document base size. |
--cf-line-height |
Reader/editor document line height. |
--cf-content-max-width |
Reader/editor document column width. |
--cf-doc-content-padding-block-start |
Document top padding. |
--cf-doc-content-padding-block-end |
Document bottom padding. |
--cf-doc-content-padding-inline |
Document inline padding. |
--cf-doc-paragraph-margin |
Reader paragraph margin. |
--cf-doc-heading-margin |
Reader heading margin. |
--cf-doc-list-margin |
Reader list margin. |
--cf-doc-list-item-margin |
Reader list item margin. |
--cf-doc-code-block-margin |
Reader code block margin. |
--cf-doc-blockquote-margin |
Reader blockquote margin. |
--cf-h1-size … --cf-h6-size |
Heading sizes. |
--cf-h1-weight … --cf-h6-weight |
Heading weights. |
--cf-h1-style … --cf-h6-style |
Heading styles. |
--cf-block-{type}-accent |
Semantic block accent, e.g. theorem, proof. |
--cf-block-{type}-style |
Semantic block body font style. |
--cf-block-title-color |
Semantic block title color. |
--cf-block-title-weight |
Semantic block title weight. |
--cf-block-title-separator |
Separator after rendered block title. |
--cf-block-margin |
Semantic block margin. |
--cf-proof-marker |
Proof-ending marker. |
--cf-table-border |
Table cell border. |
--cf-table-header-border |
Table header border. |
--cf-table-cell-padding |
Table cell padding. |
--cf-table-font-size |
Table font size. |
--cf-table-line-height |
Table line height. |
The complete typed token list is exported from
@chaoxu/coflat as themeTokenNames. External full-CSS themes
may use additional private variables under their own prefix.
.my-host-doc.cf-theme-scope {
--cf-color-link: #c84600;
--cf-color-code-bg: #faf6ef;
}The host applies .my-host-doc to the container that wraps the
reader's output. The cascade does the rest — no JS coordination needed.
The optional blueprint/book theme is a single-document presentation theme inspired by Lean blueprint output. It does not include dependency graphs, Lean metadata, or a TeX/plasTeX compatibility layer.
import "@chaoxu/coflat/style.css";
import "@chaoxu/coflat/themes/blueprint-book.css";Apply it on a scoped root:
<div class="cf-theme-scope cf-theme-blueprint-book">
<div class="cf-reader cf-doc-surface cf-doc-flow">...</div>
</div>For an optional table of contents, use the reader shell classes shown at the top of this document. The host owns TOC generation and selection UI.