highlight

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 3, 2026 License: MIT Imports: 5 Imported by: 0

README

highlight

A small syntax highlighter for server-rendered HTML. One hand-written, line-oriented scanner per language over a shared token type: Go, Ruby, sh, SQL, CSS, JavaScript, JSON, Lua, HTML, Markdown, and hml.

highlight.Code(w, "main.go", src)   // or "go", from a markdown fence
highlight.Diff("main.go", patch)    // a unified-diff patch

Five classes come out — k keywords, n names, s strings, m numbers, c comments — plus four for a diff's rows: gi inserted, gd deleted, gu hunk header, gc context. Colors are yours; those nine names are the whole contract.

The curation is the point. It is fast and small because it is deliberately incomplete and covers only a few languages. A format with no scanner is escaped and rendered uncolored, so callers can mix. See doc.go.

This repo is a mirror

Development happens on cibot, a self-hosted review and CI server, which holds the branches. GitHub receives main and the tags, so go get works and a commit hash is browsable, and pull requests are closed because there is nothing here to merge into.

main arrives with each merge. A tag is deliberate:

scripts/tag v0.1.0

License

MIT

Documentation

Overview

Package highlight colors source code for server-rendered HTML.

It is a hand-written, line-oriented scanner per language over a shared token type, for a curated set of formats: Go, sh, SQL, CSS, JavaScript, Markdown, and hml. A format it has no scanner for is escaped and rendered uncolored, so callers can mix.

Scope

Five classes come out -- k keywords, n names, s strings, m numbers, c comments -- and nothing else. The curation is the product: this is fast and small because it is deliberately incomplete and covers only a handful of languages. It is not a lexer framework, not a plugin registry, and not correctness-complete for any language. A word a keyword list misses is uncolored, not wrong.

Two layers

Tokens are the lower layer: a scanFunc reads one line, given the state the line before it ended in, and returns the state this one ended in. Carrying state is the whole point -- a lexer restarted per line colors the second half of a raw string as code.

Emitters are the upper layer, and HTML is one consumer rather than the interface. Code writes a whole file; Diff writes a unified-diff patch, where each row also carries a diff class (gi inserted, gd deleted, gu hunk header, gc context).

Escaping

Both emitters HTML-escape every byte they write. The source may be a file a stranger pushed, so nothing in it can become markup.

Styling

The nine class names are the whole contract with a stylesheet, and there is no shipped palette: colors are the consuming site's.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Code

func Code(w io.Writer, name, src string) error

Code writes src as HTML-escaped text with each colored run wrapped in a class span. name is a filename or a language name; a format with no scanner is escaped and left uncolored.

Nothing frames the output: no <pre>, no <code>, no wrapper class. The caller already knows what it is putting the code inside, and a markup opinion here would be one to work around there.

func Diff

func Diff(filename, patch string) template.HTML

Diff renders a unified-diff patch with two layers of coloring: each line carries a row-wide diff class (gi inserted, gd deleted, gu hunk header, gc context) and, underneath, its content is tokenized by the scanner matched to filename.

Style the per-line spans display:block and the row tint extends across the full <pre> width, GitHub-style. Marker chars (+/-) inherit the row's foreground color; language tokens override it.

A patch is two interleaved programs, so it needs two carry states: context plus deletions is the old file, context plus insertions is the new one. One state would let an edit inside a string miscolor the rest of the hunk. A hunk header resets both, since the file jumped.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL