On this page:
HTML5 Printer
xexpr->html5
9.3

HTML5 Printer🔗

Joel Dueck

 (require html-printer) package: html-printer-lib

If you use Racket to generate web pages, you should use this package to make your HTML both readable and correct. Why go to the trouble of designing clean, semantic markup if you’re just going to slap it all on one line that scrolls horizontally forever?

This package provides a single function — xexpr->html5 — for converting X-expressions to strings of HTML. Unlike other functions which can be used for this purpose, this one is focused on a tidy presentation of HTML5 content specifically. It indents and wraps lines, allowing you to set the width of the output. Line breaks are only ever placed where the input already contains whitespace, or where added whitespace has no effect (such as directly after a block-level opening tag), so the wrapped output renders exactly like the unwrapped input. It favors HTML5 syntax over XML syntax in some cases.

This package is also Unicode-aware, measuring line length in graphemes rather than characters. So, for example the emoji 🧝‍♂️ — which actually consists of four Unicode “characters” — is counted as having length 1 rather than 4.

If you encounter a bug, please open an issue on the GitHub repo.

Requires Racket 8.13 or later.

procedure

(xexpr->html5 xpr    
  [#:wrap wrap-col    
  #:add-breaks? add-breaks?])  string?
  xpr : xexpr?
  wrap-col : exact-positive-integer? = 100
  add-breaks? : any/c = #f
Converts xpr to a string of HTML, nicely wrapped and indented, ready for consumption. Leave wrap-col at its default of 100 columns, or shrink it down hard to test the line-wrapping algorithm. No line will be longer than wrap-col columns unless it consists of a single run that cannot be broken, such as a long word or an attribute value, and no line ends in whitespace.

Example:
> (display
   (xexpr->html5 #:wrap 25
                 '(body
                   (article
                    (h1 "My Title")
                    (p "Welcome to the blog!"))
                   (footer
                    (div (p "Right here in River City"))))))

<body>

  <article>

    <h1>My Title</h1>

    <p>Welcome to the

    blog!</p>

  </article>

  <footer>

    <div>

      <p>Right here in

      River City</p>

    </div>

  </footer>

</body>

If xpr begins with 'html, then the HTML5 doctype is prepended to the document:

Example:
> (display
   (xexpr->html5 '(html (head (meta [[charset "UTF-8"]])))))

<!DOCTYPE html>

<html>

  <head>

    <meta charset="UTF-8">

  </head>

</html>

If add-breaks? is not #f, additional line breaks will be added between closing block/flow tags (except for <meta>, <link> and <title>) and any opening tags:

> (display (xexpr->html5
            #:add-breaks? #t
            '(body
              (article
               (h1 "My Title")
               (p "Welcome to the blog!"))
              (footer
               (div (p "Right here in River City"))))))

<body>

  <article>

    <h1>My Title</h1>

 

    <p>Welcome to the blog!</p>

  </article>

 

  <footer>

    <div>

      <p>Right here in River City</p>

    </div>

  </footer>

</body>

That’s all there is to it, really. But if you want more info, check out the Crunchy details.

Changed in version 1.1 of package html-printer-lib: Added ability to recognize custom elements.