post HTML rendering filters for org-export
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


posthtml provides a fluent interface to decorating a string of HTML like "<ul><li/><li/></ul>" - to add attributes such as class or id to elements, or to do custom processing.

(posthtml-decorate "<ul><li/><li/></ul>"
                   '($ [ul] :attr :id 'CONTAINER)
                   '($each [ul li] :attr :class 'ELEMENT))

The string is parsed into an esxml representation of the DOM tree by libxml-parse-html-region - the defined decorators are applied, and a string rendered via esxml-to-xml is returned. Querying is done with enlive.

As a typical use case scenario, org-export-filter-final-output-functions provide access to the final output of any org-export, or org-publishing sequence; this list consists of the last functions called with the rendered output, their output being what's written to disk.

(add-to-list 'org-export-filter-final-output-functions
             (lambda (contents backend info)
               (posthtml-decorate contents
                                  '($ [body] :attr :style "background-color: black;"))))

posthtml-decorate string &rest decorators

'($ [h1] :append " APPEND")             ; append to contents of h1 element
'($ [ul] :attr :class 'COLUMNS)         ; add COLUMNS class to ul element
'($ [h1] :attrs-set :id 'TWO :class "") ; set h1's id to TWO, remove all classes
'($ [ul] :attr-set :id "")              ; remove ul's id attribute

posthtml-decorate translates the syntax decorators into a call to posthtml-apply or posthtml-apply-each, respectively. They are responsible for querying CONTAINER for SELECTOR, and applying (each) found element - as an esxml parse-tree - and ARGS to FN.

'($each [ul li]
        (lambda (list-element current-uri)
          (let ((link-uri (posthtml-attribute (posthtml-find list-element [a]) 'href)))
            (when (string= link-uri current-uri)
              (posthtml-attribute list-element :class 'CURRENT))))

As the element provided to each function is an esxml parse-tree, it is available for further querying and processing. In the following, the ul is updated with a dynamically created CSS class name, to reflect how many elements it contains.

'($ [ul]
    (lambda (ul)
      (posthtml-attribute ul :class
                          (format "COLUMNSWIDTH%s"
                                   (posthtml-find-all ul [li]))))))))

Here is the result of running this contrived test case, with input on the left.

<html><body>                                | <html><body>
    <h1 class=\"ONE\">headline</h1>         |     <h1 id=\"TWO\">headline APPEND</h1>
    <ul id=\"ONE\">                         |     <ul class=\"COLUMNS COLUMNSWIDTH3\">
      <li><a href="/uri-one">uri</a></li>   |       <li><a href="/uri-one">uri</a></li>
      <li><a href="/uri-two">uri</a></li>   |       <li class="CURRENT"><a href="/uri-two">uri</a></li>
      <li><a href="/uri-three">uri</a></li> |       <li><a href="/uri-three">uri</a></li>
    </ul>                                   |     </ul>
</body></html>                              | </body></html>

syntax decorators

  • $: posthtml-apply
  • $each: posthtml-apply-each
  • lambda: called with esxml parse-tree, and optional args
  • fn: called with esxml parse-tree, and optional args


  • :append: posthtml-append
  • :prepend: posthtml-prepend
  • :attr: posthtml-attribute
  • :attr-set: posthtml-attributes-set
  • :attrs: posthtml-attributes
  • :attrs-set: posthtml-attributes-set

posthtml-find esxml selector

Wrapper function to enlive-query - please see source for full list of selector examples.

posthtml-findall esxml selector

Selectors are vector objects, resembling CSS selectors which can have id-s, classes, attributes - as per enlive.

posthtml-append esxml element

Element can be a string or an esxml element.

posthtml-prepend esxml element

Element can be a string or an esxml element.

posthtml-attribute esxml attribute &optional value force

Returns the value of an esxml element's attribute. Optionally, when provided with a value, set or add attribute to element - set as only property with force.

  • attributes can start with or without an initial :

posthtml-attributes esxml &rest attributes

posthtml-attributes-set esxml &rest attributes


emacs -batch \
      -l ert \
      -l posthtml-tests.el \
      -f ert-run-tests-batch-and-exit