md
Render Markdown to HTML, turn HTML back into Markdown, and strip unsafe content from Markdown you did not write.
import "std:md"md converts between Markdown and HTML. Use it to publish posts and docs, to show user-written text on a web page, or to bring HTML from elsewhere into Markdown. It understands GitHub Flavored Markdown: tables, task lists, strikethrough and autolinks.
import "std:md"Markdown to HTML#
md.toHTML returns a string. Every heading gets an id, so you can link to it.
import "std:md"
string text = "# Hello there\n\nSome *emphasis*, **strong text** and `code`.\n\n- one\n- two\n"
log md.toHTML(text)Try it: add a ## Second heading and see its id.
GitHub extensions#
Tables, task lists and strikethrough work as they do on GitHub.
import "std:md"
string text = [
"| name | qty |",
"|------|-----|",
"| bolt | 12 |",
"",
"- [x] write",
"- [ ] test",
"",
"~~old~~ new"
].join("\n")
log md.toHTML(text)Untrusted input is made safe#
Raw HTML and javascript: links in the text are dropped, so you can render what visitors type without opening the door to script injection. The raw tags are replaced by comments.
import "std:md"
log md.toHTML("hi <script>steal()</script> [click](javascript:alert(1)) [ok](https://example.com)")Notice that the text between the tags stays as plain text. If you trust the source, such as your own documents, pass {unsafe: true} to keep raw HTML:
import "std:md"
log md.toHTML("A <kbd>Ctrl</kbd> key", {unsafe: true})HTML to Markdown#
md.fromHTML goes the other way. It returns a result: HTML it can't convert is a ParseError.
import "std:md"
string html = [
`<h1>Title</h1>`,
`<p>Hello <b>bold</b> and <a href="http://example.com">a link</a>.</p>`,
`<ul><li>one</li><li>two</li></ul>`
].join("")
log md.fromHTML(html).unwrap()This is useful for importing pages you scraped or for turning rich-text editor output into something you can store and diff.
Try it: add an <h2> and an <em> to the HTML.
Sanitising Markdown#
md.sanitize takes Markdown and returns Markdown with raw HTML tags and unsafe links removed. It does this by rendering to safe HTML and converting back, so the result is still Markdown you can store.
import "std:md"
string cleaned = md.sanitize(
"**bold** <script>x()</script> [bad](javascript:alert(1)) [good](https://example.com)"
).unwrap()
log cleanedTag text such as x() survives as plain text, and the unsafe link loses its address. Sanitise what you store, or render with toHTML, which applies the same rules.
A small page generator#
Put it together with fs to turn a Markdown file into a page:
import "std:md"
import "std:fs"
fs.writeFile("post.md", "# First post\n\nWritten in *Markdown*.\n").unwrap()
string body = md.toHTML(fs.readFile("post.md").unwrap())
string page = "<!doctype html>\n<title>Post</title>\n" ++ body
fs.writeFile("post.html", page).unwrap()
log fs.readFile("post.html").unwrap()A visitor posts <script>alert(1)</script> in a comment. What does md.toHTML(comment) do with it?
A heading helper
Write heading(text) that returns the HTML for a level-one heading with that text, and print it for Hello.
<h1 id="hello">Hello</h1>
API reference#
4 members, generated from the std:md source of OSL 9.3.0.
Functions
md.fromHTML(string html) result<string, error>fromHTML converts HTML to Markdown. Fails with ParseError when the HTML can't be converted.
md.sanitize(string text) result<string, error>sanitize returns Markdown text with raw HTML and unsafe links removed, by rendering it to safe HTML and converting that back to Markdown. Fails with ParseError when the rendered HTML can't be converted back.
md.toHTML(string text, object? options) stringtoHTML renders Markdown text as HTML, with GitHub Flavored Markdown (tables, task lists, strikethrough, autolinks) and an id on every heading. Raw HTML in the text and javascript: links are dropped unless the unsafe option is true; only set it for text you trust. Options: unsafe (boolean, default false).
md.toHTMLUnsafe(any text) stringDeprecated. Deprecated: use md.toHTML(text, {unsafe: true}) instead.
toHTMLUnsafe renders Markdown text as HTML and keeps any raw HTML in it.