No description
- Go 77.6%
- JavaScript 18.7%
- Shell 2.1%
- CSS 1.6%
| bin | ||
| cmd/xmarkgen | ||
| js | ||
| AGENTS.md | ||
| allowlists_test.go | ||
| buffer.go | ||
| buffer_test.go | ||
| generate.go | ||
| go.mod | ||
| go.sum | ||
| prompt.go | ||
| README.md | ||
| stream_test.go | ||
| x-mark.md | ||
| xmark.go | ||
| xmark_test.go | ||
xmark
quorum.dev/wwww/xmark — LLM-flavored markdown rendering for Go web UIs,
ported out of autonaut (internal/mkd).
xmark renders markdown the way an agentic chat UI needs it:
Render(src string) string— markdown → sanitized HTML fragment. goldmark (GFM + chroma class-based syntax highlighting) followed by a bluemonday sanitizer. The x-mark custom elements (<x-note>,<x-sh>,<x-ref>,<x-tree>, …) and their semantic attributes survive sanitization so the client can hydrate them into rich components.Buffer— accumulates streamed LLM deltas and flushes rendered fragments only at structurally safe boundaries (never mid-block, never inside an unclosed<x-*>/HTML element), so each fragment can be appended to the DOM as-is.Write(delta)per token batch,Close()at stream end,Open()to detect a live-streaming<svg>diagram.- SVG diagrams — a standalone (or fenced, or inline)
<svg>is routed around goldmark/bluemonday, which would fragment or lowercase-mangle it, and delivered inert viaRenderDiagram/RenderDiagramLive: HTML-escaped inside adiv.svg-hostfor the client's DOMPurify pass to hydrate. StylesheetCSS()— the chroma CSS for the class-based highlighting.Prompt— the embedded x-mark.md authoring guide. Append it to a model's system prompt so it emits<x-*>markup and theme-aware SVG this package renders.
import "quorum.dev/wwww/xmark"
html := xmark.Render("# hello\n\n<x-note type=\"info\">hi</x-note>")
buf := xmark.New()
for delta := range stream {
if frag := buf.Write(delta); frag != "" {
send(frag) // append to the DOM
}
}
send(buf.Close())
Client contract
js/ is the browser half, plain ESM with no dependencies (DOMPurify is
injected by the host app):
js/xmark.js—createXmark({ purify, postRenderSelector })returns the enhancers:installPurifyHooks()(teaches DOMPurify the x-mark / SVG tags and attrs),hydrateSvgHosts/hydrateXTrees,enhance(root),watch(root, { onAdded })(re-enhance as server-rendered fragments land),installTreeToggles(), and thepostRenderersafety net that lifts escaped<svg>source out of streamed text into live diagrams — always through DOMPurify.js/allowlists.js— the tag/attr allowlists, generated from the Go vars (go generate ./..., seecmd/xmarkgen);allowlists_test.gofails when it's stale. Go is the single source of truth for both sanitizer layers.js/xmark.css— structural styles only (svg-host hidden until hydrated, diagram sizing, the live-preview pulse). Component themes belong to the host app via the--x-*custom properties.
<script type="module">
import { createXmark } from "./xmark.js";
const xm = createXmark({ purify: window.DOMPurify });
xm.installPurifyHooks();
xm.enhance(document.body);
xm.watch(document.body, { onAdded: () => scrollToBottom() });
xm.installTreeToggles();
</script>
Scripts
bin/test—bin/fmt+bin/cibuildbin/fmt—go mod tidy+go generate ./...+goimports+ node syntax check ofjs/bin/cibuild— staticcheck +go test+go vet