John Gruber’s original spec.
Fenced code blocks as on GitHub. The optional language is returned as (pre ([class "brush: lang"]) ....). You can extract to use with a highlighter such as Pygments.
Smart punctuation (quotes, dashes, ellipses).
You can run this at the command-line: Pipe in markdown and it pipes out HTML.
$ raco markdown I am _emph_ and I am **strong**. ^D <!DOCTYPE html> <html> <head> <meta charset="utf-8" /></head> <body> <p>I am <em>emph</em> and I am <strong>strong</strong>.</p></body></html>
; 1. Parse string to a list of xexprs
(define xs (parse-markdown "I am _emph_ and I am **strong**."))
'((p () "I am " (em () "emph") " and I am " (strong () "strong") "."))
; 2. Optionally, process the xexprs somehow: ; ... nom nom nom ... ; 3. Splice them into an HTML `xexpr` and... ; 4. Convert to HTML text:
(display-xexpr `(html () (head ()) (body () ,@xs)))
<p>I am <em>emph</em> and I am <strong>strong</strong>.</p></body></html>
display-xexpr is provided as a "warm bowl of porridge" —
The xexprs returned by read-markdown can also be fed to the
function xexprs->scribble-pres, which returns a Scribble
#lang racket/base (require markdown markdown/scrib net/sendurl racket/class racket/format racket/runtime-path scribble/base-render scribble/decode scribble/html-render) (define work-dir (find-system-path 'temp-dir)) (define (build-html-doc docs dest-file) (let* ([renderer (new (render-mixin render%) [dest-dir work-dir])] [fns (list (build-path work-dir dest-file))] [fp (send renderer traverse docs fns)] [info (send renderer collect docs fns fp)] [r-info (send renderer resolve docs fns info)]) (send renderer render docs fns r-info) (send renderer get-undefined r-info))) (define-runtime-path test.md "test/test.md") (define part (decode (xexprs->scribble-pres (with-input-from-file test.md read-markdown)))) (build-html-doc (list part) "test.html") (send-url (~a "file://" work-dir "test.html"))
Originally this was implemented using a pile of regular expressions,
somewhat like how Markdown.pl works —
In October 2013 I redesigned it to be a "real" parser with a grammar, using Stephen Chang’s parsack, a monadic parser combinator library. The grammar was developed by looking first at peg-markdown and later at pandoc. For a few edge cases I found Babelmark and Babelmark2 helpful to compare result with many other implementations. The many unit tests from the old version also helped.
|(require markdown)||package: markdown|
|(require markdown/parse)||package: markdown|
Deletes all \r (including but not limited to \r\n).
Appends a \r\n to simplify whole-document processing.
(current-strict-markdown? strict?) → void? strict? : boolean?
NOTE: This function is deprecated; use parse-markdown, instead.
|(require markdown/toc)||package: markdown|
> (toc (parse-markdown (string-join '("# 1" "## 1.1" "# 2" "## 2.1") "\n\n")))
(li (a ((href "#1")) "1") (ul (li (a ((href "#11")) "1.1"))))
(li (a ((href "#2")) "2") (ul (li (a ((href "#21")) "2.1"))))))
|(require markdown/display-xexpr)||package: markdown|
|(require markdown/scrib)||package: markdown|
The bindings documented in this section are not provided by the markdown module.
→ (listof (or/c pre-part? pre-flow? pre-content?)) xexprs : (listof xexpr?)
Although this could be generalized, currently it’s only intended to handle the subset of HTML that read-markdown returns.