As a pair, {markdown} renders its content first - its fields and tags resolve like anywhere else - and then reads the result as Markdown and writes the HTML. The text is dedented first, so a block indented along with the template does not turn into a code block. With a parameter instead, {markdown $post.body} writes the value of the parameter, the way the markdown pipe does.

The converter is built in (lib/markdown.php), a CommonMark subset: ATX and setext headings, paragraphs, emphasis and strong emphasis, code spans, fenced code blocks (with a language- class) and indented ones, bullet and ordered lists (nested, tight or loose, with a start number), links, images, autolinks, block quotes, thematic breaks, hard line breaks and backslash escapes. Reference-style links, tables and footnotes are not supported.

Safety

Raw HTML in the text is escaped, and a link or image whose address names a scheme other than http, https, mailto, ftp or tel - javascript:, data: - keeps only its text. The bare html option lets the author's own markup through; use it only for text the application wrote. The HTML made from a value stays a value: a {php:getcwd} in a post is shown, not run.

Braces

Because the content is rendered before it is read as Markdown, a { in it starts a tag. A code sample with braces needs the ignore option, which keeps the whole content as text - fields included. A pair that is never closed, and the single form without a value, are strict errors.