# Markdown to HTML RETRO's source files generally use a subset of Markdown for formatting. This is a small tool to convert this into HTML. ## Features Recognizes: - lists - indented code blocks - paragraphs - headers - fenced code blocks - horizontal rules - *inline* _formatting_ elements ## Limitations This only supports a limited subset of full Markdown. I am not adding support for the various linking formats, ordered lists, underlined headers, doubled asterisk, doubled underscores, multiple line/paragraph list entries, or images. The CSS used is extracted from the end of this file. I only do a tiny bit of styling by default; just enough to ensure that code blocks are easily identified. ---- ## The Code Begin by locating and extracting the CSS. ~~~ ' s:put nl ~~~ The first couple of words are a variation of `s:put` that generates HTML codes for specific characters. This ensures that code output displays correctly. ~~~ :c:put $< [ '< s:put ] case $> [ '> s:put ] case $& [ '& s:put ] case ASCII:SPACE [ '  s:put ] case c:put ; :s:put [ c:put ] s:for-each ; ~~~ For regular text, there are a couple of inline formatting things to deal with. ~~~ 'Emphasis var 'Strong var 'Escape var 'Code var :format @Escape [ &Escape v:on ] if; $` [ @Escape [ &Escape v:off $* c:put ] if; @Code n:zero? [ ' &Code v:on ] [ ' &Code v:off ] choose s:put ] case $* [ @Escape @Code or [ &Escape v:off $* c:put ] if; @Strong n:zero? [ ' &Strong v:on ] [ ' &Strong v:off ] choose s:put ] case $_ [ @Escape @Code or [ &Escape v:off $_ c:put ] if; @Emphasis n:zero? [ ' &Emphasis v:on ] [ ' &Emphasis v:off ] choose s:put ] case c:put ; :s:put [ format ] s:for-each ; ~~~ Next, handling of code blocks. The fences need to start and end with `~~~` on a line by itself. (This will also handle test blocks using three bacticks as well) ~~~ 'Block var :in-block? @Block ; :block? dup [ '~~~ s:eq? ] [ '``` s:eq? ] bi or ; :toggle drop @Block n:zero? !Block ; :format:block ' s:put s:put ' s:put nl ; ~~~ After this, I define detection and formatting of headers. The headers should look like: # Level 1 ## Level 2 ### Level 3 ~~~ :header? dup [ '# s:begins-with? ] [ '## s:begins-with? ] [ '### s:begins-with? ] tri or or ; :format:head ASCII:SPACE s:split '# [ '

s:put n:inc s:put '

s:put nl ] s:case '## [ '

s:put n:inc s:put '

s:put nl ] s:case '### [ '

s:put n:inc s:put '

s:put nl ] s:case drop ; ~~~ Indented code blocks are lines indented by four spaces. ~~~ :code? dup '____ s:begins-with? ; :format:code ' s:put #4 + s:put ' s:put nl ; ~~~ Horizonal rules consist of four or more - characters on a line. E.g., ---- -------- ~~~ :rule? dup '---- s:begins-with? ; :format:rule drop '
s:put nl ; ~~~ Lists start with a `-` or `*`, followed by a space, then the item text. ~~~ :list? dup [ '-_ s:begins-with? ] [ '*_ s:begins-with? ] bi or ; :format:list '
  • s:put #2 + s:put '
  • s:put nl ; ~~~ Blank lines denote paragraph breaks. ~~~ :blank? dup s:length n:zero? ; ~~~ ~~~ :format block? [ toggle ] if; in-block? [ format:block ] if; blank? [ drop '

    s:put nl ] if; header? [ format:head ] if; code? [ format:code ] if; list? [ format:list ] if; rule? [ format:rule ] if; s:put nl ; #0 script:get-argument [ format ] file:for-each-line ~~~ This concludes the Markdown (subset) in RETRO utility. ## CSS tt, pre { background: #eee; color: #111; font-family: monospace; white-space: pre; display: block; width: 100%; }