Skip to content

HTML and themes

phil/highlight

Token types

Every language writes the same 26 types, so one theme serves them all. The class of a type is hl- and its value.

TypeClassWhat it marks
Keywordhl-keywordReserved words, CSS at-rules, Dockerfile instructions
Typehl-typeType names, and capitalized names in the languages that say so
Builtinhl-builtinFunctions the language provides, often called without parentheses
Constanthl-constanttrue, null, Ruby symbols, YAML and INI booleans
Numberhl-numberNumbers, CSS dimensions and colours
Stringhl-stringQuoted texts, attribute values, YAML and INI plain values
Regexhl-regexRegular expression literals
Commenthl-commentComments, diff notes
Operatorhl-operatorOperators, YAML block indicators, INI's =
Punctuationhl-punctuationBrackets, separators, markup's angle brackets, Markdown marks
Variablehl-variableVariables with a sigil, CSS custom properties, YAML anchors and aliases, SCSS interpolations
Functionhl-functionCalls, macros, filters, CSS functions
Metahl-metaPreprocessor lines, decorators, attributes, shebangs, PHP tags, doctypes, YAML tags, fence info
Taghl-tagMarkup tag names
AttributeNamehl-attr-nameMarkup attribute names
Entityhl-entityCharacter references
Propertyhl-propertyCSS properties, JSON, YAML and INI keys
Selectorhl-selectorCSS selectors
Sectionhl-sectionINI sections, diff hunk headers
Headinghl-headingMarkdown headings
Emphasishl-emphasisMarkdown emphasis
Stronghl-strongMarkdown strong emphasis
Linkhl-linkMarkdown links, images and autolinks
Codehl-codeMarkdown code spans and fenced blocks
Insertedhl-insertedLines a diff adds
Deletedhl-deletedLines a diff removes

The HTML

HtmlFormatter::format() escapes every text with htmlspecialchars() — &, <, >, " and ' — and wraps each typed token in <span class="hl-…">; plain text, such as spaces and ordinary names, is not wrapped. Tokens of the same type next to each other are already joined by the tokenizer, so a run of punctuation is one span. Invalid UTF-8 is replaced by U+FFFD. The output holds no other markup and no line structure of its own: put it inside <pre><code class="language-…">, whose white-space keeps the lines.

The language-… class is what the highlight controller of phil/ux-bundle reads in the browser; a block already holding hl- spans is left as it is, so code coloured on the server is not coloured twice.

Given LineOptions, the same tokens are written line by line, each line in a <span class="hl-line"> with its marks and its number: see Lines.

The themes

themes/light.css, themes/dark.css and themes/auto.css set custom properties on :root and colour the classes with them; pre holding a code with a language, or any element with the class hl, takes the theme's background and text colour. Each colour meets the WCAG AA contrast for normal text against its background.

PropertyColours
--hl-background, --hl-textThe block
--hl-keywordKeywords, selectors, sections, headings
--hl-typeTypes and built-ins
--hl-functionCalls, links
--hl-numberNumbers, constants, references
--hl-stringStrings, regular expressions, Markdown code
--hl-commentComments, in italics
--hl-punctuationOperators and punctuation
--hl-variableVariables
--hl-metaMeta
--hl-tagTag names
--hl-propertyAttribute names and properties
--hl-inserted, --hl-inserted-background, --hl-deleted, --hl-deleted-backgroundDiff lines
--hl-line-highlighted-background, --hl-line-inserted-background, --hl-line-deleted-backgroundMarked lines

A page changes a colour by redefining its property, on :root or on one block:

:root { --hl-keyword: #7c3aed; }

A theme of your own is a stylesheet of the hl- classes: the list above is the whole contract, with the classes of the lines below.

Lines

When a block is written line by line, each theme lays the lines out:

ClassLaid out as
hl-lineA box as wide as the block at least, with room at its start for a bar and a sign
hl-line-numberRight-aligned in the colour of comments; it cannot be selected, so a copy of the block holds the code alone
hl-line-highlightedIts tint and a bar in the colour of calls
hl-line-insertedIts tint, a bar and a + in the colour of inserted lines
hl-line-deletedIts tint, a bar and a - in the colour of deleted lines

A mark is never told by colour alone: the bar and the sign say it too, and the sign is hidden from screen readers. Every colour of a token keeps the WCAG AA contrast on the three tints; in the light theme, whose colours sit close to that limit against its background, the tints are faint and the bar does most of the telling.