Blazingly fast Micron parser and HTML renderer for Go and WebAssembly, based on micron-parser-js. For Go (library) or web based (WASM) applications.
Playground: https://micron-parser-go.quad4.io/
- Go 1.26.2+
- No third-party Go modules (standard library only)
- Node.js (optional): interop tests, reference-JS benchmarks, and the
bench-jsMakefile target
Import path:
import "git.quad4.io/Go-Libs/micron-parser-go/micron"micron.Parser holds only two settings: DarkTheme picks light or dark default colors for the HTML output, and ForceMonospace toggles monospace styling for the rendered page. The type has no mutable conversion state; a single Parser value is safe to reuse from multiple goroutines.
Lines that contain only > section markers and optional spaces set the depth for following lines but do not render an empty heading block. Literal mode toggles on a line whose trimmed content is exactly `= (so padded toggle lines match NomadNet). Multi-line documents are handled line by line in document order.
ConvertMicronToHTML parses the full document, applies optional leading #!fg= / #!bg= header lines (see below), and returns a self-contained HTML fragment safe for insertion into a host page (escaping is applied consistently with the reference implementation).
package main
import (
"fmt"
"git.quad4.io/Go-Libs/micron-parser-go/micron"
)
func main() {
p := micron.Parser{
DarkTheme: true,
ForceMonospace: true,
}
src := "> Title\n\nHello `!world`! and `*micron`*.\n"
html := p.ConvertMicronToHTML(src)
fmt.Print(html)
}For a light theme and proportional fonts (closer to some terminal themes):
p := micron.Parser{DarkTheme: false, ForceMonospace: false}
html := p.ConvertMicronToHTML(markup)Leading lines of the form #!fg=RGB and #!bg=RGB (three or six hex digits per color) set default page foreground and background. You can read them without rendering via ParseHeaderTags, for example to style a surrounding shell or iframe:
markup := "#!fg=ccc\n#!bg=222\n\n> Section\nBody.\n"
colors := micron.ParseHeaderTags(markup)
// colors.FG, colors.BG — may be empty if not set
_ = colors
p := micron.Parser{DarkTheme: true, ForceMonospace: true}
html := p.ConvertMicronToHTML(markup) // header tags are applied during conversionFor applications that render HTML to the client and submit Micron-style links, CollectFormFields and BuildRequestPayload mirror the WASM helpers: turn a list of input snapshots into a field map, then combine with link destination and fieldsSpec (e.g. * for all fields, or name|other).
inputs := []micron.FieldInput{
{Type: "text", Name: "user", Value: "alice"},
{Type: "checkbox", Name: "opts", Value: "1", Checked: true},
{Type: "radio", Name: "plan", Value: "pro", Checked: true},
}
fields := micron.CollectFormFields(inputs)
payload := micron.BuildRequestPayload(
fields,
"/page/submit.mu`action=run|amount=10",
"user|plan",
)
// payload.Destination, payload.Fields, payload.RequestVars — use as needed (JSON tags on RequestPayload)
_ = payloadBenchmarks use the NomadNet guide micron source from Micron-Parser-JS (11248 input bytes).
| Implementation | Environment | Mean time / conversion | Notes |
|---|---|---|---|
| This package (Go) | go test native amd64 |
~0.86 ms | 10x BenchmarkConvertNomadNetGuide runs (pinned); ~0.82-0.91 ms/op, ~2.08 MB/op, 538 allocs/op |
| This package (Go WASM) | Browser bench.html |
~1.68 ms | 10 runs (128 inner iterations); stdev ~0.025 ms; min/max ~1.65-1.72 ms; ~6.4 MiB/s |
| Reference micron-parser-js | Browser bench.html |
~2.63 ms | 10 runs (64 inner iterations); stdev ~0.056 ms; min/max ~2.57-2.77 ms; ~4.1 MiB/s |
WebAssembly: The browser build uses the same Go code as the native benchmark, but timing includes JS/WASM call overhead and is strongly browser-dependent. It will not match the go test numbers above.
WASM vs reference JS (browser mean): 1.57x faster.
Reproduce
make bench
Runs native Go (bench-go, -count=10) and the Node script (bench-js). To summarize Go variance with benchstat:
go test ./micron -bench=BenchmarkConvertNomadNetGuide -benchmem -count=10 | tee /tmp/go.txt
benchstat /tmp/go.txt
make wasm
Open web/index.html in a browser (local file or any static server).
make wasm writes both web/micron.wasm and web/wasm_exec.js. These artifacts are generated into web/ and are intentionally gitignored.
After wasm_exec.js loads the module, the following functions are available on globalThis / window:
| Symbol | Signature | Purpose |
|---|---|---|
micronConvert |
(markup: string, darkTheme?: boolean, forceMonospace?: boolean) => string |
Render Micron source to an HTML string. Defaults match the demo: dark true, monospace true. |
micronCollectFields |
(rootSelector?: string) => string |
JSON string of form field values under document.querySelector(rootSelector) (default #preview). |
micronResolveLink |
(rootSelector?: string, destination?: string, fieldsSpec?: string) => string |
JSON payload for link navigation, using the same field collection rules as the Go helpers. |
The WASM program registers these and then blocks on the Go scheduler (select {}); initialization is synchronous from the host perspective once instantiation completes.
window.onMicronLink— Optional. If defined, the demo calls it when the user activates a rendered Micron link (data-action="openNode"). Receives(payload: object, element: Element)wherepayloadis the JSON frommicronResolveLink. Use this to route in-app navigation, logging, or analytics without forking the stock HTML.- Preview container — Host pages should keep a single preview root (e.g.
#preview) somicronCollectFieldsandmicronResolveLinkresolve inputs consistently.
- Unit tests and edge/smoke suites are in
micron/*_test.go - Security tests cover HTML escaping and attribute escaping
- Fuzz targets cover parser conversion and header parsing
- Race/concurrency coverage is included in concurrent conversion tests
- Goroutine leak guard checks repeated conversion paths
- JS interop test compares output signatures against
micron-parser-js - Benchmarks:
make bench(native Go + reference JS, NomadNet corpus) - Property-based tests in
micron/property_test.go make fuzzruns every fuzz target inmicron/fuzz_test.go(override duration withFUZZTIME=30s)
0BSD. See LICENSE.