go-ruby-erb

Ruby's ERB template compiler in pure Go โ€” MRI-compatible byte-for-byte, no cgo.

pure Go ยท zero cgo ERB::Compiler all tag kinds every trim mode <%% %%> literals magic comments String#dump encoding ERB::Util ยท h / u MRI byte-exact 100% coverage 6 arches
Documentation GitHub
Documentation (MkDocs Material + mike) License: BSD-3-Clause Go 1.26.4+ Coverage 100%

go-ruby-erb is a pure-Go (no cgo) reimplementation of ERB, Ruby's templating system โ€” the deterministic, interpreter-independent core of MRI's ERB::Compiler. It turns an ERB template string into the Ruby source that renders it, matching MRI 4.0.5 byte-for-byte, and provides ERB::Util's html_escape / url_encode helpers. Compiling a template โ€” tag scanning, trim modes, the <%% %%> literals, magic-comment detection, the String#dump text encoding โ€” is fully deterministic and needs no interpreter, so it lives here as pure Go. The final eval(compiled_src, binding) that produces the rendered string does need a Ruby interpreter and stays in the consumer (e.g. rbgo) โ€” this library compiles, the host evaluates. It is the ERB backend for go-embedded-ruby, but a standalone, reusable module with no dependency on the Ruby runtime โ€” differential-tested against MRI, 100% coverage, CI green across 6 arches.

Tag scanner & literals ready

The MRI tag scanner for <% code %>, <%= expression %> and <%# comment %>, plus the <%% / %%> literal escapes โ€” split into the exact stags/etags the reference ERB::Compiler produces.

Trim modes ready

Every MRI trim_mode and its combinations โ€” - explicit -%> newline strip, > end-of-line strip, <> start-and-end strip, and % percent-line code (%% escaping a literal %).

Compiler & text encoding ready

AST โ†’ Ruby source via MRI’s put/insert/pre/post command wiring, with literal runs emitted through Ruby’s String#dump on the binary string so quotes, newlines, control bytes and multibyte UTF-8 round-trip byte-for-byte.

Magic comments & ERB::Util ready

Leading <%# coding: โ€ฆ %> / frozen_string_literal: โ€ฆ detection (incl. the emacs -*- โ€ฆ -*- form) reflected in the emitted prefix, plus ERB::Util’s HTMLEscape / URLEncode helpers.

Differential oracle & coverage ready

A wide template corpus compiled both here and by the system ruby, comparing emitted source and rendered output byte-for-byte against MRI; 100% coverage, gofmt + go vet clean, green across all six 64-bit Go arches.

Ruby surface planned

Downstream, not part of this compiler module: the final eval(compiled_src, binding) that renders the string needs a Ruby interpreter and lives in the go-embedded-ruby consumer (rbgo). This library compiles; the host evaluates.

A faithful port of MRI's lib/erb/compiler.rb in pure Go, cgo disabled, so it cross-compiles and embeds anywhere. It implements every tag kind, the <%% %%> literals, all trim modes (- > <> %), magic-comment detection, and binary-exact String#dump text encoding, plus ERB::Util's HTMLEscape / URLEncode. Validated differentially against the system ruby binary โ€” emitted source and rendered output compared byte-for-byte. It is a standalone, reusable module and the ERB backend for the sibling org github.com/go-embedded-ruby.