Markdown & HTML
Turn Markdown into HTML and sanitize untrusted HTML.
On this page
valk.markdown turns Markdown into HTML, and valk.html escapes text and checks URLs for safe use in a page.
Markdown to HTML#
use valk.markdown
fn main() {
let html = markdown.to_html("# Notes\n\nSome **bold** and `code`.\n\n- one\n- two")
println(html)
}
Supported: # and underlined headings, paragraphs, > quotes, -, +, * and 1. lists, fenced code blocks, --- rules, inline code, *emphasis*, **bold**, ~~strikethrough~~, links and images with an optional "title", and backslash escapes.
Raw HTML in the input is not supported: every <, >, ", ' and & is escaped. The output is therefore safe to put in a page, also for Markdown from users.
Options#
use valk.markdown
fn main() {
let options = markdown.ToHtmlOptions {
paragraph_class: "text"
code_class: "code-block"
allowed_schemes: .{ "https" }
}
println(markdown.to_html("[ok](https://valk-lang.dev) [bad](javascript:alert(1))", options))
// <p class="text"><a href="https://valk-lang.dev">ok</a> bad</p>
}
| Option | Meaning |
|---|---|
paragraph_class |
class of every <p> |
code_class |
class of the <code> in fenced code blocks |
allowed_schemes |
Link and image schemes allowed; default http, https, mailto |
A link with another scheme (javascript:, data:, ...) keeps its text but loses the link, and such an image is dropped. Relative URLs are always allowed. markdown.to_html_into(md, writer) writes to a writer.
Escape text for HTML#
use valk.html
fn main() {
let comment = "<script>alert('hi')</script> & more"
println(html.escape(comment)) // <script>alert('hi')</script> & more
}
The result is safe as element text and inside a quoted attribute. html.EscapeOptions leaves chosen characters alone, and html.escape_into(text, writer) writes to a writer. Templates escape {{ }} output this way by default.
Check URLs in HTML#
For HTML you did not write, html.sanitize_url_attributes empties every URL attribute (href, src, ...) whose scheme is not allowed, and html.url_is_allowed checks one URL:
use valk.html
fn main() {
println(html.url_is_allowed("https://example.com")) // true
println(html.url_is_allowed("javascript:alert(1)")) // false
println(html.sanitize_url_attributes("<a href=\"javascript:alert(1)\">x</a>")) // <a href="">x</a>
}
Both take the allowed schemes as their last argument (default http, https, mailto). They only handle URLs: they do not remove tags, scripts or event attributes. To show untrusted text, escape it; to let users format text, have them write Markdown.
