Markdown → HTML, rendered through MDEx (comrak),
on two paths that share one pipeline: to_html/1 for untrusted input
(agent or user output) and to_trusted_html/1 for an authored manual. Both
return a binary of HTML; a Phoenix caller wraps it in Phoenix.HTML.raw/1.
The untrusted path closes two holes that a plain markdown-to-HTML call
leaves open (Fountain #323):
- Raw HTML — an agent emitting
<img src=x onerror=...>as its own paragraph must not become live markup. - Markdown link/image syntax accepts any URL scheme —
[x](javascript:...)must not render as a live link.
to_html/1 walks the parsed document before rendering: every raw-HTML node
(block and inline) is replaced by a text node carrying its source, so the
renderer escapes it and the HTML displays as text rather than executing.
Links and images are dropped unless their URL scheme is on the allowlist —
http/https/mailto for links, http/https for images, relative URLs for both
— and a dropped link or image is unwrapped to its text/alt so the content
still reads. The untrusted path additionally renders with comrak's
unsafe: false + escape: true, so even a raw-HTML node the walk missed
would be escaped rather than emitted.
Scheme checks run on a normalized copy of the URL: character references
decoded and the whitespace/control characters browsers ignore stripped, so
javascript: or java\tscript: cannot smuggle a scheme past the
check. Normalization is deliberately generous — over-decoding can only
make the filter stricter.
Summary
Functions
The default list of languages whose parsers a host bakes into its image;
see @languages. A host's docs module returns its own list from
languages/0 (the languages: option of use Managoat.Docs, this list
when the option is absent), and its Dockerfile passes that to
Lumis.Languages.cache/1 before mix release.
Renders untrusted markdown to HTML with raw HTML neutralized and unsafe link/image URLs removed. Returns a binary of HTML.
Renders trusted markdown (an authored manual, compiled from files in
the repository and reviewed in a PR) exactly like to_html/1, with one
addition: a <figure>/<svg> block is kept as real markup so hand-authored
diagrams render, after scrubbing the script-bearing subset (<script>,
<style>, <foreignObject>, on* handlers, and javascript:/data:/
vbscript: URLs). Everything else — every other raw-HTML block — is still
neutralized to text, and the untrusted to_html/1 path is untouched.
Functions
@spec languages() :: [String.t()]
The default list of languages whose parsers a host bakes into its image;
see @languages. A host's docs module returns its own list from
languages/0 (the languages: option of use Managoat.Docs, this list
when the option is absent), and its Dockerfile passes that to
Lumis.Languages.cache/1 before mix release.
Renders untrusted markdown to HTML with raw HTML neutralized and unsafe link/image URLs removed. Returns a binary of HTML.
Renders trusted markdown (an authored manual, compiled from files in
the repository and reviewed in a PR) exactly like to_html/1, with one
addition: a <figure>/<svg> block is kept as real markup so hand-authored
diagrams render, after scrubbing the script-bearing subset (<script>,
<style>, <foreignObject>, on* handlers, and javascript:/data:/
vbscript: URLs). Everything else — every other raw-HTML block — is still
neutralized to text, and the untrusted to_html/1 path is untouched.
Fenced code is syntax highlighted here too, for the same reason: the fences are authored, and a docs page whose whole job is showing code should show it highlighted.
This is only ever fed authored documentation. Never pass agent- or
user-supplied markdown here; use to_html/1 for that. Returns a binary
of HTML.