diff --git a/AUTHORS.md b/AUTHORS.md
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -63,6 +63,7 @@
 - Greg Rundlett
 - Grégory Bataille
 - Gwern Branwen
+- Hamish Mackenzie
 - Hans-Peter Deifel
 - Henrik Tramberend
 - Henry de Valence
diff --git a/MANUAL.txt b/MANUAL.txt
--- a/MANUAL.txt
+++ b/MANUAL.txt
@@ -1,6 +1,6 @@
 % Pandoc User's Guide
 % John MacFarlane
-% December 8, 2017
+% December 27, 2017
 
 Synopsis
 ========
@@ -16,12 +16,12 @@
 Markdown], [MultiMarkdown], and (subsets of) [Textile],
 [reStructuredText], [HTML], [LaTeX], [MediaWiki markup], [TWiki
 markup], [TikiWiki markup], [Creole 1.0], [Haddock markup], [OPML],
-[Emacs Org mode], [DocBook], [Muse], [txt2tags], [Vimwiki], [EPUB],
-[ODT], and [Word docx]; and it can write plain text, [Markdown],
+[Emacs Org mode], [DocBook], [JATS], [Muse], [txt2tags], [Vimwiki],
+[EPUB], [ODT], and [Word docx]; and it can write plain text, [Markdown],
 [CommonMark], [PHP Markdown Extra], [GitHub-Flavored Markdown],
 [MultiMarkdown], [reStructuredText], [XHTML], [HTML5], [LaTeX]
 \(including [`beamer`] slide shows\), [ConTeXt], [RTF], [OPML],
-[DocBook], [OpenDocument], [ODT], [Word docx], [GNU Texinfo],
+[DocBook], [JATS], [OpenDocument], [ODT], [Word docx], [GNU Texinfo],
 [MediaWiki markup], [DokuWiki markup], [ZimWiki markup], [Haddock
 markup], [EPUB] \(v2 or v3\), [FictionBook2], [Textile], [groff man],
 [groff ms], [Emacs Org mode], [AsciiDoc], [InDesign ICML], [TEI
@@ -75,6 +75,7 @@
 [ConTeXt]: http://www.contextgarden.net/
 [RTF]: http://en.wikipedia.org/wiki/Rich_Text_Format
 [DocBook]: http://docbook.org
+[JATS]: https://jats.nlm.nih.gov
 [txt2tags]: http://txt2tags.org
 [EPUB]: http://idpf.org/epub
 [OPML]: http://dev.opml.org/spec2.html
@@ -283,16 +284,9 @@
     (`markdown_github` provides deprecated and less accurate support
     for Github-Flavored Markdown; please use `gfm` instead, unless you
     need to use extensions other than `smart`.)
-    If `+lhs` is appended to `markdown`, `rst`, `latex`, or
-    `html`, the input will be treated as literate Haskell source: see
-    [Literate Haskell support], below. Markdown
-    syntax extensions can be individually enabled or disabled by
-    appending `+EXTENSION` or `-EXTENSION` to the format name. So, for
-    example, `markdown_strict+footnotes+definition_lists` is strict
-    Markdown with footnotes and definition lists enabled, and
-    `markdown-pipe_tables+hard_line_breaks` is pandoc's Markdown
-    without pipe tables and with hard line breaks. See [Pandoc's
-    Markdown], below, for a list of extensions and
+    Extensions can be individually enabled or disabled by
+    appending `+EXTENSION` or `-EXTENSION` to the format name.
+    See [Extensions] below, for a list of extensions and
     their names.  See `--list-input-formats` and `--list-extensions`,
     below.
 
@@ -326,13 +320,10 @@
     unless you use extensions that do not work with `gfm`.) Note that
     `odt`, `epub`, and `epub3` output will not be directed to
     *stdout*; an output filename must be specified using the
-    `-o/--output` option. If `+lhs` is appended to `markdown`, `rst`,
-    `latex`, `beamer`, `html4`, or `html5`, the output will be
-    rendered as literate Haskell source: see [Literate Haskell
-    support], below.  Markdown syntax extensions can be individually
-    enabled or disabled by appending `+EXTENSION` or `-EXTENSION` to
-    the format name, as described above under `-f`.  See
-    `--list-output-formats` and `--list-extensions`, below.
+    `-o/--output` option.  Extensions can be individually enabled or
+    disabled by appending `+EXTENSION` or `-EXTENSION` to the format
+    name.  See [Extensions] below, for a list of extensions and their
+    names.  See `--list-output-formats` and `--list-extensions`, below.
 
 `-o` *FILE*, `--output=`*FILE*
 
@@ -396,11 +387,12 @@
 
 :   List supported output formats, one per line.
 
-`--list-extensions`
+`--list-extensions`[`=`*FORMAT*]
 
-:   List supported Markdown extensions, one per line, followed
+:   List supported Markdown extensions, one per line, preceded
     by a `+` or `-` indicating whether it is enabled by default
-    in pandoc's Markdown.
+    in *FORMAT*. If *FORMAT* is not specified, defaults for
+    pandoc's Markdown are given.
 
 `--list-highlight-languages`
 
@@ -863,8 +855,8 @@
 
 `--section-divs`
 
-:   Wrap sections in `<div>` tags (or `<section>` tags in HTML5),
-    and attach identifiers to the enclosing `<div>` (or `<section>`)
+:   Wrap sections in `<section>` tags (or `<div>` tags for `html4`),
+    and attach identifiers to the enclosing `<section>` (or `<div>`)
     rather than the header itself. See
     [Header identifiers], below.
 
@@ -1105,7 +1097,7 @@
     The *URL* should point to the `MathJax.js` load script.
     If a *URL* is not provided, a link to the Cloudflare CDN will
     be inserted.
- 
+
 `--mathml`
 
 :   Convert TeX math to [MathML] (in `epub3`, `docbook4`, `docbook5`, `jats`,
@@ -1697,6 +1689,269 @@
 
 [pandoc-templates]: https://github.com/jgm/pandoc-templates
 
+Extensions
+==========
+
+The behavior of some of the readers and writers can be adjusted by
+enabling or disabling various extensions.
+
+An extension can be enabled by adding `+EXTENSION`
+to the format name and disabled by adding `-EXTENSION`. For example,
+`--from markdown_strict+footnotes` is strict Markdown with footnotes
+enabled, while `--from markdown-footnotes-pipe_tables` is pandoc's
+Markdown without footnotes or pipe tables.
+
+The markdown reader and writer make by far the most use of extensions.
+Extensions only used by them are therefore covered in the
+section [Pandoc's Markdown] below (See [Markdown variants] for
+`commonmark` and `gfm`.) In the following, extensions that also work
+for other formats are covered.
+
+Typography
+----------
+
+#### Extension: `smart` ####
+
+Interpret straight quotes as curly quotes, `---` as em-dashes,
+`--` as en-dashes, and `...` as ellipses. Nonbreaking spaces are
+inserted after certain abbreviations, such as "Mr." 
+
+This extension can be enabled/disabled for the following formats:
+
+input formats
+:  `markdown`, `commonmark`, `latex`, `mediawiki`, `org`, `rst`, `twiki`
+
+output formats
+:  `markdown`, `latex`, `context`, `rst`
+
+enabled by default in
+:  `markdown`, `latex`, `context` (both input and output)
+
+Note: If you are *writing* Markdown, then the `smart` extension
+has the reverse effect: what would have been curly quotes comes
+out straight.
+
+In LaTeX, `smart` means to use the standard TeX ligatures
+for quotation marks (` `` ` and ` '' ` for double quotes,
+`` ` `` and `` ' `` for single quotes) and dashes (`--` for
+en-dash and `---` for em-dash).  If `smart` is disabled,
+then in reading LaTeX pandoc will parse these characters
+literally.  In writing LaTeX, enabling `smart` tells pandoc
+to use the ligatures when possible; if `smart` is disabled
+pandoc will use unicode quotation mark and dash characters.
+
+Headers and sections
+--------------------
+
+#### Extension: `auto_identifiers` ####
+
+A header without an explicitly specified identifier will be
+automatically assigned a unique identifier based on the header text.
+
+This extension can be enabled/disabled for the following formats:
+
+input formats
+:  `markdown`, `latex`, `rst`, `mediawiki`, `textile`
+
+output formats
+:  `markdown`, `muse`
+
+enabled by default in
+:  `markdown`, `muse`
+
+The algorithm used to derive the identifier from the header text is:
+
+  - Remove all formatting, links, etc.
+  - Remove all footnotes.
+  - Remove all punctuation, except underscores, hyphens, and periods.
+  - Replace all spaces and newlines with hyphens.
+  - Convert all alphabetic characters to lowercase.
+  - Remove everything up to the first letter (identifiers may
+    not begin with a number or punctuation mark).
+  - If nothing is left after this, use the identifier `section`.
+
+Thus, for example,
+
+  Header                            Identifier
+  -------------------------------   ----------------------------
+  `Header identifiers in HTML`      `header-identifiers-in-html`
+  `*Dogs*?--in *my* house?`         `dogs--in-my-house`
+  `[HTML], [S5], or [RTF]?`         `html-s5-or-rtf`
+  `3. Applications`                 `applications`
+  `33`                              `section`
+
+These rules should, in most cases, allow one to determine the identifier
+from the header text. The exception is when several headers have the
+same text; in this case, the first will get an identifier as described
+above; the second will get the same identifier with `-1` appended; the
+third with `-2`; and so on.
+
+These identifiers are used to provide link targets in the table of
+contents generated by the `--toc|--table-of-contents` option. They
+also make it easy to provide links from one section of a document to
+another. A link to this section, for example, might look like this:
+
+    See the section on
+    [header identifiers](#header-identifiers-in-html-latex-and-context).
+
+Note, however, that this method of providing links to sections works
+only in HTML, LaTeX, and ConTeXt formats.
+
+If the `--section-divs` option is specified, then each section will
+be wrapped in a `section` (or a `div`, if `html4` was specified),
+and the identifier will be attached to the enclosing `<section>`
+(or `<div>`) tag rather than the header itself. This allows entire
+sections to be manipulated using JavaScript or treated differently in
+CSS.
+
+#### Extension: `ascii_identifiers` ####
+
+Causes the identifiers produced by `auto_identifiers` to be pure ASCII.
+Accents are stripped off of accented Latin letters, and non-Latin
+letters are omitted.
+
+Math Input
+----------
+
+The extensions [`tex_math_dollars`](#extension-tex_math_dollars),
+[`tex_math_single_backslash`](#extension-tex_math_single_backslash), and
+[`tex_math_double_backslash`](#extension-tex_math_double_backslash)
+are described in the section about Pandoc's Markdown.
+
+However, they can also be used with HTML input. This is handy for
+reading web pages formatted using MathJax, for example.
+
+Raw HTML/TeX
+------------
+
+The following extensions (especially how they affect Markdown
+input/output) are also described in more detail in their respective
+sections of [Pandoc's Markdown].
+
+#### [Extension: `raw_html`] {#raw_html}
+
+When converting from HTML, parse elements to raw HTML which are not
+representable in pandoc's AST.
+By default, this is disabled for HTML input.
+
+#### [Extension: `raw_tex`] {#raw_tex}
+
+Allows raw LaTeX, TeX, and ConTeXt to be included in a document.
+
+This extension can be enabled/disabled for the following formats
+(in addition to `markdown`):
+
+input formats
+:  `latex`, `org`, `textile`
+
+output formats
+:  `textile`
+
+#### [Extension: `native_divs`] {#native_divs}
+
+This extension is enabled by default for HTML input. This means that
+`div`s are parsed to pandoc native elements. (Alternatively, you
+can parse them to raw HTML using `-f html-native_divs+raw_html`.)
+
+When converting HTML to Markdown, for example, you may want to drop all
+`div`s and `span`s:
+
+    pandoc -f html-native_divs-native_spans -t markdown
+
+#### [Extension: `native_spans`] {#native_spans}
+
+Analogous to `native_divs` above.
+
+
+Literate Haskell support
+------------------------
+
+#### Extension: `literate_haskell` ####
+
+Treat the document as literate Haskell source.
+
+This extension can be enabled/disabled for the following formats:
+
+input formats
+:  `markdown`, `rst`, `latex`
+
+output formats
+:  `markdown`, `rst`, `latex`, `html`
+
+If you append `+lhs` (or `+literate_haskell`) to one of the formats
+above, pandoc will treat the document as literate Haskell source.
+This means that
+
+  - In Markdown input, "bird track" sections will be parsed as Haskell
+    code rather than block quotations.  Text between `\begin{code}`
+    and `\end{code}` will also be treated as Haskell code.  For
+    ATX-style headers the character '=' will be used instead of '#'.
+
+  - In Markdown output, code blocks with classes `haskell` and `literate`
+    will be rendered using bird tracks, and block quotations will be
+    indented one space, so they will not be treated as Haskell code.
+    In addition, headers will be rendered setext-style (with underlines)
+    rather than ATX-style (with '#' characters). (This is because ghc
+    treats '#' characters in column 1 as introducing line numbers.)
+
+  - In restructured text input, "bird track" sections will be parsed
+    as Haskell code.
+
+  - In restructured text output, code blocks with class `haskell` will
+    be rendered using bird tracks.
+
+  - In LaTeX input, text in `code` environments will be parsed as
+    Haskell code.
+
+  - In LaTeX output, code blocks with class `haskell` will be rendered
+    inside `code` environments.
+
+  - In HTML output, code blocks with class `haskell` will be rendered
+    with class `literatehaskell` and bird tracks.
+
+Examples:
+
+    pandoc -f markdown+lhs -t html
+
+reads literate Haskell source formatted with Markdown conventions and writes
+ordinary HTML (without bird tracks).
+
+    pandoc -f markdown+lhs -t html+lhs
+
+writes HTML with the Haskell code in bird tracks, so it can be copied
+and pasted as literate Haskell source.
+
+Note that GHC expects the bird tracks in the first column, so indentend literate
+code blocks (e.g. inside an itemized environment) will not be picked up by the
+Haskell compiler.
+
+Other extensions
+----------------
+
+#### Extension: `empty_paragraphs` ####
+
+Allows empty paragraphs.  By default empty paragraphs are
+omitted.
+
+This extension can be enabled/disabled for the following formats:
+
+input formats
+:  `docx`, `html`
+
+output formats
+:  `markdown`, `docx`, `odt`, `opendocument`, `html`
+
+#### Extension: `amuse` ####
+
+In the `muse` input format, this enables Text::Amuse
+extensions to Emacs Muse markup.
+
+#### Extension: `citations` {#org-citations}
+
+Some aspects of [Pandoc's Markdown citation syntax](#citations) are also accepted
+in `org` input.
+
+
 Pandoc's Markdown
 =================
 
@@ -1704,11 +1959,9 @@
 John Gruber's [Markdown] syntax.  This document explains the syntax,
 noting differences from standard Markdown. Except where noted, these
 differences can be suppressed by using the `markdown_strict` format instead
-of `markdown`.  An extensions can be enabled by adding `+EXTENSION`
-to the format name and disabled by adding `-EXTENSION`. For example,
-`markdown_strict+footnotes` is strict Markdown with footnotes
-enabled, while `markdown-footnotes-pipe_tables` is pandoc's
-Markdown without footnotes or pipe tables.
+of `markdown`. Extensions can be enabled or disabled to specify the
+behavior more granularly. They are described in the following. See also
+[Extensions] above, for extensions that work also on other formats.
 
 Philosophy
 ----------
@@ -1800,6 +2053,8 @@
 
 ### Header identifiers ###
 
+See also the [`auto_identifiers` extension](#extension-auto_identifiers) above.
+
 #### Extension: `header_attributes` ####
 
 Headers can be assigned attributes using this syntax at the end
@@ -1836,55 +2091,6 @@
 
     # My header {.unnumbered}
 
-#### Extension: `auto_identifiers` ####
-
-A header without an explicitly specified identifier will be
-automatically assigned a unique identifier based on the header text.
-To derive the identifier from the header text,
-
-  - Remove all formatting, links, etc.
-  - Remove all footnotes.
-  - Remove all punctuation, except underscores, hyphens, and periods.
-  - Replace all spaces and newlines with hyphens.
-  - Convert all alphabetic characters to lowercase.
-  - Remove everything up to the first letter (identifiers may
-    not begin with a number or punctuation mark).
-  - If nothing is left after this, use the identifier `section`.
-
-Thus, for example,
-
-  Header                            Identifier
-  -------------------------------   ----------------------------
-  `Header identifiers in HTML`      `header-identifiers-in-html`
-  `*Dogs*?--in *my* house?`         `dogs--in-my-house`
-  `[HTML], [S5], or [RTF]?`         `html-s5-or-rtf`
-  `3. Applications`                 `applications`
-  `33`                              `section`
-
-These rules should, in most cases, allow one to determine the identifier
-from the header text. The exception is when several headers have the
-same text; in this case, the first will get an identifier as described
-above; the second will get the same identifier with `-1` appended; the
-third with `-2`; and so on.
-
-These identifiers are used to provide link targets in the table of
-contents generated by the `--toc|--table-of-contents` option. They
-also make it easy to provide links from one section of a document to
-another. A link to this section, for example, might look like this:
-
-    See the section on
-    [header identifiers](#header-identifiers-in-html-latex-and-context).
-
-Note, however, that this method of providing links to sections works
-only in HTML, LaTeX, and ConTeXt formats.
-
-If the `--section-divs` option is specified, then each section will
-be wrapped in a `div` (or a `section`, if `html5` was specified),
-and the identifier will be attached to the enclosing `<div>`
-(or `<section>`) tag rather than the header itself. This allows entire
-sections to be manipulated using JavaScript or treated differently in
-CSS.
-
 #### Extension: `implicit_header_references` ####
 
 Pandoc behaves as if reference links have been defined for each header.
@@ -2369,6 +2575,12 @@
 The label can be any string of alphanumeric characters, underscores,
 or hyphens.
 
+Note:  continuation paragraphs in example lists must always
+be indented four spaces, regardless of the length of the
+list marker.  That is, example lists always behave as if the
+`four_space_rule` extension is set.  This is because example
+labels tend to be long, and indenting content to the
+first non-space character after the label would be awkward.
 
 ### Compact and loose lists ###
 
@@ -3021,8 +3233,6 @@
     command-line options selected. Therefore see [Math rendering in HTML]
     above.
 
-This extension can be used with both `markdown` and `html` input.
-
 [interpreted text role `:math:`]: http://docutils.sourceforge.net/docs/ref/rst/roles.html#math
 
 Raw HTML
@@ -3188,18 +3398,22 @@
 
 #### Extension: `latex_macros` ####
 
-For output formats other than LaTeX, pandoc will parse LaTeX `\newcommand` and
-`\renewcommand` definitions and apply the resulting macros to all LaTeX
-math.  So, for example, the following will work in all output formats,
-not just LaTeX:
+For output formats other than LaTeX, pandoc will parse LaTeX
+macro definitions and apply the resulting macros to all LaTeX
+math and raw LaTeX.  So, for example, the following will work in
+all output formats, not just LaTeX:
 
     \newcommand{\tuple}[1]{\langle #1 \rangle}
 
     $\tuple{a, b, c}$
 
-In LaTeX output, the `\newcommand` definition will simply be passed
-unchanged to the output.
+In LaTeX output, the macro definitions will not be passed
+through as raw LaTeX.
 
+When `latex_macros` is disabled, the macro definitions will
+be passed through as raw LaTeX, and the raw LaTeX and math will
+not have macros applied. This is usually a better approach when
+you are targeting LaTeX or PDF.
 
 Links
 -----
@@ -3446,31 +3660,6 @@
 
 Inline and regular footnotes may be mixed freely.
 
-Typography
-----------
-
-#### Extension: `smart` ####
-
-Interpret straight quotes as curly quotes, `---` as em-dashes,
-`--` as en-dashes, and `...` as ellipses. Nonbreaking spaces are
-inserted after certain abbreviations, such as "Mr."  This
-option currently affects the input formats `markdown`,
-`commonmark`, `latex`, `mediawiki`, `org`, `rst`, and `twiki`,
-and the output formats `markdown`, `latex`, and `context`.
-
-Note: If you are *writing* Markdown, then the `smart` extension
-has the reverse effect: what would have been curly quotes comes
-out straight.
-
-In LaTeX, `smart` means to use the standard TeX ligatures
-for quotation marks (` `` ` and ` '' ` for double quotes,
-`` ` `` and `` ' `` for single quotes) and dashes (`--` for
-en-dash and `---` for em-dash).  If `smart` is disabled,
-then in reading LaTeX pandoc will parse these characters
-literally.  In writing LaTeX, enabling `smart` tells pandoc
-to use the ligatures when possible; if `smart` is disabled
-pandoc will use unicode quotation mark and dash characters.
-
 Citations
 ---------
 
@@ -3733,8 +3922,6 @@
 as display TeX math.  Note: a drawback of this extension is that
 it precludes escaping `(` and `[`.
 
-This extension can be used with both `markdown` and `html` input.
-
 #### Extension: `tex_math_double_backslash` ####
 
 Causes anything between `\\(` and `\\)` to be interpreted as inline
@@ -3777,12 +3964,6 @@
 Makes all absolute URIs into links, even when not surrounded by
 pointy braces `<...>`.
 
-#### Extension: `ascii_identifiers` ####
-
-Causes the identifiers produced by `auto_identifiers` to be pure ASCII.
-Accents are stripped off of accented Latin letters, and non-Latin
-letters are omitted.
-
 #### Extension: `mmd_link_attributes` ####
 
 Parses multimarkdown style key-value attributes on link
@@ -3826,12 +4007,6 @@
     we must either disallow lazy wrapping or require a blank line between
     list items.
 
-#### Extension: `empty_paragraphs` ####
-
-Allows empty paragraphs.  By default empty paragraphs are
-omitted.  This affects the `docx` reader and writer, the
-`opendocument` and `odt` writer, and all HTML-based readers and writers.
-
 Markdown variants
 -----------------
 
@@ -3865,34 +4040,21 @@
 :   `raw_html`, `shortcut_reference_links`,
     `spaced_reference_links`.
 
-We also support `gfm` (GitHub-Flavored Markdown) as a set of
-extensions on `commonmark`:
+We also support `commonmark` and `gfm` (GitHub-Flavored Markdown,
+which is implemented as a set of extensions on `commonmark`).
 
+Note, however, that `commonmark` and `gfm` have limited support
+for extensions. Only those  listed below (and `smart` and
+`raw_tex`) will work. The extensions can, however, all be
+individually disabled.
+Also, `raw_tex` only affects `gfm` output, not input.
+
+`gfm` (GitHub-Flavored Markdown)
 :   `pipe_tables`, `raw_html`, `fenced_code_blocks`, `auto_identifiers`,
     `ascii_identifiers`, `backtick_code_blocks`, `autolink_bare_uris`,
     `intraword_underscores`, `strikeout`, `hard_line_breaks`, `emoji`,
     `shortcut_reference_links`, `angle_brackets_escapable`.
 
-    These can all be individually disabled. Note, however, that
-    `commonmark` and `gfm` have limited support for extensions:
-    extensions other than those listed above (and `smart` and
-    `raw_tex`) will have no effect on `commonmark` or `gfm`.
-    And `raw_tex` only affects `gfm` output, not input.
-
-Extensions with formats other than Markdown
--------------------------------------------
-
-Some of the extensions discussed above can be used with formats
-other than Markdown:
-
-* `auto_identifiers` can be used with `latex`, `rst`, `mediawiki`,
-  and `textile` input (and is used by default).
-
-* `tex_math_dollars`, `tex_math_single_backslash`, and
-  `tex_math_double_backslash` can be used with `html` input.
-  (This is handy for reading web pages formatted using MathJax,
-  for example.)
-
 Producing slide shows with pandoc
 =================================
 
@@ -4244,57 +4406,6 @@
       </source>
     </audio>
 
-Literate Haskell support
-========================
-
-If you append `+lhs` (or `+literate_haskell`) to an appropriate input or output
-format (`markdown`, `markdown_strict`, `rst`, or `latex` for input or output;
-`beamer`, `html4` or `html5` for output only), pandoc will treat the document as
-literate Haskell source. This means that
-
-  - In Markdown input, "bird track" sections will be parsed as Haskell
-    code rather than block quotations.  Text between `\begin{code}`
-    and `\end{code}` will also be treated as Haskell code.  For
-    ATX-style headers the character '=' will be used instead of '#'.
-
-  - In Markdown output, code blocks with classes `haskell` and `literate`
-    will be rendered using bird tracks, and block quotations will be
-    indented one space, so they will not be treated as Haskell code.
-    In addition, headers will be rendered setext-style (with underlines)
-    rather than ATX-style (with '#' characters). (This is because ghc
-    treats '#' characters in column 1 as introducing line numbers.)
-
-  - In restructured text input, "bird track" sections will be parsed
-    as Haskell code.
-
-  - In restructured text output, code blocks with class `haskell` will
-    be rendered using bird tracks.
-
-  - In LaTeX input, text in `code` environments will be parsed as
-    Haskell code.
-
-  - In LaTeX output, code blocks with class `haskell` will be rendered
-    inside `code` environments.
-
-  - In HTML output, code blocks with class `haskell` will be rendered
-    with class `literatehaskell` and bird tracks.
-
-Examples:
-
-    pandoc -f markdown+lhs -t html
-
-reads literate Haskell source formatted with Markdown conventions and writes
-ordinary HTML (without bird tracks).
-
-    pandoc -f markdown+lhs -t html+lhs
-
-writes HTML with the Haskell code in bird tracks, so it can be copied
-and pasted as literate Haskell source.
-
-Note that GHC expects the bird tracks in the first column, so indentend literate
-code blocks (e.g. inside an itemized environment) will not be picked up by the
-Haskell compiler.
-
 Syntax highlighting
 ===================
 
@@ -4327,19 +4438,19 @@
 
 If you define a `div` or `span` with the attribute `custom-style`,
 pandoc will apply your specified style to the contained elements. So,
-for example,
+for example using the `bracketed_spans` syntax,
 
-    <span custom-style="Emphatically">Get out,</span> he said.
+    [Get out]{custom-style="Emphatically"}, he said.
 
-would produce a docx file with "Get out," styled with character
-style `Emphatically`. Similarly,
+would produce a docx file with "Get out" styled with character
+style `Emphatically`. Similarly, using the `fenced_divs` syntax,
 
     Dickinson starts the poem simply:
 
-    <div custom-style="Poetry">
+    ::: {custom-style="Poetry"}
     | A Bird came down the Walk---
     | He did not know I saw---
-    </div>
+    :::
 
 would style the two contained lines with the `Poetry` paragraph style.
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -20,11 +20,11 @@
 Markdown], [MultiMarkdown], and (subsets of) [Textile],
 [reStructuredText], [HTML], [LaTeX], [MediaWiki markup], [TWiki markup],
 [TikiWiki markup], [Creole 1.0], [Haddock markup], [OPML], [Emacs Org mode],
-[DocBook], [Muse], [txt2tags], [Vimwiki], [EPUB], [ODT], and [Word docx];
-and it can write plain text, [Markdown], [CommonMark], [PHP Markdown
-Extra], [GitHub-Flavored Markdown], [MultiMarkdown],
+[DocBook], [JATS], [Muse], [txt2tags], [Vimwiki], [EPUB], [ODT], and
+[Word docx]; and it can write plain text, [Markdown], [CommonMark], [PHP
+Markdown Extra], [GitHub-Flavored Markdown], [MultiMarkdown],
 [reStructuredText], [XHTML], [HTML5], [LaTeX] \(including
-[`beamer`] slide shows\), [ConTeXt], [RTF], [OPML], [DocBook],
+[`beamer`] slide shows\), [ConTeXt], [RTF], [OPML], [DocBook], [JATS],
 [OpenDocument], [ODT], [Word docx], [GNU Texinfo], [MediaWiki
 markup], [DokuWiki markup], [ZimWiki markup], [Haddock markup],
 [EPUB] \(v2 or v3\), [FictionBook2], [Textile], [groff man],
@@ -79,6 +79,7 @@
 [RTF]: http://en.wikipedia.org/wiki/Rich_Text_Format
 [Creole 1.0]: http://www.wikicreole.org/wiki/Creole1.0
 [DocBook]: http://docbook.org
+[JATS]: https://jats.nlm.nih.gov
 [txt2tags]: http://txt2tags.org
 [EPUB]: http://idpf.org/epub
 [OPML]: http://dev.opml.org/spec2.html
@@ -106,7 +107,6 @@
 [Muse]: https://amusewiki.org/library/manual
 [PowerPoint]: https://en.wikipedia.org/wiki/Microsoft_PowerPoint
 [Vimwiki]: https://vimwiki.github.io
-
 
 
 
diff --git a/changelog b/changelog
--- a/changelog
+++ b/changelog
@@ -1,3 +1,271 @@
+pandoc (2.0.6)
+
+  * Added `jats` as an input format.
+
+    + Add Text.Pandoc.Readers.JATS, exporting `readJATS` (API
+      change) (Hamish Mackenzie).
+    + Improved citation handling in JATS reader.  JATS citations
+      are now converted to pandoc citations, and JATS ref-lists
+      are converted into a `references` field in metadata, suitable
+      for use with pandoc-citeproc. Thus a JATS article with embedded
+      bibliographic information can be processed with pandoc and
+      pandoc-citeproc to produce a formatted bibliography.
+
+  * Allow `--list-extensions` to take an optional FORMAT argument.
+    This lists the extensions set by default for the selected FORMAT.
+    The extensions are now alphabetized, and the `+` or `-`
+    indicating the default setting comes before, rather than after,
+    the extension.
+
+  * Markdown reader:
+
+    + Preserve original whitespace between blocks.
+    + Recognize `\placeformula` as context.
+    + Be pickier about table captions.  A caption starts with a `:` which
+      can't be followed by punctuation.  Otherwise we can falsely interpret
+      the start of a fenced div, or even a table header line like
+      `:--:|:--:`, as a caption.
+    + Always use four space rule for example lists.  It would be awkward
+      to indent example list contents to the first non-space character after
+      the label, since example list labels are often long.  Thanks to
+      Bernhard Fisseni for the suggestion.
+    + Improve raw tex parsing.  Note that the Markdown reader is also
+      affected by the `latex_macros` extension changes described below
+      under the LaTeX reader.
+
+  * LaTeX reader:
+
+    + `latex_macros` extension changes (#4179).  Don't pass through macro
+      definitions themselves when `latex_macros` is set.  The macros
+      have already been applied.  If `latex_macros` is enabled, then
+      `rawLaTeXBlock` in Text.Pandoc.Readers.LaTeX will succeed in parsing
+      a macro definition, and will update pandoc's internal macro map
+      accordingly, but the empty string will be returned.
+    + Export `tokenize`, `untokenize` (API change).
+    + Use `applyMacros` in `rawLaTeXBlock`, `rawLaTeXInline`.
+    + Refactored `inlineCommand`.
+    + Fix bug in tokenizer.  Material following `^^` was
+      dropped if it wasn't a character escape.  This only affected
+      invalid LaTeX, so we didn't see it in the wild, but it appeared
+      in a QuickCheck test failure.
+    + Fix regression in LateX tokenization (#4159).  This mainly affects the
+      Markdown reader when parsing raw LaTeX with escaped spaces.
+    + Add tests of LaTeX tokenizer.
+    + Support `\foreignlanguage` from babel.
+    + Be more tolerant of `&` character (#4208).  This allows us to parse
+      unknown tabular environments as raw LaTeX.
+
+  * Muse reader (Alexander Krotov):
+
+    + Parse anchors immediately after headings as IDs.
+    + Require that note references does not start with 0.
+    + Parse empty comments correctly.
+
+  * Org reader (Albert Krewinkel):
+
+    + Fix asterisks-related parsing error (#4180).
+    + Support minlevel option for includes (#4154).  The level of headers
+      in included files can be shifted to a higher level by specifying a
+      minimum header level via the `:minlevel` parameter. E.g.
+      `#+include: "tour.org" :minlevel 1` will shift the headers in
+      tour.org such that the topmost headers become level 1 headers.
+    + Break-up org reader test file into multiple modules.
+
+  * OPML reader:
+
+    + Enable raw HTML and other extensions by default for notes
+      (#4164).  This fixes a regression in 2.0.  Note that extensions can
+      now be individually disabled, e.g.  `-f opml-smart-raw_html`.
+
+  * RST reader:
+
+    + Allow empty list items (#4193).
+    + More accurate parsing of references (#4156).  Previously we erroneously
+      included the enclosing backticks in a reference ID (#4156).  This
+      change also disables interpretation of syntax inside references, as
+      in docutils.  So, there is no emphasis in `` `my *link*`_ ``.
+
+  * Docx reader:
+
+    + Continue lists after interruption (#4025, Jesse Rosenthal).
+      Docx expects that lists will continue where they left off after an
+      interruption and introduces a new id if a list is starting again. So
+      we keep track of the state of lists and use them to define a "start"
+      attribute, if necessary.
+    + Add tests for structured document tags unwrapping (Jesse Rosenthal).
+    + Preprocess Document body to unwrap `w:sdt` elements (Jesse Rosenthal,
+      #4190).
+
+  * Plain writer:
+
+    + Don't linkify table of contents.
+
+  * RST writer:
+
+    + Fix anchors for headers (#4188).  We were missing an `_`.
+
+  * PowerPoint writer (Jesse Rosenthal):
+
+    + Treat lists inside BlockQuotes as lists.  We don't yet produce
+      incremental lists in PowerPoint, but we should at least treat lists
+      inside BlockQuotes as lists, for compatibility with other slide formats.
+    + Add ability to force size.  This replaces the more specific
+      `blockQuote runProp`, which only affected the size of blockquotes. We
+      can use this for notes, etc.
+    + Implement notes.  This currently prints all notes on a final slide.
+      Note that at the moment, there is a danger of text overflowing the
+      note slide, since there is no logic for adding further slides.
+    + Implement basic definition list functionality to PowerPoint writer.
+    + Don't look for default template file for Powerpoint (#4181).
+    + Add pptx to isTextFormat list.  This is used to check standalone
+      and not writing to the terminal.
+    + Obey slide level option (Jesse Rosenthal).
+    + Introduce tests.
+
+  * Docx writer:
+
+    + Ensure that `distArchive` is the one that comes with pandoc
+      (#4182).  Previously a `reference.docx` in `~/.pandoc` (or the user data
+      dir) would be used instead, and this could cause problems because a
+      user-modified docx sometimes lacks vital sections that we count
+      on the `distArchive` to supply.
+
+  * Org writer:
+
+    + Do not wrap "-" to avoid accidental bullet lists (Alexander Krotov).
+    + Don't allow fn refs to wrap to beginning of line (#4171, with help from
+      Alexander Krotov).  Otherwise they can be interpreted as footnote
+      definitions.
+
+  * Muse writer (Alexander Krotov):
+
+    + Don't wrap note references to the next line (#4172).
+
+  * HTML writer:
+
+    + Use br elements in line blocks instead of relying on CSS
+      (#4162).  HTML-based templates have had the custom CSS for
+      `div.line-block` removed.  Those maintaining custom templates will want
+      to remove this too.  We still enclose line blocks in a div with class
+      `line-block`.
+
+  * LaTeX writer:
+
+    + Use `\renewcommand` for `\textlatin` with babel (#4161).
+      This avoids a clash with a deprecated `\textlatin` command defined
+      in Babel.
+    + Allow fragile=singleslide attribute in beamer slides (#4169).
+    + Use `\endhead` after `\toprule` in headerless tables (#4207).
+
+  * FB2 writer:
+
+    + Add cover image specified by `cover-image` meta (Alexander Krotov,
+      #4195).
+
+  * JATS writer (Hamish Mackenzie):
+
+    + Support writing `<fig>` and `<table-wrap>` elements
+      with `<title>` and `<caption>` inside them by using Divs with class set
+      to one of `fig`, `table-wrap` or `caption` (Hamish Mackenzie).  The
+      title is included as a Heading so the constraint on where Heading can
+      occur is also relaxed.
+    + Leave out empty alt attributes on links.
+    + Deduplicate image mime type code.
+    + Make `<p>` optional in `<td>` and `<th>` (#4178).
+    + Self closing tags for empty xref (#4187).
+    + Improve support for code language.
+
+  * Custom writer:
+
+    + Use init file to setup Lua interpreter (Albert Krewinkel).
+      The same init file (`data/init`) that is used to setup the Lua
+      interpreter for Lua filters is also used to setup the interpreter of
+      custom writers.lua.
+    + Define instances for newtype wrapper (Albert Krewinkel).  The custom
+      writer used its own `ToLuaStack` instance definitions, which made
+      it difficult to share code with Lua filters, as this could result
+      in conflicting instances.  A `Stringify` wrapper is introduced to
+      avoid this problem.
+    + Added tests for custom writer.
+    + Fixed definition lists and tables in `data/sample.lua`.
+
+  * Fixed regression: when target is PDF, writer extensions were being
+    ignored.  So, for example, `pandoc -t latex-smart -o file.pdf`
+    did not work properly.
+
+  * Lua modules (Albert Krewinkel):
+
+    + Add `pandoc.utils` module, to hold utility functions.
+    + Create a Haskell module Text.Pandoc.Lua.Module.Pandoc to
+      define the `pandoc` lua module.
+    + Make a Haskell module for each Lua module. Move definitions for the
+      `pandoc.mediabag` modules to a separate Haskell module.
+    + Move `sha1` from the main `pandoc` module to `pandoc.utils`.
+    + Add function `pandoc.utils.hierarchicalize` (convert list of
+      Pandoc blocks into (hierarchical) list of Elements).
+    + Add function `pandoc.utils.normalize_date` (parses a date and
+      converts it (if possible) to "YYYY-MM-DD" format).
+    + Add function `pandoc.utils.to_roman_numeral` (allows conversion
+      of numbers below 4000 into roman numerals).
+    + Add function `pandoc.utils.stringify` (converts any AST element
+      to a string with formatting removed).
+    + `data/init.lua`: load `pandoc.utils` by default
+    + Turn pipe, read into full Haskell functions.  The `pipe` and `read`
+      utility functions are converted from hybrid lua/haskell functions
+      into full Haskell functions. This avoids the need for intermediate
+      `_pipe`/`_read` helper functions, which have dropped.
+    + pandoc.lua: re-add missing MetaMap function.  This was a bug
+      introduced in version 2.0.4.
+
+  * Text.Pandoc.Class: Add `insertInFileTree` [API change].  This gives
+    a pure way to insert an ersatz file into a `FileTree`.  In addition, we
+    normalize paths both on insertion and on lookup.
+
+  * Text.Pandoc.Shared: export `blocksToInlines'` (API change, Maura Bieg).
+
+  * Text.Pandoc.MIME: Add opus to MIME type table as audio/ogg (#4198).
+
+  * Text.Pandoc.Extensions:   Alphabetical order constructors for
+    `Extension`.  This makes them appear in order in `--list-extensions`.
+
+  * Allow lenient decoding of latex error logs, which are not always
+    properly UTF8-encoded (#4200).
+
+  * Update latex template to work with recent versions of beamer.
+    The old template produced numbered sections with some recent
+    versions of beamer.  Thanks to Thomas Hodgson.
+
+  * Updated reference.docx (#4175).  Instead of just "Hello, world", the
+    document now contains exemplars of most of the styles that have an
+    effect on pandoc documents.  This makes it easier to see the effect
+    of style changes.
+
+  * Removed `default.theme` data file (#4096).  It is no longer needed now
+    that we have `--print-highlight-style`.
+
+  * Added `stack.lts9.yaml` for building with lts 9 and ghc 8.0.2.
+    We still need this for the alpine static linux build, since
+    we don't have ghc 8.2.2 for that yet.
+
+  * Removed `stack.pkg.yaml`.  We only really need `stack.yaml`; we
+    can put flag settings for pandoc-citeproc there.
+
+  * Makefile: Add 'trypandoc' and 'pandoc-templates' targets to
+    make releases easier.
+
+  * MANUAL.txt:
+
+    + Add note on what formats have `+smart` by default.
+    + Use native syntax for custom-style (#4174, Mauro Bieg).
+    + Introduce dedicated Extensions section, since some extensions
+      affect formats other than markdown (Mauro Bieg, #4204).
+    + Clarify default html output for `--section-divs` (Richard Edwards).
+
+  * filters.md: say that Text.Pandoc.JSON comes form pandoc-types.
+    Closes jgm/pandoc-website#16.
+
+  * epub.md: Delete removed `-S` option from command (#4151, Georger Araújo).
+
 pandoc (2.0.5)
 
   * Fix a bug in 2.0.4, whereby pandoc could not read the theme files
@@ -38,7 +306,7 @@
     + Revert "Docx reader: don't strip out empty paragraphs."
       This reverts commit d6c58eb836f033a48955796de4d9ffb3b30e297b.
     + Implement `empty_paragraphs` extension in docx reader and writer,
-      opendocument writer, html reader and writer.
+      opendocument writer, HTML reader and writer.
     + Add tests for `empty_paragraphs` extension.
 
   * Markdown reader:
@@ -318,6 +586,8 @@
     + Allow spaces after `\(` and before `\)` with `tex_math_single_backslash`.
       Previously `\( \frac{1}{a} < \frac{1}{b} \)` was not parsed as math in
       `markdown` or `html` `+tex_math_single_backslash`.
+    + Parse div with class `line-block` as LineBlock.
+    + Don't fail with block-level content in figcaption (Mauro Bieg, #4183).
 
   * MANUAL: clarify that math extensions work with HTML.
     Clarify that `tex_math_dollars` and `tex_math_single_backslash`
diff --git a/data/default.theme b/data/default.theme
deleted file mode 100644
--- a/data/default.theme
+++ /dev/null
@@ -1,177 +0,0 @@
-{
-    "metadata" : {
-        "revision" : 1,
-        "name" : "Default",
-        "author" : "Kate Authors",
-        "license" : "MIT",
-        "read-only" : true
-    },
-    "text-styles": {
-        "Normal" : {
-            "text-color" : "#1f1c1b",
-            "selected-text-color" : "#ffffff",
-            "bold" : false,
-            "italic" : false,
-            "underline" : false,
-            "strike-through" : false
-        },
-        "Keyword" : {
-            "text-color" : "#1f1c1b",
-            "selected-text-color" : "#ffffff",
-            "bold" : true
-        },
-        "Function" : {
-            "text-color" : "#644a9b",
-            "selected-text-color" : "#452886"
-        },
-        "Variable" : {
-            "text-color" : "#0057ae",
-            "selected-text-color" : "#00316e"
-        },
-        "ControlFlow" : {
-            "text-color" : "#1f1c1b",
-            "selected-text-color" : "#ffffff",
-            "bold" : true
-        },
-        "Operator" : {
-            "text-color" : "#1f1c1b",
-            "selected-text-color" : "#ffffff"
-        },
-        "BuiltIn" : {
-            "text-color" : "#644a9b",
-            "selected-text-color" : "#452886",
-            "bold" : true
-        },
-        "Extension" : {
-            "text-color" : "#0095ff",
-            "selected-text-color" : "#ffffff",
-            "bold" : true
-        },
-        "Preprocessor" : {
-            "text-color" : "#006e28",
-            "selected-text-color" : "#006e28"
-        },
-        "Attribute" : {
-            "text-color" : "#0057ae",
-            "selected-text-color" : "#00316e"
-        },
-        "Char" : {
-            "text-color" : "#924c9d",
-            "selected-text-color" : "#6c2477"
-        },
-        "SpecialChar" : {
-            "text-color" : "#3daee9",
-            "selected-text-color" : "#fcfcfc"
-        },
-        "String" : {
-            "text-color" : "#bf0303",
-            "selected-text-color" : "#9c0e0e"
-        },
-        "VerbatimString" : {
-            "text-color" : "#bf0303",
-            "selected-text-color" : "#9c0e0e"
-        },
-        "SpecialString" : {
-            "text-color" : "#ff5500",
-            "selected-text-color" : "#ff5500"
-        },
-        "Import" : {
-            "text-color" : "#ff5500",
-            "selected-text-color" : "#ff5500"
-        },
-        "DataType" : {
-            "text-color" : "#0057ae",
-            "selected-text-color" : "#00316e"
-        },
-        "DecVal" : {
-            "text-color" : "#b08000",
-            "selected-text-color" : "#805c00"
-        },
-        "BaseN" : {
-            "text-color" : "#b08000",
-            "selected-text-color" : "#805c00"
-        },
-        "Float" : {
-            "text-color" : "#b08000",
-            "selected-text-color" : "#805c00"
-        },
-        "Constant" : {
-            "text-color" : "#aa5500",
-            "selected-text-color" : "#5e2f00"
-        },
-        "Comment" : {
-            "text-color" : "#898887",
-            "selected-text-color" : "#5e5d5d"
-        },
-        "Documentation" : {
-            "text-color" : "#607880",
-            "selected-text-color" : "#46585e"
-        },
-        "Annotation" : {
-            "text-color" : "#ca60ca",
-            "selected-text-color" : "#a44ea4"
-        },
-        "CommentVar" : {
-            "text-color" : "#0095ff",
-            "selected-text-color" : "#ffffff"
-        },
-        "RegionMarker" : {
-            "text-color" : "#0057ae",
-            "selected-text-color" : "#00316e",
-            "background-color" : "#e0e9f8"
-        },
-        "Information" : {
-            "text-color" : "#b08000",
-            "selected-text-color" : "#805c00"
-        },
-        "Warning" : {
-            "text-color" : "#bf0303",
-            "selected-text-color" : "#9c0e0e"
-        },
-        "Alert" : {
-            "text-color" : "#bf0303",
-            "selected-text-color" : "#9c0e0e",
-            "background-color" : "#f7e6e6",
-            "bold" : true
-        },
-        "Error" : {
-            "text-color" : "#bf0303",
-            "selected-text-color" : "#9c0e0e",
-            "underline" : true
-        },
-        "Others" : {
-            "text-color" : "#006e28",
-            "selected-text-color" : "#006e28"
-        }
-   },
-    "editor-colors": {
-        "background-color" : "#ffffff",
-        "code-folding" : "#94caef",
-        "bracket-matching" : "#ffff00",
-        "current-line" : "#f8f7f6",
-        "icon-border" : "#f0f0f0",
-        "indentation-line" : "#d2d2d2",
-        "line-numbers" : "#a0a0a0",
-        "current-line-number" : "#1e1e1e",
-        "mark-bookmark" : "#0000ff",
-        "mark-breakpoint-active" : "#ff0000",
-        "mark-breakpoint-reached" : "#ffff00",
-        "mark-breakpoint-disabled" : "#ff00ff",
-        "mark-execution" : "#a0a0a4",
-        "mark-warning" : "#00ff00",
-        "mark-error" : "#ff0000",
-        "modified-lines" : "#fdbc4b",
-        "replace-highlight" : "#00ff00",
-        "saved-lines" : "#2ecc71",
-        "search-highlight" : "#ffff00",
-        "selection" : "#94caef",
-        "separator" : "#898887",
-        "spell-checking" : "#bf0303",
-        "tab-marker" : "#d2d2d2",
-        "template-background" : "#d6d2d0",
-        "template-placeholder" : "#baf8ce",
-        "template-focused-placeholder" : "#76da98",
-        "template-read-only-placeholder" : "#f6e6e6",
-        "word-wrap-marker" : "#ededed"
-    }
-}
diff --git a/data/docx/[Content_Types].xml b/data/docx/[Content_Types].xml
--- a/data/docx/[Content_Types].xml
+++ b/data/docx/[Content_Types].xml
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="xml" ContentType="application/xml" /><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml" /><Override PartName="/word/webSettings.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml" /><Override PartName="/word/numbering.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml" /><Override PartName="/word/settings.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml" /><Override PartName="/word/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml" /><Override PartName="/word/fontTable.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml" /><Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml" /><Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml" /><Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml" /><Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml" /><Override PartName="/word/footnotes.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml" /></Types>
+<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="xml" ContentType="application/xml" /><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml" /><Override PartName="/word/webSettings.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml" /><Override PartName="/word/numbering.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml" /><Override PartName="/word/settings.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml" /><Override PartName="/word/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml" /><Override PartName="/word/fontTable.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml" /><Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml" /><Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml" /><Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml" /><Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml" /><Override PartName="/word/comments.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml" /><Override PartName="/word/footnotes.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml" /></Types>
diff --git a/data/docx/docProps/core.xml b/data/docx/docProps/core.xml
--- a/data/docx/docProps/core.xml
+++ b/data/docx/docProps/core.xml
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><dc:title></dc:title><dc:creator></dc:creator></cp:coreProperties>
+<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><dc:title>Title</dc:title><dc:creator>Author</dc:creator><cp:keywords></cp:keywords><dcterms:created xsi:type="dcterms:W3CDTF">2017-12-27T05:22:50Z</dcterms:created><dcterms:modified xsi:type="dcterms:W3CDTF">2017-12-27T05:22:50Z</dcterms:modified></cp:coreProperties>
diff --git a/data/docx/word/_rels/document.xml.rels b/data/docx/word/_rels/document.xml.rels
--- a/data/docx/word/_rels/document.xml.rels
+++ b/data/docx/word/_rels/document.xml.rels
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering" Id="rId1" Target="numbering.xml" /><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Id="rId2" Target="styles.xml" /><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings" Id="rId3" Target="settings.xml" /><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings" Id="rId4" Target="webSettings.xml" /><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable" Id="rId5" Target="fontTable.xml" /><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Id="rId6" Target="theme/theme1.xml" /><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes" Id="rId7" Target="footnotes.xml" /></Relationships>
+<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering" Id="rId1" Target="numbering.xml" /><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Id="rId2" Target="styles.xml" /><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings" Id="rId3" Target="settings.xml" /><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings" Id="rId4" Target="webSettings.xml" /><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable" Id="rId5" Target="fontTable.xml" /><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Id="rId6" Target="theme/theme1.xml" /><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes" Id="rId7" Target="footnotes.xml" /><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments" Id="rId8" Target="comments.xml" /><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" Id="rId30" Target="http://example.com" TargetMode="External" /></Relationships>
diff --git a/data/docx/word/_rels/footnotes.xml.rels b/data/docx/word/_rels/footnotes.xml.rels
--- a/data/docx/word/_rels/footnotes.xml.rels
+++ b/data/docx/word/_rels/footnotes.xml.rels
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships" />
+<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" Id="rId30" Target="http://example.com" TargetMode="External" /></Relationships>
diff --git a/data/docx/word/comments.xml b/data/docx/word/comments.xml
new file mode 100644
--- /dev/null
+++ b/data/docx/word/comments.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<w:comments xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" />
diff --git a/data/docx/word/document.xml b/data/docx/word/document.xml
--- a/data/docx/word/document.xml
+++ b/data/docx/word/document.xml
@@ -1,2 +1,398 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"><w:body><w:p><w:r><w:t xml:space="preserve">Hello world.</w:t></w:r></w:p></w:body></w:document>
+<?xml version="1.0" encoding="utf-8"?>
+<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
+xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"
+xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
+xmlns:o="urn:schemas-microsoft-com:office:office"
+xmlns:v="urn:schemas-microsoft-com:vml"
+xmlns:w10="urn:schemas-microsoft-com:office:word"
+xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
+xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"
+xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing">
+
+  <w:body>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="Title" />
+      </w:pPr>
+      <w:r>
+        <w:t xml:space="preserve">
+Title
+</w:t>
+      </w:r>
+    </w:p>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="Subtitle" />
+      </w:pPr>
+      <w:r>
+        <w:t xml:space="preserve">
+Subtitle
+</w:t>
+      </w:r>
+    </w:p>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="Author" />
+      </w:pPr>
+      <w:r>
+        <w:t xml:space="preserve">
+Author
+</w:t>
+      </w:r>
+    </w:p>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="Date" />
+      </w:pPr>
+      <w:r>
+        <w:t xml:space="preserve">
+Date
+</w:t>
+      </w:r>
+    </w:p>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="Compact" />
+        <w:pStyle w:val="Abstract" />
+      </w:pPr>
+      <w:r>
+        <w:t xml:space="preserve">
+Abstract
+</w:t>
+      </w:r>
+    </w:p>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="Heading1" />
+      </w:pPr>
+      <w:bookmarkStart w:id="21" w:name="heading-1" />
+      <w:r>
+        <w:t xml:space="preserve">
+Heading 1
+</w:t>
+      </w:r>
+      <w:bookmarkEnd w:id="21" />
+    </w:p>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="Heading2" />
+      </w:pPr>
+      <w:bookmarkStart w:id="22" w:name="heading-2" />
+      <w:r>
+        <w:t xml:space="preserve">
+Heading 2
+</w:t>
+      </w:r>
+      <w:bookmarkEnd w:id="22" />
+    </w:p>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="Heading3" />
+      </w:pPr>
+      <w:bookmarkStart w:id="23" w:name="heading-3" />
+      <w:r>
+        <w:t xml:space="preserve">
+Heading 3
+</w:t>
+      </w:r>
+      <w:bookmarkEnd w:id="23" />
+    </w:p>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="Heading4" />
+      </w:pPr>
+      <w:bookmarkStart w:id="24" w:name="heading-4" />
+      <w:r>
+        <w:t xml:space="preserve">
+Heading 4
+</w:t>
+      </w:r>
+      <w:bookmarkEnd w:id="24" />
+    </w:p>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="Heading5" />
+      </w:pPr>
+      <w:bookmarkStart w:id="25" w:name="heading-5" />
+      <w:r>
+        <w:t xml:space="preserve">
+Heading 5
+</w:t>
+      </w:r>
+      <w:bookmarkEnd w:id="25" />
+    </w:p>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="Heading6" />
+      </w:pPr>
+      <w:bookmarkStart w:id="26" w:name="heading-6" />
+      <w:r>
+        <w:t xml:space="preserve">
+Heading 6
+</w:t>
+      </w:r>
+      <w:bookmarkEnd w:id="26" />
+    </w:p>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="Heading7" />
+      </w:pPr>
+      <w:bookmarkStart w:id="27" w:name="heading-7" />
+      <w:r>
+        <w:t xml:space="preserve">
+Heading 7
+</w:t>
+      </w:r>
+      <w:bookmarkEnd w:id="27" />
+    </w:p>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="Heading8" />
+      </w:pPr>
+      <w:bookmarkStart w:id="28" w:name="heading-8" />
+      <w:r>
+        <w:t xml:space="preserve">
+Heading 8
+</w:t>
+      </w:r>
+      <w:bookmarkEnd w:id="28" />
+    </w:p>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="Heading9" />
+      </w:pPr>
+      <w:bookmarkStart w:id="29" w:name="heading-9" />
+      <w:r>
+        <w:t xml:space="preserve">
+Heading 9
+</w:t>
+      </w:r>
+      <w:bookmarkEnd w:id="29" />
+    </w:p>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="FirstParagraph" />
+      </w:pPr>
+      <w:r>
+        <w:t xml:space="preserve">
+First Paragraph.
+</w:t>
+      </w:r>
+    </w:p>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="BodyText" />
+      </w:pPr>
+      <w:r>
+        <w:t xml:space="preserve">
+Body Text. Body Text Char.
+</w:t>
+      </w:r>
+      <w:r>
+        <w:t xml:space="preserve">
+ 
+</w:t>
+      </w:r>
+      <w:r>
+        <w:rPr>
+          <w:rStyle w:val="VerbatimChar" />
+        </w:rPr>
+        <w:t xml:space="preserve">
+Verbatim Char
+</w:t>
+      </w:r>
+      <w:r>
+        <w:t xml:space="preserve">
+.
+</w:t>
+      </w:r>
+      <w:r>
+        <w:t xml:space="preserve">
+ 
+</w:t>
+      </w:r>
+      <w:hyperlink r:id="rId30">
+        <w:r>
+          <w:rPr>
+            <w:rStyle w:val="Hyperlink" />
+          </w:rPr>
+          <w:t xml:space="preserve">
+Hyperlink
+</w:t>
+        </w:r>
+      </w:hyperlink>
+      <w:r>
+        <w:t xml:space="preserve">
+.
+</w:t>
+      </w:r>
+      <w:r>
+        <w:t xml:space="preserve">
+ 
+</w:t>
+      </w:r>
+      <w:r>
+        <w:t xml:space="preserve">
+Footnote.
+</w:t>
+      </w:r>
+      <w:r>
+        <w:rPr>
+          <w:rStyle w:val="FootnoteReference" />
+        </w:rPr>
+        <w:footnoteReference w:id="31" />
+      </w:r>
+    </w:p>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="BlockText" />
+      </w:pPr>
+      <w:r>
+        <w:t xml:space="preserve">
+Block Text.
+</w:t>
+      </w:r>
+    </w:p>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="TableCaption" />
+      </w:pPr>
+      <w:r>
+        <w:t xml:space="preserve">
+Table caption.
+</w:t>
+      </w:r>
+    </w:p>
+    <w:tbl>
+      <w:tblPr>
+        <w:tblStyle w:val="Table" />
+        <w:tblW w:type="pct" w:w="0.0" />
+        <w:tblLook w:firstRow="1" />
+        <w:tblCaption w:val="Table caption." />
+      </w:tblPr>
+      <w:tblGrid />
+      <w:tr>
+        <w:trPr>
+          <w:cnfStyle w:firstRow="1" />
+        </w:trPr>
+        <w:tc>
+          <w:tcPr>
+            <w:tcBorders>
+              <w:bottom w:val="single" />
+            </w:tcBorders>
+            <w:vAlign w:val="bottom" />
+          </w:tcPr>
+          <w:p>
+            <w:pPr>
+              <w:pStyle w:val="Compact" />
+              <w:jc w:val="left" />
+            </w:pPr>
+            <w:r>
+              <w:t xml:space="preserve">
+Table
+</w:t>
+            </w:r>
+          </w:p>
+        </w:tc>
+        <w:tc>
+          <w:tcPr>
+            <w:tcBorders>
+              <w:bottom w:val="single" />
+            </w:tcBorders>
+            <w:vAlign w:val="bottom" />
+          </w:tcPr>
+          <w:p>
+            <w:pPr>
+              <w:pStyle w:val="Compact" />
+              <w:jc w:val="left" />
+            </w:pPr>
+            <w:r>
+              <w:t xml:space="preserve">
+Table
+</w:t>
+            </w:r>
+          </w:p>
+        </w:tc>
+      </w:tr>
+      <w:tr>
+        <w:tc>
+          <w:p>
+            <w:pPr>
+              <w:pStyle w:val="Compact" />
+              <w:jc w:val="left" />
+            </w:pPr>
+            <w:r>
+              <w:t xml:space="preserve">
+1
+</w:t>
+            </w:r>
+          </w:p>
+        </w:tc>
+        <w:tc>
+          <w:p>
+            <w:pPr>
+              <w:pStyle w:val="Compact" />
+              <w:jc w:val="left" />
+            </w:pPr>
+            <w:r>
+              <w:t xml:space="preserve">
+2
+</w:t>
+            </w:r>
+          </w:p>
+        </w:tc>
+      </w:tr>
+    </w:tbl>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="ImageCaption" />
+      </w:pPr>
+      <w:r>
+        <w:t xml:space="preserve">
+Image Caption
+</w:t>
+      </w:r>
+    </w:p>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="DefinitionTerm" />
+      </w:pPr>
+      <w:r>
+        <w:t xml:space="preserve">
+DefinitionTerm
+</w:t>
+      </w:r>
+    </w:p>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="Definition" />
+      </w:pPr>
+      <w:r>
+        <w:t xml:space="preserve">
+Definition
+</w:t>
+      </w:r>
+    </w:p>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="DefinitionTerm" />
+      </w:pPr>
+      <w:r>
+        <w:t xml:space="preserve">
+DefinitionTerm
+</w:t>
+      </w:r>
+    </w:p>
+    <w:p>
+      <w:pPr>
+        <w:pStyle w:val="Definition" />
+      </w:pPr>
+      <w:r>
+        <w:t xml:space="preserve">
+Definition
+</w:t>
+      </w:r>
+    </w:p>
+    <w:sectPr />
+  </w:body>
+</w:document>
diff --git a/data/docx/word/footnotes.xml b/data/docx/word/footnotes.xml
--- a/data/docx/word/footnotes.xml
+++ b/data/docx/word/footnotes.xml
@@ -1,26 +1,7 @@
-<?xml version="1.0" encoding="utf-8"?>
-<w:footnotes xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
-xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"
-xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
-xmlns:o="urn:schemas-microsoft-com:office:office"
-xmlns:v="urn:schemas-microsoft-com:vml"
-xmlns:w10="urn:schemas-microsoft-com:office:word"
-xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
-xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"
-xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing">
-
-  <w:footnote w:type="continuationSeparator" w:id="0">
-    <w:p>
-      <w:r>
-        <w:continuationSeparator />
-      </w:r>
-    </w:p>
-  </w:footnote>
-  <w:footnote w:type="separator" w:id="-1">
-    <w:p>
-      <w:r>
-        <w:separator />
-      </w:r>
-    </w:p>
-  </w:footnote>
-</w:footnotes>
+<?xml version="1.0" encoding="UTF-8"?>
+<w:footnotes xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"><w:footnote w:type="continuationSeparator" w:id="0"><w:p><w:r><w:continuationSeparator /></w:r></w:p></w:footnote><w:footnote w:type="separator" w:id="-1"><w:p><w:r><w:separator /></w:r></w:p></w:footnote><w:footnote w:id="31"><w:p><w:pPr><w:pStyle w:val="FootnoteText" /></w:pPr><w:r>
+  <w:rPr>
+    <w:rStyle w:val="FootnoteReference" />
+  </w:rPr>
+  <w:footnoteRef />
+</w:r><w:r><w:t xml:space="preserve"> </w:t></w:r><w:r><w:t xml:space="preserve">Footnote Text.</w:t></w:r></w:p></w:footnote></w:footnotes>
diff --git a/data/docx/word/numbering.xml b/data/docx/word/numbering.xml
--- a/data/docx/word/numbering.xml
+++ b/data/docx/word/numbering.xml
@@ -1,3 +1,2 @@
-<?xml version="1.0" encoding="utf-8"?>
-<w:numbering xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
-</w:numbering>
+<?xml version="1.0" encoding="UTF-8"?>
+<w:numbering xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"><w:abstractNum w:abstractNumId="990"><w:nsid w:val="170cd2de" /><w:multiLevelType w:val="multilevel" /><w:lvl w:ilvl="0"><w:numFmt w:val="bullet" /><w:lvlText w:val=" " /><w:lvlJc w:val="left" /><w:pPr><w:tabs><w:tab w:val="num" w:pos="0" /></w:tabs><w:ind w:left="480" w:hanging="480" /></w:pPr></w:lvl><w:lvl w:ilvl="1"><w:numFmt w:val="bullet" /><w:lvlText w:val=" " /><w:lvlJc w:val="left" /><w:pPr><w:tabs><w:tab w:val="num" w:pos="720" /></w:tabs><w:ind w:left="1200" w:hanging="480" /></w:pPr></w:lvl><w:lvl w:ilvl="2"><w:numFmt w:val="bullet" /><w:lvlText w:val=" " /><w:lvlJc w:val="left" /><w:pPr><w:tabs><w:tab w:val="num" w:pos="1440" /></w:tabs><w:ind w:left="1920" w:hanging="480" /></w:pPr></w:lvl><w:lvl w:ilvl="3"><w:numFmt w:val="bullet" /><w:lvlText w:val=" " /><w:lvlJc w:val="left" /><w:pPr><w:tabs><w:tab w:val="num" w:pos="2160" /></w:tabs><w:ind w:left="2640" w:hanging="480" /></w:pPr></w:lvl><w:lvl w:ilvl="4"><w:numFmt w:val="bullet" /><w:lvlText w:val=" " /><w:lvlJc w:val="left" /><w:pPr><w:tabs><w:tab w:val="num" w:pos="2880" /></w:tabs><w:ind w:left="3360" w:hanging="480" /></w:pPr></w:lvl><w:lvl w:ilvl="5"><w:numFmt w:val="bullet" /><w:lvlText w:val=" " /><w:lvlJc w:val="left" /><w:pPr><w:tabs><w:tab w:val="num" w:pos="3600" /></w:tabs><w:ind w:left="4080" w:hanging="480" /></w:pPr></w:lvl><w:lvl w:ilvl="6"><w:numFmt w:val="bullet" /><w:lvlText w:val=" " /><w:lvlJc w:val="left" /><w:pPr><w:tabs><w:tab w:val="num" w:pos="4320" /></w:tabs><w:ind w:left="4800" w:hanging="480" /></w:pPr></w:lvl><w:lvl w:ilvl="7"><w:numFmt w:val="bullet" /><w:lvlText w:val=" " /><w:lvlJc w:val="left" /><w:pPr><w:tabs><w:tab w:val="num" w:pos="5040" /></w:tabs><w:ind w:left="5520" w:hanging="480" /></w:pPr></w:lvl><w:lvl w:ilvl="8"><w:numFmt w:val="bullet" /><w:lvlText w:val=" " /><w:lvlJc w:val="left" /><w:pPr><w:tabs><w:tab w:val="num" w:pos="5760" /></w:tabs><w:ind w:left="6240" w:hanging="480" /></w:pPr></w:lvl></w:abstractNum><w:num w:numId="1000"><w:abstractNumId w:val="990" /></w:num></w:numbering>
diff --git a/data/docx/word/settings.xml b/data/docx/word/settings.xml
--- a/data/docx/word/settings.xml
+++ b/data/docx/word/settings.xml
diff --git a/data/docx/word/styles.xml b/data/docx/word/styles.xml
--- a/data/docx/word/styles.xml
+++ b/data/docx/word/styles.xml
@@ -450,8 +450,7 @@
       <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />
       <w:b w:val="0" />
       <w:bCs w:val="0" />
-      <w:color w:val="365F91" w:themeColor="accent1"
-      w:themeShade="BF" />
+      <w:color w:val="365F91" w:themeColor="accent1" w:themeShade="BF" />
     </w:rPr>
   </w:style>
 </w:styles>
diff --git a/data/init.lua b/data/init.lua
--- a/data/init.lua
+++ b/data/init.lua
@@ -4,3 +4,4 @@
 
 pandoc = require 'pandoc'
 pandoc.mediabag = require 'pandoc.mediabag'
+pandoc.utils = require 'pandoc.utils'
diff --git a/data/pandoc.lua b/data/pandoc.lua
--- a/data/pandoc.lua
+++ b/data/pandoc.lua
@@ -202,7 +202,10 @@
 --- Meta map
 -- @function MetaMap
 -- @tparam table key_value_map a string-indexed map of meta values
-M.MetaValue:create_constructor("MetaMap", function (mm) return mm end)
+M.MetaMap = M.MetaValue:create_constructor(
+  "MetaMap",
+  function (mm) return mm end
+)
 
 --- Creates string to be used in meta data.
 -- Does nothing, lua strings are meta strings.
@@ -871,53 +874,6 @@
 -- Helper Functions
 -- @section helpers
 
---- Parse the given string into a Pandoc document.
--- The method used to interpret input is specified by *format*. Acceptable
--- values for this parameter are equal to those that can be given to the
--- `--from` command line option.
--- @tparam      string markup the markup to be parsed
--- @tparam[opt] string format format specification, defaults to "markdown".
--- @treturn Pandoc pandoc document
--- @usage
--- local org_markup = "/emphasis/"  -- Input to be read
--- local document = pandoc.read(org_markup, "org")
--- -- Get the first block of the document
--- local block = document.blocks[1]
--- -- The inline element in that block is an `Emph`
--- assert(block.content[1].t == "Emph")
-function M.read(markup, format)
-  format = format or "markdown"
-  local pd = pandoc._read(format, markup)
-  if type(pd) == "string" then
-    error(pd)
-  else
-    return pd
-  end
-end
-
---- Runs command with arguments, passing it some input, and returns the output.
--- @treturn string Output of command.
--- @raise A table containing the keys `command`, `error_code`, and `output` is
--- thrown if the command exits with a non-zero error code.
--- @usage
--- local ec, output = pandoc.pipe("sed", {"-e","s/a/b/"}, "abc")
-function M.pipe (command, args, input)
-  local ec, output = pandoc._pipe(command, args, input)
-  if ec ~= 0 then
-    err = setmetatable(
-      { command = command, error_code = ec, output = output},
-      { __tostring = function(e)
-          return "Error running " .. e.command
-            .. " (error code " .. e.error_code .. "): "
-            .. e.output
-        end
-      }
-    )
-    error(err)
-  end
-  return output
-end
-
 --- Use functions defined in the global namespace to create a pandoc filter.
 -- All globally defined functions which have names of pandoc elements are
 -- collected into a new table.
@@ -946,5 +902,10 @@
   end
   return res
 end
+
+------------------------------------------------------------------------
+-- Functions which have moved to different modules
+local utils = require 'pandoc.utils'
+M.sha1 = utils.sha1
 
 return M
diff --git a/data/sample.lua b/data/sample.lua
--- a/data/sample.lua
+++ b/data/sample.lua
@@ -242,14 +242,12 @@
   return "<ol>\n" .. table.concat(buffer, "\n") .. "\n</ol>"
 end
 
--- Revisit association list STackValue instance.
 function DefinitionList(items)
   local buffer = {}
   for _,item in pairs(items) do
-    for k, v in pairs(item) do
-      table.insert(buffer,"<dt>" .. k .. "</dt>\n<dd>" ..
-                        table.concat(v,"</dd>\n<dd>") .. "</dd>")
-    end
+    local k, v = next(item)
+    table.insert(buffer, "<dt>" .. k .. "</dt>\n<dd>" ..
+                   table.concat(v, "</dd>\n<dd>") .. "</dd>")
   end
   return "<dl>\n" .. table.concat(buffer, "\n") .. "\n</dl>"
 end
@@ -288,7 +286,7 @@
   end
   if widths and widths[1] ~= 0 then
     for _, w in pairs(widths) do
-      add('<col width="' .. string.format("%d%%", w * 100) .. '" />')
+      add('<col width="' .. string.format("%.0f%%", w * 100) .. '" />')
     end
   end
   local header_row = {}
diff --git a/data/templates/default.dzslides b/data/templates/default.dzslides
--- a/data/templates/default.dzslides
+++ b/data/templates/default.dzslides
@@ -16,7 +16,6 @@
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
       span.underline{text-decoration: underline;}
-      div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
 $if(quotes)$
       q { quotes: "“" "”" "‘" "’"; }
diff --git a/data/templates/default.epub2 b/data/templates/default.epub2
--- a/data/templates/default.epub2
+++ b/data/templates/default.epub2
@@ -10,7 +10,6 @@
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
       span.underline{text-decoration: underline;}
-      div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
 $if(quotes)$
       q { quotes: "“" "”" "‘" "’"; }
diff --git a/data/templates/default.epub3 b/data/templates/default.epub3
--- a/data/templates/default.epub3
+++ b/data/templates/default.epub3
@@ -9,7 +9,6 @@
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
       span.underline{text-decoration: underline;}
-      div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
 $if(quotes)$
       q { quotes: "“" "”" "‘" "’"; }
diff --git a/data/templates/default.html4 b/data/templates/default.html4
--- a/data/templates/default.html4
+++ b/data/templates/default.html4
@@ -18,7 +18,6 @@
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
       span.underline{text-decoration: underline;}
-      div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
 $if(quotes)$
       q { quotes: "“" "”" "‘" "’"; }
diff --git a/data/templates/default.html5 b/data/templates/default.html5
--- a/data/templates/default.html5
+++ b/data/templates/default.html5
@@ -18,7 +18,6 @@
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
       span.underline{text-decoration: underline;}
-      div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
 $if(quotes)$
       q { quotes: "“" "”" "‘" "’"; }
diff --git a/data/templates/default.latex b/data/templates/default.latex
--- a/data/templates/default.latex
+++ b/data/templates/default.latex
@@ -193,22 +193,34 @@
 \widowpenalties 1 10000
 \raggedbottom
 $if(section-titles)$
+\setbeamertemplate{part page}{
+\centering
+\begin{beamercolorbox}[sep=16pt,center]{part title}
+  \usebeamerfont{part title}\insertpart\par
+\end{beamercolorbox}
+}
+\setbeamertemplate{section page}{
+\centering
+\begin{beamercolorbox}[sep=12pt,center]{part title}
+  \usebeamerfont{section title}\insertsection\par
+\end{beamercolorbox}
+}
+\setbeamertemplate{subsection page}{
+\centering
+\begin{beamercolorbox}[sep=8pt,center]{part title}
+  \usebeamerfont{subsection title}\insertsubsection\par
+\end{beamercolorbox}
+}
 \AtBeginPart{
-  \let\insertpartnumber\relax
-  \let\partname\relax
   \frame{\partpage}
 }
 \AtBeginSection{
   \ifbibliography
   \else
-    \let\insertsectionnumber\relax
-    \let\sectionname\relax
     \frame{\sectionpage}
   \fi
 }
 \AtBeginSubsection{
-  \let\insertsubsectionnumber\relax
-  \let\subsectionname\relax
   \frame{\subsectionpage}
 }
 $endif$
diff --git a/data/templates/default.revealjs b/data/templates/default.revealjs
--- a/data/templates/default.revealjs
+++ b/data/templates/default.revealjs
@@ -21,7 +21,6 @@
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
       span.underline{text-decoration: underline;}
-      div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
 $if(quotes)$
       q { quotes: "“" "”" "‘" "’"; }
diff --git a/data/templates/default.s5 b/data/templates/default.s5
--- a/data/templates/default.s5
+++ b/data/templates/default.s5
@@ -19,7 +19,6 @@
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
       span.underline{text-decoration: underline;}
-      div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
 $if(quotes)$
       q { quotes: "“" "”" "‘" "’"; }
diff --git a/data/templates/default.slideous b/data/templates/default.slideous
--- a/data/templates/default.slideous
+++ b/data/templates/default.slideous
@@ -20,7 +20,6 @@
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
       span.underline{text-decoration: underline;}
-      div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
 $if(quotes)$
       q { quotes: "“" "”" "‘" "’"; }
diff --git a/data/templates/default.slidy b/data/templates/default.slidy
--- a/data/templates/default.slidy
+++ b/data/templates/default.slidy
@@ -20,7 +20,6 @@
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
       span.underline{text-decoration: underline;}
-      div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
 $if(quotes)$
       q { quotes: "“" "”" "‘" "’"; }
diff --git a/man/pandoc.1 b/man/pandoc.1
--- a/man/pandoc.1
+++ b/man/pandoc.1
@@ -1,5 +1,5 @@
 .\"t
-.TH PANDOC 1 "December 8, 2017" "pandoc 2.0.5"
+.TH PANDOC 1 "December 27, 2017" "pandoc 2.0.6"
 .SH NAME
 pandoc - general markup converter
 .SH SYNOPSIS
@@ -12,16 +12,16 @@
 It can read Markdown, CommonMark, PHP Markdown Extra, GitHub\-Flavored
 Markdown, MultiMarkdown, and (subsets of) Textile, reStructuredText,
 HTML, LaTeX, MediaWiki markup, TWiki markup, TikiWiki markup, Creole
-1.0, Haddock markup, OPML, Emacs Org mode, DocBook, Muse, txt2tags,
-Vimwiki, EPUB, ODT, and Word docx; and it can write plain text,
-Markdown, CommonMark, PHP Markdown Extra, GitHub\-Flavored Markdown,
-MultiMarkdown, reStructuredText, XHTML, HTML5, LaTeX (including
-\f[C]beamer\f[] slide shows), ConTeXt, RTF, OPML, DocBook, OpenDocument,
-ODT, Word docx, GNU Texinfo, MediaWiki markup, DokuWiki markup, ZimWiki
-markup, Haddock markup, EPUB (v2 or v3), FictionBook2, Textile, groff
-man, groff ms, Emacs Org mode, AsciiDoc, InDesign ICML, TEI Simple,
-Muse, PowerPoint slide shows and Slidy, Slideous, DZSlides, reveal.js or
-S5 HTML slide shows.
+1.0, Haddock markup, OPML, Emacs Org mode, DocBook, JATS, Muse,
+txt2tags, Vimwiki, EPUB, ODT, and Word docx; and it can write plain
+text, Markdown, CommonMark, PHP Markdown Extra, GitHub\-Flavored
+Markdown, MultiMarkdown, reStructuredText, XHTML, HTML5, LaTeX
+(including \f[C]beamer\f[] slide shows), ConTeXt, RTF, OPML, DocBook,
+JATS, OpenDocument, ODT, Word docx, GNU Texinfo, MediaWiki markup,
+DokuWiki markup, ZimWiki markup, Haddock markup, EPUB (v2 or v3),
+FictionBook2, Textile, groff man, groff ms, Emacs Org mode, AsciiDoc,
+InDesign ICML, TEI Simple, Muse, PowerPoint slide shows and Slidy,
+Slideous, DZSlides, reveal.js or S5 HTML slide shows.
 It can also produce PDF output on systems where LaTeX, ConTeXt,
 \f[C]pdfroff\f[], \f[C]wkhtmltopdf\f[], \f[C]prince\f[], or
 \f[C]weasyprint\f[] is installed.
@@ -242,19 +242,10 @@
 1.0), \f[C]haddock\f[] (Haddock markup), or \f[C]latex\f[] (LaTeX).
 (\f[C]markdown_github\f[] provides deprecated and less accurate support
 for Github\-Flavored Markdown; please use \f[C]gfm\f[] instead, unless
-you need to use extensions other than \f[C]smart\f[].) If \f[C]+lhs\f[]
-is appended to \f[C]markdown\f[], \f[C]rst\f[], \f[C]latex\f[], or
-\f[C]html\f[], the input will be treated as literate Haskell source: see
-Literate Haskell support, below.
-Markdown syntax extensions can be individually enabled or disabled by
-appending \f[C]+EXTENSION\f[] or \f[C]\-EXTENSION\f[] to the format
-name.
-So, for example, \f[C]markdown_strict+footnotes+definition_lists\f[] is
-strict Markdown with footnotes and definition lists enabled, and
-\f[C]markdown\-pipe_tables+hard_line_breaks\f[] is pandoc\[aq]s Markdown
-without pipe tables and with hard line breaks.
-See Pandoc\[aq]s Markdown, below, for a list of extensions and their
-names.
+you need to use extensions other than \f[C]smart\f[].) Extensions can be
+individually enabled or disabled by appending \f[C]+EXTENSION\f[] or
+\f[C]\-EXTENSION\f[] to the format name.
+See Extensions below, for a list of extensions and their names.
 See \f[C]\-\-list\-input\-formats\f[] and \f[C]\-\-list\-extensions\f[],
 below.
 .RS
@@ -295,13 +286,9 @@
 \f[C]odt\f[], \f[C]epub\f[], and \f[C]epub3\f[] output will not be
 directed to \f[I]stdout\f[]; an output filename must be specified using
 the \f[C]\-o/\-\-output\f[] option.
-If \f[C]+lhs\f[] is appended to \f[C]markdown\f[], \f[C]rst\f[],
-\f[C]latex\f[], \f[C]beamer\f[], \f[C]html4\f[], or \f[C]html5\f[], the
-output will be rendered as literate Haskell source: see Literate Haskell
-support, below.
-Markdown syntax extensions can be individually enabled or disabled by
-appending \f[C]+EXTENSION\f[] or \f[C]\-EXTENSION\f[] to the format
-name, as described above under \f[C]\-f\f[].
+Extensions can be individually enabled or disabled by appending
+\f[C]+EXTENSION\f[] or \f[C]\-EXTENSION\f[] to the format name.
+See Extensions below, for a list of extensions and their names.
 See \f[C]\-\-list\-output\-formats\f[] and
 \f[C]\-\-list\-extensions\f[], below.
 .RS
@@ -398,10 +385,12 @@
 .RS
 .RE
 .TP
-.B \f[C]\-\-list\-extensions\f[]
-List supported Markdown extensions, one per line, followed by a
+.B \f[C]\-\-list\-extensions\f[][\f[C]=\f[]\f[I]FORMAT\f[]]
+List supported Markdown extensions, one per line, preceded by a
 \f[C]+\f[] or \f[C]\-\f[] indicating whether it is enabled by default in
-pandoc\[aq]s Markdown.
+\f[I]FORMAT\f[].
+If \f[I]FORMAT\f[] is not specified, defaults for pandoc\[aq]s Markdown
+are given.
 .RS
 .RE
 .TP
@@ -951,9 +940,9 @@
 .RE
 .TP
 .B \f[C]\-\-section\-divs\f[]
-Wrap sections in \f[C]<div>\f[] tags (or \f[C]<section>\f[] tags in
-HTML5), and attach identifiers to the enclosing \f[C]<div>\f[] (or
-\f[C]<section>\f[]) rather than the header itself.
+Wrap sections in \f[C]<section>\f[] tags (or \f[C]<div>\f[] tags for
+\f[C]html4\f[]), and attach identifiers to the enclosing
+\f[C]<section>\f[] (or \f[C]<div>\f[]) rather than the header itself.
 See Header identifiers, below.
 .RS
 .RE
@@ -2035,6 +2024,336 @@
 .PP
 Templates may contain comments: anything on a line after \f[C]$\-\-\f[]
 will be treated as a comment and ignored.
+.SH EXTENSIONS
+.PP
+The behavior of some of the readers and writers can be adjusted by
+enabling or disabling various extensions.
+.PP
+An extension can be enabled by adding \f[C]+EXTENSION\f[] to the format
+name and disabled by adding \f[C]\-EXTENSION\f[].
+For example, \f[C]\-\-from\ markdown_strict+footnotes\f[] is strict
+Markdown with footnotes enabled, while
+\f[C]\-\-from\ markdown\-footnotes\-pipe_tables\f[] is pandoc\[aq]s
+Markdown without footnotes or pipe tables.
+.PP
+The markdown reader and writer make by far the most use of extensions.
+Extensions only used by them are therefore covered in the section
+Pandoc\[aq]s Markdown below (See Markdown variants for
+\f[C]commonmark\f[] and \f[C]gfm\f[].) In the following, extensions that
+also work for other formats are covered.
+.SS Typography
+.SS Extension: \f[C]smart\f[]
+.PP
+Interpret straight quotes as curly quotes, \f[C]\-\-\-\f[] as
+em\-dashes, \f[C]\-\-\f[] as en\-dashes, and \f[C]\&...\f[] as ellipses.
+Nonbreaking spaces are inserted after certain abbreviations, such as
+"Mr."
+.PP
+This extension can be enabled/disabled for the following formats:
+.TP
+.B input formats
+\f[C]markdown\f[], \f[C]commonmark\f[], \f[C]latex\f[],
+\f[C]mediawiki\f[], \f[C]org\f[], \f[C]rst\f[], \f[C]twiki\f[]
+.RS
+.RE
+.TP
+.B output formats
+\f[C]markdown\f[], \f[C]latex\f[], \f[C]context\f[], \f[C]rst\f[]
+.RS
+.RE
+.TP
+.B enabled by default in
+\f[C]markdown\f[], \f[C]latex\f[], \f[C]context\f[] (both input and
+output)
+.RS
+.RE
+.PP
+Note: If you are \f[I]writing\f[] Markdown, then the \f[C]smart\f[]
+extension has the reverse effect: what would have been curly quotes
+comes out straight.
+.PP
+In LaTeX, \f[C]smart\f[] means to use the standard TeX ligatures for
+quotation marks (\f[C]``\f[] and \f[C]\[aq]\[aq]\f[] for double quotes,
+\f[C]`\f[] and \f[C]\[aq]\f[] for single quotes) and dashes
+(\f[C]\-\-\f[] for en\-dash and \f[C]\-\-\-\f[] for em\-dash).
+If \f[C]smart\f[] is disabled, then in reading LaTeX pandoc will parse
+these characters literally.
+In writing LaTeX, enabling \f[C]smart\f[] tells pandoc to use the
+ligatures when possible; if \f[C]smart\f[] is disabled pandoc will use
+unicode quotation mark and dash characters.
+.SS Headers and sections
+.SS Extension: \f[C]auto_identifiers\f[]
+.PP
+A header without an explicitly specified identifier will be
+automatically assigned a unique identifier based on the header text.
+.PP
+This extension can be enabled/disabled for the following formats:
+.TP
+.B input formats
+\f[C]markdown\f[], \f[C]latex\f[], \f[C]rst\f[], \f[C]mediawiki\f[],
+\f[C]textile\f[]
+.RS
+.RE
+.TP
+.B output formats
+\f[C]markdown\f[], \f[C]muse\f[]
+.RS
+.RE
+.TP
+.B enabled by default in
+\f[C]markdown\f[], \f[C]muse\f[]
+.RS
+.RE
+.PP
+The algorithm used to derive the identifier from the header text is:
+.IP \[bu] 2
+Remove all formatting, links, etc.
+.IP \[bu] 2
+Remove all footnotes.
+.IP \[bu] 2
+Remove all punctuation, except underscores, hyphens, and periods.
+.IP \[bu] 2
+Replace all spaces and newlines with hyphens.
+.IP \[bu] 2
+Convert all alphabetic characters to lowercase.
+.IP \[bu] 2
+Remove everything up to the first letter (identifiers may not begin with
+a number or punctuation mark).
+.IP \[bu] 2
+If nothing is left after this, use the identifier \f[C]section\f[].
+.PP
+Thus, for example,
+.PP
+.TS
+tab(@);
+l l.
+T{
+Header
+T}@T{
+Identifier
+T}
+_
+T{
+\f[C]Header\ identifiers\ in\ HTML\f[]
+T}@T{
+\f[C]header\-identifiers\-in\-html\f[]
+T}
+T{
+\f[C]*Dogs*?\-\-in\ *my*\ house?\f[]
+T}@T{
+\f[C]dogs\-\-in\-my\-house\f[]
+T}
+T{
+\f[C][HTML],\ [S5],\ or\ [RTF]?\f[]
+T}@T{
+\f[C]html\-s5\-or\-rtf\f[]
+T}
+T{
+\f[C]3.\ Applications\f[]
+T}@T{
+\f[C]applications\f[]
+T}
+T{
+\f[C]33\f[]
+T}@T{
+\f[C]section\f[]
+T}
+.TE
+.PP
+These rules should, in most cases, allow one to determine the identifier
+from the header text.
+The exception is when several headers have the same text; in this case,
+the first will get an identifier as described above; the second will get
+the same identifier with \f[C]\-1\f[] appended; the third with
+\f[C]\-2\f[]; and so on.
+.PP
+These identifiers are used to provide link targets in the table of
+contents generated by the \f[C]\-\-toc|\-\-table\-of\-contents\f[]
+option.
+They also make it easy to provide links from one section of a document
+to another.
+A link to this section, for example, might look like this:
+.IP
+.nf
+\f[C]
+See\ the\ section\ on
+[header\ identifiers](#header\-identifiers\-in\-html\-latex\-and\-context).
+\f[]
+.fi
+.PP
+Note, however, that this method of providing links to sections works
+only in HTML, LaTeX, and ConTeXt formats.
+.PP
+If the \f[C]\-\-section\-divs\f[] option is specified, then each section
+will be wrapped in a \f[C]section\f[] (or a \f[C]div\f[], if
+\f[C]html4\f[] was specified), and the identifier will be attached to
+the enclosing \f[C]<section>\f[] (or \f[C]<div>\f[]) tag rather than the
+header itself.
+This allows entire sections to be manipulated using JavaScript or
+treated differently in CSS.
+.SS Extension: \f[C]ascii_identifiers\f[]
+.PP
+Causes the identifiers produced by \f[C]auto_identifiers\f[] to be pure
+ASCII.
+Accents are stripped off of accented Latin letters, and non\-Latin
+letters are omitted.
+.SS Math Input
+.PP
+The extensions \f[C]tex_math_dollars\f[],
+\f[C]tex_math_single_backslash\f[], and
+\f[C]tex_math_double_backslash\f[] are described in the section about
+Pandoc\[aq]s Markdown.
+.PP
+However, they can also be used with HTML input.
+This is handy for reading web pages formatted using MathJax, for
+example.
+.SS Raw HTML/TeX
+.PP
+The following extensions (especially how they affect Markdown
+input/output) are also described in more detail in their respective
+sections of Pandoc\[aq]s Markdown.
+.SS Extension: \f[C]raw_html\f[]
+.PP
+When converting from HTML, parse elements to raw HTML which are not
+representable in pandoc\[aq]s AST.
+By default, this is disabled for HTML input.
+.SS Extension: \f[C]raw_tex\f[]
+.PP
+Allows raw LaTeX, TeX, and ConTeXt to be included in a document.
+.PP
+This extension can be enabled/disabled for the following formats (in
+addition to \f[C]markdown\f[]):
+.TP
+.B input formats
+\f[C]latex\f[], \f[C]org\f[], \f[C]textile\f[]
+.RS
+.RE
+.TP
+.B output formats
+\f[C]textile\f[]
+.RS
+.RE
+.SS Extension: \f[C]native_divs\f[]
+.PP
+This extension is enabled by default for HTML input.
+This means that \f[C]div\f[]s are parsed to pandoc native elements.
+(Alternatively, you can parse them to raw HTML using
+\f[C]\-f\ html\-native_divs+raw_html\f[].)
+.PP
+When converting HTML to Markdown, for example, you may want to drop all
+\f[C]div\f[]s and \f[C]span\f[]s:
+.IP
+.nf
+\f[C]
+pandoc\ \-f\ html\-native_divs\-native_spans\ \-t\ markdown
+\f[]
+.fi
+.SS Extension: \f[C]native_spans\f[]
+.PP
+Analogous to \f[C]native_divs\f[] above.
+.SS Literate Haskell support
+.SS Extension: \f[C]literate_haskell\f[]
+.PP
+Treat the document as literate Haskell source.
+.PP
+This extension can be enabled/disabled for the following formats:
+.TP
+.B input formats
+\f[C]markdown\f[], \f[C]rst\f[], \f[C]latex\f[]
+.RS
+.RE
+.TP
+.B output formats
+\f[C]markdown\f[], \f[C]rst\f[], \f[C]latex\f[], \f[C]html\f[]
+.RS
+.RE
+.PP
+If you append \f[C]+lhs\f[] (or \f[C]+literate_haskell\f[]) to one of
+the formats above, pandoc will treat the document as literate Haskell
+source.
+This means that
+.IP \[bu] 2
+In Markdown input, "bird track" sections will be parsed as Haskell code
+rather than block quotations.
+Text between \f[C]\\begin{code}\f[] and \f[C]\\end{code}\f[] will also
+be treated as Haskell code.
+For ATX\-style headers the character \[aq]=\[aq] will be used instead of
+\[aq]#\[aq].
+.IP \[bu] 2
+In Markdown output, code blocks with classes \f[C]haskell\f[] and
+\f[C]literate\f[] will be rendered using bird tracks, and block
+quotations will be indented one space, so they will not be treated as
+Haskell code.
+In addition, headers will be rendered setext\-style (with underlines)
+rather than ATX\-style (with \[aq]#\[aq] characters).
+(This is because ghc treats \[aq]#\[aq] characters in column 1 as
+introducing line numbers.)
+.IP \[bu] 2
+In restructured text input, "bird track" sections will be parsed as
+Haskell code.
+.IP \[bu] 2
+In restructured text output, code blocks with class \f[C]haskell\f[]
+will be rendered using bird tracks.
+.IP \[bu] 2
+In LaTeX input, text in \f[C]code\f[] environments will be parsed as
+Haskell code.
+.IP \[bu] 2
+In LaTeX output, code blocks with class \f[C]haskell\f[] will be
+rendered inside \f[C]code\f[] environments.
+.IP \[bu] 2
+In HTML output, code blocks with class \f[C]haskell\f[] will be rendered
+with class \f[C]literatehaskell\f[] and bird tracks.
+.PP
+Examples:
+.IP
+.nf
+\f[C]
+pandoc\ \-f\ markdown+lhs\ \-t\ html
+\f[]
+.fi
+.PP
+reads literate Haskell source formatted with Markdown conventions and
+writes ordinary HTML (without bird tracks).
+.IP
+.nf
+\f[C]
+pandoc\ \-f\ markdown+lhs\ \-t\ html+lhs
+\f[]
+.fi
+.PP
+writes HTML with the Haskell code in bird tracks, so it can be copied
+and pasted as literate Haskell source.
+.PP
+Note that GHC expects the bird tracks in the first column, so indentend
+literate code blocks (e.g.
+inside an itemized environment) will not be picked up by the Haskell
+compiler.
+.SS Other extensions
+.SS Extension: \f[C]empty_paragraphs\f[]
+.PP
+Allows empty paragraphs.
+By default empty paragraphs are omitted.
+.PP
+This extension can be enabled/disabled for the following formats:
+.TP
+.B input formats
+\f[C]docx\f[], \f[C]html\f[]
+.RS
+.RE
+.TP
+.B output formats
+\f[C]markdown\f[], \f[C]docx\f[], \f[C]odt\f[], \f[C]opendocument\f[],
+\f[C]html\f[]
+.RS
+.RE
+.SS Extension: \f[C]amuse\f[]
+.PP
+In the \f[C]muse\f[] input format, this enables Text::Amuse extensions
+to Emacs Muse markup.
+.SS Extension: \f[C]citations\f[]
+.PP
+Some aspects of Pandoc\[aq]s Markdown citation syntax are also accepted
+in \f[C]org\f[] input.
 .SH PANDOC\[aq]S MARKDOWN
 .PP
 Pandoc understands an extended and slightly revised version of John
@@ -2043,11 +2362,11 @@
 Markdown.
 Except where noted, these differences can be suppressed by using the
 \f[C]markdown_strict\f[] format instead of \f[C]markdown\f[].
-An extensions can be enabled by adding \f[C]+EXTENSION\f[] to the format
-name and disabled by adding \f[C]\-EXTENSION\f[].
-For example, \f[C]markdown_strict+footnotes\f[] is strict Markdown with
-footnotes enabled, while \f[C]markdown\-footnotes\-pipe_tables\f[] is
-pandoc\[aq]s Markdown without footnotes or pipe tables.
+Extensions can be enabled or disabled to specify the behavior more
+granularly.
+They are described in the following.
+See also Extensions above, for extensions that work also on other
+formats.
 .SS Philosophy
 .PP
 Markdown is designed to be easy to write, and, even more importantly,
@@ -2149,6 +2468,8 @@
 \f[C]#5\ bolt\f[] and \f[C]#hashtag\f[] count as headers.
 With this extension, pandoc does require the space.
 .SS Header identifiers
+.PP
+See also the \f[C]auto_identifiers\f[] extension above.
 .SS Extension: \f[C]header_attributes\f[]
 .PP
 Headers can be assigned attributes using this syntax at the end of the
@@ -2203,96 +2524,6 @@
 #\ My\ header\ {.unnumbered}
 \f[]
 .fi
-.SS Extension: \f[C]auto_identifiers\f[]
-.PP
-A header without an explicitly specified identifier will be
-automatically assigned a unique identifier based on the header text.
-To derive the identifier from the header text,
-.IP \[bu] 2
-Remove all formatting, links, etc.
-.IP \[bu] 2
-Remove all footnotes.
-.IP \[bu] 2
-Remove all punctuation, except underscores, hyphens, and periods.
-.IP \[bu] 2
-Replace all spaces and newlines with hyphens.
-.IP \[bu] 2
-Convert all alphabetic characters to lowercase.
-.IP \[bu] 2
-Remove everything up to the first letter (identifiers may not begin with
-a number or punctuation mark).
-.IP \[bu] 2
-If nothing is left after this, use the identifier \f[C]section\f[].
-.PP
-Thus, for example,
-.PP
-.TS
-tab(@);
-l l.
-T{
-Header
-T}@T{
-Identifier
-T}
-_
-T{
-\f[C]Header\ identifiers\ in\ HTML\f[]
-T}@T{
-\f[C]header\-identifiers\-in\-html\f[]
-T}
-T{
-\f[C]*Dogs*?\-\-in\ *my*\ house?\f[]
-T}@T{
-\f[C]dogs\-\-in\-my\-house\f[]
-T}
-T{
-\f[C][HTML],\ [S5],\ or\ [RTF]?\f[]
-T}@T{
-\f[C]html\-s5\-or\-rtf\f[]
-T}
-T{
-\f[C]3.\ Applications\f[]
-T}@T{
-\f[C]applications\f[]
-T}
-T{
-\f[C]33\f[]
-T}@T{
-\f[C]section\f[]
-T}
-.TE
-.PP
-These rules should, in most cases, allow one to determine the identifier
-from the header text.
-The exception is when several headers have the same text; in this case,
-the first will get an identifier as described above; the second will get
-the same identifier with \f[C]\-1\f[] appended; the third with
-\f[C]\-2\f[]; and so on.
-.PP
-These identifiers are used to provide link targets in the table of
-contents generated by the \f[C]\-\-toc|\-\-table\-of\-contents\f[]
-option.
-They also make it easy to provide links from one section of a document
-to another.
-A link to this section, for example, might look like this:
-.IP
-.nf
-\f[C]
-See\ the\ section\ on
-[header\ identifiers](#header\-identifiers\-in\-html\-latex\-and\-context).
-\f[]
-.fi
-.PP
-Note, however, that this method of providing links to sections works
-only in HTML, LaTeX, and ConTeXt formats.
-.PP
-If the \f[C]\-\-section\-divs\f[] option is specified, then each section
-will be wrapped in a \f[C]div\f[] (or a \f[C]section\f[], if
-\f[C]html5\f[] was specified), and the identifier will be attached to
-the enclosing \f[C]<div>\f[] (or \f[C]<section>\f[]) tag rather than the
-header itself.
-This allows entire sections to be manipulated using JavaScript or
-treated differently in CSS.
 .SS Extension: \f[C]implicit_header_references\f[]
 .PP
 Pandoc behaves as if reference links have been defined for each header.
@@ -2911,6 +3142,13 @@
 .PP
 The label can be any string of alphanumeric characters, underscores, or
 hyphens.
+.PP
+Note: continuation paragraphs in example lists must always be indented
+four spaces, regardless of the length of the list marker.
+That is, example lists always behave as if the \f[C]four_space_rule\f[]
+extension is set.
+This is because example labels tend to be long, and indenting content to
+the first non\-space character after the label would be awkward.
 .SS Compact and loose lists
 .PP
 Pandoc behaves differently from \f[C]Markdown.pl\f[] on some "edge
@@ -3756,9 +3994,6 @@
 Therefore see Math rendering in HTML above.
 .RS
 .RE
-.PP
-This extension can be used with both \f[C]markdown\f[] and \f[C]html\f[]
-input.
 .SS Raw HTML
 .SS Extension: \f[C]raw_html\f[]
 .PP
@@ -3951,9 +4186,9 @@
 .SS LaTeX macros
 .SS Extension: \f[C]latex_macros\f[]
 .PP
-For output formats other than LaTeX, pandoc will parse LaTeX
-\f[C]\\newcommand\f[] and \f[C]\\renewcommand\f[] definitions and apply
-the resulting macros to all LaTeX math.
+For output formats other than LaTeX, pandoc will parse LaTeX macro
+definitions and apply the resulting macros to all LaTeX math and raw
+LaTeX.
 So, for example, the following will work in all output formats, not just
 LaTeX:
 .IP
@@ -3965,8 +4200,13 @@
 \f[]
 .fi
 .PP
-In LaTeX output, the \f[C]\\newcommand\f[] definition will simply be
-passed unchanged to the output.
+In LaTeX output, the macro definitions will not be passed through as raw
+LaTeX.
+.PP
+When \f[C]latex_macros\f[] is disabled, the macro definitions will be
+passed through as raw LaTeX, and the raw LaTeX and math will not have
+macros applied.
+This is usually a better approach when you are targeting LaTeX or PDF.
 .SS Links
 .PP
 Markdown allows links to be specified in several ways.
@@ -4288,30 +4528,6 @@
 .fi
 .PP
 Inline and regular footnotes may be mixed freely.
-.SS Typography
-.SS Extension: \f[C]smart\f[]
-.PP
-Interpret straight quotes as curly quotes, \f[C]\-\-\-\f[] as
-em\-dashes, \f[C]\-\-\f[] as en\-dashes, and \f[C]\&...\f[] as ellipses.
-Nonbreaking spaces are inserted after certain abbreviations, such as
-"Mr." This option currently affects the input formats \f[C]markdown\f[],
-\f[C]commonmark\f[], \f[C]latex\f[], \f[C]mediawiki\f[], \f[C]org\f[],
-\f[C]rst\f[], and \f[C]twiki\f[], and the output formats
-\f[C]markdown\f[], \f[C]latex\f[], and \f[C]context\f[].
-.PP
-Note: If you are \f[I]writing\f[] Markdown, then the \f[C]smart\f[]
-extension has the reverse effect: what would have been curly quotes
-comes out straight.
-.PP
-In LaTeX, \f[C]smart\f[] means to use the standard TeX ligatures for
-quotation marks (\f[C]``\f[] and \f[C]\[aq]\[aq]\f[] for double quotes,
-\f[C]`\f[] and \f[C]\[aq]\f[] for single quotes) and dashes
-(\f[C]\-\-\f[] for en\-dash and \f[C]\-\-\-\f[] for em\-dash).
-If \f[C]smart\f[] is disabled, then in reading LaTeX pandoc will parse
-these characters literally.
-In writing LaTeX, enabling \f[C]smart\f[] tells pandoc to use the
-ligatures when possible; if \f[C]smart\f[] is disabled pandoc will use
-unicode quotation mark and dash characters.
 .SS Citations
 .SS Extension: \f[C]citations\f[]
 .PP
@@ -4675,9 +4891,6 @@
 to be interpreted as display TeX math.
 Note: a drawback of this extension is that it precludes escaping
 \f[C](\f[] and \f[C][\f[].
-.PP
-This extension can be used with both \f[C]markdown\f[] and \f[C]html\f[]
-input.
 .SS Extension: \f[C]tex_math_double_backslash\f[]
 .PP
 Causes anything between \f[C]\\\\(\f[] and \f[C]\\\\)\f[] to be
@@ -4725,12 +4938,6 @@
 .PP
 Makes all absolute URIs into links, even when not surrounded by pointy
 braces \f[C]<...>\f[].
-.SS Extension: \f[C]ascii_identifiers\f[]
-.PP
-Causes the identifiers produced by \f[C]auto_identifiers\f[] to be pure
-ASCII.
-Accents are stripped off of accented Latin letters, and non\-Latin
-letters are omitted.
 .SS Extension: \f[C]mmd_link_attributes\f[]
 .PP
 Parses multimarkdown style key\-value attributes on link and image
@@ -4765,13 +4972,6 @@
 .IP \[bu] 2
 Lazy wrapping of paragraphs is not allowed: the entire definition must
 be indented four spaces.
-.SS Extension: \f[C]empty_paragraphs\f[]
-.PP
-Allows empty paragraphs.
-By default empty paragraphs are omitted.
-This affects the \f[C]docx\f[] reader and writer, the
-\f[C]opendocument\f[] and \f[C]odt\f[] writer, and all HTML\-based
-readers and writers.
 .SS Markdown variants
 .PP
 In addition to pandoc\[aq]s extended Markdown, the following Markdown
@@ -4817,37 +5017,26 @@
 .RS
 .RE
 .PP
-We also support \f[C]gfm\f[] (GitHub\-Flavored Markdown) as a set of
-extensions on \f[C]commonmark\f[]:
+We also support \f[C]commonmark\f[] and \f[C]gfm\f[] (GitHub\-Flavored
+Markdown, which is implemented as a set of extensions on
+\f[C]commonmark\f[]).
 .PP
-: \f[C]pipe_tables\f[], \f[C]raw_html\f[], \f[C]fenced_code_blocks\f[],
+Note, however, that \f[C]commonmark\f[] and \f[C]gfm\f[] have limited
+support for extensions.
+Only those listed below (and \f[C]smart\f[] and \f[C]raw_tex\f[]) will
+work.
+The extensions can, however, all be individually disabled.
+Also, \f[C]raw_tex\f[] only affects \f[C]gfm\f[] output, not input.
+.TP
+.B \f[C]gfm\f[] (GitHub\-Flavored Markdown)
+\f[C]pipe_tables\f[], \f[C]raw_html\f[], \f[C]fenced_code_blocks\f[],
 \f[C]auto_identifiers\f[], \f[C]ascii_identifiers\f[],
 \f[C]backtick_code_blocks\f[], \f[C]autolink_bare_uris\f[],
 \f[C]intraword_underscores\f[], \f[C]strikeout\f[],
 \f[C]hard_line_breaks\f[], \f[C]emoji\f[],
 \f[C]shortcut_reference_links\f[], \f[C]angle_brackets_escapable\f[].
-.IP
-.nf
-\f[C]
-These\ can\ all\ be\ individually\ disabled.\ Note,\ however,\ that
-`commonmark`\ and\ `gfm`\ have\ limited\ support\ for\ extensions:
-extensions\ other\ than\ those\ listed\ above\ (and\ `smart`\ and
-`raw_tex`)\ will\ have\ no\ effect\ on\ `commonmark`\ or\ `gfm`.
-And\ `raw_tex`\ only\ affects\ `gfm`\ output,\ not\ input.
-\f[]
-.fi
-.SS Extensions with formats other than Markdown
-.PP
-Some of the extensions discussed above can be used with formats other
-than Markdown:
-.IP \[bu] 2
-\f[C]auto_identifiers\f[] can be used with \f[C]latex\f[], \f[C]rst\f[],
-\f[C]mediawiki\f[], and \f[C]textile\f[] input (and is used by default).
-.IP \[bu] 2
-\f[C]tex_math_dollars\f[], \f[C]tex_math_single_backslash\f[], and
-\f[C]tex_math_double_backslash\f[] can be used with \f[C]html\f[] input.
-(This is handy for reading web pages formatted using MathJax, for
-example.)
+.RS
+.RE
 .SH PRODUCING SLIDE SHOWS WITH PANDOC
 .PP
 You can use pandoc to produce an HTML + JavaScript slide presentation
@@ -5299,70 +5488,6 @@
 </audio>
 \f[]
 .fi
-.SH LITERATE HASKELL SUPPORT
-.PP
-If you append \f[C]+lhs\f[] (or \f[C]+literate_haskell\f[]) to an
-appropriate input or output format (\f[C]markdown\f[],
-\f[C]markdown_strict\f[], \f[C]rst\f[], or \f[C]latex\f[] for input or
-output; \f[C]beamer\f[], \f[C]html4\f[] or \f[C]html5\f[] for output
-only), pandoc will treat the document as literate Haskell source.
-This means that
-.IP \[bu] 2
-In Markdown input, "bird track" sections will be parsed as Haskell code
-rather than block quotations.
-Text between \f[C]\\begin{code}\f[] and \f[C]\\end{code}\f[] will also
-be treated as Haskell code.
-For ATX\-style headers the character \[aq]=\[aq] will be used instead of
-\[aq]#\[aq].
-.IP \[bu] 2
-In Markdown output, code blocks with classes \f[C]haskell\f[] and
-\f[C]literate\f[] will be rendered using bird tracks, and block
-quotations will be indented one space, so they will not be treated as
-Haskell code.
-In addition, headers will be rendered setext\-style (with underlines)
-rather than ATX\-style (with \[aq]#\[aq] characters).
-(This is because ghc treats \[aq]#\[aq] characters in column 1 as
-introducing line numbers.)
-.IP \[bu] 2
-In restructured text input, "bird track" sections will be parsed as
-Haskell code.
-.IP \[bu] 2
-In restructured text output, code blocks with class \f[C]haskell\f[]
-will be rendered using bird tracks.
-.IP \[bu] 2
-In LaTeX input, text in \f[C]code\f[] environments will be parsed as
-Haskell code.
-.IP \[bu] 2
-In LaTeX output, code blocks with class \f[C]haskell\f[] will be
-rendered inside \f[C]code\f[] environments.
-.IP \[bu] 2
-In HTML output, code blocks with class \f[C]haskell\f[] will be rendered
-with class \f[C]literatehaskell\f[] and bird tracks.
-.PP
-Examples:
-.IP
-.nf
-\f[C]
-pandoc\ \-f\ markdown+lhs\ \-t\ html
-\f[]
-.fi
-.PP
-reads literate Haskell source formatted with Markdown conventions and
-writes ordinary HTML (without bird tracks).
-.IP
-.nf
-\f[C]
-pandoc\ \-f\ markdown+lhs\ \-t\ html+lhs
-\f[]
-.fi
-.PP
-writes HTML with the Haskell code in bird tracks, so it can be copied
-and pasted as literate Haskell source.
-.PP
-Note that GHC expects the bird tracks in the first column, so indentend
-literate code blocks (e.g.
-inside an itemized environment) will not be picked up by the Haskell
-compiler.
 .SH SYNTAX HIGHLIGHTING
 .PP
 Pandoc will automatically highlight syntax in fenced code blocks that
@@ -5395,26 +5520,26 @@
 If you define a \f[C]div\f[] or \f[C]span\f[] with the attribute
 \f[C]custom\-style\f[], pandoc will apply your specified style to the
 contained elements.
-So, for example,
+So, for example using the \f[C]bracketed_spans\f[] syntax,
 .IP
 .nf
 \f[C]
-<span\ custom\-style="Emphatically">Get\ out,</span>\ he\ said.
+[Get\ out]{custom\-style="Emphatically"},\ he\ said.
 \f[]
 .fi
 .PP
-would produce a docx file with "Get out," styled with character style
+would produce a docx file with "Get out" styled with character style
 \f[C]Emphatically\f[].
-Similarly,
+Similarly, using the \f[C]fenced_divs\f[] syntax,
 .IP
 .nf
 \f[C]
 Dickinson\ starts\ the\ poem\ simply:
 
-<div\ custom\-style="Poetry">
+:::\ {custom\-style="Poetry"}
 |\ A\ Bird\ came\ down\ the\ Walk\-\-\-
 |\ He\ did\ not\ know\ I\ saw\-\-\-
-</div>
+:::
 \f[]
 .fi
 .PP
diff --git a/pandoc.cabal b/pandoc.cabal
--- a/pandoc.cabal
+++ b/pandoc.cabal
@@ -1,5 +1,5 @@
 name:            pandoc
-version:         2.0.5
+version:         2.0.6
 cabal-version:   >= 1.10
 build-type:      Custom
 license:         GPL
@@ -16,7 +16,7 @@
 description:     Pandoc is a Haskell library for converting from one markup
                  format to another, and a command-line tool that uses
                  this library. It can read several dialects of Markdown and
-                 (subsets of) HTML, reStructuredText, LaTeX, DocBook,
+                 (subsets of) HTML, reStructuredText, LaTeX, DocBook, JATS,
                  MediaWiki markup, TWiki markup, TikiWiki markup, Creole 1.0,
                  Haddock markup, OPML, Emacs Org-Mode, Emacs Muse, txt2tags,
                  Vimwiki, Word Docx, ODT, and Textile, and it can write
@@ -81,6 +81,7 @@
                  data/docx/docProps/core.xml
                  data/docx/word/document.xml
                  data/docx/word/fontTable.xml
+                 data/docx/word/comments.xml
                  data/docx/word/footnotes.xml
                  data/docx/word/numbering.xml
                  data/docx/word/settings.xml
@@ -104,28 +105,28 @@
                  data/pptx/docProps/thumbnail.jpeg
                  data/pptx/docProps/app.xml
                  data/pptx/docProps/core.xml
-                 data/pptx/ppt/slideLayouts/slideLayout4.xml
-                 data/pptx/ppt/slideLayouts/_rels/slideLayout9.xml.rels
-                 data/pptx/ppt/slideLayouts/_rels/slideLayout2.xml.rels
-                 data/pptx/ppt/slideLayouts/_rels/slideLayout10.xml.rels
                  data/pptx/ppt/slideLayouts/_rels/slideLayout1.xml.rels
+                 data/pptx/ppt/slideLayouts/_rels/slideLayout2.xml.rels
                  data/pptx/ppt/slideLayouts/_rels/slideLayout3.xml.rels
+                 data/pptx/ppt/slideLayouts/_rels/slideLayout4.xml.rels
                  data/pptx/ppt/slideLayouts/_rels/slideLayout5.xml.rels
+                 data/pptx/ppt/slideLayouts/_rels/slideLayout6.xml.rels
                  data/pptx/ppt/slideLayouts/_rels/slideLayout7.xml.rels
                  data/pptx/ppt/slideLayouts/_rels/slideLayout8.xml.rels
+                 data/pptx/ppt/slideLayouts/_rels/slideLayout9.xml.rels
+                 data/pptx/ppt/slideLayouts/_rels/slideLayout10.xml.rels
                  data/pptx/ppt/slideLayouts/_rels/slideLayout11.xml.rels
-                 data/pptx/ppt/slideLayouts/_rels/slideLayout4.xml.rels
-                 data/pptx/ppt/slideLayouts/_rels/slideLayout6.xml.rels
+                 data/pptx/ppt/slideLayouts/slideLayout1.xml
                  data/pptx/ppt/slideLayouts/slideLayout2.xml
-                 data/pptx/ppt/slideLayouts/slideLayout8.xml
-                 data/pptx/ppt/slideLayouts/slideLayout11.xml
                  data/pptx/ppt/slideLayouts/slideLayout3.xml
-                 data/pptx/ppt/slideLayouts/slideLayout6.xml
-                 data/pptx/ppt/slideLayouts/slideLayout9.xml
+                 data/pptx/ppt/slideLayouts/slideLayout4.xml
                  data/pptx/ppt/slideLayouts/slideLayout5.xml
+                 data/pptx/ppt/slideLayouts/slideLayout6.xml
                  data/pptx/ppt/slideLayouts/slideLayout7.xml
-                 data/pptx/ppt/slideLayouts/slideLayout1.xml
+                 data/pptx/ppt/slideLayouts/slideLayout8.xml
+                 data/pptx/ppt/slideLayouts/slideLayout9.xml
                  data/pptx/ppt/slideLayouts/slideLayout10.xml
+                 data/pptx/ppt/slideLayouts/slideLayout11.xml
                  data/pptx/ppt/_rels/presentation.xml.rels
                  data/pptx/ppt/theme/theme1.xml
                  data/pptx/ppt/presProps.xml
@@ -155,8 +156,6 @@
                  data/pandoc.lua
                  -- lua List module
                  data/pandoc.List.lua
-                 -- sample highlighting theme
-                 data/default.theme
                  -- bash completion template
                  data/bash_completion.tpl
                  -- jats csl
@@ -214,6 +213,7 @@
                  test/creole-reader.txt
                  test/creole-reader.native
                  test/rst-reader.rst
+                 test/jats-reader.xml
                  test/s5-basic.html
                  test/s5-fancy.html
                  test/s5-fragment.html
@@ -245,6 +245,7 @@
                  test/tables.txt
                  test/tables.fb2
                  test/tables.muse
+                 test/tables.custom
                  test/testsuite.txt
                  test/writer.latex
                  test/writer.context
@@ -273,6 +274,7 @@
                  test/writer.dokuwiki
                  test/writer.zimwiki
                  test/writer.muse
+                 test/writer.custom
                  test/writers-lang-and-dir.latex
                  test/writers-lang-and-dir.context
                  test/dokuwiki_inline_formatting.dokuwiki
@@ -436,6 +438,7 @@
                    Text.Pandoc.Readers.RST,
                    Text.Pandoc.Readers.Org,
                    Text.Pandoc.Readers.DocBook,
+                   Text.Pandoc.Readers.JATS,
                    Text.Pandoc.Readers.OPML,
                    Text.Pandoc.Readers.Textile,
                    Text.Pandoc.Readers.Native,
@@ -523,9 +526,12 @@
                    Text.Pandoc.Readers.Org.ParserState,
                    Text.Pandoc.Readers.Org.Parsing,
                    Text.Pandoc.Readers.Org.Shared,
-                   Text.Pandoc.Lua.Packages,
-                   Text.Pandoc.Lua.PandocModule,
                    Text.Pandoc.Lua.Filter,
+                   Text.Pandoc.Lua.Init,
+                   Text.Pandoc.Lua.Module.MediaBag,
+                   Text.Pandoc.Lua.Module.Pandoc,
+                   Text.Pandoc.Lua.Module.Utils,
+                   Text.Pandoc.Lua.Packages,
                    Text.Pandoc.Lua.StackInstances,
                    Text.Pandoc.Lua.Util,
                    Text.Pandoc.CSS,
@@ -600,7 +606,9 @@
                   pandoc,
                   pandoc-types >= 1.17.3 && < 1.18,
                   bytestring >= 0.9 && < 0.11,
+                  base64-bytestring >= 0.1 && < 1.1,
                   text >= 0.11 && < 1.3,
+                  time >= 1.5 && < 1.9,
                   directory >= 1 && < 1.4,
                   filepath >= 1.1 && < 1.5,
                   hslua >= 0.9 && < 0.10,
@@ -615,6 +623,11 @@
                   containers >= 0.4.2.1 && < 0.6,
                   executable-path >= 0.0 && < 0.1,
                   zip-archive >= 0.2.3.4 && < 0.4
+  if flag(old-locale)
+     build-depends: old-locale >= 1 && < 1.1,
+                    time >= 1.2 && < 1.5
+  else
+     build-depends: time >= 1.5 && < 1.9
   other-modules:  Tests.Old
                   Tests.Command
                   Tests.Helpers
@@ -622,8 +635,21 @@
                   Tests.Shared
                   Tests.Readers.LaTeX
                   Tests.Readers.HTML
+                  Tests.Readers.JATS
                   Tests.Readers.Markdown
                   Tests.Readers.Org
+                  Tests.Readers.Org.Block
+                  Tests.Readers.Org.Block.CodeBlock
+                  Tests.Readers.Org.Block.Figure
+                  Tests.Readers.Org.Block.Header
+                  Tests.Readers.Org.Block.List
+                  Tests.Readers.Org.Block.Table
+                  Tests.Readers.Org.Directive
+                  Tests.Readers.Org.Inline
+                  Tests.Readers.Org.Inline.Note
+                  Tests.Readers.Org.Inline.Smart
+                  Tests.Readers.Org.Meta
+                  Tests.Readers.Org.Shared
                   Tests.Readers.RST
                   Tests.Readers.Docx
                   Tests.Readers.Odt
@@ -635,6 +661,7 @@
                   Tests.Writers.ConTeXt
                   Tests.Writers.Docbook
                   Tests.Writers.HTML
+                  Tests.Writers.JATS
                   Tests.Writers.Markdown
                   Tests.Writers.Org
                   Tests.Writers.Plain
@@ -645,6 +672,7 @@
                   Tests.Writers.TEI
                   Tests.Writers.Muse
                   Tests.Writers.FB2
+                  Tests.Writers.Powerpoint
   ghc-options:  -rtsopts -Wall -fno-warn-unused-do-bind -threaded
   default-language: Haskell98
 
diff --git a/src/Text/Pandoc/App.hs b/src/Text/Pandoc/App.hs
--- a/src/Text/Pandoc/App.hs
+++ b/src/Text/Pandoc/App.hs
@@ -58,6 +58,9 @@
 import qualified Data.Set as Set
 import Data.Text (Text)
 import qualified Data.Text as T
+import qualified Data.Text.Lazy as TL
+import qualified Data.Text.Lazy.Encoding as TE
+import qualified Data.Text.Encoding.Error as TE
 import Data.Yaml (decode)
 import qualified Data.Yaml as Yaml
 import GHC.Generics
@@ -143,7 +146,7 @@
                  -> IO (String, Maybe String) -- ^ IO (writerName, maybePdfEngineProg)
 pdfWriterAndProg mWriter mEngine = do
   let panErr msg = liftIO $ E.throwIO $ PandocAppError msg
-  case go (baseWriterName <$> mWriter) mEngine of
+  case go mWriter mEngine of
       Right (writ, prog) -> return (writ, Just prog)
       Left err           -> panErr err
     where
@@ -151,7 +154,7 @@
       go (Just writer) Nothing = (writer,) <$> engineForWriter writer
       go Nothing (Just engine) = (,engine) <$> writerForEngine engine
       go (Just writer) (Just engine) =
-           case find (== (writer, engine)) engines of
+           case find (== (baseWriterName writer, engine)) engines of
                 Just _  -> Right (writer, engine)
                 Nothing -> Left $ "pdf-engine " ++ engine ++
                            " is not compatible with output format " ++ writer
@@ -161,7 +164,7 @@
                                  []      -> Left $
                                    "pdf-engine " ++ eng ++ " not known"
 
-      engineForWriter w = case [e |  (f,e) <- engines, f == w] of
+      engineForWriter w = case [e |  (f,e) <- engines, f == baseWriterName w] of
                                 eng : _ -> Right eng
                                 []      -> Left $
                                    "cannot produce pdf output from " ++ w
@@ -223,7 +226,7 @@
             if ".lua" `isSuffixOf` format
                -- note:  use non-lowercased version writerName
                then return (TextWriter
-                       (\o d -> liftIO $ writeCustom writerName o d)
+                       (\o d -> writeCustom writerName o d)
                                :: Writer PandocIO, mempty)
                else case getWriter writerName of
                          Left e  -> E.throwIO $ PandocAppError $
@@ -513,7 +516,9 @@
                 case res of
                      Right pdf -> writeFnBinary outputFile pdf
                      Left err' -> liftIO $
-                       E.throwIO $ PandocPDFError (UTF8.toStringLazy err')
+                       E.throwIO $ PandocPDFError $
+                                     TL.unpack (TE.decodeUtf8With TE.lenientDecode err')
+
         Nothing -> do
                 let htmlFormat = format `elem`
                       ["html","html4","html5","s5","slidy",
@@ -538,7 +543,7 @@
 type Transform = Pandoc -> Pandoc
 
 isTextFormat :: String -> Bool
-isTextFormat s = s `notElem` ["odt","docx","epub2","epub3","epub"]
+isTextFormat s = s `notElem` ["odt","docx","epub2","epub3","epub","pptx"]
 
 externalFilter :: MonadIO m
                => ReaderOptions -> FilePath -> [String] -> Pandoc -> m Pandoc
@@ -846,7 +851,7 @@
 applyLuaFilters mbDatadir filters format d = do
   expandedFilters <- mapM (expandFilterPath mbDatadir) filters
   let go f d' = do
-        res <- runLuaFilter mbDatadir f format d'
+        res <- runLuaFilter f format d'
         case res of
           Right x               -> return x
           Left (LuaException s) -> E.throw (PandocFilterError f s)
@@ -1584,15 +1589,16 @@
                  ""
 
     , Option "" ["list-extensions"]
-                 (NoArg
-                  (\_ -> do
-                     let showExt x = drop 4 (show x) ++
-                                       if extensionEnabled x pandocExtensions
-                                          then " +"
-                                          else " -"
+                 (OptArg
+                  (\arg _ -> do
+                     let exts = getDefaultExtensions (fromMaybe "markdown" arg)
+                     let showExt x = (if extensionEnabled x exts
+                                         then '+'
+                                         else '-') : drop 4 (show x)
                      mapM_ (UTF8.hPutStrLn stdout . showExt)
                                ([minBound..maxBound] :: [Extension])
-                     exitSuccess ))
+                     exitSuccess )
+                  "FORMAT")
                  ""
 
     , Option "" ["list-highlight-languages"]
diff --git a/src/Text/Pandoc/Class.hs b/src/Text/Pandoc/Class.hs
--- a/src/Text/Pandoc/Class.hs
+++ b/src/Text/Pandoc/Class.hs
@@ -81,6 +81,7 @@
                          , FileTree(..)
                          , FileInfo(..)
                          , addToFileTree
+                         , insertInFileTree
                          , runIO
                          , runIOorExplode
                          , runPure
@@ -144,6 +145,8 @@
 import System.FilePath ((</>), (<.>), takeDirectory,
          takeExtension, dropExtension, isRelative, normalise)
 import qualified System.FilePath.Glob as IO (glob)
+import qualified System.FilePath.Posix as Posix
+import System.FilePath (splitDirectories)
 import qualified System.Directory as IO (getModificationTime)
 import Control.Monad as M (fail)
 import Control.Monad.State.Strict
@@ -160,8 +163,6 @@
 import qualified Debug.Trace
 #ifdef EMBED_DATA_FILES
 import Text.Pandoc.Data (dataFiles)
-import qualified System.FilePath.Posix as Posix
-import System.FilePath (splitDirectories)
 #else
 import qualified Paths_pandoc as Paths
 #endif
@@ -453,7 +454,7 @@
 runIO ma = flip evalStateT def $ runExceptT $ unPandocIO ma
 
 -- | Evaluate a 'PandocIO' operation, handling any errors
--- by exiting with an appropriate message and error status. 
+-- by exiting with an appropriate message and error status.
 runIOorExplode :: PandocIO a -> IO a
 runIOorExplode ma = runIO ma >>= handleError
 
@@ -620,6 +621,7 @@
                "word/document.xml",
                "word/fontTable.xml",
                "word/footnotes.xml",
+               "word/comments.xml",
                "word/numbering.xml",
                "word/settings.xml",
                "word/webSettings.xml",
@@ -686,8 +688,6 @@
               , "ppt/presProps.xml"
               , "ppt/presentation.xml"
               , "ppt/slideLayouts/_rels/slideLayout1.xml.rels"
-              , "ppt/slideLayouts/_rels/slideLayout10.xml.rels"
-              , "ppt/slideLayouts/_rels/slideLayout11.xml.rels"
               , "ppt/slideLayouts/_rels/slideLayout2.xml.rels"
               , "ppt/slideLayouts/_rels/slideLayout3.xml.rels"
               , "ppt/slideLayouts/_rels/slideLayout4.xml.rels"
@@ -696,6 +696,8 @@
               , "ppt/slideLayouts/_rels/slideLayout7.xml.rels"
               , "ppt/slideLayouts/_rels/slideLayout8.xml.rels"
               , "ppt/slideLayouts/_rels/slideLayout9.xml.rels"
+              , "ppt/slideLayouts/_rels/slideLayout10.xml.rels"
+              , "ppt/slideLayouts/_rels/slideLayout11.xml.rels"
               , "ppt/slideLayouts/slideLayout1.xml"
               , "ppt/slideLayouts/slideLayout10.xml"
               , "ppt/slideLayouts/slideLayout11.xml"
@@ -711,6 +713,8 @@
               , "ppt/slideMasters/slideMaster1.xml"
               , "ppt/slides/_rels/slide1.xml.rels"
               , "ppt/slides/slide1.xml"
+              , "ppt/slides/_rels/slide2.xml.rels"
+              , "ppt/slides/slide2.xml"
               , "ppt/tableStyles.xml"
               , "ppt/theme/theme1.xml"
               , "ppt/viewProps.xml"
@@ -720,7 +724,7 @@
         epochtime <- (floor . utcTimeToPOSIXSeconds) <$> getCurrentTime
         contents <- toLazy <$> readDataFile ("pptx/" ++ path)
         return $ toEntry path epochtime contents
-  datadir <- getUserDataDir        
+  datadir <- getUserDataDir
   mbArchive <- case datadir of
                     Nothing   -> return Nothing
                     Just d    -> do
@@ -732,8 +736,8 @@
      Just arch -> toArchive <$> readFileLazy arch
      Nothing   -> foldr addEntryToArchive emptyArchive <$>
                      mapM pathToEntry paths
-                     
 
+
 -- | Read file from user data directory or,
 -- if not found there, from Cabal data directory.
 readDataFile :: PandocMonad m => FilePath -> m B.ByteString
@@ -760,11 +764,6 @@
   case lookup (makeCanonical fname) dataFiles of
     Nothing       -> throwError $ PandocCouldNotFindDataFileError fname
     Just contents -> return contents
-  where makeCanonical = Posix.joinPath . transformPathParts . splitDirectories
-        transformPathParts = reverse . foldl go []
-        go as     "."  = as
-        go (_:as) ".." = as
-        go as     x    = x : as
 #else
   getDataFileName fname' >>= checkExistence >>= readFileStrict
     where fname' = if fname == "MANUAL.txt" then fname else "data" </> fname
@@ -777,6 +776,13 @@
      else throwError $ PandocCouldNotFindDataFileError fn
 #endif
 
+makeCanonical :: FilePath -> FilePath
+makeCanonical = Posix.joinPath . transformPathParts . splitDirectories
+ where  transformPathParts = reverse . foldl go []
+        go as     "."  = as
+        go (_:as) ".." = as
+        go as     x    = x : as
+
 withPaths :: PandocMonad m => [FilePath] -> (FilePath -> m a) -> FilePath -> m a
 withPaths [] _ fp = throwError $ PandocResourceNotFound fp
 withPaths (p:ps) action fp =
@@ -912,12 +918,13 @@
   deriving (Monoid)
 
 getFileInfo :: FilePath -> FileTree -> Maybe FileInfo
-getFileInfo fp tree = M.lookup fp $ unFileTree tree
+getFileInfo fp tree =
+  M.lookup (makeCanonical fp) (unFileTree tree)
 
 -- | Add the specified file to the FileTree. If file
 -- is a directory, add its contents recursively.
 addToFileTree :: FileTree -> FilePath -> IO FileTree
-addToFileTree (FileTree treemap) fp = do
+addToFileTree tree fp = do
   isdir <- doesDirectoryExist fp
   if isdir
      then do -- recursively add contents of directories
@@ -925,13 +932,17 @@
            isSpecial "."  = True
            isSpecial _    = False
        fs <- (map (fp </>) . filter (not . isSpecial)) <$> getDirectoryContents fp
-       foldM addToFileTree (FileTree treemap) fs
+       foldM addToFileTree tree fs
      else do
        contents <- B.readFile fp
        mtime <- IO.getModificationTime fp
-       return $ FileTree $
-                M.insert fp FileInfo{ infoFileMTime = mtime
-                                    , infoFileContents = contents } treemap
+       return $ insertInFileTree fp FileInfo{ infoFileMTime = mtime
+                                            , infoFileContents = contents } tree
+
+-- | Insert an ersatz file into the 'FileTree'.
+insertInFileTree :: FilePath -> FileInfo -> FileTree -> FileTree
+insertInFileTree fp info (FileTree treemap) =
+  FileTree $ M.insert (makeCanonical fp) info treemap
 
 newtype PandocPure a = PandocPure {
   unPandocPure :: ExceptT PandocError
diff --git a/src/Text/Pandoc/Data.hs b/src/Text/Pandoc/Data.hs
--- a/src/Text/Pandoc/Data.hs
+++ b/src/Text/Pandoc/Data.hs
@@ -18,5 +18,5 @@
              -- handle the hidden file separately, since embedDir doesn't
              -- include it:
              ("docx/_rels/.rels", $(embedFile "data/docx/_rels/.rels")) :
-             ("pptx/_rels/.rels", $(embedFile "data/pptx/_rels/.rels")) :             
+             ("pptx/_rels/.rels", $(embedFile "data/pptx/_rels/.rels")) :
              $(embedDir "data")
diff --git a/src/Text/Pandoc/Extensions.hs b/src/Text/Pandoc/Extensions.hs
--- a/src/Text/Pandoc/Extensions.hs
+++ b/src/Text/Pandoc/Extensions.hs
@@ -80,79 +80,79 @@
 
 -- | Individually selectable syntax extensions.
 data Extension =
-      Ext_footnotes           -- ^ Pandoc/PHP/MMD style footnotes
-    | Ext_inline_notes        -- ^ Pandoc-style inline notes
-    | Ext_pandoc_title_block  -- ^ Pandoc title block
-    | Ext_yaml_metadata_block -- ^ YAML metadata block
-    | Ext_mmd_title_block     -- ^ Multimarkdown metadata block
-    | Ext_table_captions      -- ^ Pandoc-style table captions
-    | Ext_implicit_figures    -- ^ A paragraph with just an image is a figure
-    | Ext_simple_tables       -- ^ Pandoc-style simple tables
-    | Ext_multiline_tables    -- ^ Pandoc-style multiline tables
-    | Ext_grid_tables         -- ^ Grid tables (pandoc, reST)
-    | Ext_pipe_tables         -- ^ Pipe tables (as in PHP markdown extra)
-    | Ext_citations           -- ^ Pandoc/citeproc citations
-    | Ext_raw_tex             -- ^ Allow raw TeX (other than math)
-    | Ext_raw_html            -- ^ Allow raw HTML
-    | Ext_tex_math_dollars    -- ^ TeX math between $..$ or $$..$$
-    | Ext_tex_math_single_backslash  -- ^ TeX math btw \(..\) \[..\]
-    | Ext_tex_math_double_backslash  -- ^ TeX math btw \\(..\\) \\[..\\]
-    | Ext_latex_macros        -- ^ Parse LaTeX macro definitions (for math only)
-    | Ext_fenced_code_blocks  -- ^ Parse fenced code blocks
-    | Ext_fenced_code_attributes  -- ^ Allow attributes on fenced code blocks
-    | Ext_backtick_code_blocks    -- ^ GitHub style ``` code blocks
-    | Ext_inline_code_attributes  -- ^ Allow attributes on inline code
-    | Ext_raw_attribute           -- ^ Allow explicit raw blocks/inlines
-    | Ext_markdown_in_html_blocks -- ^ Interpret as markdown inside HTML blocks
-    | Ext_native_divs             -- ^ Use Div blocks for contents of <div> tags
-    | Ext_fenced_divs             -- ^ Allow fenced div syntax :::
-    | Ext_native_spans            -- ^ Use Span inlines for contents of <span>
-    | Ext_bracketed_spans         -- ^ Bracketed spans with attributes
-    | Ext_markdown_attribute      -- ^ Interpret text inside HTML as markdown
-                                  --   iff container has attribute 'markdown'
-    | Ext_escaped_line_breaks     -- ^ Treat a backslash at EOL as linebreak
-    | Ext_link_attributes         -- ^ link and image attributes
-    | Ext_mmd_link_attributes     -- ^ MMD style reference link attributes
-    | Ext_autolink_bare_uris  -- ^ Make all absolute URIs into links
-    | Ext_fancy_lists         -- ^ Enable fancy list numbers and delimiters
-    | Ext_lists_without_preceding_blankline -- ^ Allow lists without preceding blank
-    | Ext_four_space_rule     -- ^ Require 4-space indent for list contents
-    | Ext_startnum            -- ^ Make start number of ordered list significant
-    | Ext_definition_lists    -- ^ Definition lists as in pandoc, mmd, php
-    | Ext_compact_definition_lists  -- ^ Definition lists without
-                               -- space between items, and disallow laziness
-    | Ext_example_lists       -- ^ Markdown-style numbered examples
+      Ext_abbreviations       -- ^ PHP markdown extra abbreviation definitions
     | Ext_all_symbols_escapable  -- ^ Make all non-alphanumerics escapable
+    | Ext_amuse -- ^ Enable Text::Amuse extensions to Emacs Muse markup
     | Ext_angle_brackets_escapable  -- ^ Make < and > escapable
-    | Ext_intraword_underscores  -- ^ Treat underscore inside word as literal
+    | Ext_ascii_identifiers   -- ^ ascii-only identifiers for headers
+    | Ext_auto_identifiers    -- ^ Automatic identifiers for headers
+    | Ext_autolink_bare_uris  -- ^ Make all absolute URIs into links
+    | Ext_backtick_code_blocks    -- ^ GitHub style ``` code blocks
     | Ext_blank_before_blockquote -- ^ Require blank line before a blockquote
     | Ext_blank_before_header     -- ^ Require blank line before a header
-    | Ext_space_in_atx_header -- ^ Require space between # and header text
-    | Ext_strikeout           -- ^ Strikeout using ~~this~~ syntax
-    | Ext_superscript         -- ^ Superscript using ^this^ syntax
-    | Ext_subscript           -- ^ Subscript using ~this~ syntax
-    | Ext_hard_line_breaks    -- ^ All newlines become hard line breaks
-    | Ext_ignore_line_breaks  -- ^ Newlines in paragraphs are ignored
+    | Ext_bracketed_spans         -- ^ Bracketed spans with attributes
+    | Ext_citations           -- ^ Pandoc/citeproc citations
+    | Ext_compact_definition_lists  -- ^ Definition lists without space between items,
+                                    --   and disallow laziness
+    | Ext_definition_lists    -- ^ Definition lists as in pandoc, mmd, php
     | Ext_east_asian_line_breaks  -- ^ Newlines in paragraphs are ignored between
-                              -- East Asian wide characters
-    | Ext_literate_haskell    -- ^ Enable literate Haskell conventions
-    | Ext_abbreviations       -- ^ PHP markdown extra abbreviation definitions
+                                  --   East Asian wide characters
     | Ext_emoji               -- ^ Support emoji like :smile:
-    | Ext_auto_identifiers    -- ^ Automatic identifiers for headers
-    | Ext_gfm_auto_identifiers  -- ^ Automatic identifiers for headers,
-                                -- using GitHub's method for generating identifiers
-    | Ext_ascii_identifiers   -- ^ ascii-only identifiers for headers
+    | Ext_empty_paragraphs -- ^ Allow empty paragraphs
+    | Ext_epub_html_exts      -- ^ Recognise the EPUB extended version of HTML
+    | Ext_escaped_line_breaks     -- ^ Treat a backslash at EOL as linebreak
+    | Ext_example_lists       -- ^ Markdown-style numbered examples
+    | Ext_fancy_lists         -- ^ Enable fancy list numbers and delimiters
+    | Ext_fenced_code_attributes  -- ^ Allow attributes on fenced code blocks
+    | Ext_fenced_code_blocks  -- ^ Parse fenced code blocks
+    | Ext_fenced_divs             -- ^ Allow fenced div syntax :::
+    | Ext_footnotes           -- ^ Pandoc/PHP/MMD style footnotes
+    | Ext_four_space_rule     -- ^ Require 4-space indent for list contents
+    | Ext_gfm_auto_identifiers  -- ^ Automatic identifiers for headers, using
+                                --  GitHub's method for generating identifiers
+    | Ext_grid_tables         -- ^ Grid tables (pandoc, reST)
+    | Ext_hard_line_breaks    -- ^ All newlines become hard line breaks
     | Ext_header_attributes   -- ^ Explicit header attributes {#id .class k=v}
-    | Ext_mmd_header_identifiers -- ^ Multimarkdown style header identifiers [myid]
+    | Ext_ignore_line_breaks  -- ^ Newlines in paragraphs are ignored
+    | Ext_implicit_figures    -- ^ A paragraph with just an image is a figure
     | Ext_implicit_header_references -- ^ Implicit reference links for headers
+    | Ext_inline_code_attributes  -- ^ Allow attributes on inline code
+    | Ext_inline_notes        -- ^ Pandoc-style inline notes
+    | Ext_intraword_underscores  -- ^ Treat underscore inside word as literal
+    | Ext_latex_macros        -- ^ Parse LaTeX macro definitions (for math only)
     | Ext_line_blocks         -- ^ RST style line blocks
-    | Ext_epub_html_exts      -- ^ Recognise the EPUB extended version of HTML
+    | Ext_link_attributes         -- ^ link and image attributes
+    | Ext_lists_without_preceding_blankline -- ^ Allow lists without preceding blank
+    | Ext_literate_haskell    -- ^ Enable literate Haskell conventions
+    | Ext_markdown_attribute      -- ^ Interpret text inside HTML as markdown iff
+                                  --   container has attribute 'markdown'
+    | Ext_markdown_in_html_blocks -- ^ Interpret as markdown inside HTML blocks
+    | Ext_mmd_header_identifiers -- ^ Multimarkdown style header identifiers [myid]
+    | Ext_mmd_link_attributes     -- ^ MMD style reference link attributes
+    | Ext_mmd_title_block     -- ^ Multimarkdown metadata block
+    | Ext_multiline_tables    -- ^ Pandoc-style multiline tables
+    | Ext_native_divs             -- ^ Use Div blocks for contents of <div> tags
+    | Ext_native_spans            -- ^ Use Span inlines for contents of <span>
+    | Ext_old_dashes          -- ^ -- = em, - before number = en
+    | Ext_pandoc_title_block  -- ^ Pandoc title block
+    | Ext_pipe_tables         -- ^ Pipe tables (as in PHP markdown extra)
+    | Ext_raw_attribute           -- ^ Allow explicit raw blocks/inlines
+    | Ext_raw_html            -- ^ Allow raw HTML
+    | Ext_raw_tex             -- ^ Allow raw TeX (other than math)
     | Ext_shortcut_reference_links -- ^ Shortcut reference links
+    | Ext_simple_tables       -- ^ Pandoc-style simple tables
     | Ext_smart               -- ^ "Smart" quotes, apostrophes, ellipses, dashes
-    | Ext_old_dashes          -- ^ -- = em, - before number = en
+    | Ext_space_in_atx_header -- ^ Require space between # and header text
     | Ext_spaced_reference_links -- ^ Allow space between two parts of ref link
-    | Ext_amuse -- ^ Enable Text::Amuse extensions to Emacs Muse markup
-    | Ext_empty_paragraphs -- ^ Allow empty paragraphs
+    | Ext_startnum            -- ^ Make start number of ordered list significant
+    | Ext_strikeout           -- ^ Strikeout using ~~this~~ syntax
+    | Ext_subscript           -- ^ Subscript using ~this~ syntax
+    | Ext_superscript         -- ^ Superscript using ^this^ syntax
+    | Ext_table_captions      -- ^ Pandoc-style table captions
+    | Ext_tex_math_dollars    -- ^ TeX math between $..$ or $$..$$
+    | Ext_tex_math_double_backslash  -- ^ TeX math btw \\(..\\) \\[..\\]
+    | Ext_tex_math_single_backslash  -- ^ TeX math btw \(..\) \[..\]
+    | Ext_yaml_metadata_block -- ^ YAML metadata block
     deriving (Show, Read, Enum, Eq, Ord, Bounded, Data, Typeable, Generic)
 
 -- | Extensions to be used with pandoc-flavored markdown.
@@ -321,6 +321,7 @@
 getDefaultExtensions "html"            = extensionsFromList
                                           [Ext_auto_identifiers,
                                            Ext_native_divs,
+                                           Ext_line_blocks,
                                            Ext_native_spans]
 getDefaultExtensions "html4"           = getDefaultExtensions "html"
 getDefaultExtensions "html5"           = getDefaultExtensions "html"
@@ -343,6 +344,7 @@
                                            Ext_smart,
                                            Ext_raw_html,
                                            Ext_auto_identifiers]
+getDefaultExtensions "opml"            = pandocExtensions -- affects notes
 getDefaultExtensions _                 = extensionsFromList
                                           [Ext_auto_identifiers]
 
diff --git a/src/Text/Pandoc/Lua.hs b/src/Text/Pandoc/Lua.hs
--- a/src/Text/Pandoc/Lua.hs
+++ b/src/Text/Pandoc/Lua.hs
@@ -1,9 +1,3 @@
-{-# LANGUAGE CPP                   #-}
-{-# LANGUAGE FlexibleContexts      #-}
-{-# LANGUAGE FlexibleInstances     #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE ScopedTypeVariables   #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
 {-
 Copyright © 2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
 
@@ -29,48 +23,36 @@
    Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
    Stability   : alpha
 
-Pandoc lua utils.
+Running pandoc Lua filters.
 -}
 module Text.Pandoc.Lua
   ( LuaException (..)
-  , LuaPackageParams (..)
-  , pushPandocModule
   , runLuaFilter
-  , initLuaState
-  , luaPackageParams
+  , runPandocLua
+  , pushPandocModule
   ) where
 
 import Control.Monad (when, (>=>))
-import Control.Monad.Identity (Identity)
-import Control.Monad.Trans (MonadIO (..))
-import Data.IORef (newIORef, readIORef)
 import Foreign.Lua (FromLuaStack (peek), Lua, LuaException (..),
                     Status (OK), ToLuaStack (push))
-import Text.Pandoc.Class (PandocIO, getCommonState, getMediaBag, setMediaBag)
-import Text.Pandoc.Definition
+import Text.Pandoc.Class (PandocIO)
+import Text.Pandoc.Definition (Pandoc)
 import Text.Pandoc.Lua.Filter (LuaFilter, walkMWithLuaFilter)
-import Text.Pandoc.Lua.Packages (LuaPackageParams (..),
-                                 installPandocPackageSearcher)
-import Text.Pandoc.Lua.PandocModule (pushPandocModule) -- TODO: remove
-import Text.Pandoc.Lua.Util (loadScriptFromDataDir)
+import Text.Pandoc.Lua.Init (runPandocLua)
+import Text.Pandoc.Lua.Module.Pandoc (pushModule) -- TODO: remove
 import qualified Foreign.Lua as Lua
-import qualified Foreign.Lua.Module.Text as Lua
 
-runLuaFilter :: Maybe FilePath -> FilePath -> String
+-- | Run the Lua filter in @filterPath@ for a transformation to target
+-- format @format@. Pandoc uses Lua init files to setup the Lua
+-- interpreter.
+runLuaFilter :: FilePath -> String
              -> Pandoc -> PandocIO (Either LuaException Pandoc)
-runLuaFilter datadir filterPath format pd = do
-  luaPkgParams <- luaPackageParams datadir
-  res <- liftIO . Lua.runLuaEither $
-         runLuaFilter' luaPkgParams filterPath format pd
-  newMediaBag <- liftIO (readIORef (luaPkgMediaBag luaPkgParams))
-  setMediaBag newMediaBag
-  return res
+runLuaFilter filterPath format doc =
+  runPandocLua (runLuaFilter' filterPath format doc)
 
-runLuaFilter' :: LuaPackageParams
-              -> FilePath -> String
+runLuaFilter' :: FilePath -> String
               -> Pandoc -> Lua Pandoc
-runLuaFilter' luaPkgOpts filterPath format pd = do
-  initLuaState luaPkgOpts
+runLuaFilter' filterPath format pd = do
   -- store module in global "pandoc"
   registerFormat
   top <- Lua.gettop
@@ -90,24 +72,6 @@
     push format
     Lua.setglobal "FORMAT"
 
-luaPackageParams :: Maybe FilePath -> PandocIO LuaPackageParams
-luaPackageParams datadir = do
-  commonState <- getCommonState
-  mbRef <- liftIO . newIORef =<< getMediaBag
-  return LuaPackageParams
-    { luaPkgCommonState = commonState
-    , luaPkgDataDir = datadir
-    , luaPkgMediaBag = mbRef
-    }
-
--- Initialize the lua state with all required values
-initLuaState :: LuaPackageParams -> Lua ()
-initLuaState luaPkgParams = do
-  Lua.openlibs
-  Lua.preloadTextModule "text"
-  installPandocPackageSearcher luaPkgParams
-  loadScriptFromDataDir (luaPkgDataDir luaPkgParams) "init.lua"
-
 pushGlobalFilter :: Lua ()
 pushGlobalFilter = do
   Lua.newtable
@@ -118,5 +82,6 @@
 runAll :: [LuaFilter] -> Pandoc -> Lua Pandoc
 runAll = foldr ((>=>) . walkMWithLuaFilter) return
 
-instance (FromLuaStack a) => FromLuaStack (Identity a) where
-  peek = fmap return . peek
+-- | DEPRECATED: Push the pandoc module to the Lua Stack.
+pushPandocModule :: Maybe FilePath -> Lua Lua.NumResults
+pushPandocModule = pushModule
diff --git a/src/Text/Pandoc/Lua/Init.hs b/src/Text/Pandoc/Lua/Init.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/Lua/Init.hs
@@ -0,0 +1,79 @@
+{-
+Copyright © 2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+-}
+{- |
+   Module      : Text.Pandoc.Lua
+   Copyright   : Copyright © 2017 Albert Krewinkel
+   License     : GNU GPL, version 2 or above
+
+   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
+   Stability   : alpha
+
+Functions to initialize the Lua interpreter.
+-}
+module Text.Pandoc.Lua.Init
+  ( LuaException (..)
+  , LuaPackageParams (..)
+  , runPandocLua
+  , initLuaState
+  , luaPackageParams
+  ) where
+
+import Control.Monad.Trans (MonadIO (..))
+import Data.IORef (newIORef, readIORef)
+import Foreign.Lua (Lua, LuaException (..))
+import GHC.IO.Encoding (getForeignEncoding, setForeignEncoding, utf8)
+import Text.Pandoc.Class (PandocIO, getCommonState, getUserDataDir, getMediaBag,
+                          setMediaBag)
+import Text.Pandoc.Lua.Packages (LuaPackageParams (..),
+                                 installPandocPackageSearcher)
+import Text.Pandoc.Lua.Util (loadScriptFromDataDir)
+
+import qualified Foreign.Lua as Lua
+import qualified Foreign.Lua.Module.Text as Lua
+
+-- | Run the lua interpreter, using pandoc's default way of environment
+-- initalization.
+runPandocLua :: Lua a -> PandocIO (Either LuaException a)
+runPandocLua luaOp = do
+  luaPkgParams <- luaPackageParams
+  enc <- liftIO $ getForeignEncoding <* setForeignEncoding utf8
+  res <- liftIO $ Lua.runLuaEither (initLuaState luaPkgParams *> luaOp)
+  liftIO $ setForeignEncoding enc
+  newMediaBag <- liftIO (readIORef (luaPkgMediaBag luaPkgParams))
+  setMediaBag newMediaBag
+  return res
+
+-- | Generate parameters required to setup pandoc's lua environment.
+luaPackageParams :: PandocIO LuaPackageParams
+luaPackageParams = do
+  commonState <- getCommonState
+  datadir <- getUserDataDir
+  mbRef <- liftIO . newIORef =<< getMediaBag
+  return LuaPackageParams
+    { luaPkgCommonState = commonState
+    , luaPkgDataDir = datadir
+    , luaPkgMediaBag = mbRef
+    }
+
+-- Initialize the lua state with all required values
+initLuaState :: LuaPackageParams -> Lua ()
+initLuaState luaPkgParams = do
+  Lua.openlibs
+  Lua.preloadTextModule "text"
+  installPandocPackageSearcher luaPkgParams
+  loadScriptFromDataDir (luaPkgDataDir luaPkgParams) "init.lua"
diff --git a/src/Text/Pandoc/Lua/Module/MediaBag.hs b/src/Text/Pandoc/Lua/Module/MediaBag.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/Lua/Module/MediaBag.hs
@@ -0,0 +1,108 @@
+{-
+Copyright © 2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+-}
+{- |
+   Module      : Text.Pandoc.Lua.Module.MediaBag
+   Copyright   : Copyright © 2017 Albert Krewinkel
+   License     : GNU GPL, version 2 or above
+
+   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
+   Stability   : alpha
+
+The lua module @pandoc.mediabag@.
+-}
+module Text.Pandoc.Lua.Module.MediaBag
+  ( pushModule
+  ) where
+
+import Control.Monad (zipWithM_)
+import Data.IORef (IORef, modifyIORef', readIORef)
+import Data.Maybe (fromMaybe)
+import Foreign.Lua (Lua, NumResults, liftIO)
+import Text.Pandoc.Class (CommonState (..), fetchItem, putCommonState,
+                          runIOorExplode, setMediaBag)
+import Text.Pandoc.Lua.StackInstances ()
+import Text.Pandoc.Lua.Util (OrNil (toMaybe), addFunction)
+import Text.Pandoc.MIME (MimeType)
+
+import qualified Data.ByteString.Lazy as BL
+import qualified Foreign.Lua as Lua
+import qualified Text.Pandoc.MediaBag as MB
+
+--
+-- MediaBag submodule
+--
+pushModule :: CommonState -> IORef MB.MediaBag -> Lua NumResults
+pushModule commonState mediaBagRef = do
+  Lua.newtable
+  addFunction "insert" (insertMediaFn mediaBagRef)
+  addFunction "lookup" (lookupMediaFn mediaBagRef)
+  addFunction "list" (mediaDirectoryFn mediaBagRef)
+  addFunction "fetch" (fetch commonState mediaBagRef)
+  return 1
+
+insertMediaFn :: IORef MB.MediaBag
+              -> FilePath
+              -> OrNil MimeType
+              -> BL.ByteString
+              -> Lua NumResults
+insertMediaFn mbRef fp nilOrMime contents = do
+  liftIO . modifyIORef' mbRef $
+    MB.insertMedia fp (toMaybe nilOrMime) contents
+  return 0
+
+lookupMediaFn :: IORef MB.MediaBag
+              -> FilePath
+              -> Lua NumResults
+lookupMediaFn mbRef fp = do
+  res <- MB.lookupMedia fp <$> liftIO (readIORef mbRef)
+  case res of
+    Nothing -> Lua.pushnil *> return 1
+    Just (mimeType, contents) -> do
+      Lua.push mimeType
+      Lua.push contents
+      return 2
+
+mediaDirectoryFn :: IORef MB.MediaBag
+                 -> Lua NumResults
+mediaDirectoryFn mbRef = do
+  dirContents <- MB.mediaDirectory <$> liftIO (readIORef mbRef)
+  Lua.newtable
+  zipWithM_ addEntry [1..] dirContents
+  return 1
+ where
+  addEntry :: Int -> (FilePath, MimeType, Int) -> Lua ()
+  addEntry idx (fp, mimeType, contentLength) = do
+    Lua.newtable
+    Lua.push "path" *> Lua.push fp *> Lua.rawset (-3)
+    Lua.push "type" *> Lua.push mimeType *> Lua.rawset (-3)
+    Lua.push "length" *> Lua.push contentLength *> Lua.rawset (-3)
+    Lua.rawseti (-2) idx
+
+fetch :: CommonState
+      -> IORef MB.MediaBag
+      -> String
+      -> Lua NumResults
+fetch commonState mbRef src = do
+  mediaBag <- liftIO $ readIORef mbRef
+  (bs, mimeType) <- liftIO . runIOorExplode $ do
+    putCommonState commonState
+    setMediaBag mediaBag
+    fetchItem src
+  Lua.push $ fromMaybe "" mimeType
+  Lua.push bs
+  return 2 -- returns 2 values: contents, mimetype
diff --git a/src/Text/Pandoc/Lua/Module/Pandoc.hs b/src/Text/Pandoc/Lua/Module/Pandoc.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/Lua/Module/Pandoc.hs
@@ -0,0 +1,135 @@
+{-
+Copyright © 2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+-}
+{-# LANGUAGE FlexibleContexts #-}
+{- |
+   Module      : Text.Pandoc.Lua.Module.Pandoc
+   Copyright   : Copyright © 2017 Albert Krewinkel
+   License     : GNU GPL, version 2 or above
+
+   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
+   Stability   : alpha
+
+Pandoc module for lua.
+-}
+module Text.Pandoc.Lua.Module.Pandoc
+  ( pushModule
+  ) where
+
+import Control.Monad (when)
+import Data.Default (Default (..))
+import Data.Maybe (fromMaybe)
+import Data.Text (pack)
+import Foreign.Lua (ToLuaStack, FromLuaStack, Lua, NumResults, liftIO)
+import System.Exit (ExitCode (..))
+import Text.Pandoc.Class (runIO)
+import Text.Pandoc.Definition (Block, Inline)
+import Text.Pandoc.Lua.Filter (walkInlines, walkBlocks, LuaFilter)
+import Text.Pandoc.Lua.StackInstances ()
+import Text.Pandoc.Lua.Util (OrNil (toMaybe), addFunction, addValue,
+                             loadScriptFromDataDir, raiseError)
+import Text.Pandoc.Walk (Walkable)
+import Text.Pandoc.Options (ReaderOptions (readerExtensions))
+import Text.Pandoc.Process (pipeProcess)
+import Text.Pandoc.Readers (Reader (..), getReader)
+
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.ByteString.Lazy.Char8 as BSL
+import qualified Foreign.Lua as Lua
+
+-- | Push the "pandoc" on the lua stack. Requires the `list` module to be
+-- loaded.
+pushModule :: Maybe FilePath -> Lua NumResults
+pushModule datadir = do
+  loadScriptFromDataDir datadir "pandoc.lua"
+  addFunction "read" readDoc
+  addFunction "pipe" pipeFn
+  addFunction "walk_block" walkBlock
+  addFunction "walk_inline" walkInline
+  return 1
+
+walkElement :: (ToLuaStack a, Walkable [Inline] a, Walkable [Block] a)
+            => a -> LuaFilter -> Lua a
+walkElement x f = walkInlines f x >>= walkBlocks f
+
+walkInline :: Inline -> LuaFilter -> Lua Inline
+walkInline = walkElement
+
+walkBlock :: Block -> LuaFilter -> Lua Block
+walkBlock = walkElement
+
+readDoc :: String -> OrNil String -> Lua NumResults
+readDoc content formatSpecOrNil = do
+  let formatSpec = fromMaybe "markdown" (toMaybe formatSpecOrNil)
+  case getReader formatSpec of
+    Left  s      -> raiseError s -- Unknown reader
+    Right (reader, es) ->
+      case reader of
+        TextReader r -> do
+          res <- liftIO $ runIO $ r def{ readerExtensions = es } (pack content)
+          case res of
+            Right pd -> (1 :: NumResults) <$ Lua.push pd -- success, push Pandoc
+            Left s   -> raiseError (show s)              -- error while reading
+        _  -> raiseError "Only string formats are supported at the moment."
+
+-- | Pipes input through a command.
+pipeFn :: String
+       -> [String]
+       -> BL.ByteString
+       -> Lua NumResults
+pipeFn command args input = do
+  (ec, output) <- liftIO $ pipeProcess Nothing command args input
+  case ec of
+    ExitSuccess -> 1 <$ Lua.push output
+    ExitFailure n -> raiseError (PipeError command n output)
+
+data PipeError = PipeError
+  { pipeErrorCommand :: String
+  , pipeErrorCode :: Int
+  , pipeErrorOutput :: BL.ByteString
+  }
+
+instance FromLuaStack PipeError where
+  peek idx =
+    PipeError
+    <$> (Lua.getfield idx "command"    *> Lua.peek (-1) <* Lua.pop 1)
+    <*> (Lua.getfield idx "error_code" *> Lua.peek (-1) <* Lua.pop 1)
+    <*> (Lua.getfield idx "output"     *> Lua.peek (-1) <* Lua.pop 1)
+
+instance ToLuaStack PipeError where
+  push pipeErr = do
+    Lua.newtable
+    addValue "command" (pipeErrorCommand pipeErr)
+    addValue "error_code" (pipeErrorCode pipeErr)
+    addValue "output" (pipeErrorOutput pipeErr)
+    pushPipeErrorMetaTable
+    Lua.setmetatable (-2)
+      where
+        pushPipeErrorMetaTable :: Lua ()
+        pushPipeErrorMetaTable = do
+          v <- Lua.newmetatable "pandoc pipe error"
+          when v $ addFunction "__tostring" pipeErrorMessage
+
+        pipeErrorMessage :: PipeError -> Lua BL.ByteString
+        pipeErrorMessage (PipeError cmd errorCode output) = return $ mconcat
+          [ BSL.pack "Error running "
+          , BSL.pack cmd
+          , BSL.pack " (error code "
+          , BSL.pack $ show errorCode
+          , BSL.pack "): "
+          , if output == mempty then BSL.pack "<no output>" else output
+          ]
diff --git a/src/Text/Pandoc/Lua/Module/Utils.hs b/src/Text/Pandoc/Lua/Module/Utils.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/Lua/Module/Utils.hs
@@ -0,0 +1,100 @@
+{-
+Copyright © 2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+-}
+{- |
+   Module      : Text.Pandoc.Lua.Module.Utils
+   Copyright   : Copyright © 2017 Albert Krewinkel
+   License     : GNU GPL, version 2 or above
+
+   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
+   Stability   : alpha
+
+Utility module for lua, exposing internal helper functions.
+-}
+module Text.Pandoc.Lua.Module.Utils
+  ( pushModule
+  ) where
+
+import Control.Applicative ((<|>))
+import Foreign.Lua (FromLuaStack, Lua, LuaInteger, NumResults)
+import Text.Pandoc.Definition (Pandoc, Meta, Block, Inline)
+import Text.Pandoc.Lua.StackInstances ()
+import Text.Pandoc.Lua.Util (OrNil (OrNil), addFunction)
+
+import qualified Data.Digest.Pure.SHA as SHA
+import qualified Data.ByteString.Lazy as BSL
+import qualified Foreign.Lua as Lua
+import qualified Text.Pandoc.Shared as Shared
+
+-- | Push the "pandoc.utils" module to the lua stack.
+pushModule :: Lua NumResults
+pushModule = do
+  Lua.newtable
+  addFunction "hierarchicalize" hierarchicalize
+  addFunction "normalize_date" normalizeDate
+  addFunction "sha1" sha1
+  addFunction "stringify" stringify
+  addFunction "to_roman_numeral" toRomanNumeral
+  return 1
+
+-- | Convert list of Pandoc blocks into (hierarchical) list of Elements.
+hierarchicalize :: [Block] -> Lua [Shared.Element]
+hierarchicalize = return . Shared.hierarchicalize
+
+-- | Parse a date and convert (if possible) to "YYYY-MM-DD" format. We
+-- limit years to the range 1601-9999 (ISO 8601 accepts greater than
+-- or equal to 1583, but MS Word only accepts dates starting 1601).
+-- Returns nil instead of a string if the conversion failed.
+normalizeDate :: String -> Lua (OrNil String)
+normalizeDate = return . OrNil . Shared.normalizeDate
+
+-- | Calculate the hash of the given contents.
+sha1 :: BSL.ByteString
+     -> Lua String
+sha1 = return . SHA.showDigest . SHA.sha1
+
+-- | Convert pandoc structure to a string with formatting removed.
+-- Footnotes are skipped (since we don't want their contents in link
+-- labels).
+stringify :: AstElement -> Lua String
+stringify el = return $ case el of
+  PandocElement pd -> Shared.stringify pd
+  InlineElement i  -> Shared.stringify i
+  BlockElement b   -> Shared.stringify b
+  MetaElement m    -> Shared.stringify m
+
+data AstElement
+  = PandocElement Pandoc
+  | MetaElement Meta
+  | BlockElement Block
+  | InlineElement Inline
+  deriving (Show)
+
+instance FromLuaStack AstElement where
+  peek idx  = do
+    res <- Lua.tryLua $  (PandocElement <$> Lua.peek idx)
+                     <|> (InlineElement <$> Lua.peek idx)
+                     <|> (BlockElement <$> Lua.peek idx)
+                     <|> (MetaElement <$> Lua.peek idx)
+    case res of
+      Right x -> return x
+      Left _ -> Lua.throwLuaError
+        "Expected an AST element, but could not parse value as such."
+
+-- | Convert a number < 4000 to uppercase roman numeral.
+toRomanNumeral :: LuaInteger -> Lua String
+toRomanNumeral = return . Shared.toRomanNumeral . fromIntegral
diff --git a/src/Text/Pandoc/Lua/Packages.hs b/src/Text/Pandoc/Lua/Packages.hs
--- a/src/Text/Pandoc/Lua/Packages.hs
+++ b/src/Text/Pandoc/Lua/Packages.hs
@@ -38,10 +38,12 @@
 import Foreign.Lua (Lua, NumResults, liftIO)
 import Text.Pandoc.Class (CommonState, readDataFile, runIO, setUserDataDir)
 import Text.Pandoc.MediaBag (MediaBag)
-import Text.Pandoc.Lua.PandocModule (pushPandocModule, pushMediaBagModule)
 import Text.Pandoc.Lua.Util (dostring')
 
 import qualified Foreign.Lua as Lua
+import Text.Pandoc.Lua.Module.Pandoc as Pandoc
+import Text.Pandoc.Lua.Module.MediaBag as MediaBag
+import Text.Pandoc.Lua.Module.Utils as Utils
 
 -- | Parameters used to create lua packages/modules.
 data LuaPackageParams = LuaPackageParams
@@ -72,10 +74,11 @@
 pandocPackageSearcher luaPkgParams pkgName =
   case pkgName of
     "pandoc"          -> let datadir = luaPkgDataDir luaPkgParams
-                         in pushWrappedHsFun (pushPandocModule datadir)
+                         in pushWrappedHsFun (Pandoc.pushModule datadir)
     "pandoc.mediabag" -> let st    = luaPkgCommonState luaPkgParams
                              mbRef = luaPkgMediaBag luaPkgParams
-                         in pushWrappedHsFun (pushMediaBagModule st mbRef)
+                         in pushWrappedHsFun (MediaBag.pushModule st mbRef)
+    "pandoc.utils"    -> pushWrappedHsFun Utils.pushModule
     _ -> searchPureLuaLoader
  where
   pushWrappedHsFun f = do
diff --git a/src/Text/Pandoc/Lua/PandocModule.hs b/src/Text/Pandoc/Lua/PandocModule.hs
deleted file mode 100644
--- a/src/Text/Pandoc/Lua/PandocModule.hs
+++ /dev/null
@@ -1,199 +0,0 @@
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-
-Copyright © 2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
--}
-{-# LANGUAGE CPP #-}
-{- |
-   Module      : Text.Pandoc.Lua.PandocModule
-   Copyright   : Copyright © 2017 Albert Krewinkel
-   License     : GNU GPL, version 2 or above
-
-   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
-   Stability   : alpha
-
-Pandoc module for lua.
--}
-module Text.Pandoc.Lua.PandocModule
-  ( pushPandocModule
-  , pushMediaBagModule
-  ) where
-
-import Control.Monad (zipWithM_)
-import Data.Default (Default (..))
-import Data.Digest.Pure.SHA (sha1, showDigest)
-import Data.IORef (IORef, modifyIORef', readIORef)
-import Data.Maybe (fromMaybe)
-import Data.Text (pack)
-import Foreign.Lua (ToLuaStack, FromLuaStack, Lua, NumResults, liftIO)
-import Foreign.Lua.FunctionCalling (ToHaskellFunction)
-import System.Exit (ExitCode (..))
-import Text.Pandoc.Class (CommonState (..), fetchItem, putCommonState,
-                          runIO, runIOorExplode, setMediaBag)
-import Text.Pandoc.Definition (Block, Inline)
-import Text.Pandoc.Lua.Filter (walkInlines, walkBlocks, LuaFilter)
-import Text.Pandoc.Lua.StackInstances ()
-import Text.Pandoc.Lua.Util (loadScriptFromDataDir)
-import Text.Pandoc.Walk (Walkable)
-import Text.Pandoc.MIME (MimeType)
-import Text.Pandoc.Options (ReaderOptions (readerExtensions))
-import Text.Pandoc.Process (pipeProcess)
-import Text.Pandoc.Readers (Reader (..), getReader)
-
-import qualified Data.ByteString.Lazy as BL
-import qualified Foreign.Lua as Lua
-import qualified Text.Pandoc.MediaBag as MB
-
--- | Push the "pandoc" on the lua stack. Requires the `list` module to be
--- loaded.
-pushPandocModule :: Maybe FilePath -> Lua NumResults
-pushPandocModule datadir = do
-  loadScriptFromDataDir datadir "pandoc.lua"
-  addFunction "_pipe" pipeFn
-  addFunction "_read" readDoc
-  addFunction "sha1" sha1HashFn
-  addFunction "walk_block" walkBlock
-  addFunction "walk_inline" walkInline
-  return 1
-
-walkElement :: (ToLuaStack a, Walkable [Inline] a, Walkable [Block] a)
-            => a -> LuaFilter -> Lua NumResults
-walkElement x f = do
-  x' <- walkInlines f x >>= walkBlocks f
-  Lua.push x'
-  return 1
-
-walkInline :: Inline -> LuaFilter -> Lua NumResults
-walkInline = walkElement
-
-walkBlock :: Block -> LuaFilter -> Lua NumResults
-walkBlock = walkElement
-
-readDoc :: String -> String -> Lua NumResults
-readDoc formatSpec content = do
-  case getReader formatSpec of
-    Left  s      -> Lua.push s -- Unknown reader
-    Right (reader, es) ->
-      case reader of
-        TextReader r -> do
-          res <- liftIO $ runIO $ r def{ readerExtensions = es } (pack content)
-          case res of
-            Left s   -> Lua.push $ show s -- error while reading
-            Right pd -> Lua.push pd       -- success, push Pandoc
-        _  -> Lua.push "Only string formats are supported at the moment."
-  return 1
-
---
--- MediaBag submodule
---
-pushMediaBagModule :: CommonState -> IORef MB.MediaBag -> Lua NumResults
-pushMediaBagModule commonState mediaBagRef = do
-  Lua.newtable
-  addFunction "insert" (insertMediaFn mediaBagRef)
-  addFunction "lookup" (lookupMediaFn mediaBagRef)
-  addFunction "list" (mediaDirectoryFn mediaBagRef)
-  addFunction "fetch" (fetch commonState mediaBagRef)
-  return 1
-
-addFunction :: ToHaskellFunction a => String -> a -> Lua ()
-addFunction name fn = do
-  Lua.push name
-  Lua.pushHaskellFunction fn
-  Lua.rawset (-3)
-
-sha1HashFn :: BL.ByteString
-           -> Lua NumResults
-sha1HashFn contents = do
-  Lua.push $ showDigest (sha1 contents)
-  return 1
-
-pipeFn :: String
-       -> [String]
-       -> BL.ByteString
-       -> Lua NumResults
-pipeFn command args input = do
-  (ec, output) <- liftIO $ pipeProcess Nothing command args input
-  Lua.push $ case ec of
-                  ExitSuccess   -> 0
-                  ExitFailure n -> n
-  Lua.push output
-  return 2
-
-insertMediaFn :: IORef MB.MediaBag
-              -> FilePath
-              -> OrNil MimeType
-              -> BL.ByteString
-              -> Lua NumResults
-insertMediaFn mbRef fp nilOrMime contents = do
-  liftIO . modifyIORef' mbRef $
-    MB.insertMedia fp (toMaybe nilOrMime) contents
-  return 0
-
-lookupMediaFn :: IORef MB.MediaBag
-              -> FilePath
-              -> Lua NumResults
-lookupMediaFn mbRef fp = do
-  res <- MB.lookupMedia fp <$> liftIO (readIORef mbRef)
-  case res of
-    Nothing -> Lua.pushnil *> return 1
-    Just (mimeType, contents) -> do
-      Lua.push mimeType
-      Lua.push contents
-      return 2
-
-mediaDirectoryFn :: IORef MB.MediaBag
-                 -> Lua NumResults
-mediaDirectoryFn mbRef = do
-  dirContents <- MB.mediaDirectory <$> liftIO (readIORef mbRef)
-  Lua.newtable
-  zipWithM_ addEntry [1..] dirContents
-  return 1
- where
-  addEntry :: Int -> (FilePath, MimeType, Int) -> Lua ()
-  addEntry idx (fp, mimeType, contentLength) = do
-    Lua.newtable
-    Lua.push "path" *> Lua.push fp *> Lua.rawset (-3)
-    Lua.push "type" *> Lua.push mimeType *> Lua.rawset (-3)
-    Lua.push "length" *> Lua.push contentLength *> Lua.rawset (-3)
-    Lua.rawseti (-2) idx
-
-fetch :: CommonState
-      -> IORef MB.MediaBag
-      -> String
-      -> Lua NumResults
-fetch commonState mbRef src = do
-  mediaBag <- liftIO $ readIORef mbRef
-  (bs, mimeType) <- liftIO . runIOorExplode $ do
-    putCommonState commonState
-    setMediaBag mediaBag
-    fetchItem src
-  Lua.push $ fromMaybe "" mimeType
-  Lua.push bs
-  return 2 -- returns 2 values: contents, mimetype
-
---
--- Helper types and orphan instances
---
-
-newtype OrNil a = OrNil { toMaybe :: Maybe a }
-
-instance FromLuaStack a => FromLuaStack (OrNil a) where
-  peek idx = do
-    noValue <- Lua.isnil idx
-    if noValue
-      then return (OrNil Nothing)
-      else OrNil . Just <$> Lua.peek idx
diff --git a/src/Text/Pandoc/Lua/StackInstances.hs b/src/Text/Pandoc/Lua/StackInstances.hs
--- a/src/Text/Pandoc/Lua/StackInstances.hs
+++ b/src/Text/Pandoc/Lua/StackInstances.hs
@@ -33,13 +33,15 @@
 module Text.Pandoc.Lua.StackInstances () where
 
 import Control.Applicative ((<|>))
+import Control.Monad (when)
 import Foreign.Lua (FromLuaStack (peek), Lua, LuaInteger, LuaNumber, StackIndex,
                     ToLuaStack (push), Type (..), throwLuaError, tryLua)
 import Text.Pandoc.Definition
 import Text.Pandoc.Lua.Util (adjustIndexBy, getTable, pushViaConstructor)
-import Text.Pandoc.Shared (safeRead)
+import Text.Pandoc.Shared (Element (Blk, Sec), safeRead)
 
 import qualified Foreign.Lua as Lua
+import qualified Text.Pandoc.Lua.Util as LuaUtil
 
 instance ToLuaStack Pandoc where
   push (Pandoc meta blocks) =
@@ -306,3 +308,27 @@
 
 instance FromLuaStack LuaAttr where
   peek idx = LuaAttr <$> peek idx
+
+--
+-- Hierarchical elements
+--
+instance ToLuaStack Element where
+  push (Blk blk) = push blk
+  push (Sec lvl num attr label contents) = do
+    Lua.newtable
+    LuaUtil.addValue "level" lvl
+    LuaUtil.addValue "numbering" num
+    LuaUtil.addValue "attr" (LuaAttr attr)
+    LuaUtil.addValue "label" label
+    LuaUtil.addValue "contents" contents
+    pushSecMetaTable
+    Lua.setmetatable (-2)
+      where
+        pushSecMetaTable :: Lua ()
+        pushSecMetaTable = do
+          inexistant <- Lua.newmetatable "PandocElementSec"
+          when inexistant $ do
+            LuaUtil.addValue "t" "Sec"
+            Lua.push "__index"
+            Lua.pushvalue (-2)
+            Lua.rawset (-3)
diff --git a/src/Text/Pandoc/Lua/Util.hs b/src/Text/Pandoc/Lua/Util.hs
--- a/src/Text/Pandoc/Lua/Util.hs
+++ b/src/Text/Pandoc/Lua/Util.hs
@@ -32,9 +32,12 @@
   ( adjustIndexBy
   , getTable
   , addValue
+  , addFunction
   , getRawInt
   , setRawInt
   , addRawInt
+  , raiseError
+  , OrNil (..)
   , PushViaCall
   , pushViaCall
   , pushViaConstructor
@@ -44,8 +47,8 @@
 
 import Control.Monad (when)
 import Data.ByteString.Char8 (unpack)
-import Foreign.Lua (FromLuaStack (..), Lua, NumArgs, StackIndex,
-                    ToLuaStack (..), getglobal')
+import Foreign.Lua (FromLuaStack (..), NumResults, Lua, NumArgs, StackIndex,
+                    ToLuaStack (..), ToHaskellFunction, getglobal')
 import Foreign.Lua.Api (Status, call, pop, rawget, rawgeti, rawset, rawseti)
 import Text.Pandoc.Class (readDataFile, runIOorExplode, setUserDataDir)
 
@@ -64,21 +67,28 @@
 getTable idx key = do
   push key
   rawget (idx `adjustIndexBy` 1)
-  peek (-1) <* pop 1
+  popValue
 
--- | Add a key-value pair to the table at the top of the stack
+-- | Add a key-value pair to the table at the top of the stack.
 addValue :: (ToLuaStack a, ToLuaStack b) => a -> b -> Lua ()
 addValue key value = do
   push key
   push value
   rawset (-3)
 
+-- | Add a function to the table at the top of the stack, using the given name.
+addFunction :: ToHaskellFunction a => String -> a -> Lua ()
+addFunction name fn = do
+  Lua.push name
+  Lua.pushHaskellFunction fn
+  Lua.wrapHaskellFunction
+  Lua.rawset (-3)
+
 -- | Get value behind key from table at given index.
 getRawInt :: FromLuaStack a => StackIndex -> Int -> Lua a
-getRawInt idx key =
+getRawInt idx key = do
   rawgeti idx key
-  *> peek (-1)
-  <* pop 1
+  popValue
 
 -- | Set numeric key/value in table at the given index
 setRawInt :: ToLuaStack a => StackIndex -> Int -> a -> Lua ()
@@ -89,6 +99,35 @@
 -- | Set numeric key/value in table at the top of the stack.
 addRawInt :: ToLuaStack a => Int -> a -> Lua ()
 addRawInt = setRawInt (-1)
+
+raiseError :: ToLuaStack a => a -> Lua NumResults
+raiseError e = do
+  Lua.push e
+  fromIntegral <$> Lua.lerror
+
+-- | Get, then pop the value at the top of the stack.
+popValue :: FromLuaStack a => Lua a
+popValue = do
+  resOrError <- Lua.peekEither (-1)
+  pop 1
+  case resOrError of
+    Left err -> Lua.throwLuaError err
+    Right x -> return x
+
+-- | Newtype wrapper intended to be used for optional Lua values. Nesting this
+-- type is strongly discouraged and will likely lead to a wrong result.
+newtype OrNil a = OrNil { toMaybe :: Maybe a }
+
+instance FromLuaStack a => FromLuaStack (OrNil a) where
+  peek idx = do
+    noValue <- Lua.isnoneornil idx
+    if noValue
+      then return (OrNil Nothing)
+      else OrNil . Just <$> Lua.peek idx
+
+instance ToLuaStack a => ToLuaStack (OrNil a) where
+  push (OrNil Nothing)  = Lua.pushnil
+  push (OrNil (Just x)) = Lua.push x
 
 -- | Helper class for pushing a single value to the stack via a lua function.
 -- See @pushViaCall@.
diff --git a/src/Text/Pandoc/MIME.hs b/src/Text/Pandoc/MIME.hs
--- a/src/Text/Pandoc/MIME.hs
+++ b/src/Text/Pandoc/MIME.hs
@@ -325,6 +325,7 @@
            ,("ogv","video/ogg")
            ,("ogx","application/ogg")
            ,("old","application/x-trash")
+           ,("opus","audio/ogg")
            ,("otg","application/vnd.oasis.opendocument.graphics-template")
            ,("oth","application/vnd.oasis.opendocument.text-web")
            ,("otp","application/vnd.oasis.opendocument.presentation-template")
diff --git a/src/Text/Pandoc/Readers.hs b/src/Text/Pandoc/Readers.hs
--- a/src/Text/Pandoc/Readers.hs
+++ b/src/Text/Pandoc/Readers.hs
@@ -52,6 +52,7 @@
   , readOrg
   , readLaTeX
   , readHtml
+  , readJATS
   , readTextile
   , readDocBook
   , readOPML
@@ -84,7 +85,8 @@
 import Text.Pandoc.Readers.Docx
 import Text.Pandoc.Readers.EPUB
 import Text.Pandoc.Readers.Haddock
-import Text.Pandoc.Readers.HTML
+import Text.Pandoc.Readers.HTML (readHtml)
+import Text.Pandoc.Readers.JATS (readJATS)
 import Text.Pandoc.Readers.LaTeX
 import Text.Pandoc.Readers.Markdown
 import Text.Pandoc.Readers.MediaWiki
@@ -129,6 +131,7 @@
            ,("org"          , TextReader readOrg)
            ,("textile"      , TextReader readTextile) -- TODO : textile+lhs
            ,("html"         , TextReader readHtml)
+           ,("jats"         , TextReader readJATS)
            ,("latex"        , TextReader readLaTeX)
            ,("haddock"      , TextReader readHaddock)
            ,("twiki"        , TextReader readTWiki)
diff --git a/src/Text/Pandoc/Readers/Docx.hs b/src/Text/Pandoc/Readers/Docx.hs
--- a/src/Text/Pandoc/Readers/Docx.hs
+++ b/src/Text/Pandoc/Readers/Docx.hs
@@ -121,6 +121,9 @@
                      , docxMediaBag  :: MediaBag
                      , docxDropCap   :: Inlines
                      , docxWarnings  :: [String]
+                     -- keep track of (numId, lvl) values for
+                     -- restarting
+                     , docxListState :: M.Map (String, String) Integer
                      }
 
 instance Default DState where
@@ -128,6 +131,7 @@
                , docxMediaBag  = mempty
                , docxDropCap   = mempty
                , docxWarnings  = []
+               , docxListState = M.empty
                }
 
 data DEnv = DEnv { docxOptions       :: ReaderOptions
@@ -333,7 +337,7 @@
   unless (null $ filter notParaOrPlain blkList) $
     lift $ P.report $ DocxParserWarning $
       "Docx comment " ++ cmtId ++ " will not retain formatting"
-  return $ fromList $ blocksToInlines blkList
+  return $ blocksToInlines' blkList
 
 parPartToInlines :: PandocMonad m => ParPart -> DocxContext m Inlines
 parPartToInlines (PlainRun r) = runToInlines r
@@ -539,22 +543,25 @@
                  then return mempty
                  else return $ parStyleToTransform pPr $ para ils'
 bodyPartToBlocks (ListItem pPr numId lvl (Just levelInfo) parparts) = do
-  let
-    kvs = case levelInfo of
-      (_, fmt, txt, Just start) -> [ ("level", lvl)
-                                   , ("num-id", numId)
-                                   , ("format", fmt)
-                                   , ("text", txt)
-                                   , ("start", show start)
-                                   ]
-
-      (_, fmt, txt, Nothing)    -> [ ("level", lvl)
-                                   , ("num-id", numId)
-                                   , ("format", fmt)
-                                   , ("text", txt)
-                                   ]
+  -- We check whether this current numId has previously been used,
+  -- since Docx expects us to pick up where we left off.
+  listState <- gets docxListState
+  let startFromState = M.lookup (numId, lvl) listState
+      (_, fmt,txt, startFromLevelInfo) = levelInfo
+      start = case startFromState of
+        Just n -> n + 1
+        Nothing -> case startFromLevelInfo of
+          Just n' -> n'
+          Nothing -> 1
+      kvs = [ ("level", lvl)
+            , ("num-id", numId)
+            , ("format", fmt)
+            , ("text", txt)
+            , ("start", show start)
+            ]
+  modify $ \st -> st{ docxListState = M.insert (numId, lvl) start listState}
   blks <- bodyPartToBlocks (Paragraph pPr parparts)
-  return $ divWith ("", ["list-item"], kvs) blks
+  return $ divWith ("", ["list-item"], kvs) blks 
 bodyPartToBlocks (ListItem pPr _ _ _ parparts) =
   let pPr' = pPr {pStyle = "ListParagraph": pStyle pPr}
   in
diff --git a/src/Text/Pandoc/Readers/Docx/Parse.hs b/src/Text/Pandoc/Readers/Docx/Parse.hs
--- a/src/Text/Pandoc/Readers/Docx/Parse.hs
+++ b/src/Text/Pandoc/Readers/Docx/Parse.hs
@@ -73,6 +73,7 @@
 import Text.TeXMath.Readers.OMML (readOMML)
 import Text.TeXMath.Unicode.Fonts (Font (..), getUnicode, stringToFont)
 import Text.XML.Light
+import qualified Text.XML.Light.Cursor as XMLC
 
 data ReaderEnv = ReaderEnv { envNotes         :: Notes
                            , envComments      :: Comments
@@ -117,6 +118,32 @@
   in
    concatMapM handler xs
 
+unwrapSDT :: NameSpaces -> Content -> Content
+unwrapSDT ns (Elem element)
+  | isElem ns "w" "sdt" element
+  , Just sdtContent <- findChildByName ns "w" "sdtContent" element
+  , child : _    <- elChildren sdtContent
+  = Elem child
+unwrapSDT _ content = content
+
+walkDocument' :: NameSpaces -> XMLC.Cursor -> XMLC.Cursor
+walkDocument' ns cur =
+  let modifiedCur = XMLC.modifyContent (unwrapSDT ns) cur
+  in
+    case XMLC.nextDF modifiedCur of
+      Just cur' -> walkDocument' ns cur'
+      Nothing   -> XMLC.root modifiedCur
+
+walkDocument :: NameSpaces -> Element -> Maybe Element
+walkDocument ns element =
+  let cur = XMLC.fromContent (Elem element)
+      cur' = walkDocument' ns cur
+  in
+    case XMLC.toTree cur' of
+      Elem element' -> Just element'
+      _             -> Nothing
+
+
 data Docx = Docx Document
           deriving Show
 
@@ -298,7 +325,10 @@
   docElem <- maybeToD $ (parseXMLDoc . UTF8.toStringLazy . fromEntry) entry
   let namespaces = elemToNameSpaces docElem
   bodyElem <- maybeToD $ findChildByName namespaces "w" "body" docElem
-  body <- elemToBody namespaces bodyElem
+  let bodyElem' = case walkDocument namespaces bodyElem of
+        Just e -> e
+        Nothing -> bodyElem
+  body <- elemToBody namespaces bodyElem'
   return $ Document namespaces body
 
 elemToBody :: NameSpaces -> Element -> D Body
diff --git a/src/Text/Pandoc/Readers/HTML.hs b/src/Text/Pandoc/Readers/HTML.hs
--- a/src/Text/Pandoc/Readers/HTML.hs
+++ b/src/Text/Pandoc/Readers/HTML.hs
@@ -51,7 +51,7 @@
 import Data.Default (Default (..), def)
 import Data.Foldable (for_)
 import Data.List (intercalate, isPrefixOf)
-import Data.List.Split (wordsBy)
+import Data.List.Split (wordsBy, splitWhen)
 import qualified Data.Map as M
 import Data.Maybe (fromMaybe, isJust, isNothing)
 import Data.Monoid (First (..), (<>))
@@ -70,12 +70,12 @@
 import Text.Pandoc.Logging
 import Text.Pandoc.Options (
     Extension (Ext_epub_html_exts, Ext_empty_paragraphs, Ext_native_divs,
-               Ext_native_spans, Ext_raw_html),
+               Ext_native_spans, Ext_raw_html, Ext_line_blocks),
     ReaderOptions (readerExtensions, readerStripComments),
     extensionEnabled)
 import Text.Pandoc.Parsing hiding ((<|>))
-import Text.Pandoc.Shared (addMetaField, crFilter, escapeURI, extractSpaces,
-                           safeRead, underlineSpan)
+import Text.Pandoc.Shared (addMetaField, blocksToInlines', crFilter, escapeURI,
+                           extractSpaces, safeRead, underlineSpan)
 import Text.Pandoc.Walk
 import Text.Parsec.Error
 import Text.TeXMath (readMathML, writeTeX)
@@ -191,6 +191,7 @@
             , pHtml
             , pHead
             , pBody
+            , pLineBlock
             , pDiv
             , pPlain
             , pFigure
@@ -377,6 +378,16 @@
      then return mempty
      else return $ renderTags' [tag]
 
+pLineBlock :: PandocMonad m => TagParser m Blocks
+pLineBlock = try $ do
+  guardEnabled Ext_line_blocks
+  _ <- pSatisfy $ tagOpen (=="div") (== [("class","line-block")])
+  ils <- trimInlines . mconcat <$> manyTill inline (pSatisfy (tagClose (=="div")))
+  let lns = map B.fromList $
+            splitWhen (== LineBreak) $ filter (/= SoftBreak) $
+            B.toList ils
+  return $ B.lineBlock lns
+
 pDiv :: PandocMonad m => TagParser m Blocks
 pDiv = try $ do
   guardEnabled Ext_native_divs
@@ -588,8 +599,9 @@
   skipMany pBlank
   let pImg  = (\x -> (Just x, Nothing)) <$>
                (pOptInTag "p" pImage <* skipMany pBlank)
-      pCapt = (\x -> (Nothing, Just x)) <$>
-               (pInTags "figcaption" inline <* skipMany pBlank)
+      pCapt = (\x -> (Nothing, Just x)) <$> do
+                bs <- pInTags "figcaption" block
+                return $ blocksToInlines' $ B.toList bs
       pSkip = (Nothing, Nothing) <$ pSatisfy (not . matchTagClose "figure")
   res <- many (pImg <|> pCapt <|> pSkip)
   let mbimg = msum $ map fst res
diff --git a/src/Text/Pandoc/Readers/JATS.hs b/src/Text/Pandoc/Readers/JATS.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/Readers/JATS.hs
@@ -0,0 +1,497 @@
+{-# LANGUAGE ExplicitForAll, TupleSections #-}
+module Text.Pandoc.Readers.JATS ( readJATS ) where
+import Control.Monad.State.Strict
+import Data.Char (isDigit, isSpace, toUpper)
+import Data.Default
+import Data.Generics
+import Data.List (intersperse)
+import qualified Data.Map as Map
+import Data.Maybe (maybeToList, fromMaybe)
+import Data.Text (Text)
+import qualified Data.Text as T
+import Text.HTML.TagSoup.Entity (lookupEntity)
+import Text.Pandoc.Builder
+import Text.Pandoc.Class (PandocMonad)
+import Text.Pandoc.Options
+import Text.Pandoc.Shared (underlineSpan, crFilter, safeRead)
+import Text.TeXMath (readMathML, writeTeX)
+import Text.XML.Light
+import qualified Data.Set as S (fromList, member)
+import Data.Set ((\\))
+
+type JATS m = StateT JATSState m
+
+data JATSState = JATSState{ jatsSectionLevel :: Int
+                          , jatsQuoteType    :: QuoteType
+                          , jatsMeta         :: Meta
+                          , jatsBook         :: Bool
+                          , jatsFigureTitle  :: Inlines
+                          , jatsContent      :: [Content]
+                          } deriving Show
+
+instance Default JATSState where
+  def = JATSState{ jatsSectionLevel = 0
+                 , jatsQuoteType = DoubleQuote
+                 , jatsMeta = mempty
+                 , jatsBook = False
+                 , jatsFigureTitle = mempty
+                 , jatsContent = [] }
+
+
+readJATS :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+readJATS _ inp = do
+  let tree = normalizeTree . parseXML
+               $ T.unpack $ crFilter inp
+  (bs, st') <- flip runStateT (def{ jatsContent = tree }) $ mapM parseBlock tree
+  return $ Pandoc (jatsMeta st') (toList . mconcat $ bs)
+
+-- normalize input, consolidating adjacent Text and CRef elements
+normalizeTree :: [Content] -> [Content]
+normalizeTree = everywhere (mkT go)
+  where go :: [Content] -> [Content]
+        go (Text (CData CDataRaw _ _):xs) = xs
+        go (Text (CData CDataText s1 z):Text (CData CDataText s2 _):xs) =
+           Text (CData CDataText (s1 ++ s2) z):xs
+        go (Text (CData CDataText s1 z):CRef r:xs) =
+           Text (CData CDataText (s1 ++ convertEntity r) z):xs
+        go (CRef r:Text (CData CDataText s1 z):xs) =
+             Text (CData CDataText (convertEntity r ++ s1) z):xs
+        go (CRef r1:CRef r2:xs) =
+             Text (CData CDataText (convertEntity r1 ++ convertEntity r2) Nothing):xs
+        go xs = xs
+
+convertEntity :: String -> String
+convertEntity e = Data.Maybe.fromMaybe (map toUpper e) (lookupEntity e)
+
+-- convenience function to get an attribute value, defaulting to ""
+attrValue :: String -> Element -> String
+attrValue attr =
+  fromMaybe "" . maybeAttrValue attr
+
+maybeAttrValue :: String -> Element -> Maybe String
+maybeAttrValue attr elt =
+  lookupAttrBy (\x -> qName x == attr) (elAttribs elt)
+
+-- convenience function
+named :: String -> Element -> Bool
+named s e = qName (elName e) == s
+
+--
+
+addMeta :: PandocMonad m => ToMetaValue a => String -> a -> JATS m ()
+addMeta field val = modify (setMeta field val)
+
+instance HasMeta JATSState where
+  setMeta field v s =  s {jatsMeta = setMeta field v (jatsMeta s)}
+  deleteMeta field s = s {jatsMeta = deleteMeta field (jatsMeta s)}
+
+isBlockElement :: Content -> Bool
+isBlockElement (Elem e) = qName (elName e) `S.member` blocktags
+  where blocktags = S.fromList (paragraphLevel ++ lists ++ mathML ++ other) \\ S.fromList inlinetags
+        paragraphLevel = ["address", "array", "boxed-text", "chem-struct-wrap",
+            "code", "fig", "fig-group", "graphic", "media", "preformat",
+            "supplementary-material", "table-wrap", "table-wrap-group",
+            "alternatives", "disp-formula", "disp-formula-group"]
+        lists = ["def-list", "list"]
+        mathML = ["tex-math", "mml:math"]
+        other = ["p", "related-article", "related-object", "ack", "disp-quote",
+            "speech", "statement", "verse-group", "x"]
+        inlinetags = ["email", "ext-link", "uri", "inline-supplementary-material",
+            "related-article", "related-object", "hr", "bold", "fixed-case",
+            "italic", "monospace", "overline", "overline-start", "overline-end",
+            "roman", "sans-serif", "sc", "strike", "underline", "underline-start",
+            "underline-end", "ruby", "alternatives", "inline-graphic", "private-char",
+            "chem-struct", "inline-formula", "tex-math", "mml:math", "abbrev",
+            "milestone-end", "milestone-start", "named-content", "styled-content",
+            "fn", "target", "xref", "sub", "sup", "x", "address", "array",
+            "boxed-text", "chem-struct-wrap", "code", "fig", "fig-group", "graphic",
+            "media", "preformat", "supplementary-material", "table-wrap",
+            "table-wrap-group", "disp-formula", "disp-formula-group",
+            "citation-alternatives", "element-citation", "mixed-citation",
+            "nlm-citation", "award-id", "funding-source", "open-access",
+            "def-list", "list", "ack", "disp-quote", "speech", "statement",
+            "verse-group"]
+isBlockElement _ = False
+
+-- Trim leading and trailing newline characters
+trimNl :: String -> String
+trimNl = reverse . go . reverse . go
+  where go ('\n':xs) = xs
+        go xs        = xs
+
+-- function that is used by both graphic (in parseBlock)
+-- and inline-graphic (in parseInline)
+getGraphic :: PandocMonad m => Element -> JATS m Inlines
+getGraphic e = do
+  let atVal a = attrValue a e
+      attr = (atVal "id", words $ atVal "role", [])
+      imageUrl = atVal "href"
+      captionOrLabel = case filterChild (\x -> named "caption" x
+                                            || named "label" x) e of
+                        Nothing -> return mempty
+                        Just z  -> mconcat <$>
+                                         mapM parseInline (elContent z)
+  figTitle <- gets jatsFigureTitle
+  let (caption, title) = if isNull figTitle
+                            then (captionOrLabel, atVal "title")
+                            else (return figTitle, "fig:")
+  fmap (imageWith attr imageUrl title) caption
+
+getBlocks :: PandocMonad m => Element -> JATS m Blocks
+getBlocks e =  mconcat <$>
+                 mapM parseBlock (elContent e)
+
+
+parseBlock :: PandocMonad m => Content -> JATS m Blocks
+parseBlock (Text (CData CDataRaw _ _)) = return mempty -- DOCTYPE
+parseBlock (Text (CData _ s _)) = if all isSpace s
+                                     then return mempty
+                                     else return $ plain $ trimInlines $ text s
+parseBlock (CRef x) = return $ plain $ str $ map toUpper x
+parseBlock (Elem e) =
+  case qName (elName e) of
+        "p" -> parseMixed para (elContent e)
+        "code" -> codeBlockWithLang
+        "preformat" -> codeBlockWithLang
+        "disp-quote" -> parseBlockquote
+        "list" -> case attrValue "list-type" e of
+                    "bullet" -> bulletList <$> listitems
+                    listType -> do
+                      let start = fromMaybe 1 $
+                                  (strContent <$> (filterElement (named "list-item") e
+                                               >>= filterElement (named "lable")))
+                                   >>= safeRead
+                      orderedListWith (start, parseListStyleType listType, DefaultDelim)
+                        <$> listitems
+        "def-list" -> definitionList <$> deflistitems
+        "sec" -> gets jatsSectionLevel >>= sect . (+1)
+        "graphic" -> para <$> getGraphic e
+        "journal-meta" -> parseMetadata e
+        "article-meta" -> parseMetadata e
+        "custom-meta" -> parseMetadata e
+        "title" -> return mempty -- processed by header
+        "table" -> parseTable
+        "fig" -> divWith (attrValue "id" e, ["fig"], []) <$> getBlocks e
+        "table-wrap" -> divWith (attrValue "id" e, ["table-wrap"], []) <$> getBlocks e
+        "caption" -> divWith (attrValue "id" e, ["caption"], []) <$> sect 6
+        "ref-list" -> parseRefList e
+        "?xml"  -> return mempty
+        _       -> getBlocks e
+   where parseMixed container conts = do
+           let (ils,rest) = break isBlockElement conts
+           ils' <- (trimInlines . mconcat) <$> mapM parseInline ils
+           let p = if ils' == mempty then mempty else container ils'
+           case rest of
+                 []     -> return p
+                 (r:rs) -> do
+                    b <- parseBlock r
+                    x <- parseMixed container rs
+                    return $ p <> b <> x
+         codeBlockWithLang = do
+           let classes' = case attrValue "language" e of
+                                "" -> []
+                                x  -> [x]
+           return $ codeBlockWith (attrValue "id" e, classes', [])
+                  $ trimNl $ strContentRecursive e
+         parseBlockquote = do
+            attrib <- case filterChild (named "attribution") e of
+                             Nothing  -> return mempty
+                             Just z   -> (para . (str "— " <>) . mconcat)
+                                         <$>
+                                              mapM parseInline (elContent z)
+            contents <- getBlocks e
+            return $ blockQuote (contents <> attrib)
+         parseListStyleType "roman-lower" = LowerRoman
+         parseListStyleType "roman-upper" = UpperRoman
+         parseListStyleType "alpha-lower" = LowerAlpha
+         parseListStyleType "alpha-upper" = UpperAlpha
+         parseListStyleType _             = DefaultStyle
+         listitems = mapM getBlocks $ filterChildren (named "list-item") e
+         deflistitems = mapM parseVarListEntry $ filterChildren
+                     (named "def-item") e
+         parseVarListEntry e' = do
+                     let terms = filterChildren (named "term") e'
+                     let items = filterChildren (named "def") e'
+                     terms' <- mapM getInlines terms
+                     items' <- mapM getBlocks items
+                     return (mconcat $ intersperse (str "; ") terms', items')
+         parseTable = do
+                      let isCaption x = named "title" x || named "caption" x
+                      caption <- case filterChild isCaption e of
+                                       Just t  -> getInlines t
+                                       Nothing -> return mempty
+                      let e' = fromMaybe e $ filterChild (named "tgroup") e
+                      let isColspec x = named "colspec" x || named "col" x
+                      let colspecs = case filterChild (named "colgroup") e' of
+                                           Just c -> filterChildren isColspec c
+                                           _      -> filterChildren isColspec e'
+                      let isRow x = named "row" x || named "tr" x
+                      headrows <- case filterChild (named "thead") e' of
+                                       Just h  -> case filterChild isRow h of
+                                                       Just x  -> parseRow x
+                                                       Nothing -> return []
+                                       Nothing -> return []
+                      bodyrows <- case filterChild (named "tbody") e' of
+                                       Just b  -> mapM parseRow
+                                                  $ filterChildren isRow b
+                                       Nothing -> mapM parseRow
+                                                  $ filterChildren isRow e'
+                      let toAlignment c = case findAttr (unqual "align") c of
+                                                Just "left"   -> AlignLeft
+                                                Just "right"  -> AlignRight
+                                                Just "center" -> AlignCenter
+                                                _             -> AlignDefault
+                      let toWidth c = case findAttr (unqual "colwidth") c of
+                                                Just w -> fromMaybe 0
+                                                   $ safeRead $ '0': filter (\x ->
+                                                     isDigit x || x == '.') w
+                                                Nothing -> 0 :: Double
+                      let numrows = case bodyrows of
+                                         [] -> 0
+                                         xs -> maximum $ map length xs
+                      let aligns = case colspecs of
+                                     [] -> replicate numrows AlignDefault
+                                     cs -> map toAlignment cs
+                      let widths = case colspecs of
+                                     []  -> replicate numrows 0
+                                     cs  -> let ws = map toWidth cs
+                                                tot = sum ws
+                                            in  if all (> 0) ws
+                                                   then map (/ tot) ws
+                                                   else replicate numrows 0
+                      let headrows' = if null headrows
+                                         then replicate numrows mempty
+                                         else headrows
+                      return $ table caption (zip aligns widths)
+                                 headrows' bodyrows
+         isEntry x  = named "entry" x || named "td" x || named "th" x
+         parseRow = mapM (parseMixed plain . elContent) . filterChildren isEntry
+         sect n = do isbook <- gets jatsBook
+                     let n' = if isbook || n == 0 then n + 1 else n
+                     headerText <- case filterChild (named "title") e `mplus`
+                                        (filterChild (named "info") e >>=
+                                            filterChild (named "title")) of
+                                      Just t  -> getInlines t
+                                      Nothing -> return mempty
+                     oldN <- gets jatsSectionLevel
+                     modify $ \st -> st{ jatsSectionLevel = n }
+                     b <- getBlocks e
+                     let ident = attrValue "id" e
+                     modify $ \st -> st{ jatsSectionLevel = oldN }
+                     return $ headerWith (ident,[],[]) n' headerText <> b
+
+getInlines :: PandocMonad m => Element -> JATS m Inlines
+getInlines e' = (trimInlines . mconcat) <$>
+                 mapM parseInline (elContent e')
+
+parseMetadata :: PandocMonad m => Element -> JATS m Blocks
+parseMetadata e = do
+  getTitle e
+  getAuthors e
+  getAffiliations e
+  return mempty
+
+getTitle :: PandocMonad m => Element -> JATS m ()
+getTitle e = do
+  tit <-  case filterElement (named "article-title") e of
+               Just s  -> getInlines s
+               Nothing -> return mempty
+  subtit <-  case filterElement (named "subtitle") e of
+               Just s  -> (text ": " <>) <$>
+                           getInlines s
+               Nothing -> return mempty
+  when (tit /= mempty) $ addMeta "title" tit
+  when (subtit /= mempty) $ addMeta "subtitle" subtit
+
+getAuthors :: PandocMonad m => Element -> JATS m ()
+getAuthors e = do
+  authors <- mapM getContrib $ filterElements
+              (\x -> named "contrib" x &&
+                     attrValue "contrib-type" x == "author") e
+  authorNotes <- mapM getInlines $ filterElements (named "author-notes") e
+  let authors' = case (reverse authors, authorNotes) of
+                   ([], _)    -> []
+                   (_, [])    -> authors
+                   (a:as, ns) -> reverse as ++ [a <> mconcat ns]
+  unless (null authors) $ addMeta "author" authors'
+
+getAffiliations :: PandocMonad m => Element -> JATS m ()
+getAffiliations x = do
+  affs <- mapM getInlines $ filterChildren (named "aff") x
+  unless (null affs) $ addMeta "institute" affs
+
+getContrib :: PandocMonad m => Element -> JATS m Inlines
+getContrib x = do
+  given <- maybe (return mempty) getInlines
+            $ filterElement (named "given-names") x
+  family <- maybe (return mempty) getInlines
+            $ filterElement (named "surname") x
+  if given == mempty && family == mempty
+     then return mempty
+     else if given == mempty || family == mempty
+          then return $ given <> family
+          else return $ given <> space <> family
+
+parseRefList :: PandocMonad m => Element -> JATS m Blocks
+parseRefList e = do
+  refs <- mapM parseRef $ filterChildren (named "ref") e
+  addMeta "references" refs
+  return mempty
+
+parseRef :: PandocMonad m
+         => Element -> JATS m (Map.Map String MetaValue)
+parseRef e = do
+  let refId = text $ attrValue "id" e
+  let getInlineText n = maybe (return mempty) getInlines . filterChild (named n)
+  case filterChild (named "element-citation") e of
+       Just c  -> do
+         let refType = text $
+               case attrValue "publication-type" c of
+                  "journal" -> "article-journal"
+                  x -> x
+         (refTitle, refContainerTitle) <- do
+           t <- getInlineText "article-title" c
+           ct <- getInlineText "source" c
+           if t == mempty
+              then return (ct, mempty)
+              else return (t, ct)
+         refLabel <- getInlineText "label" c
+         refYear <- getInlineText "year" c
+         refVolume <- getInlineText "volume" c
+         refFirstPage <- getInlineText "fpage" c
+         refLastPage <- getInlineText "lpage" c
+         refPublisher <- getInlineText "publisher-name" c
+         refPublisherPlace <- getInlineText "publisher-loc" c
+         let refPages = refFirstPage <> (if refLastPage == mempty
+                                            then mempty
+                                            else text "\x2013" <> refLastPage)
+         let personGroups' = filterChildren (named "person-group") c
+         let getName nm = do
+               given <- maybe (return mempty) getInlines
+                         $ filterChild (named "given-names") nm
+               family <- maybe (return mempty) getInlines
+                         $ filterChild (named "surname") nm
+               return $ toMetaValue $ Map.fromList [
+                   ("given", given)
+                 , ("family", family)
+                 ]
+         personGroups <- mapM (\pg ->
+                                do names <- mapM getName
+                                            (filterChildren (named "name") pg)
+                                   return (attrValue "person-group-type" pg,
+                                           toMetaValue names))
+                         personGroups'
+         return $ Map.fromList $
+           [ ("id", toMetaValue refId)
+           , ("type", toMetaValue refType)
+           , ("title", toMetaValue refTitle)
+           , ("container-title", toMetaValue refContainerTitle)
+           , ("publisher", toMetaValue refPublisher)
+           , ("publisher-place", toMetaValue refPublisherPlace)
+           , ("title", toMetaValue refTitle)
+           , ("issued", toMetaValue
+                        $ Map.fromList [
+                            ("year", refYear)
+                          ])
+           , ("volume", toMetaValue refVolume)
+           , ("page", toMetaValue refPages)
+           , ("citation-label", toMetaValue refLabel)
+           ] ++ personGroups
+       Nothing -> return $ Map.insert "id" (toMetaValue refId) mempty
+       -- TODO handle mixed-citation
+
+strContentRecursive :: Element -> String
+strContentRecursive = strContent .
+  (\e' -> e'{ elContent = map elementToStr $ elContent e' })
+
+elementToStr :: Content -> Content
+elementToStr (Elem e') = Text $ CData CDataText (strContentRecursive e') Nothing
+elementToStr x = x
+
+parseInline :: PandocMonad m => Content -> JATS m Inlines
+parseInline (Text (CData _ s _)) = return $ text s
+parseInline (CRef ref) =
+  return $ maybe (text $ map toUpper ref) text $ lookupEntity ref
+parseInline (Elem e) =
+  case qName (elName e) of
+        "italic" -> emph <$> innerInlines
+        "bold" -> strong <$> innerInlines
+        "strike" -> strikeout <$> innerInlines
+        "sub" -> subscript <$> innerInlines
+        "sup" -> superscript <$> innerInlines
+        "underline" -> underlineSpan <$> innerInlines
+        "break" -> return linebreak
+        "sc" -> smallcaps <$> innerInlines
+
+        "code" -> codeWithLang
+        "monospace" -> codeWithLang
+
+        "inline-graphic" -> getGraphic e
+        "disp-quote" -> do
+            qt <- gets jatsQuoteType
+            let qt' = if qt == SingleQuote then DoubleQuote else SingleQuote
+            modify $ \st -> st{ jatsQuoteType = qt' }
+            contents <- innerInlines
+            modify $ \st -> st{ jatsQuoteType = qt }
+            return $ if qt == SingleQuote
+                        then singleQuoted contents
+                        else doubleQuoted contents
+
+        "xref" -> do
+            ils <- innerInlines
+            let rid = attrValue "rid" e
+            let refType = ("ref-type",) <$> maybeAttrValue "ref-type" e
+            let attr = (attrValue "id" e, [], maybeToList refType)
+            return $ if refType == Just ("ref-type","bibr")
+                        then cite [Citation{
+                                         citationId = rid
+                                       , citationPrefix = []
+                                       , citationSuffix = []
+                                       , citationMode = NormalCitation
+                                       , citationNoteNum = 0
+                                       , citationHash = 0}] ils
+                        else linkWith attr ('#' : rid) "" ils
+        "ext-link" -> do
+             ils <- innerInlines
+             let title = fromMaybe "" $ findAttr (QName "title" (Just "http://www.w3.org/1999/xlink") Nothing) e
+             let href = case findAttr (QName "href" (Just "http://www.w3.org/1999/xlink") Nothing) e of
+                               Just h -> h
+                               _      -> '#' : attrValue "rid" e
+             let ils' = if ils == mempty then str href else ils
+             let attr = (attrValue "id" e, [], [])
+             return $ linkWith attr href title ils'
+
+        "disp-formula" -> formula displayMath
+        "inline-formula" -> formula math
+        "math" | qPrefix (elName e) == Just "mml" -> return . math $ mathML e
+        "tex-math" -> return . math $ strContent e
+
+        "email" -> return $ link ("mailto:" ++ strContent e) ""
+                          $ str $ strContent e
+        "uri" -> return $ link (strContent e) "" $ str $ strContent e
+        "fn" -> (note . mconcat) <$>
+                         mapM parseBlock (elContent e)
+        _          -> innerInlines
+   where innerInlines = (trimInlines . mconcat) <$>
+                          mapM parseInline (elContent e)
+         mathML x =
+            case readMathML . showElement $ everywhere (mkT removePrefix) x of
+                Left _ -> mempty
+                Right m -> writeTeX m
+         formula constructor = do
+            let whereToLook = fromMaybe e $ filterElement (named "alternatives") e
+                texMaths = map strContent $
+                            filterChildren (named  "tex-math") whereToLook
+                mathMLs = map mathML $
+                            filterChildren isMathML whereToLook
+            return . mconcat . take 1 . map constructor $ texMaths ++ mathMLs
+
+         isMathML x = qName   (elName x) == "math" &&
+                      qPrefix (elName x) == Just "mml"
+         removePrefix elname = elname { qPrefix = Nothing }
+         codeWithLang = do
+           let classes' = case attrValue "language" e of
+                               "" -> []
+                               l  -> [l]
+           return $ codeWith (attrValue "id" e,classes',[]) $ strContentRecursive e
+
diff --git a/src/Text/Pandoc/Readers/LaTeX.hs b/src/Text/Pandoc/Readers/LaTeX.hs
--- a/src/Text/Pandoc/Readers/LaTeX.hs
+++ b/src/Text/Pandoc/Readers/LaTeX.hs
@@ -37,7 +37,9 @@
                                    applyMacros,
                                    rawLaTeXInline,
                                    rawLaTeXBlock,
-                                   inlineCommand
+                                   inlineCommand,
+                                   tokenize,
+                                   untokenize
                                  ) where
 
 import Control.Applicative (many, optional, (<|>))
@@ -235,19 +237,21 @@
   return result
 
 rawLaTeXParser :: (PandocMonad m, HasMacros s, HasReaderOptions s)
-               => LP m a -> ParserT String s m String
+               => LP m a -> ParserT String s m (a, String)
 rawLaTeXParser parser = do
   inp <- getInput
   let toks = tokenize "source" $ T.pack inp
   pstate <- getState
-  let lstate = def{ sOptions = extractReaderOptions pstate }
-  res <- lift $ runParserT ((,) <$> try (snd <$> withRaw parser) <*> getState)
-            lstate "source" toks
+  let lstate = def{ sOptions = extractReaderOptions pstate
+                  , sMacros = extractMacros pstate }
+  let rawparser = (,) <$> withRaw parser <*> getState
+  res <- lift $ runParserT rawparser lstate "chunk" toks
   case res of
        Left _    -> mzero
-       Right (raw, st) -> do
+       Right ((val, raw), st) -> do
          updateState (updateMacros (sMacros st <>))
-         takeP (T.length (untokenize raw))
+         rawstring <- takeP (T.length (untokenize raw))
+         return (val, rawstring)
 
 applyMacros :: (PandocMonad m, HasMacros s, HasReaderOptions s)
             => String -> ParserT String s m String
@@ -266,33 +270,23 @@
               => ParserT String s m String
 rawLaTeXBlock = do
   lookAhead (try (char '\\' >> letter))
-  rawLaTeXParser (environment <|> macroDef <|> blockCommand)
+  -- we don't want to apply newly defined latex macros to their own
+  -- definitions:
+  (do (_, raw) <- rawLaTeXParser macroDef
+      (guardDisabled Ext_latex_macros >> return raw) <|> return "")
+  <|> (do (_, raw) <- rawLaTeXParser (environment <|> blockCommand)
+          applyMacros raw)
 
 rawLaTeXInline :: (PandocMonad m, HasMacros s, HasReaderOptions s)
                => ParserT String s m String
 rawLaTeXInline = do
   lookAhead (try (char '\\' >> letter) <|> char '$')
-  rawLaTeXParser (inlineEnvironment <|> inlineCommand')
+  rawLaTeXParser (inlineEnvironment <|> inlineCommand') >>= applyMacros . snd
 
 inlineCommand :: PandocMonad m => ParserT String ParserState m Inlines
 inlineCommand = do
   lookAhead (try (char '\\' >> letter) <|> char '$')
-  inp <- getInput
-  let toks = tokenize "chunk" $ T.pack inp
-  let rawinline = do
-         (il, raw) <- try $ withRaw (inlineEnvironment <|> inlineCommand')
-         st <- getState
-         return (il, raw, st)
-  pstate <- getState
-  let lstate = def{ sOptions = extractReaderOptions pstate
-                  , sMacros  = extractMacros pstate }
-  res <- runParserT rawinline lstate "source" toks
-  case res of
-       Left _ -> mzero
-       Right (il, raw, s) -> do
-         updateState $ updateMacros (const $ sMacros s)
-         takeP (T.length (untokenize raw))
-         return il
+  fst <$> rawLaTeXParser (inlineEnvironment <|> inlineCommand')
 
 tokenize :: SourceName -> Text -> [Tok]
 tokenize sourcename = totoks (initialPos sourcename)
@@ -320,7 +314,7 @@
                : totoks (incSourceColumn pos (1 + T.length cs)) rest'
          | c == '\\' ->
            case T.uncons rest of
-                Nothing -> [Tok pos Symbol (T.singleton c)]
+                Nothing -> [Tok pos (CtrlSeq " ") "\\"]
                 Just (d, rest')
                   | isLetterOrAt d ->
                       -- \makeatletter is common in macro defs;
@@ -338,7 +332,7 @@
                                           Just ('\n', r2)
                                                   -> (T.pack "\n",
                                                         T.span isSpaceOrTab r2)
-                                          _ -> (mempty, (w1, r1))
+                                          _ -> (mempty, (mempty, r1))
                       in  case T.uncons r3 of
                                Just ('\n', _) ->
                                  Tok pos (CtrlSeq " ") ("\\" <> w1)
@@ -374,8 +368,9 @@
                          | d < '\128' ->
                                   Tok pos Esc1 (T.pack ['^','^',d])
                                   : totoks (incSourceColumn pos 3) rest''
-                       _ -> [Tok pos Symbol ("^"),
-                             Tok (incSourceColumn pos 1) Symbol ("^")]
+                       _ -> Tok pos Symbol ("^") :
+                            Tok (incSourceColumn pos 1) Symbol ("^") :
+                            totoks (incSourceColumn pos 2) rest'
                 _ -> Tok pos Symbol ("^")
                      : totoks (incSourceColumn pos 1) rest
          | otherwise ->
@@ -1494,8 +1489,17 @@
   -- biblatex misc
   , ("RN", romanNumeralUpper)
   , ("Rn", romanNumeralLower)
+  -- babel
+  , ("foreignlanguage", foreignlanguage)
   ]
 
+foreignlanguage :: PandocMonad m => LP m Inlines
+foreignlanguage = do
+  babelLang <- T.unpack . untokenize <$> braced
+  case babelLangToBCP47 babelLang of
+       Just lang -> spanWith ("", [], [("lang", renderLang $ lang)]) <$> tok
+       _ -> tok
+
 inlineLanguageCommands :: PandocMonad m => M.Map Text (LP m Inlines)
 inlineLanguageCommands = M.fromList $ mk <$> M.toList polyglossiaLangToBCP47
   where
@@ -1722,7 +1726,7 @@
      <|> (guardEnabled Ext_literate_haskell *> symbol '|' *> doLHSverb)
      <|> (str . (:[]) <$> primEscape)
      <|> regularSymbol
-     <|> (do res <- symbolIn "#^'`\"[]"
+     <|> (do res <- symbolIn "#^'`\"[]&"
              pos <- getPosition
              let s = T.unpack (untoken res)
              report $ ParsingUnescaped s pos
@@ -2660,3 +2664,24 @@
   , ("urdu", \_ -> Lang "ur" "" "" [])
   , ("vietnamese", \_ -> Lang "vi" "" "" [])
   ]
+
+babelLangToBCP47 :: String -> Maybe Lang
+babelLangToBCP47 s =
+  case s of
+       "austrian" -> Just $ Lang "de" "" "AT" ["1901"]
+       "naustrian" -> Just $ Lang "de" "" "AT" []
+       "swissgerman" -> Just $ Lang "de" "" "CH" ["1901"]
+       "nswissgerman" -> Just $ Lang "de" "" "CH" []
+       "german" -> Just $ Lang "de" "" "DE" ["1901"]
+       "ngerman" -> Just $ Lang "de" "" "DE" []
+       "lowersorbian" -> Just $ Lang "dsb" "" "" []
+       "uppersorbian" -> Just $ Lang "hsb" "" "" []
+       "polutonikogreek" -> Just $ Lang "el" "" "" ["polyton"]
+       "slovene" -> Just $ Lang "sl" "" "" []
+       "australian" -> Just $ Lang "en" "" "AU" []
+       "canadian" -> Just $ Lang "en" "" "CA" []
+       "british" -> Just $ Lang "en" "" "GB" []
+       "newzealand" -> Just $ Lang "en" "" "NZ" []
+       "american" -> Just $ Lang "en" "" "US" []
+       "classiclatin" -> Just $ Lang "la" "" "" ["x-classic"]
+       _ -> fmap ($ "") $ M.lookup s polyglossiaLangToBCP47
diff --git a/src/Text/Pandoc/Readers/Markdown.hs b/src/Text/Pandoc/Readers/Markdown.hs
--- a/src/Text/Pandoc/Readers/Markdown.hs
+++ b/src/Text/Pandoc/Readers/Markdown.hs
@@ -863,14 +863,16 @@
 
 -- parse raw text for one list item, excluding start marker and continuations
 rawListItem :: PandocMonad m
-            => MarkdownParser m a
+            => Bool -- four space rule
+            -> MarkdownParser m a
             -> MarkdownParser m (String, Int)
-rawListItem start = try $ do
+rawListItem fourSpaceRule start = try $ do
   pos1 <- getPosition
   start
   pos2 <- getPosition
-  continuationIndent <- (4 <$ guardEnabled Ext_four_space_rule)
-                    <|> return (sourceColumn pos2 - sourceColumn pos1)
+  let continuationIndent = if fourSpaceRule
+                              then 4
+                              else (sourceColumn pos2 - sourceColumn pos1)
   first <- listLineCommon
   rest <- many (do notFollowedBy listStart
                    notFollowedBy (() <$ codeBlockFenced)
@@ -914,10 +916,11 @@
         Nothing -> return ()
 
 listItem :: PandocMonad m
-         => MarkdownParser m a
+         => Bool -- four-space rule
+         -> MarkdownParser m a
          -> MarkdownParser m (F Blocks)
-listItem start = try $ do
-  (first, continuationIndent) <- rawListItem start
+listItem fourSpaceRule start = try $ do
+  (first, continuationIndent) <- rawListItem fourSpaceRule start
   continuations <- many (listContinuation continuationIndent)
   -- parsing with ListItemState forces markers at beginning of lines to
   -- count as list item markers, even if not separated by blank space.
@@ -938,14 +941,18 @@
           delim `elem` [DefaultDelim, Period]) $
     guardEnabled Ext_fancy_lists
   when (style == Example) $ guardEnabled Ext_example_lists
-  items <- fmap sequence $ many1 $ listItem
+  fourSpaceRule <- (True <$ guardEnabled Ext_four_space_rule)
+               <|> return (style == Example)
+  items <- fmap sequence $ many1 $ listItem fourSpaceRule
                  (orderedListStart (Just (style, delim)))
   start' <- (start <$ guardEnabled Ext_startnum) <|> return 1
   return $ B.orderedListWith (start', style, delim) <$> fmap compactify items
 
 bulletList :: PandocMonad m => MarkdownParser m (F Blocks)
 bulletList = do
-  items <- fmap sequence $ many1 $ listItem  bulletListStart
+  fourSpaceRule <- (True <$ guardEnabled Ext_four_space_rule)
+               <|> return False
+  items <- fmap sequence $ many1 $ listItem fourSpaceRule bulletListStart
   return $ B.bulletList <$> fmap compactify items
 
 -- definition lists
@@ -1113,13 +1120,20 @@
 rawTeXBlock :: PandocMonad m => MarkdownParser m (F Blocks)
 rawTeXBlock = do
   guardEnabled Ext_raw_tex
-  result <- (B.rawBlock "context" . concat <$>
-                  rawConTeXtEnvironment `sepEndBy1` blankline)
-        <|> (B.rawBlock "latex" . concat <$>
-                  rawLaTeXBlock `sepEndBy1` blankline)
+  result <- (B.rawBlock "context" . trim . concat <$>
+                many1 ((++) <$> (rawConTeXtEnvironment <|> conTeXtCommand)
+                            <*> (blanklines <|> many spaceChar)))
+          <|> (B.rawBlock "latex" . trim . concat <$>
+                many1 ((++) <$> rawLaTeXBlock
+                            <*> (blanklines <|> many spaceChar)))
+  return $ case B.toList result of
+                [RawBlock _ cs]
+                  | all (`elem` [' ','\t','\n']) cs -> return mempty
+                -- don't create a raw block for suppressed macro defs
+                _ -> return result
 
-  optional blanklines
-  return $ return result
+conTeXtCommand :: PandocMonad m => MarkdownParser m String
+conTeXtCommand = oneOfStrings ["\\placeformula"]
 
 rawHtmlBlocks :: PandocMonad m => MarkdownParser m (F Blocks)
 rawHtmlBlocks = do
@@ -1267,7 +1281,7 @@
 tableCaption = try $ do
   guardEnabled Ext_table_captions
   skipNonindentSpaces
-  (string ":" <* notFollowedBy (string "::")) <|> string "Table:"
+  (string ":" <* notFollowedBy (satisfy isPunctuation)) <|> string "Table:"
   trimInlinesF <$> inlines1 <* blanklines
 
 -- Parse a simple table with '---' header and one line per row.
diff --git a/src/Text/Pandoc/Readers/Muse.hs b/src/Text/Pandoc/Readers/Muse.hs
--- a/src/Text/Pandoc/Readers/Muse.hs
+++ b/src/Text/Pandoc/Readers/Muse.hs
@@ -31,7 +31,6 @@
 {-
 TODO:
 - Page breaks (five "*")
-- Headings with anchors (make it round trip with Muse writer)
 - Org tables
 - table.el tables
 - Images with attributes (floating and width)
@@ -220,8 +219,7 @@
 comment :: PandocMonad m => MuseParser m (F Blocks)
 comment = try $ do
   char ';'
-  space
-  many $ noneOf "\n"
+  optionMaybe (spaceChar >> (many $ noneOf "\n"))
   eol
   return mempty
 
@@ -242,7 +240,8 @@
   guard $ level <= 5
   spaceChar
   content <- trimInlinesF . mconcat <$> manyTill inline eol
-  attr <- registerHeader ("", [], []) (runF content defaultParserState)
+  anchorId <- option "" parseAnchor
+  attr <- registerHeader (anchorId, [], []) (runF content defaultParserState)
   return $ B.headerWith attr level <$> content
 
 example :: PandocMonad m => MuseParser m (F Blocks)
@@ -337,7 +336,9 @@
 noteMarker :: PandocMonad m => MuseParser m String
 noteMarker = try $ do
   char '['
-  many1Till digit $ char ']'
+  first <- oneOf "123456789"
+  rest <- manyTill digit (char ']')
+  return $ first:rest
 
 -- Amusewiki version of note
 -- Parsing is similar to list item, except that note marker is used instead of list marker
@@ -628,14 +629,18 @@
   notFollowedBy blankline
   returnF B.softbreak
 
-anchor :: PandocMonad m => MuseParser m (F Inlines)
-anchor = try $ do
+parseAnchor :: PandocMonad m => MuseParser m String
+parseAnchor = try $ do
   getPosition >>= \pos -> guard (sourceColumn pos == 1)
   char '#'
   first <- letter
   rest <- many (letter <|> digit)
   skipMany spaceChar <|> void newline
-  let anchorId = first:rest
+  return $ first:rest
+
+anchor :: PandocMonad m => MuseParser m (F Inlines)
+anchor = try $ do
+  anchorId <- parseAnchor
   return $ return $ B.spanWith (anchorId, [], []) mempty
 
 footnote :: PandocMonad m => MuseParser m (F Inlines)
diff --git a/src/Text/Pandoc/Readers/OPML.hs b/src/Text/Pandoc/Readers/OPML.hs
--- a/src/Text/Pandoc/Readers/OPML.hs
+++ b/src/Text/Pandoc/Readers/OPML.hs
@@ -12,7 +12,7 @@
 import Text.Pandoc.Options
 import Text.Pandoc.Readers.HTML (readHtml)
 import Text.Pandoc.Readers.Markdown (readMarkdown)
-import Text.Pandoc.Shared (crFilter)
+import Text.Pandoc.Shared (crFilter, blocksToInlines')
 import Text.XML.Light
 
 type OPML m = StateT OPMLState m
@@ -22,6 +22,7 @@
                       , opmlDocTitle     :: Inlines
                       , opmlDocAuthors   :: [Inlines]
                       , opmlDocDate      :: Inlines
+                      , opmlOptions      :: ReaderOptions
                       } deriving Show
 
 instance Default OPMLState where
@@ -29,13 +30,14 @@
                  , opmlDocTitle = mempty
                  , opmlDocAuthors = []
                  , opmlDocDate = mempty
-                  }
+                 , opmlOptions = def
+                 }
 
 readOPML :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
-readOPML _ inp  = do
+readOPML opts inp  = do
   (bs, st') <- runStateT
                  (mapM parseBlock $ normalizeTree $
-                    parseXML (unpack (crFilter inp))) def
+                    parseXML (unpack (crFilter inp))) def{ opmlOptions = opts }
   return $
     setTitle (opmlDocTitle st') $
     setAuthors (opmlDocAuthors st') $
@@ -69,13 +71,16 @@
 -- exceptT = either throwError return
 
 asHtml :: PandocMonad m => String -> OPML m Inlines
-asHtml s =
-  (\(Pandoc _ bs) -> case bs of
-                                [Plain ils] -> fromList ils
-                                _           -> mempty) <$> lift (readHtml def (pack s))
+asHtml s = do
+  opts <- gets opmlOptions
+  Pandoc _ bs <- readHtml def{ readerExtensions = readerExtensions opts } (pack s)
+  return $ blocksToInlines' bs
 
 asMarkdown :: PandocMonad m => String -> OPML m Blocks
-asMarkdown s = (\(Pandoc _ bs) -> fromList bs) <$> lift (readMarkdown def (pack s))
+asMarkdown s = do
+  opts <- gets opmlOptions
+  Pandoc _ bs <- readMarkdown def{ readerExtensions = readerExtensions opts }  (pack s)
+  return $ fromList bs
 
 getBlocks :: PandocMonad m => Element -> OPML m Blocks
 getBlocks e =  mconcat <$> mapM parseBlock (elContent e)
diff --git a/src/Text/Pandoc/Readers/Org/Blocks.hs b/src/Text/Pandoc/Readers/Org/Blocks.hs
--- a/src/Text/Pandoc/Readers/Org/Blocks.hs
+++ b/src/Text/Pandoc/Readers/Org/Blocks.hs
@@ -41,7 +41,6 @@
                                        originalLang, translateLang)
 
 import Text.Pandoc.Builder (Blocks, Inlines)
-import qualified Text.Pandoc.Builder as B
 import Text.Pandoc.Class (PandocMonad)
 import Text.Pandoc.Definition
 import Text.Pandoc.Options
@@ -54,6 +53,9 @@
 import Data.Maybe (fromMaybe, isJust, isNothing)
 import Data.Monoid ((<>))
 
+import qualified Text.Pandoc.Builder as B
+import qualified Text.Pandoc.Walk as Walk
+
 --
 -- parsing blocks
 --
@@ -509,19 +511,18 @@
 include = try $ do
   metaLineStart <* stringAnyCase "include:" <* skipSpaces
   filename <- includeTarget
-  blockType <- optionMaybe $ skipSpaces *> many1 alphaNum
-  blocksParser <- case blockType of
-                    Just "example" ->
-                      return $ pure . B.codeBlock <$> parseRaw
-                    Just "export" -> do
-                      format <- skipSpaces *> many (noneOf "\n\r\t ")
-                      return $ pure . B.rawBlock format <$> parseRaw
-                    Just "src" -> do
-                      language <- skipSpaces *> many (noneOf "\n\r\t ")
-                      let attr = (mempty, [language], mempty)
-                      return $ pure . B.codeBlockWith attr <$> parseRaw
-                    _ -> return $ pure . B.fromList <$> blockList
-  anyLine
+  includeArgs <- many (try $ skipSpaces *> many1 alphaNum)
+  params <- keyValues
+  blocksParser <- case includeArgs of
+      ("example" : _) -> return $ pure . B.codeBlock <$> parseRaw
+      ["export"] -> return . returnF $ B.fromList []
+      ("export" : format : []) -> return $ pure . B.rawBlock format <$> parseRaw
+      ("src" : rest) -> do
+        let attr = case rest of
+                     [lang] -> (mempty, [lang], mempty)
+                     _ -> nullAttr
+        return $ pure . B.codeBlockWith attr <$> parseRaw
+      _ -> return $ return . B.fromList . blockFilter params <$> blockList
   insertIncludedFileF blocksParser ["."] filename
  where
   includeTarget :: PandocMonad m => OrgParser m FilePath
@@ -532,6 +533,28 @@
   parseRaw :: PandocMonad m => OrgParser m String
   parseRaw = many anyChar
 
+  blockFilter :: [(String, String)] -> [Block] -> [Block]
+  blockFilter params blks =
+    let minlvl = lookup "minlevel" params
+    in case (minlvl >>= safeRead :: Maybe Int) of
+         Nothing -> blks
+         Just lvl -> let levels = Walk.query headerLevel blks
+                         -- CAVE: partial function in else
+                         curMin = if null levels then 0 else minimum levels
+                     in Walk.walk (shiftHeader (curMin - lvl)) blks
+
+  headerLevel :: Block -> [Int]
+  headerLevel (Header lvl _attr _content) = [lvl]
+  headerLevel _ = []
+
+  shiftHeader :: Int -> Block -> Block
+  shiftHeader shift blk =
+    if shift <= 0
+    then blk
+    else case blk of
+      (Header lvl attr content) -> Header (lvl - shift) attr content
+      _ -> blk
+
 rawExportLine :: PandocMonad m => OrgParser m Blocks
 rawExportLine = try $ do
   metaLineStart
@@ -737,7 +760,7 @@
 paraOrPlain :: PandocMonad m => OrgParser m (F Blocks)
 paraOrPlain = try $ do
   -- Make sure we are not looking at a headline
-  notFollowedBy' (char '*' *> oneOf " *")
+  notFollowedBy' headerStart
   ils <- inlines
   nl <- option False (newline *> return True)
   -- Read block as paragraph, except if we are in a list context and the block
diff --git a/src/Text/Pandoc/Readers/RST.hs b/src/Text/Pandoc/Readers/RST.hs
--- a/src/Text/Pandoc/Readers/RST.hs
+++ b/src/Text/Pandoc/Readers/RST.hs
@@ -547,7 +547,7 @@
 bulletListStart = try $ do
   notFollowedBy' hrule  -- because hrules start out just like lists
   marker <- oneOf bulletListMarkers
-  white <- many1 spaceChar
+  white <- many1 spaceChar <|> "" <$ lookAhead (char '\n')
   return $ length (marker:white)
 
 -- parses ordered list start and returns its length (inc following whitespace)
@@ -556,7 +556,7 @@
                  -> RSTParser m Int
 orderedListStart style delim = try $ do
   (_, markerLen) <- withHorizDisplacement (orderedListMarker style delim)
-  white <- many1 spaceChar
+  white <- many1 spaceChar <|> "" <$ lookAhead (char '\n')
   return $ markerLen + length white
 
 -- parse a line of a list item
@@ -1030,7 +1030,7 @@
 citationMarker :: Monad m => RSTParser m [Char]
 citationMarker = do
   char '['
-  res <- simpleReferenceName'
+  res <- simpleReferenceName
   char ']'
   return res
 
@@ -1039,7 +1039,7 @@
   char '['
   res <- many1 digit
       <|>
-                  try (char '#' >> liftM ('#':) simpleReferenceName')
+                  try (char '#' >> liftM ('#':) simpleReferenceName)
       <|> count 1 (oneOf "#*")
   char ']'
   return res
@@ -1048,34 +1048,24 @@
 -- reference key
 --
 
-quotedReferenceName :: PandocMonad m => RSTParser m Inlines
+quotedReferenceName :: PandocMonad m => RSTParser m String
 quotedReferenceName = try $ do
   char '`' >> notFollowedBy (char '`') -- `` means inline code!
-  trimInlines . mconcat <$> many1Till inline (char '`')
-
-unquotedReferenceName :: PandocMonad m => RSTParser m Inlines
-unquotedReferenceName = try $ do -- `` means inline code!
-  trimInlines . mconcat <$> many1Till inline (lookAhead $ char ':')
+  manyTill anyChar (char '`')
 
 -- Simple reference names are single words consisting of alphanumerics
 -- plus isolated (no two adjacent) internal hyphens, underscores,
 -- periods, colons and plus signs; no whitespace or other characters
 -- are allowed.
-simpleReferenceName' :: Monad m => ParserT [Char] st m String
-simpleReferenceName' = do
+simpleReferenceName :: Monad m => ParserT [Char] st m String
+simpleReferenceName = do
   x <- alphaNum
   xs <- many $  alphaNum
-            <|>
-                  try (oneOf "-_:+." <* lookAhead alphaNum)
+            <|> try (oneOf "-_:+." <* lookAhead alphaNum)
   return (x:xs)
 
-simpleReferenceName :: Monad m => ParserT [Char] st m Inlines
-simpleReferenceName = B.str <$> simpleReferenceName'
-
-referenceName :: PandocMonad m => RSTParser m Inlines
-referenceName = quotedReferenceName <|>
-                try (simpleReferenceName <* lookAhead (char ':')) <|>
-                unquotedReferenceName
+referenceName :: PandocMonad m => RSTParser m String
+referenceName = quotedReferenceName <|> simpleReferenceName
 
 referenceKey :: PandocMonad m => RSTParser m [Char]
 referenceKey = do
@@ -1123,16 +1113,17 @@
   updateState $ \s -> s { stateKeys = M.insert key ((src,""), nullAttr) $
                           stateKeys s }
 
-stripTicks :: String -> String
-stripTicks = reverse . stripTick . reverse . stripTick
-  where stripTick ('`':xs) = xs
-        stripTick xs       = xs
-
 referenceNames :: PandocMonad m => RSTParser m [String]
 referenceNames = do
   let rn = try $ do
              string ".. _"
-             (_, ref) <- withRaw referenceName
+             ref <- quotedReferenceName
+                  <|> many (  noneOf ":\n"
+                          <|> try (char '\n' <*
+                                   string "   " <*
+                                   notFollowedBy blankline)
+                          <|> try (char ':' <* lookAhead alphaNum)
+                           )
              char ':'
              return ref
   first <- rn
@@ -1147,16 +1138,15 @@
   refs <- referenceNames
   src <- targetURI
   guard $ not (null src)
-  let keys = map (toKey . stripTicks) refs
+  let keys = map toKey refs
   forM_ keys $ \key ->
     updateState $ \s -> s { stateKeys = M.insert key ((src,""), nullAttr) $
                             stateKeys s }
 
 anchorDef :: PandocMonad m => RSTParser m [Char]
 anchorDef = try $ do
-  (refs, raw) <- withRaw (try (referenceNames <* blanklines))
-  let keys = map stripTicks refs
-  forM_ keys $ \rawkey ->
+  (refs, raw) <- withRaw $ try (referenceNames <* blanklines)
+  forM_ refs $ \rawkey ->
     updateState $ \s -> s { stateKeys =
        M.insert (toKey rawkey) (('#':rawkey,""), nullAttr) $ stateKeys s }
   -- keep this for 2nd round of parsing, where we'll add the divs (anchor)
@@ -1479,22 +1469,20 @@
                           _      -> return ((src, ""), nullAttr)
   return $ B.linkWith attr (escapeURI src') tit label''
 
-citationName :: PandocMonad m => RSTParser m Inlines
+citationName :: PandocMonad m => RSTParser m String
 citationName = do
   raw <- citationMarker
-  return $ B.str $ "[" ++ raw ++ "]"
+  return $ "[" ++ raw ++ "]"
 
 referenceLink :: PandocMonad m => RSTParser m Inlines
 referenceLink = try $ do
-  (label',ref) <- withRaw (quotedReferenceName
-                          <|> simpleReferenceName
-                          <|> citationName) <*
-                   char '_'
+  ref <- (referenceName <|> citationName) <* char '_'
+  let label' = B.text ref
   let isAnonKey (Key ('_':_)) = True
       isAnonKey _             = False
   state <- getState
   let keyTable = stateKeys state
-  key <- option (toKey $ stripTicks ref) $
+  key <- option (toKey ref) $
                 do char '_'
                    let anonKeys = sort $ filter isAnonKey $ M.keys keyTable
                    case anonKeys of
diff --git a/src/Text/Pandoc/Shared.hs b/src/Text/Pandoc/Shared.hs
--- a/src/Text/Pandoc/Shared.hs
+++ b/src/Text/Pandoc/Shared.hs
@@ -91,6 +91,7 @@
                      mapLeft,
                      -- * for squashing blocks
                      blocksToInlines,
+                     blocksToInlines',
                      -- * Safe read
                      safeRead,
                      -- * Temp directory
diff --git a/src/Text/Pandoc/Templates.hs b/src/Text/Pandoc/Templates.hs
--- a/src/Text/Pandoc/Templates.hs
+++ b/src/Text/Pandoc/Templates.hs
@@ -59,6 +59,7 @@
        "json"    -> return ""
        "docx"    -> return ""
        "fb2"     -> return ""
+       "pptx"    -> return ""
        "odt"     -> getDefaultTemplate "opendocument"
        "html"    -> getDefaultTemplate "html5"
        "docbook" -> getDefaultTemplate "docbook5"
diff --git a/src/Text/Pandoc/Writers/Custom.hs b/src/Text/Pandoc/Writers/Custom.hs
--- a/src/Text/Pandoc/Writers/Custom.hs
+++ b/src/Text/Pandoc/Writers/Custom.hs
@@ -1,11 +1,5 @@
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-{-# LANGUAGE CPP                  #-}
 {-# LANGUAGE DeriveDataTypeable   #-}
 {-# LANGUAGE FlexibleInstances    #-}
-#if MIN_VERSION_base(4,8,0)
-#else
-{-# LANGUAGE OverlappingInstances #-}
-#endif
 {- Copyright (C) 2012-2017 John MacFarlane <jgm@berkeley.edu>
 
 This program is free software; you can redistribute it and/or modify
@@ -36,19 +30,23 @@
 a lua writer.
 -}
 module Text.Pandoc.Writers.Custom ( writeCustom ) where
+import Control.Arrow ((***))
 import Control.Exception
 import Control.Monad (when)
+import Control.Monad.Trans (MonadIO (liftIO))
 import Data.Char (toLower)
 import Data.List (intersperse)
 import qualified Data.Map as M
 import Data.Text (Text, pack)
 import Data.Typeable
-import Foreign.Lua (Lua, ToLuaStack (..), callFunc, runLua)
+import Foreign.Lua (Lua, ToLuaStack (..), callFunc)
 import Foreign.Lua.Api
-import GHC.IO.Encoding (getForeignEncoding, setForeignEncoding, utf8)
+import Text.Pandoc.Class (PandocIO)
 import Text.Pandoc.Definition
 import Text.Pandoc.Error
-import Text.Pandoc.Lua.Util (addValue)
+import Text.Pandoc.Lua.Init (runPandocLua)
+import Text.Pandoc.Lua.StackInstances ()
+import Text.Pandoc.Lua.Util (addValue, dostring')
 import Text.Pandoc.Options
 import Text.Pandoc.Templates
 import qualified Text.Pandoc.UTF8 as UTF8
@@ -60,74 +58,69 @@
     : ("class", unwords classes)
     : keyvals
 
-instance ToLuaStack Double where
-  push = push . (realToFrac :: Double -> LuaNumber)
-
-instance ToLuaStack Int where
-  push = push . (fromIntegral :: Int -> LuaInteger)
+newtype Stringify a = Stringify a
 
-instance ToLuaStack Format where
-  push (Format f) = push (map toLower f)
+instance ToLuaStack (Stringify Format) where
+  push (Stringify (Format f)) = push (map toLower f)
 
-#if MIN_VERSION_base(4,8,0)
-instance {-# OVERLAPS #-} ToLuaStack [Inline] where
-#else
-instance ToLuaStack [Inline] where
-#endif
-  push ils = push =<< inlineListToCustom ils
+instance ToLuaStack (Stringify [Inline]) where
+  push (Stringify ils) = push =<< inlineListToCustom ils
 
-#if MIN_VERSION_base(4,8,0)
-instance {-# OVERLAPS #-} ToLuaStack [Block] where
-#else
-instance ToLuaStack [Block] where
-#endif
-  push ils = push =<< blockListToCustom ils
+instance ToLuaStack (Stringify [Block]) where
+  push (Stringify blks) = push =<< blockListToCustom blks
 
-instance ToLuaStack MetaValue where
-  push (MetaMap m)       = push m
-  push (MetaList xs)     = push xs
-  push (MetaBool x)      = push x
-  push (MetaString s)    = push s
-  push (MetaInlines ils) = push ils
-  push (MetaBlocks bs)   = push bs
+instance ToLuaStack (Stringify MetaValue) where
+  push (Stringify (MetaMap m))       = push (fmap Stringify m)
+  push (Stringify (MetaList xs))     = push (map Stringify xs)
+  push (Stringify (MetaBool x))      = push x
+  push (Stringify (MetaString s))    = push s
+  push (Stringify (MetaInlines ils)) = push (Stringify ils)
+  push (Stringify (MetaBlocks bs))   = push (Stringify bs)
 
-instance ToLuaStack Citation where
-  push cit = do
+instance ToLuaStack (Stringify Citation) where
+  push (Stringify cit) = do
     createtable 6 0
     addValue "citationId" $ citationId cit
-    addValue "citationPrefix" $ citationPrefix cit
-    addValue "citationSuffix" $ citationSuffix cit
+    addValue "citationPrefix" . Stringify $ citationPrefix cit
+    addValue "citationSuffix" . Stringify $ citationSuffix cit
     addValue "citationMode" $ show (citationMode cit)
     addValue "citationNoteNum" $ citationNoteNum cit
     addValue "citationHash" $ citationHash cit
 
+-- | Key-value pair, pushed as a table with @a@ as the only key and @v@ as the
+-- associated value.
+newtype KeyValue a b = KeyValue (a, b)
+
+instance (ToLuaStack a, ToLuaStack b) => ToLuaStack (KeyValue a b) where
+  push (KeyValue (k, v)) = do
+    newtable
+    addValue k v
+
 data PandocLuaException = PandocLuaException String
     deriving (Show, Typeable)
 
 instance Exception PandocLuaException
 
 -- | Convert Pandoc to custom markup.
-writeCustom :: FilePath -> WriterOptions -> Pandoc -> IO Text
+writeCustom :: FilePath -> WriterOptions -> Pandoc -> PandocIO Text
 writeCustom luaFile opts doc@(Pandoc meta _) = do
-  luaScript <- UTF8.readFile luaFile
-  enc <- getForeignEncoding
-  setForeignEncoding utf8
-  (body, context) <- runLua $ do
-    openlibs
-    stat <- loadstring luaScript
+  luaScript <- liftIO $ UTF8.readFile luaFile
+  res <- runPandocLua $ do
+    stat <- dostring' luaScript
     -- check for error in lua script (later we'll change the return type
     -- to handle this more gracefully):
     when (stat /= OK) $
       tostring 1 >>= throw . PandocLuaException . UTF8.toString
-    call 0 0
-  -- TODO - call hierarchicalize, so we have that info
+    -- TODO - call hierarchicalize, so we have that info
     rendered <- docToCustom opts doc
     context <- metaToJSON opts
                blockListToCustom
                inlineListToCustom
                meta
     return (rendered, context)
-  setForeignEncoding enc
+  let (body, context) = case res of
+        Left e -> throw (PandocLuaException (show e))
+        Right x -> x
   case writerTemplate opts of
        Nothing  -> return $ pack body
        Just tpl ->
@@ -138,7 +131,7 @@
 docToCustom :: WriterOptions -> Pandoc -> Lua String
 docToCustom opts (Pandoc (Meta metamap) blocks) = do
   body <- blockListToCustom blocks
-  callFunc "Doc" body metamap (writerVariables opts)
+  callFunc "Doc" body (fmap Stringify metamap) (writerVariables opts)
 
 -- | Convert Pandoc block element to Custom.
 blockToCustom :: Block         -- ^ Block element
@@ -146,41 +139,46 @@
 
 blockToCustom Null = return ""
 
-blockToCustom (Plain inlines) = callFunc "Plain" inlines
+blockToCustom (Plain inlines) = callFunc "Plain" (Stringify inlines)
 
 blockToCustom (Para [Image attr txt (src,tit)]) =
-  callFunc "CaptionedImage" src tit txt (attrToMap attr)
+  callFunc "CaptionedImage" src tit (Stringify txt) (attrToMap attr)
 
-blockToCustom (Para inlines) = callFunc "Para" inlines
+blockToCustom (Para inlines) = callFunc "Para" (Stringify inlines)
 
-blockToCustom (LineBlock linesList) = callFunc "LineBlock" linesList
+blockToCustom (LineBlock linesList) = callFunc "LineBlock" (map Stringify linesList)
 
 blockToCustom (RawBlock format str) =
-  callFunc "RawBlock" format str
+  callFunc "RawBlock" (Stringify format) str
 
 blockToCustom HorizontalRule = callFunc "HorizontalRule"
 
 blockToCustom (Header level attr inlines) =
-  callFunc "Header" level inlines (attrToMap attr)
+  callFunc "Header" level (Stringify inlines) (attrToMap attr)
 
 blockToCustom (CodeBlock attr str) =
   callFunc "CodeBlock" str (attrToMap attr)
 
-blockToCustom (BlockQuote blocks) = callFunc "BlockQuote" blocks
+blockToCustom (BlockQuote blocks) = callFunc "BlockQuote" (Stringify blocks)
 
-blockToCustom (Table capt aligns widths headers rows') =
-  callFunc "Table" capt (map show aligns) widths headers rows'
+blockToCustom (Table capt aligns widths headers rows) =
+  let aligns' = map show aligns
+      capt' = Stringify capt
+      headers' = map Stringify headers
+      rows' = map (map Stringify) rows
+  in callFunc "Table" capt' aligns' widths headers' rows'
 
-blockToCustom (BulletList items) = callFunc "BulletList" items
+blockToCustom (BulletList items) = callFunc "BulletList" (map Stringify items)
 
 blockToCustom (OrderedList (num,sty,delim) items) =
-  callFunc "OrderedList" items num (show sty) (show delim)
+  callFunc "OrderedList" (map Stringify items) num (show sty) (show delim)
 
 blockToCustom (DefinitionList items) =
-  callFunc "DefinitionList" items
+  callFunc "DefinitionList"
+           (map (KeyValue . (Stringify *** map Stringify)) items)
 
 blockToCustom (Div attr items) =
-  callFunc "Div" items (attrToMap attr)
+  callFunc "Div" (Stringify items) (attrToMap attr)
 
 -- | Convert list of Pandoc block elements to Custom.
 blockListToCustom :: [Block]       -- ^ List of block elements
@@ -205,23 +203,23 @@
 
 inlineToCustom SoftBreak = callFunc "SoftBreak"
 
-inlineToCustom (Emph lst) = callFunc "Emph" lst
+inlineToCustom (Emph lst) = callFunc "Emph" (Stringify lst)
 
-inlineToCustom (Strong lst) = callFunc "Strong" lst
+inlineToCustom (Strong lst) = callFunc "Strong" (Stringify lst)
 
-inlineToCustom (Strikeout lst) = callFunc "Strikeout" lst
+inlineToCustom (Strikeout lst) = callFunc "Strikeout" (Stringify lst)
 
-inlineToCustom (Superscript lst) = callFunc "Superscript" lst
+inlineToCustom (Superscript lst) = callFunc "Superscript" (Stringify lst)
 
-inlineToCustom (Subscript lst) = callFunc "Subscript" lst
+inlineToCustom (Subscript lst) = callFunc "Subscript" (Stringify lst)
 
-inlineToCustom (SmallCaps lst) = callFunc "SmallCaps" lst
+inlineToCustom (SmallCaps lst) = callFunc "SmallCaps" (Stringify lst)
 
-inlineToCustom (Quoted SingleQuote lst) = callFunc "SingleQuoted" lst
+inlineToCustom (Quoted SingleQuote lst) = callFunc "SingleQuoted" (Stringify lst)
 
-inlineToCustom (Quoted DoubleQuote lst) = callFunc "DoubleQuoted" lst
+inlineToCustom (Quoted DoubleQuote lst) = callFunc "DoubleQuoted" (Stringify lst)
 
-inlineToCustom (Cite cs lst) = callFunc "Cite" lst cs
+inlineToCustom (Cite cs lst) = callFunc "Cite" (Stringify lst) (map Stringify cs)
 
 inlineToCustom (Code attr str) =
   callFunc "Code" str (attrToMap attr)
@@ -233,17 +231,17 @@
   callFunc "InlineMath" str
 
 inlineToCustom (RawInline format str) =
-  callFunc "RawInline" format str
+  callFunc "RawInline" (Stringify format) str
 
 inlineToCustom LineBreak = callFunc "LineBreak"
 
 inlineToCustom (Link attr txt (src,tit)) =
-  callFunc "Link" txt src tit (attrToMap attr)
+  callFunc "Link" (Stringify txt) src tit (attrToMap attr)
 
 inlineToCustom (Image attr alt (src,tit)) =
-  callFunc "Image" alt src tit (attrToMap attr)
+  callFunc "Image" (Stringify alt) src tit (attrToMap attr)
 
-inlineToCustom (Note contents) = callFunc "Note" contents
+inlineToCustom (Note contents) = callFunc "Note" (Stringify contents)
 
 inlineToCustom (Span attr items) =
-  callFunc "Span" items (attrToMap attr)
+  callFunc "Span" (Stringify items) (attrToMap attr)
diff --git a/src/Text/Pandoc/Writers/Docx.hs b/src/Text/Pandoc/Writers/Docx.hs
--- a/src/Text/Pandoc/Writers/Docx.hs
+++ b/src/Text/Pandoc/Writers/Docx.hs
@@ -213,8 +213,12 @@
   let doc' = walk fixDisplayMath doc
   username <- P.lookupEnv "USERNAME"
   utctime <- P.getCurrentTime
-  distArchive <- (toArchive . BL.fromStrict) <$>
-                      P.readDefaultDataFile "reference.docx"
+  distArchive <- (toArchive . BL.fromStrict) <$> do
+    oldUserDataDir <- P.getUserDataDir
+    P.setUserDataDir Nothing
+    res <- P.readDefaultDataFile "reference.docx"
+    P.setUserDataDir oldUserDataDir
+    return res
   refArchive <- case writerReferenceDoc opts of
                      Just f  -> toArchive <$> P.readFileLazy f
                      Nothing -> (toArchive . BL.fromStrict) <$>
diff --git a/src/Text/Pandoc/Writers/FB2.hs b/src/Text/Pandoc/Writers/FB2.hs
--- a/src/Text/Pandoc/Writers/FB2.hs
+++ b/src/Text/Pandoc/Writers/FB2.hs
@@ -121,9 +121,18 @@
                Just (MetaString s)        -> [el "lang" $ iso639 s]
                _                          -> []
              where iso639 = takeWhile (/= '-') -- Convert BCP 47 to ISO 639
+  let coverimage url = do
+        let img = Image nullAttr mempty (url, "")
+        im <- insertImage InlineImage img
+        return [el "coverpage" im]
+  coverpage <- case lookupMeta "cover-image" meta' of
+                    Just (MetaInlines [Str s]) -> coverimage s
+                    Just (MetaString s) -> coverimage s
+                    _       -> return []
   return $ el "description"
     [ el "title-info" (genre : (bt ++ as ++ dd ++ lang))
-    , el "document-info" [ el "program-used" "pandoc" ] -- FIXME: +version
+    , el "document-info" ([ el "program-used" "pandoc" ] -- FIXME: +version
+                          ++ coverpage)
     ]
 
 booktitle :: PandocMonad m => Meta -> FBM m [Content]
diff --git a/src/Text/Pandoc/Writers/HTML.hs b/src/Text/Pandoc/Writers/HTML.hs
--- a/src/Text/Pandoc/Writers/HTML.hs
+++ b/src/Text/Pandoc/Writers/HTML.hs
@@ -670,8 +670,7 @@
   if writerWrapText opts == WrapNone
   then blockToHtml opts $ linesToPara lns
   else do
-    let lf = preEscapedString "\n"
-    htmlLines <- mconcat . intersperse lf <$> mapM (inlineListToHtml opts) lns
+    htmlLines <- inlineListToHtml opts $ intercalate [LineBreak] lns
     return $ H.div ! A.class_ "line-block" $ htmlLines
 blockToHtml opts (Div attr@(ident, classes, kvs') bs) = do
   html5 <- gets stHtml5
diff --git a/src/Text/Pandoc/Writers/JATS.hs b/src/Text/Pandoc/Writers/JATS.hs
--- a/src/Text/Pandoc/Writers/JATS.hs
+++ b/src/Text/Pandoc/Writers/JATS.hs
@@ -159,6 +159,39 @@
            maybe empty (\lbl -> inTagsIndented "label" (text lbl)) mbmarker
            $$ contents
 
+imageMimeType :: String -> [(String, String)] -> (String, String)
+imageMimeType src kvs =
+  let mbMT = getMimeType src
+      maintype = fromMaybe "image" $
+                  lookup "mimetype" kvs `mplus`
+                  (takeWhile (/='/') <$> mbMT)
+      subtype = fromMaybe "" $
+                  lookup "mime-subtype" kvs `mplus`
+                  ((drop 1 . dropWhile (/='/')) <$> mbMT)
+  in (maintype, subtype)
+
+languageFor :: [String] -> String
+languageFor classes =
+  case langs of
+     (l:_) -> escapeStringForXML l
+     []    -> ""
+    where isLang l    = map toLower l `elem` map (map toLower) languages
+          langsFrom s = if isLang s
+                           then [s]
+                           else languagesByExtension . map toLower $ s
+          langs       = concatMap langsFrom classes
+
+codeAttr :: Attr -> (String, [(String, String)])
+codeAttr (ident,classes,kvs) = (lang, attr)
+    where
+       attr = [("id",ident) | not (null ident)] ++
+              [("language",lang) | not (null lang)] ++
+              [(k,v) | (k,v) <- kvs, k `elem` ["code-type",
+                "code-version", "executable",
+                "language-version", "orientation",
+                    "platforms", "position", "specific-use"]]
+       lang  = languageFor classes
+
 -- | Convert a Pandoc block element to JATS.
 blockToJATS :: PandocMonad m => WriterOptions -> Block -> JATS m Doc
 blockToJATS _ Null = return empty
@@ -168,6 +201,13 @@
 blockToJATS opts (Div ("refs",_,_) xs) = do
   contents <- blocksToJATS opts xs
   return $ inTagsIndented "ref-list" contents
+blockToJATS opts (Div (ident,[cls],kvs) bs) | cls `elem` ["fig", "caption", "table-wrap"] = do
+  contents <- blocksToJATS opts bs
+  let attr = [("id", ident) | not (null ident)] ++
+             [("xml:lang",l) | ("lang",l) <- kvs] ++
+             [(k,v) | (k,v) <- kvs, k `elem` ["specific-use",
+                 "content-type", "orientation", "position"]]
+  return $ inTags True cls attr contents
 blockToJATS opts (Div (ident,_,kvs) bs) = do
   contents <- blocksToJATS opts bs
   let attr = [("id", ident) | not (null ident)] ++
@@ -175,58 +215,50 @@
              [(k,v) | (k,v) <- kvs, k `elem` ["specific-use",
                  "content-type", "orientation", "position"]]
   return $ inTags True "boxed-text" attr contents
-blockToJATS _ h@(Header{}) = do
-  -- should not occur after hierarchicalize, except inside lists/blockquotes
-  report $ BlockNotRendered h
-  return empty
+blockToJATS opts (Header _ _ title) = do
+  title' <- inlinesToJATS opts title
+  return $ inTagsSimple "title" title'
 -- No Plain, everything needs to be in a block-level tag
 blockToJATS opts (Plain lst) = blockToJATS opts (Para lst)
 -- title beginning with fig: indicates that the image is a figure
 blockToJATS opts (Para [Image (ident,_,kvs) txt
   (src,'f':'i':'g':':':tit)]) = do
   alt <- inlinesToJATS opts txt
+  let (maintype, subtype) = imageMimeType src kvs
   let capt = if null txt
                 then empty
                 else inTagsSimple "caption" alt
   let attr = [("id", ident) | not (null ident)] ++
              [(k,v) | (k,v) <- kvs, k `elem` ["fig-type", "orientation",
                                               "position", "specific-use"]]
-  let mbMT = getMimeType src
-  let maintype = fromMaybe "image" $
-                  lookup "mimetype" kvs `mplus`
-                  (takeWhile (/='/') <$> mbMT)
-  let subtype = fromMaybe "" $
-                  lookup "mime-subtype" kvs `mplus`
-                  ((drop 1 . dropWhile (/='/')) <$> mbMT)
   let graphicattr = [("mimetype",maintype),
-                     ("mime-subtype",drop 1 subtype),
+                     ("mime-subtype",subtype),
                      ("xlink:href",src),  -- do we need to URL escape this?
                      ("xlink:title",tit)]
   return $ inTags True "fig" attr $
               capt $$ selfClosingTag "graphic" graphicattr
+blockToJATS _ (Para [Image (ident,_,kvs) _ (src, tit)]) = do
+  let (maintype, subtype) = imageMimeType src kvs
+  let attr = [("id", ident) | not (null ident)] ++
+             [("mimetype", maintype),
+              ("mime-subtype", subtype),
+              ("xlink:href", src)] ++
+             [("xlink:title", tit) | not (null tit)] ++
+             [(k,v) | (k,v) <- kvs, k `elem` ["baseline-shift",
+                        "content-type", "specific-use", "xlink:actuate",
+                        "xlink:href", "xlink:role", "xlink:show",
+                        "xlink:type"]]
+  return $ selfClosingTag "graphic" attr
 blockToJATS opts (Para lst) =
   inTagsIndented "p" <$> inlinesToJATS opts lst
 blockToJATS opts (LineBlock lns) =
   blockToJATS opts $ linesToPara lns
 blockToJATS opts (BlockQuote blocks) =
   inTagsIndented "disp-quote" <$> blocksToJATS opts blocks
-blockToJATS _ (CodeBlock (ident,classes,kvs) str) = return $
+blockToJATS _ (CodeBlock a str) = return $
   inTags False tag attr (flush (text (escapeStringForXML str)))
-    where attr  = [("id",ident) | not (null ident)] ++
-                  [("language",lang) | not (null lang)] ++
-                  [(k,v) | (k,v) <- kvs, k `elem` ["code-type",
-                    "code-version", "executable",
-                    "language-version", "orientation",
-                    "platforms", "position", "specific-use"]]
-          tag   = if null lang then "preformat" else "code"
-          lang  = case langs of
-                     (l:_) -> escapeStringForXML l
-                     []    -> ""
-          isLang l    = map toLower l `elem` map (map toLower) languages
-          langsFrom s = if isLang s
-                           then [s]
-                           else languagesByExtension . map toLower $ s
-          langs       = concatMap langsFrom classes
+    where (lang, attr) = codeAttr a
+          tag          = if null lang then "preformat" else "code"
 blockToJATS _ (BulletList []) = return empty
 blockToJATS opts (BulletList lst) =
   inTags True "list" [("list-type", "bullet")] <$>
@@ -293,6 +325,9 @@
                    -> Bool
                    -> [Block]
                    -> JATS m Doc
+tableItemToJATS opts isHeader [Plain item] =
+  inTags True (if isHeader then "th" else "td") [] <$>
+    inlinesToJATS opts item
 tableItemToJATS opts isHeader item =
   (inTags True (if isHeader then "th" else "td") [] . vcat) <$>
     mapM (blockToJATS opts) item
@@ -323,8 +358,10 @@
 inlineToJATS opts (Quoted DoubleQuote lst) = do
   contents <- inlinesToJATS opts lst
   return $ char '“' <> contents <> char '”'
-inlineToJATS _ (Code _ str) =
-  return $ inTagsSimple "monospace" $ text (escapeStringForXML str)
+inlineToJATS _ (Code a str) =
+  return $ inTags False tag attr $ text (escapeStringForXML str)
+    where (lang, attr) = codeAttr a
+          tag          = if null lang then "monospace" else "code"
 inlineToJATS _ il@(RawInline f x)
   | f == "jats" = return $ text x
   | otherwise   = do
@@ -379,11 +416,14 @@
   return $ inTagsSimple "email" $ text (escapeStringForXML email)
 inlineToJATS opts (Link (ident,_,kvs) txt ('#':src, _)) = do
   let attr = [("id", ident) | not (null ident)] ++
-             [("alt", stringify txt),
-              ("rid", src)] ++
+             [("alt", stringify txt) | not (null txt)] ++
+             [("rid", src)] ++
              [(k,v) | (k,v) <- kvs, k `elem` ["ref-type", "specific-use"]]
-  contents <- inlinesToJATS opts txt
-  return $ inTags False "xref" attr contents
+  if null txt
+     then return $ selfClosingTag "xref" attr
+     else do
+        contents <- inlinesToJATS opts txt
+        return $ inTags False "xref" attr contents
 inlineToJATS opts (Link (ident,_,kvs) txt (src, tit)) = do
   let attr = [("id", ident) | not (null ident)] ++
              [("ext-link-type", "uri"),
diff --git a/src/Text/Pandoc/Writers/LaTeX.hs b/src/Text/Pandoc/Writers/LaTeX.hs
--- a/src/Text/Pandoc/Writers/LaTeX.hs
+++ b/src/Text/Pandoc/Writers/LaTeX.hs
@@ -276,10 +276,13 @@
                     "\\AddBabelHook{" ++ poly ++ "}{afterextras}" ++
                       "{\\renewcommand{\\text" ++ poly ++ "}[2][]{\\foreignlanguage{"
                       ++ poly ++ "}{##2}}}\n"
-               else "\\newcommand{\\text" ++ poly ++ "}[2][]{\\foreignlanguage{"
-                      ++ babel ++ "}{#2}}\n" ++
-                    "\\newenvironment{" ++ poly ++ "}[2][]{\\begin{otherlanguage}{"
-                      ++ babel ++ "}}{\\end{otherlanguage}}\n"
+               else (if poly == "latin" -- see #4161
+                        then "\\providecommand{\\textlatin}{}\n\\renewcommand"
+                        else "\\newcommand") ++ "{\\text" ++ poly ++
+                    "}[2][]{\\foreignlanguage{" ++ babel ++ "}{#2}}\n" ++
+                    "\\newenvironment{" ++ poly ++
+                    "}[2][]{\\begin{otherlanguage}{" ++
+                    babel ++ "}}{\\end{otherlanguage}}\n"
             )
             -- eliminate duplicates that have same polyglossia name
             $ nubBy (\a b -> fst a == fst b)
@@ -395,10 +398,10 @@
           hasCode _          = []
       let fragile = "fragile" `elem` classes ||
                     not (null $ query hasCodeBlock elts ++ query hasCode elts)
-      let frameoptions = ["allowdisplaybreaks", "allowframebreaks",
+      let frameoptions = ["allowdisplaybreaks", "allowframebreaks", "fragile",
                           "b", "c", "t", "environment",
                           "label", "plain", "shrink", "standout"]
-      let optionslist = ["fragile" | fragile] ++
+      let optionslist = ["fragile" | fragile && lookup "fragile" kvs == Nothing] ++
                         [k | k <- classes, k `elem` frameoptions] ++
                         [k ++ "=" ++ v | (k,v) <- kvs, k `elem` frameoptions]
       let options = if null optionslist
@@ -696,10 +699,9 @@
                   then return empty
                   else ($$ text "\\endfirsthead") <$> toHeaders heads
   head' <- if all null heads
-              then return empty
+              then return "\\toprule"
               -- avoid duplicate notes in head and firsthead:
-              else ($$ text "\\endhead") <$>
-                   toHeaders (if isEmpty firsthead
+              else toHeaders (if isEmpty firsthead
                                  then heads
                                  else walk removeNote heads)
   let capt = if isEmpty captionText
@@ -714,8 +716,8 @@
               -- the @{} removes extra space at beginning and end
          $$ capt
          $$ firsthead
-         $$ (if all null heads then "\\toprule" else empty)
          $$ head'
+         $$ "\\endhead"
          $$ vcat rows'
          $$ "\\bottomrule"
          $$ "\\end{longtable}"
diff --git a/src/Text/Pandoc/Writers/Markdown.hs b/src/Text/Pandoc/Writers/Markdown.hs
--- a/src/Text/Pandoc/Writers/Markdown.hs
+++ b/src/Text/Pandoc/Writers/Markdown.hs
@@ -305,22 +305,24 @@
        _ -> c : escapeString opts cs
 
 -- | Construct table of contents from list of header blocks.
-tableOfContents :: PandocMonad m => WriterOptions -> [Block] -> m Doc
-tableOfContents opts headers =
-  let contents = BulletList $ map (elementToListItem opts) $ hierarchicalize headers
-  in  evalMD (blockToMarkdown opts contents) def def
+tableOfContents :: PandocMonad m => WriterOptions -> [Block] -> MD m Doc
+tableOfContents opts headers = do
+  contents <- BulletList <$> mapM (elementToListItem opts) (hierarchicalize headers)
+  blockToMarkdown opts contents
 
 -- | Converts an Element to a list item for a table of contents,
-elementToListItem :: WriterOptions -> Element -> [Block]
+elementToListItem :: PandocMonad m => WriterOptions -> Element -> MD m [Block]
 elementToListItem opts (Sec lev _nums (ident,_,_) headerText subsecs)
-  = Plain headerLink :
-    [ BulletList (map (elementToListItem opts) subsecs) |
-      not (null subsecs) && lev < writerTOCDepth opts ]
-   where headerLink = if null ident
+  = do isPlain <- asks envPlain
+       let headerLink = if null ident || isPlain
                          then walk deNote headerText
                          else [Link nullAttr (walk deNote headerText)
                                  ('#':ident, "")]
-elementToListItem _ (Blk _) = []
+       listContents <- if null subsecs || lev >= writerTOCDepth opts
+                          then return []
+                          else mapM (elementToListItem opts) subsecs
+       return [Plain headerLink, BulletList listContents]
+elementToListItem _ (Blk _) = return []
 
 attrsToMarkdown :: Attr -> Doc
 attrsToMarkdown attribs = braces $ hsep [attribId, attribClasses, attribKeys]
diff --git a/src/Text/Pandoc/Writers/Muse.hs b/src/Text/Pandoc/Writers/Muse.hs
--- a/src/Text/Pandoc/Writers/Muse.hs
+++ b/src/Text/Pandoc/Writers/Muse.hs
@@ -229,7 +229,7 @@
                  else "#" <> text ident <> cr
   let header' = text $ replicate level '*'
   return $ blankline <> nowrap (header' <> space <> contents)
-                 <> blankline <> attr'
+                 $$ attr' <> blankline
 -- https://www.gnu.org/software/emacs-muse/manual/muse.html#Horizontal-Rules-and-Anchors
 blockToMuse HorizontalRule = return $ blankline $$ "----" $$ blankline
 blockToMuse (Table caption _ _ headers rows) =  do
@@ -313,11 +313,17 @@
 normalizeInlineList (x:xs) = x : normalizeInlineList xs
 normalizeInlineList [] = []
 
+fixNotes :: [Inline] -> [Inline]
+fixNotes [] = []
+fixNotes (Space : n@Note{} : rest) = Str " " : n : fixNotes rest
+fixNotes (SoftBreak : n@Note{} : rest) = Str " " : n : fixNotes rest
+fixNotes (x:xs) = x : fixNotes xs
+
 -- | Convert list of Pandoc inline elements to Muse.
 inlineListToMuse :: PandocMonad m
                  => [Inline]
                  -> StateT WriterState m Doc
-inlineListToMuse lst = liftM hcat (mapM inlineToMuse (normalizeInlineList lst))
+inlineListToMuse lst = hcat <$> mapM inlineToMuse (fixNotes $ normalizeInlineList lst)
 
 -- | Convert Pandoc inline element to Muse.
 inlineToMuse :: PandocMonad m
diff --git a/src/Text/Pandoc/Writers/OOXML.hs b/src/Text/Pandoc/Writers/OOXML.hs
--- a/src/Text/Pandoc/Writers/OOXML.hs
+++ b/src/Text/Pandoc/Writers/OOXML.hs
@@ -76,12 +76,12 @@
                        Nothing -> fail $ relpath ++ " corrupt in reference file"
                        Just d  -> return d
 
--- Copied from Util                       
+-- Copied from Util
 
 attrToNSPair :: XML.Attr -> Maybe (String, String)
 attrToNSPair (XML.Attr (QName s _ (Just "xmlns")) val) = Just (s, val)
 attrToNSPair _                                     = Nothing
-                       
+
 
 elemToNameSpaces :: Element -> NameSpaces
 elemToNameSpaces = mapMaybe attrToNSPair . elAttribs
diff --git a/src/Text/Pandoc/Writers/Org.hs b/src/Text/Pandoc/Writers/Org.hs
--- a/src/Text/Pandoc/Writers/Org.hs
+++ b/src/Text/Pandoc/Writers/Org.hs
@@ -308,7 +308,18 @@
 inlineListToOrg :: PandocMonad m
                 => [Inline]
                 -> Org m Doc
-inlineListToOrg lst = hcat <$> mapM inlineToOrg lst
+inlineListToOrg lst = hcat <$> mapM inlineToOrg (fixMarkers lst)
+  where fixMarkers [] = []  -- prevent note refs and list markers from wrapping, see #4171
+        fixMarkers (Space : x : rest) | shouldFix x =
+          Str " " : x : fixMarkers rest
+        fixMarkers (SoftBreak : x : rest) | shouldFix x =
+          Str " " : x : fixMarkers rest
+        fixMarkers (x : rest) = x : fixMarkers rest
+
+        shouldFix Note{} = True -- Prevent footnotes
+        shouldFix (Str "-") = True -- Prevent bullet list items
+        -- TODO: prevent ordered list items
+        shouldFix _ = False
 
 -- | Convert Pandoc inline element to Org.
 inlineToOrg :: PandocMonad m => Inline -> Org m Doc
diff --git a/src/Text/Pandoc/Writers/Powerpoint.hs b/src/Text/Pandoc/Writers/Powerpoint.hs
--- a/src/Text/Pandoc/Writers/Powerpoint.hs
+++ b/src/Text/Pandoc/Writers/Powerpoint.hs
@@ -86,6 +86,9 @@
                 , envDistArchive = distArchive
                 , envUTCTime = utctime
                 , envOpts = opts
+                , envSlideLevel = case writerSlideLevel opts of
+                                    Just n -> n
+                                    Nothing -> 2
                 }
   runP env def $ do pres <- blocksToPresentation blks'
                     archv <- presentationToArchive pres
@@ -105,6 +108,7 @@
                            , envPresentationSize :: PresentationSize
                            , envSlideHasHeader :: Bool
                            , envInList :: Bool
+                           , envInNoteSlide :: Bool
                            }
                  deriving (Show)
 
@@ -120,6 +124,7 @@
                   , envPresentationSize = def
                   , envSlideHasHeader = False
                   , envInList = False
+                  , envInNoteSlide = False
                   }
 
 data MediaInfo = MediaInfo { mInfoFilePath :: FilePath
@@ -139,6 +144,7 @@
                                -- (FP, Local ID, Global ID, Maybe Mime)
                                , stMediaIds :: M.Map Int [MediaInfo]
                                , stMediaGlobalIds :: M.Map FilePath Int
+                               , stNoteIds :: M.Map Int [Block]
                                } deriving (Show, Eq)
 
 instance Default WriterState where
@@ -147,6 +153,7 @@
                     , stLinkIds = mempty
                     , stMediaIds = mempty
                     , stMediaGlobalIds = mempty
+                    , stNoteIds = mempty
                     }
 
 type P m = ReaderT WriterEnv (StateT WriterState m)
@@ -174,7 +181,7 @@
 getPageHeight sz = case presSizeRatio sz of
   Ratio4x3 -> floor (((fromInteger (presSizeWidth sz)) / 4) * 3 :: Double)
   Ratio16x9 -> floor (((fromInteger (presSizeWidth sz)) / 16) * 9 :: Double)
-  Ratio16x10 -> floor (((fromInteger (presSizeWidth sz)) / 16) * 10 :: Double)  
+  Ratio16x10 -> floor (((fromInteger (presSizeWidth sz)) / 16) * 10 :: Double)
 
 instance Default PresentationSize where
   def = PresentationSize 720 Ratio4x3
@@ -183,7 +190,7 @@
                             , metadataSlideSubtitle :: [ParaElem]
                             , metadataSlideAuthors :: [[ParaElem]]
                             , metadataSlideDate :: [ParaElem]
-                            } 
+                            }
            | TitleSlide { titleSlideHeader :: [ParaElem]}
            | ContentSlide { contentSlideHeader :: [ParaElem]
                           , contentSlideContent :: [Shape]
@@ -206,7 +213,7 @@
 
 type ColWidth = Integer
 
-data Graphic = Tbl TableProps [ColWidth] [Cell] [[Cell]] 
+data Graphic = Tbl TableProps [ColWidth] [Cell] [[Cell]]
   deriving (Show, Eq)
 
 
@@ -217,7 +224,7 @@
 data HeaderType = TitleHeader | SlideHeader | InternalHeader Int
                 deriving (Show, Eq)
 
--- type StartingAt = Int 
+-- type StartingAt = Int
 
 -- data AutoNumType = ArabicNum
 --                  | AlphaUpperNum
@@ -300,6 +307,7 @@
                          , rLink :: Maybe (URL, String)
                          , rPropCode :: Bool
                          , rPropBlockQuote :: Bool
+                         , rPropForceSize :: Maybe Pixels
                          } deriving (Show, Eq)
 
 instance Default RunProps where
@@ -311,6 +319,7 @@
                  , rLink = Nothing
                  , rPropCode = False
                  , rPropBlockQuote = False
+                 , rPropForceSize = Nothing
                  }
 
 --------------------------------------------------
@@ -351,10 +360,24 @@
     inlineToParElems $ Str str
 inlineToParElems (Math mathtype str) =
   return [MathElem mathtype (TeXString str)]
+inlineToParElems (Note blks) = do
+  notes <- gets stNoteIds
+  let maxNoteId = case M.keys notes of
+        [] -> 0
+        lst -> maximum lst
+      curNoteId = maxNoteId + 1
+  modify $ \st -> st { stNoteIds = M.insert curNoteId blks notes }
+  inlineToParElems $ Superscript [Str $ show curNoteId]
 inlineToParElems (Span _ ils) = concatMapM inlineToParElems ils
 inlineToParElems (RawInline _ _) = return []
 inlineToParElems _ = return []
 
+isListType :: Block -> Bool
+isListType (OrderedList _ _) = True
+isListType (BulletList _) = True
+isListType (DefinitionList _) = True
+isListType _ = False
+
 blockToParagraphs :: PandocMonad m => Block -> P m [Paragraph]
 blockToParagraphs (Plain ils) = do
   parElems <- inlinesToParElems ils
@@ -362,7 +385,7 @@
   return [Paragraph pProps parElems]
 blockToParagraphs (Para ils) = do
   parElems <- inlinesToParElems ils
-  pProps <- asks envParaProps  
+  pProps <- asks envParaProps
   return [Paragraph pProps parElems]
 blockToParagraphs (LineBlock ilsList) = do
   parElems <- inlinesToParElems $ intercalate [LineBreak] ilsList
@@ -372,17 +395,23 @@
 blockToParagraphs (CodeBlock attr str) =
   local (\r -> r{envParaProps = def{pPropMarginLeft = Just 100}}) $
   blockToParagraphs $ Para [Code attr str]
--- TODO: work out the format
+-- We can't yet do incremental lists, but we should render a
+-- (BlockQuote List) as a list to maintain compatibility with other
+-- formats.
+blockToParagraphs (BlockQuote (blk : blks)) | isListType blk = do
+  ps  <- blockToParagraphs blk
+  ps' <- blockToParagraphs $ BlockQuote blks
+  return $ ps ++ ps'
 blockToParagraphs (BlockQuote blks) =
   local (\r -> r{ envParaProps = (envParaProps r){pPropMarginLeft = Just 100}
-                , envRunProps = (envRunProps r){rPropBlockQuote = True}})$
+                , envRunProps = (envRunProps r){rPropForceSize = Just blockQuoteSize}})$
   concatMapM blockToParagraphs blks
 -- TODO: work out the format
 blockToParagraphs (RawBlock _ _) = return []
   -- parElems <- inlinesToParElems [Str str]
-  -- paraProps <- asks envParaProps  
+  -- paraProps <- asks envParaProps
   -- return [Paragraph paraProps parElems]
--- TODO: work out the format  
+-- TODO: work out the format
 blockToParagraphs (Header n _ ils) = do
   slideLevel <- asks envSlideLevel
   parElems <- inlinesToParElems ils
@@ -411,6 +440,15 @@
                                            , pPropMarginLeft = Nothing
                                            }}) $
     concatMapM multiParBullet blksLst
+blockToParagraphs (DefinitionList entries) = do
+  let go :: PandocMonad m => ([Inline], [[Block]]) -> P m [Paragraph]
+      go (ils, blksLst) = do
+        term <-blockToParagraphs $ Para [Strong ils]
+        -- For now, we'll treat each definition term as a
+        -- blockquote. We can extend this further later.
+        definition <- concatMapM (blockToParagraphs . BlockQuote) blksLst
+        return $ term ++ definition
+  concatMapM go entries
 blockToParagraphs (Div _ blks)  = concatMapM blockToParagraphs blks
 -- TODO
 blockToParagraphs blk = do
@@ -490,7 +528,7 @@
     EQ -> splitBlocks' [h] (acc ++ (if null cur then [] else [cur])) blks
     GT -> splitBlocks' (cur ++ [h]) acc blks
 splitBlocks' cur acc ((Para (img@(Image _ _ _):ils)) : blks) = do
-  slideLevel <- asks envSlideLevel  
+  slideLevel <- asks envSlideLevel
   case cur of
     (Header n _ _) : [] | n == slideLevel ->
                             splitBlocks' []
@@ -500,7 +538,7 @@
           (acc ++ (if null cur then [] else [cur]) ++ [[Para [img]]])
           (if null ils then blks else (Para ils) : blks)
 splitBlocks' cur acc ((Plain (img@(Image _ _ _):ils)) : blks) = do
-  slideLevel <- asks envSlideLevel  
+  slideLevel <- asks envSlideLevel
   case cur of
     (Header n _ _) : [] | n == slideLevel ->
                             splitBlocks' []
@@ -510,7 +548,7 @@
           (acc ++ (if null cur then [] else [cur]) ++ [[Para [img]]])
           (if null ils then blks else (Plain ils) : blks)
 splitBlocks' cur acc (tbl@(Table _ _ _ _ _) : blks) = do
-  slideLevel <- asks envSlideLevel  
+  slideLevel <- asks envSlideLevel
   case cur of
     (Header n _ _) : [] | n == slideLevel ->
                             splitBlocks' [] (acc ++ [cur ++ [tbl]]) blks
@@ -527,12 +565,18 @@
       return $ TitleSlide {titleSlideHeader = hdr}
   | n == lvl = do
       hdr <- inlinesToParElems ils
-      shapes <- blocksToShapes blks
+      inNoteSlide <- asks envInNoteSlide
+      shapes <- if inNoteSlide
+                then forceFontSize noteSize $ blocksToShapes blks
+                else blocksToShapes blks
       return $ ContentSlide { contentSlideHeader = hdr
                             , contentSlideContent = shapes
                             }
 blocksToSlide' _ (blk : blks) = do
-      shapes <- blocksToShapes (blk : blks)
+      inNoteSlide <- asks envInNoteSlide
+      shapes <- if inNoteSlide
+                then forceFontSize noteSize $ blocksToShapes (blk : blks)
+                else blocksToShapes (blk : blks)
       return $ ContentSlide { contentSlideHeader = []
                             , contentSlideContent = shapes
                             }
@@ -545,6 +589,38 @@
   slideLevel <- asks envSlideLevel
   blocksToSlide' slideLevel blks
 
+makeNoteEntry :: Int -> [Block] -> [Block]
+makeNoteEntry n blks =
+  let enum = Str (show n ++ ".")
+  in
+    case blks of
+      (Para ils : blks') -> (Para $ enum : Space : ils) : blks'
+      _ -> (Para [enum]) : blks
+
+forceFontSize :: PandocMonad m => Pixels -> P m a -> P m a
+forceFontSize px x = do
+  rpr <- asks envRunProps
+  local (\r -> r {envRunProps = rpr{rPropForceSize = Just px}}) x
+
+-- Right now, there's no logic for making more than one slide, but I
+-- want to leave the option open to make multiple slides if we figure
+-- out how to guess at how much space the text of the notes will take
+-- up (or if we allow a way for it to be manually controlled). Plus a
+-- list will make it easier to put together in the final
+-- `blocksToPresentation` function (since we can just add an empty
+-- list without checking the state).
+makeNotesSlides :: PandocMonad m => P m [Slide]
+makeNotesSlides = local (\env -> env{envInNoteSlide=True}) $ do
+  noteIds <- gets stNoteIds
+  if M.null noteIds
+    then return []
+    else do let hdr = Header 2 nullAttr [Str "Notes"]
+            blks <- return $
+                    concatMap (\(n, bs) -> makeNoteEntry n bs) $
+                    M.toList noteIds
+            sld <- blocksToSlide $ hdr : blks
+            return [sld]
+
 getMetaSlide :: PandocMonad m => P m (Maybe Slide)
 getMetaSlide  = do
   meta <- asks envMetadata
@@ -570,11 +646,13 @@
 blocksToPresentation blks = do
   blksLst <- splitBlocks blks
   slides <- mapM blocksToSlide blksLst
+  noteSlides <- makeNotesSlides
+  let slides' = slides ++ noteSlides
   metadataslide <- getMetaSlide
   presSize <- asks envPresentationSize
   return $ case metadataslide of
-             Just metadataslide' -> Presentation presSize $ metadataslide' : slides
-             Nothing            -> Presentation presSize slides
+             Just metadataslide' -> Presentation presSize $ metadataslide' : slides'
+             Nothing            -> Presentation presSize slides'
 
 --------------------------------------------------------------------
 
@@ -592,8 +670,8 @@
   distArchive <- asks envDistArchive
   let allEntries = nub $ filesInArchive refArchive ++ filesInArchive distArchive
   return $ filter (isPrefixOf "ppt/media") allEntries
-  
 
+
 copyFileToArchiveIfExists :: PandocMonad m => Archive -> FilePath -> P m Archive
 copyFileToArchiveIfExists arch fp = do
   refArchive <- asks envRefArchive
@@ -635,7 +713,7 @@
                  -- , "ppt/slides/_rels/slide2.xml.rels"
                  -- This is the one we're
                  -- going to build
-                 -- , "ppt/slides/slide2.xml" 
+                 -- , "ppt/slides/slide2.xml"
                  -- , "ppt/slides/slide1.xml"
                  , "ppt/viewProps.xml"
                  , "ppt/tableStyles.xml"
@@ -670,7 +748,7 @@
     slideEntries ++
     slideRelEntries ++
     mediaEntries ++
-    [contentTypesEntry, presEntry, presRelsEntry] 
+    [contentTypesEntry, presEntry, presRelsEntry]
 
 --------------------------------------------------
 
@@ -726,25 +804,25 @@
 
 -- getContentTitleShape :: NameSpaces -> Element -> Maybe Element
 -- getContentTitleShape ns spTreeElem
---   | isElem ns "p" "spTree" spTreeElem = 
+--   | isElem ns "p" "spTree" spTreeElem =
 --   filterChild (\e -> (isElem ns "p" "sp" e) && (shapeHasName ns "Title 1" e)) spTreeElem
 --   | otherwise = Nothing
 
 -- getSubtitleShape :: NameSpaces -> Element -> Maybe Element
 -- getSubtitleShape ns spTreeElem
---   | isElem ns "p" "spTree" spTreeElem = 
+--   | isElem ns "p" "spTree" spTreeElem =
 --   filterChild (\e -> (isElem ns "p" "sp" e) && (shapeHasName ns "Subtitle 2" e)) spTreeElem
 --   | otherwise = Nothing
 
 -- getDateShape :: NameSpaces -> Element -> Maybe Element
 -- getDateShape ns spTreeElem
---   | isElem ns "p" "spTree" spTreeElem = 
+--   | isElem ns "p" "spTree" spTreeElem =
 --   filterChild (\e -> (isElem ns "p" "sp" e) && (shapeHasName ns "Date Placeholder 3" e)) spTreeElem
 --   | otherwise = Nothing
-  
+
 getContentShape :: NameSpaces -> Element -> Maybe Element
 getContentShape ns spTreeElem
-  | isElem ns "p" "spTree" spTreeElem = 
+  | isElem ns "p" "spTree" spTreeElem =
   filterChild (\e -> (isElem ns "p" "sp" e) && (shapeHasName ns "Content Placeholder 2" e)) spTreeElem
   | otherwise = Nothing
 
@@ -831,7 +909,7 @@
 
   (imgBytes, mbMt) <- P.fetchItem fp
   let imgExt = (mbMt >>= extensionFromMimeType >>= (\x -> return $ '.':x))
-               <|> 
+               <|>
                case imageType imgBytes of
                  Just Png  -> Just ".png"
                  Just Jpeg -> Just ".jpeg"
@@ -840,7 +918,7 @@
                  Just Eps  -> Just ".eps"
                  Just Svg  -> Just ".svg"
                  Nothing   -> Nothing
-  
+
   let newGlobalId = case M.lookup fp globalIds of
         Just ident -> ident
         Nothing    -> maxGlobalId + 1
@@ -893,7 +971,7 @@
       (floor x, floor y)
   | x / fromIntegral pageWidth > y / fromIntegral pageWidth =
       (pageWidth, floor $ ((fromIntegral pageWidth) / x) * y)
-  | otherwise = 
+  | otherwise =
       (floor $ ((fromIntegral pageHeight) / y) * x, pageHeight)
 
 positionImage :: (Double, Double) -> Integer -> Integer -> (Integer, Integer)
@@ -957,7 +1035,7 @@
 createCaption paraElements = do
   let para = Paragraph def{pPropAlign = Just AlgnCenter} paraElements
   elements <- mapM paragraphToElement [para]
-  let ((x, y), (cx, cy)) = captionPosition  
+  let ((x, y), (cx, cy)) = captionPosition
   let txBody = mknode "p:txBody" [] $
                [mknode "a:bodyPr" [] (), mknode "a:lstStyle" [] ()] ++ elements
   return $
@@ -1041,17 +1119,22 @@
       , blipFill
       , spPr ]
 
--- Currently hardcoded, until I figure out how to make it dynamic.    
+-- Currently hardcoded, until I figure out how to make it dynamic.
 blockQuoteSize :: Pixels
 blockQuoteSize = 20
 
+noteSize :: Pixels
+noteSize = 18
+
 paraElemToElement :: PandocMonad m => ParaElem -> P m Element
 paraElemToElement Break = return $ mknode "a:br" [] ()
 paraElemToElement (Run rpr s) = do
   let attrs =
         if rPropCode rpr
         then []
-        else (if rPropBlockQuote rpr then [("sz", (show $ blockQuoteSize * 100))] else []) ++
+        else (case rPropForceSize rpr of
+                Just n -> [("sz", (show $ n * 100))]
+                Nothing -> []) ++
              (if rPropBold rpr then [("b", "1")] else []) ++
              (if rPropItalics rpr then [("i", "1")] else []) ++
              (case rStrikethrough rpr of
@@ -1150,7 +1233,7 @@
                    [mknode "a:bodyPr" [] (), mknode "a:lstStyle" [] ()] ++ elements
           emptySpPr = mknode "p:spPr" [] ()
       return $
-        surroundWithMathAlternate $ 
+        surroundWithMathAlternate $
         replaceNamedChildren ns "p" "txBody" [txBody] $
         replaceNamedChildren ns "p" "spPr" [emptySpPr] $
         sp
@@ -1199,8 +1282,8 @@
 
 hardcodedTableMargin :: Integer
 hardcodedTableMargin = 36
-   
 
+
 graphicToElement :: PandocMonad m => Graphic -> P m Element
 graphicToElement (Tbl tblPr colWidths hdrCells rows) = do
   let cellToOpenXML paras = do elements <- mapM paragraphToElement paras
@@ -1241,7 +1324,7 @@
 
 getShapeByName :: NameSpaces -> Element -> String -> Maybe Element
 getShapeByName ns spTreeElem name
-  | isElem ns "p" "spTree" spTreeElem = 
+  | isElem ns "p" "spTree" spTreeElem =
   filterChild (\e -> (isElem ns "p" "sp" e) && (shapeHasName ns name e)) spTreeElem
   | otherwise = Nothing
 
@@ -1266,7 +1349,7 @@
 --   | ns <- elemToNameSpaces layout
 --   , Just cSld <- findChild (elemName ns "p" "cSld") layout
 --   , Just spTree <- findChild (elemName ns "p" "spTree") cSld
---   , Just sp <- getContentTitleShape ns spTree = 
+--   , Just sp <- getContentTitleShape ns spTree =
 --   let hdrPara = Paragraph def paraElems
 --       txBody = mknode "p:txBody" [] $
 --                [mknode "a:bodyPr" [] (), mknode "a:lstStyle" [] ()] ++
@@ -1387,7 +1470,7 @@
 
 slideToPresRel :: Monad m => Slide -> Int -> P m Relationship
 slideToPresRel slide idNum = do
-  n <- gets stSlideIdOffset 
+  n <- gets stSlideIdOffset
   let rId = idNum + n
       fp = "slides/" ++ slideToFilePath slide idNum
   return $ Relationship { relId = rId
@@ -1429,7 +1512,7 @@
       modifyRelNum n = n - minRelNotOne + 2 + length slides
 
       relsWithoutSlides' = map (\r -> r{relId = modifyRelNum $ relId r}) relsWithoutSlides
-  
+
   return $ mySlideRels ++ relsWithoutSlides'
 
 relToElement :: Relationship -> Element
@@ -1479,7 +1562,7 @@
   let ext = case mInfoExt mInfo of
               Just e -> e
               Nothing -> ""
-  in              
+  in
     mknode "Relationship" [ ("Id", "rId" ++ (show $ mInfoLocalId mInfo))
                           , ("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image")
                           , ("Target", "../media/image" ++ (show $ mInfoGlobalId mInfo) ++ ext)
@@ -1503,7 +1586,7 @@
                    Nothing -> []
 
   return $
-    mknode "Relationships" 
+    mknode "Relationships"
     [("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships")]
     ([mknode "Relationship" [ ("Id", "rId1")
                            , ("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout")
@@ -1546,10 +1629,10 @@
 presentationToPresEntry :: PandocMonad m => Presentation -> P m Entry
 presentationToPresEntry pres = presentationToPresentationElement pres >>=
   elemToEntry "ppt/presentation.xml"
-  
 
-  
 
+
+
 defaultContentTypeToElem :: DefaultContentType -> Element
 defaultContentTypeToElem dct =
   mknode "Default"
@@ -1558,7 +1641,7 @@
   ()
 
 overrideContentTypeToElem :: OverrideContentType -> Element
-overrideContentTypeToElem oct = 
+overrideContentTypeToElem oct =
   mknode "Override"
   [("PartName", overrideContentTypesPart oct),
     ("ContentType", overrideContentTypesType oct)]
@@ -1571,7 +1654,7 @@
     mknode "Types" [("xmlns", ns)] $
     (map defaultContentTypeToElem $ contentTypesDefaults ct) ++
     (map overrideContentTypeToElem $ contentTypesOverrides ct)
-    
+
 data DefaultContentType = DefaultContentType
                            { defContentTypesExt :: String
                            , defContentTypesType:: MimeType
@@ -1634,7 +1717,7 @@
 
 noPresML :: String
 noPresML = "application/vnd.openxmlformats-officedocument"
-  
+
 getContentType :: FilePath -> Maybe MimeType
 getContentType fp
   | fp == "ppt/presentation.xml" = Just $ presML ++ ".presentation.main+xml"
diff --git a/src/Text/Pandoc/Writers/RST.hs b/src/Text/Pandoc/Writers/RST.hs
--- a/src/Text/Pandoc/Writers/RST.hs
+++ b/src/Text/Pandoc/Writers/RST.hs
@@ -250,7 +250,7 @@
           let headerChar = if level > 5 then ' ' else "=-~^'" !! (level - 1)
           let border = text $ replicate (offset contents) headerChar
           let anchor | null name || name == autoId = empty
-                     | otherwise = ".. " <> text name <> ":" $$ blankline
+                     | otherwise = ".. _" <> text name <> ":" $$ blankline
           return $ nowrap $ anchor $$ contents $$ border $$ blankline
     else do
           let rub     = "rubric:: " <> contents
diff --git a/stack.yaml b/stack.yaml
--- a/stack.yaml
+++ b/stack.yaml
@@ -1,20 +1,16 @@
 flags:
   pandoc:
     trypandoc: false
-    embed_data_files: false
+    embed_data_files: true
     old-locale: false
     network-uri: true
+  pandoc-citeproc:
+    bibutils: true
+    embed_data_files: true
+    unicode_collation: false
+    test_citeproc: false
+    debug: false
 packages:
-extra-deps:
-- pandoc-types-1.17.3
-- hslua-0.9.3
-- hslua-module-text-0.1.2
-- skylighting-0.5
-- texmath-0.10
-- cmark-gfm-0.1.1
-- QuickCheck-2.10.0.1
-- tasty-quickcheck-0.9.1
-- doctemplates-0.2.1
-- haddock-library-1.4.3
-- tagsoup-0.14.2
-resolver: lts-9.14
+- '.'
+extra-deps: []
+resolver: lts-10.1
diff --git a/test/Tests/Lua.hs b/test/Tests/Lua.hs
--- a/test/Tests/Lua.hs
+++ b/test/Tests/Lua.hs
@@ -10,9 +10,9 @@
 import Text.Pandoc.Builder (bulletList, divWith, doc, doubleQuoted, emph,
                             header, linebreak, para, plain, rawBlock,
                             singleQuoted, space, str, strong, (<>))
-import Text.Pandoc.Class (runIOorExplode)
+import Text.Pandoc.Class (runIOorExplode, setUserDataDir)
 import Text.Pandoc.Definition (Block, Inline, Meta, Pandoc)
-import Text.Pandoc.Lua (initLuaState, runLuaFilter, luaPackageParams)
+import Text.Pandoc.Lua (runLuaFilter, runPandocLua)
 
 import qualified Foreign.Lua as Lua
 
@@ -91,12 +91,28 @@
       "attr-test.lua"
       (doc $ divWith ("", [], kv_before) (para "nil"))
       (doc $ divWith ("", [], kv_after) (para "nil"))
+
+  , testCase "Test module pandoc.utils" $
+    assertFilterConversion "pandoc.utils doesn't work as expected."
+      "test-pandoc-utils.lua"
+      (doc $ para "doesn't matter")
+      (doc $ mconcat [ plain (str "hierarchicalize: OK")
+                     , plain (str "normalize_date: OK")
+                     , plain (str "pipe: OK")
+                     , plain (str "failing pipe: OK")
+                     , plain (str "read: OK")
+                     , plain (str "failing read: OK")
+                     , plain (str "sha1: OK")
+                     , plain (str "stringify: OK")
+                     , plain (str "to_roman_numeral: OK")
+                     ])
   ]
 
 assertFilterConversion :: String -> FilePath -> Pandoc -> Pandoc -> Assertion
 assertFilterConversion msg filterPath docIn docExpected = do
-  docEither <- runIOorExplode $
-               runLuaFilter (Just "../data") ("lua" </> filterPath) [] docIn
+  docEither <- runIOorExplode $ do
+    setUserDataDir (Just "../data")
+    runLuaFilter ("lua" </> filterPath) [] docIn
   case docEither of
     Left _       -> fail "lua filter failed"
     Right docRes -> assertEqual msg docExpected docRes
@@ -105,14 +121,18 @@
 roundtripEqual x = (x ==) <$> roundtripped
  where
   roundtripped :: (Lua.FromLuaStack a, Lua.ToLuaStack a) => IO a
-  roundtripped = Lua.runLua $ do
-    initLuaState =<< Lua.liftIO (runIOorExplode (luaPackageParams (Just "../data")))
-    oldSize <- Lua.gettop
-    Lua.push x
-    size <- Lua.gettop
-    when (size - oldSize /= 1) $
-      error ("not exactly one additional element on the stack: " ++ show size)
-    res <- Lua.peekEither (-1)
+  roundtripped = runIOorExplode $ do
+    setUserDataDir (Just "../data")
+    res <- runPandocLua $ do
+      oldSize <- Lua.gettop
+      Lua.push x
+      size <- Lua.gettop
+      when (size - oldSize /= 1) $
+        error ("not exactly one additional element on the stack: " ++ show size)
+      res <- Lua.peekEither (-1)
+      case res of
+        Left _  -> error "could not read from stack"
+        Right y -> return y
     case res of
-      Left _  -> error "could not read from stack"
+      Left e -> error (show e)
       Right y -> return y
diff --git a/test/Tests/Old.hs b/test/Tests/Old.hs
--- a/test/Tests/Old.hs
+++ b/test/Tests/Old.hs
@@ -79,6 +79,8 @@
           ]
         , testGroup "jats"
           [ testGroup "writer" $ writerTests "jats"
+          , test "reader" ["-r", "jats", "-w", "native", "-s"]
+            "jats-reader.xml" "jats-reader.native"
           ]
         , testGroup "native"
           [ testGroup "writer" $ writerTests "native"
@@ -159,6 +161,12 @@
         , testGroup "creole"
           [ test "reader" ["-r", "creole", "-w", "native", "-s"]
             "creole-reader.txt" "creole-reader.native"
+          ]
+        , testGroup "custom writer"
+          [ test "basic" ["-f", "native", "-t", "../data/sample.lua"]
+            "testsuite.native" "writer.custom"
+          , test "tables" ["-f", "native", "-t", "../data/sample.lua"]
+            "tables.native" "tables.custom"
           ]
         ]
 
diff --git a/test/Tests/Readers/Docx.hs b/test/Tests/Readers/Docx.hs
--- a/test/Tests/Readers/Docx.hs
+++ b/test/Tests/Readers/Docx.hs
@@ -171,6 +171,10 @@
             "inline code in subscript and superscript"
             "docx/verbatim_subsuper.docx"
             "docx/verbatim_subsuper.native"
+          , testCompare
+            "inlines inside of Structured Document Tags"
+            "docx/sdt_elements.docx"
+            "docx/sdt_elements.native"
           ]
         , testGroup "blocks"
           [ testCompare
@@ -205,6 +209,14 @@
             "lists"
             "docx/lists.docx"
             "docx/lists.native"
+          , testCompare
+            "lists continuing after interruption"
+            "docx/lists_continuing.docx"
+            "docx/lists_continuing.native"
+          , testCompare
+            "lists restarting after interruption"
+            "docx/lists_restarting.docx"
+            "docx/lists_restarting.native"
           , testCompare
             "definition lists"
             "docx/definition_list.docx"
diff --git a/test/Tests/Readers/JATS.hs b/test/Tests/Readers/JATS.hs
new file mode 100644
--- /dev/null
+++ b/test/Tests/Readers/JATS.hs
@@ -0,0 +1,116 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.JATS (tests) where
+
+import Data.Text (Text)
+import Test.Tasty
+import Tests.Helpers
+import Text.Pandoc
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder
+
+jats :: Text -> Pandoc
+jats = purely $ readJATS def
+
+tests :: [TestTree]
+tests = [ testGroup "inline code"
+          [ test jats "basic" $ "<p>\n  <monospace>@&amp;</monospace>\n</p>" =?> para (code "@&")
+          , test jats "lang" $ "<p>\n  <code language=\"c\">@&amp;</code>\n</p>" =?> para (codeWith ("", ["c"], []) "@&")
+          ]
+        , testGroup "block code"
+          [ test jats "basic" $ "<preformat>@&amp;</preformat>" =?> codeBlock "@&"
+          , test jats "lang" $ "<code language=\"c\">@&amp;</code>" =?> codeBlockWith ("", ["c"], []) "@&"
+          ]
+        , testGroup "images"
+          [ test jats "basic" $ "<graphic mimetype=\"image\" mime-subtype=\"\" xlink:href=\"/url\" xlink:title=\"title\" />"
+            =?> para (image "/url" "title" mempty)
+          ]
+        , test jats "bullet list" $
+                            "<list list-type=\"bullet\">\n\
+                            \  <list-item>\n\
+                            \    <p>\n\
+                            \      first\n\
+                            \    </p>\n\
+                            \  </list-item>\n\
+                            \  <list-item>\n\
+                            \    <p>\n\
+                            \      second\n\
+                            \    </p>\n\
+                            \  </list-item>\n\
+                            \  <list-item>\n\
+                            \    <p>\n\
+                            \      third\n\
+                            \    </p>\n\
+                            \  </list-item>\n\
+                            \</list>"
+                =?> bulletList [ para $ text "first"
+                               , para $ text "second"
+                               , para $ text "third"
+                               ]
+        , testGroup "definition lists"
+          [ test jats "with internal link" $
+            "<def-list>\n\
+            \  <def-item>\n\
+            \    <term>\n\
+            \      <xref alt=\"testing\" rid=\"go\">testing</xref>\n\
+            \    </term>\n\
+            \    <def>\n\
+            \      <p>\n\
+            \        hi there\n\
+            \      </p>\n\
+            \    </def>\n\
+            \  </def-item>\n\
+            \</def-list>"
+            =?> definitionList [(link "#go" "" (str "testing"),
+                [para (text "hi there")])]
+          ]
+        , testGroup "math"
+          [ test jats "escape |" $
+            "<p>\n\
+            \  <inline-formula><alternatives>\n\
+            \  <tex-math><![CDATA[\\sigma|_{\\{x\\}}]]></tex-math>\n\
+            \  <mml:math display=\"inline\" xmlns:mml=\"http://www.w3.org/1998/Math/MathML\"><mml:mrow><mml:mi>σ</mml:mi><mml:msub><mml:mo stretchy=\"false\" form=\"prefix\">|</mml:mo><mml:mrow><mml:mo stretchy=\"false\" form=\"prefix\">{</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy=\"false\" form=\"postfix\">}</mml:mo></mml:mrow></mml:msub></mml:mrow></mml:math></alternatives></inline-formula>\n\
+            \</p>"
+            =?> para (math "\\sigma|_{\\{x\\}}")
+          , test jats "tex-math only" $
+            "<p>\n\
+            \  <inline-formula><alternatives>\n\
+            \  <tex-math><![CDATA[\\sigma|_{\\{x\\}}]]></tex-math>\n\
+            \</p>"
+            =?> para (math "\\sigma|_{\\{x\\}}")
+          , test jats "math ml only" $
+            "<p>\n\
+            \  <inline-formula><alternatives>\n\
+            \  <mml:math display=\"inline\" xmlns:mml=\"http://www.w3.org/1998/Math/MathML\"><mml:mrow><mml:mi>σ</mml:mi><mml:msub><mml:mo stretchy=\"false\" form=\"prefix\">|</mml:mo><mml:mrow><mml:mo stretchy=\"false\" form=\"prefix\">{</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy=\"false\" form=\"postfix\">}</mml:mo></mml:mrow></mml:msub></mml:mrow></mml:math></alternatives></inline-formula>\n\
+            \</p>"
+            =?> para (math "\\sigma|_{\\{ x\\}}")
+          ]
+        , testGroup "headers"
+-- TODO fix footnotes in headers
+--          [ test jats "unnumbered header" $
+--            "<sec>\n\
+--            \  <title>Header 1<fn>\n\
+--            \    <p>\n\
+--            \      note\n\
+--            \    </p>\n\
+--            \  </fn></title>\n\
+--            \</sec>"
+--            =?> header 1
+--                (text "Header 1" <> note (plain $ text "note"))
+          [ test jats "unnumbered sub header" $
+            "<sec id=\"foo\">\n\
+            \  <title>Header</title>\n\
+            \  <sec id=\"foo2\">\n\
+            \    <title>Sub-Header</title>\n\
+            \  </sec>\n\
+            \</sec>"
+            =?> headerWith ("foo", [], []) 1
+                  (text "Header")
+                <> headerWith  ("foo2", [], []) 2
+                  (text "Sub-Header")
+          , test jats "containing image" $
+            "<sec>\n\
+            \  <title><inline-graphic mimetype=\"image\" mime-subtype=\"jpeg\" xlink:href=\"imgs/foo.jpg\" /></title>\n\
+            \</sec>"
+            =?> header 1 (image "imgs/foo.jpg" "" mempty)
+          ]
+        ]
diff --git a/test/Tests/Readers/LaTeX.hs b/test/Tests/Readers/LaTeX.hs
--- a/test/Tests/Readers/LaTeX.hs
+++ b/test/Tests/Readers/LaTeX.hs
@@ -3,7 +3,11 @@
 
 import Data.Text (Text)
 import qualified Data.Text as T
+import qualified Text.Pandoc.UTF8 as UTF8
+import Text.Pandoc.Readers.LaTeX (tokenize, untokenize)
 import Test.Tasty
+import Test.Tasty.HUnit
+import Test.Tasty.QuickCheck
 import Tests.Helpers
 import Text.Pandoc
 import Text.Pandoc.Arbitrary ()
@@ -22,8 +26,21 @@
 simpleTable' aligns = table "" (zip aligns (repeat 0.0))
                       (map (const mempty) aligns)
 
+tokUntokRt :: String -> Bool
+tokUntokRt s = untokenize (tokenize "random" t) == t
+  where t = T.pack s
+
 tests :: [TestTree]
-tests = [ testGroup "basic"
+tests = [ testGroup "tokenization"
+          [ testCase "tokenizer round trip on test case" $ do
+                 orig <- T.pack <$> UTF8.readFile "../test/latex-reader.latex"
+                 let new = untokenize $ tokenize "../test/latex-reader.latex"
+                             orig
+                 assertEqual "untokenize . tokenize is identity" orig new
+          , testProperty "untokenize . tokenize is identity" tokUntokRt
+          ]
+
+        , testGroup "basic"
           [ "simple" =:
             "word" =?> para "word"
           , "space" =:
diff --git a/test/Tests/Readers/Muse.hs b/test/Tests/Readers/Muse.hs
--- a/test/Tests/Readers/Muse.hs
+++ b/test/Tests/Readers/Muse.hs
@@ -421,6 +421,8 @@
       , testGroup "Comments"
         [ "Comment tag" =: "<comment>\nThis is a comment\n</comment>" =?> (mempty::Blocks)
         , "Line comment" =: "; Comment" =?> (mempty::Blocks)
+        , "Empty comment" =: ";" =?> (mempty::Blocks)
+        , "Text after empty comment" =: ";\nfoo" =?> para "foo" -- Make sure we don't consume newline while looking for whitespace
         , "Not a comment (does not start with a semicolon)" =: " ; Not a comment" =?> para (text "; Not a comment")
         , "Not a comment (has no space after semicolon)" =: ";Not a comment" =?> para (text ";Not a comment")
         ]
@@ -453,6 +455,18 @@
                     , "</quote>"
                     ] =?>
           blockQuote (para "* Hi")
+        , "Headers consume anchors" =:
+          T.unlines [ "** Foo"
+                    , "#bar"
+                    ] =?>
+          headerWith ("bar",[],[]) 2 "Foo"
+        , "Headers don't consume anchors separated with a blankline" =:
+          T.unlines [ "** Foo"
+                    , ""
+                    , "#bar"
+                    ] =?>
+          header 2 "Foo" <>
+          para (spanWith ("bar", [], []) mempty)
         ]
       , testGroup "Directives"
         [ "Title" =:
@@ -503,6 +517,20 @@
                     ] =?>
           para (text "Start recursion here" <>
                 note (para "Recursion continues here[1]"))
+        , "No zero footnotes" =:
+          T.unlines [ "Here is a footnote[0]."
+                    , ""
+                    , "[0] Footnote contents"
+                    ] =?>
+          para "Here is a footnote[0]." <>
+          para "[0] Footnote contents"
+        , "Footnotes can't start with zero" =:
+          T.unlines [ "Here is a footnote[01]."
+                    , ""
+                    , "[01] Footnote contents"
+                    ] =?>
+          para "Here is a footnote[01]." <>
+          para "[01] Footnote contents"
         , testGroup "Multiparagraph footnotes"
           [ "Amusewiki multiparagraph footnotes" =:
             T.unlines [ "Multiparagraph[1] footnotes[2]"
diff --git a/test/Tests/Readers/Org.hs b/test/Tests/Readers/Org.hs
--- a/test/Tests/Readers/Org.hs
+++ b/test/Tests/Readers/Org.hs
@@ -1,1871 +1,16 @@
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Readers.Org (tests) where
 
-import Data.List (intersperse)
-import Data.Text (Text)
-import qualified Data.Text as T
-import Test.Tasty
-import Tests.Helpers
-import Text.Pandoc
-import Text.Pandoc.Builder
-import Text.Pandoc.Shared (underlineSpan)
-
-org :: Text -> Pandoc
-org = purely $ readOrg def{ readerExtensions = getDefaultExtensions "org" }
-
-orgSmart :: Text -> Pandoc
-orgSmart = purely $ readOrg def { readerExtensions =
-                     enableExtension Ext_smart $ getDefaultExtensions "org" }
-
-infix 4 =:
-(=:) :: ToString c
-     => String -> (Text, c) -> TestTree
-(=:) = test org
-
-spcSep :: [Inlines] -> Inlines
-spcSep = mconcat . intersperse space
-
-simpleTable' :: Int
-             -> [Blocks]
-             -> [[Blocks]]
-             -> Blocks
-simpleTable' n = table "" (replicate n (AlignDefault, 0.0))
-
--- | Create a span for the given tag.
-tagSpan :: String -> Inlines
-tagSpan t = spanWith ("", ["tag"], [("tag-name", t)]) . smallcaps $ str t
-
-tests :: [TestTree]
-tests =
-  [ testGroup "Inlines" $
-      [ "Plain String" =:
-          "Hello, World" =?>
-          para (spcSep [ "Hello,", "World" ])
-
-      , "Emphasis" =:
-          "/Planet Punk/" =?>
-          para (emph . spcSep $ ["Planet", "Punk"])
-
-      , "Strong" =:
-          "*Cider*" =?>
-          para (strong "Cider")
-
-      , "Strong Emphasis" =:
-          "/*strength*/" =?>
-          para (emph . strong $ "strength")
-
-      , "Emphasized Strong preceded by space" =:
-          " */super/*" =?>
-          para (strong . emph $ "super")
-
-      , "Underline" =:
-          "_underline_" =?>
-          para (underlineSpan $ "underline")
-
-      , "Strikeout" =:
-          "+Kill Bill+" =?>
-          para (strikeout . spcSep $ [ "Kill", "Bill" ])
-
-      , "Verbatim" =:
-          "=Robot.rock()=" =?>
-          para (code "Robot.rock()")
-
-      , "Code" =:
-          "~word for word~" =?>
-          para (code "word for word")
-
-      , "Math $..$" =:
-          "$E=mc^2$" =?>
-           para (math "E=mc^2")
-
-      , "Math $$..$$" =:
-          "$$E=mc^2$$" =?>
-          para (displayMath "E=mc^2")
-
-      , "Math \\[..\\]" =:
-          "\\[E=ℎν\\]" =?>
-          para (displayMath "E=ℎν")
-
-      , "Math \\(..\\)" =:
-          "\\(σ_x σ_p ≥ \\frac{ℏ}{2}\\)" =?>
-          para (math "σ_x σ_p ≥ \\frac{ℏ}{2}")
-
-      , "Symbol" =:
-          "A * symbol" =?>
-          para (str "A" <> space <> str "*" <> space <> "symbol")
-
-      , "Superscript simple expression" =:
-          "2^-λ" =?>
-          para (str "2" <> superscript "-λ")
-
-      , "Superscript multi char" =:
-          "2^{n-1}" =?>
-          para (str "2" <> superscript "n-1")
-
-      , "Subscript simple expression" =:
-          "a_n" =?>
-          para (str "a" <> subscript "n")
-
-      , "Subscript multi char" =:
-          "a_{n+1}" =?>
-          para (str "a" <> subscript "n+1")
-
-      , "Linebreak" =:
-          "line \\\\ \nbreak" =?>
-          para ("line" <> linebreak <> "break")
-
-      , "Inline note" =:
-          "[fn::Schreib mir eine E-Mail]" =?>
-          para (note $ para "Schreib mir eine E-Mail")
-
-      , "Markup-chars not occuring on word break are symbols" =:
-          T.unlines [ "this+that+ +so+on"
-                    , "seven*eight* nine*"
-                    , "+not+funny+"
-                    ] =?>
-          para ("this+that+ +so+on" <> softbreak <>
-                "seven*eight* nine*" <> softbreak <>
-                strikeout "not+funny")
-
-      , "No empty markup" =:
-          "// ** __ <> == ~~ $$" =?>
-          para (spcSep [ "//", "**", "__", "<>", "==", "~~", "$$" ])
-
-      , "Adherence to Org's rules for markup borders" =:
-          "/t/& a/ / ./r/ (*l*) /e/! /b/." =?>
-          para (spcSep [ emph $ "t/&" <> space <> "a"
-                       , "/"
-                       , "./r/"
-                       , "(" <> strong "l" <> ")"
-                       , emph "e" <> "!"
-                       , emph "b" <> "."
-                       ])
-
-      , "Quotes are allowed border chars" =:
-          "/'yep/ *sure\"*" =?>
-          para (emph "'yep" <> space <> strong "sure\"")
-
-      , "Spaces are forbidden border chars" =:
-          "/nada /" =?>
-          para "/nada /"
-
-      , "Markup should work properly after a blank line" =:
-        T.unlines ["foo", "", "/bar/"] =?>
-        (para $ text "foo") <> (para $ emph $ text "bar")
-
-      , "Inline math must stay within three lines" =:
-          T.unlines [ "$a", "b", "c$", "$d", "e", "f", "g$" ] =?>
-          para ((math "a\nb\nc") <> softbreak <>
-                "$d" <> softbreak <> "e" <> softbreak <>
-                "f" <> softbreak <> "g$")
-
-      , "Single-character math" =:
-          "$a$ $b$! $c$?" =?>
-          para (spcSep [ math "a"
-                       , "$b$!"
-                       , (math "c") <> "?"
-                       ])
-
-      , "Markup may not span more than two lines" =:
-          "/this *is +totally\nnice+ not*\nemph/" =?>
-          para ("/this" <> space <>
-                  strong ("is" <> space <>
-                          strikeout ("totally" <>
-                            softbreak <> "nice") <>
-                          space <> "not") <>
-                  softbreak <> "emph/")
-
-      , "Sub- and superscript expressions" =:
-         T.unlines [ "a_(a(b)(c)d)"
-                   , "e^(f(g)h)"
-                   , "i_(jk)l)"
-                   , "m^()n"
-                   , "o_{p{q{}r}}"
-                   , "s^{t{u}v}"
-                   , "w_{xy}z}"
-                   , "1^{}2"
-                   , "3_{{}}"
-                   , "4^(a(*b(c*)d))"
-                   ] =?>
-         para (mconcat $ intersperse softbreak
-                      [ "a" <> subscript "(a(b)(c)d)"
-                      , "e" <> superscript "(f(g)h)"
-                      , "i" <> (subscript "(jk)") <> "l)"
-                      , "m" <> (superscript "()") <> "n"
-                      , "o" <> subscript "p{q{}r}"
-                      , "s" <> superscript "t{u}v"
-                      , "w" <> (subscript "xy") <> "z}"
-                      , "1" <> (superscript "") <> "2"
-                      , "3" <> subscript "{}"
-                      , "4" <> superscript ("(a(" <> strong "b(c" <> ")d))")
-                      ])
-      , "Verbatim text can contain equal signes (=)" =:
-          "=is_subst = True=" =?>
-          para (code "is_subst = True")
-
-      , testGroup "Images"
-        [ "Image" =:
-            "[[./sunset.jpg]]" =?>
-            (para $ image "./sunset.jpg" "" "")
-
-        , "Image with explicit file: prefix" =:
-            "[[file:sunrise.jpg]]" =?>
-            (para $ image "sunrise.jpg" "" "")
-
-        , "Multiple images within a paragraph" =:
-            T.unlines [ "[[file:sunrise.jpg]]"
-                      , "[[file:sunset.jpg]]"
-                      ] =?>
-            (para $ (image "sunrise.jpg" "" "")
-                 <> softbreak
-                 <> (image "sunset.jpg" "" ""))
-
-        , "Image with html attributes" =:
-            T.unlines [ "#+ATTR_HTML: :width 50%"
-                      , "[[file:guinea-pig.gif]]"
-                      ] =?>
-            (para $ imageWith ("", [], [("width", "50%")]) "guinea-pig.gif" "" "")
-        ]
-
-      , "Explicit link" =:
-          "[[http://zeitlens.com/][pseudo-random /nonsense/]]" =?>
-          (para $ link "http://zeitlens.com/" ""
-                       ("pseudo-random" <> space <> emph "nonsense"))
-
-      , "Self-link" =:
-          "[[http://zeitlens.com/]]" =?>
-          (para $ link "http://zeitlens.com/" "" "http://zeitlens.com/")
-
-      , "Absolute file link" =:
-          "[[/url][hi]]" =?>
-          (para $ link "file:///url" "" "hi")
-
-      , "Link to file in parent directory" =:
-          "[[../file.txt][moin]]" =?>
-          (para $ link "../file.txt" "" "moin")
-
-      , "Empty link (for gitit interop)" =:
-          "[[][New Link]]" =?>
-          (para $ link "" "" "New Link")
-
-      , "Image link" =:
-          "[[sunset.png][file:dusk.svg]]" =?>
-          (para $ link "sunset.png" "" (image "dusk.svg" "" ""))
-
-      , "Image link with non-image target" =:
-          "[[http://example.com][./logo.png]]" =?>
-          (para $ link "http://example.com" "" (image "./logo.png" "" ""))
-
-      , "Plain link" =:
-          "Posts on http://zeitlens.com/ can be funny at times." =?>
-          (para $ spcSep [ "Posts", "on"
-                         , link "http://zeitlens.com/" "" "http://zeitlens.com/"
-                         , "can", "be", "funny", "at", "times."
-                         ])
-
-      , "Angle link" =:
-          "Look at <http://moltkeplatz.de> for fnords." =?>
-          (para $ spcSep [ "Look", "at"
-                         , link "http://moltkeplatz.de" "" "http://moltkeplatz.de"
-                         , "for", "fnords."
-                         ])
-
-      , "Absolute file link" =:
-          "[[file:///etc/passwd][passwd]]" =?>
-          (para $ link "file:///etc/passwd" "" "passwd")
-
-      , "File link" =:
-          "[[file:target][title]]" =?>
-          (para $ link "target" "" "title")
-
-      , "Anchor" =:
-          "<<anchor>> Link here later." =?>
-          (para $ spanWith ("anchor", [], []) mempty <>
-                  "Link" <> space <> "here" <> space <> "later.")
-
-      , "Inline code block" =:
-          "src_emacs-lisp{(message \"Hello\")}" =?>
-          (para $ codeWith ( ""
-                           , [ "commonlisp" ]
-                           , [ ("org-language", "emacs-lisp") ])
-                           "(message \"Hello\")")
-
-      , "Inline code block with arguments" =:
-          "src_sh[:export both :results output]{echo 'Hello, World'}" =?>
-          (para $ codeWith ( ""
-                           , [ "bash" ]
-                           , [ ("org-language", "sh")
-                             , ("export", "both")
-                             , ("results", "output")
-                             ]
-                           )
-                           "echo 'Hello, World'")
-
-      , "Inline code block with toggle" =:
-          "src_sh[:toggle]{echo $HOME}" =?>
-          (para $ codeWith ( ""
-                           , [ "bash" ]
-                           , [ ("org-language", "sh")
-                             , ("toggle", "yes")
-                             ]
-                           )
-                           "echo $HOME")
-
-      , "Citation" =:
-          "[@nonexistent]" =?>
-          let citation = Citation
-                         { citationId = "nonexistent"
-                         , citationPrefix = []
-                         , citationSuffix = []
-                         , citationMode = NormalCitation
-                         , citationNoteNum = 0
-                         , citationHash = 0}
-          in (para $ cite [citation] "[@nonexistent]")
-
-      , "Citation containing text" =:
-          "[see @item1 p. 34-35]" =?>
-          let citation = Citation
-                         { citationId = "item1"
-                         , citationPrefix = [Str "see"]
-                         , citationSuffix = [Space ,Str "p.",Space,Str "34-35"]
-                         , citationMode = NormalCitation
-                         , citationNoteNum = 0
-                         , citationHash = 0}
-          in (para $ cite [citation] "[see @item1 p. 34-35]")
-
-      , "Org-ref simple citation" =:
-        "cite:pandoc" =?>
-        let citation = Citation
-                       { citationId = "pandoc"
-                       , citationPrefix = mempty
-                       , citationSuffix = mempty
-                       , citationMode = AuthorInText
-                       , citationNoteNum = 0
-                       , citationHash = 0
-                       }
-        in (para $ cite [citation] "cite:pandoc")
-
-      , "Org-ref simple citation with underscores" =:
-        "cite:pandoc_org_ref" =?>
-        let citation = Citation
-                       { citationId = "pandoc_org_ref"
-                       , citationPrefix = mempty
-                       , citationSuffix = mempty
-                       , citationMode = AuthorInText
-                       , citationNoteNum = 0
-                       , citationHash = 0
-                       }
-        in (para $ cite [citation] "cite:pandoc_org_ref")
-
-      , "Org-ref simple citation succeeded by comma" =:
-        "cite:pandoc," =?>
-        let citation = Citation
-                       { citationId = "pandoc"
-                       , citationPrefix = mempty
-                       , citationSuffix = mempty
-                       , citationMode = AuthorInText
-                       , citationNoteNum = 0
-                       , citationHash = 0
-                       }
-        in (para $ cite [citation] "cite:pandoc" <> str ",")
-
-      , "Org-ref simple citation succeeded by dot" =:
-        "cite:pandoc." =?>
-        let citation = Citation
-                       { citationId = "pandoc"
-                       , citationPrefix = mempty
-                       , citationSuffix = mempty
-                       , citationMode = AuthorInText
-                       , citationNoteNum = 0
-                       , citationHash = 0
-                       }
-        in (para $ cite [citation] "cite:pandoc" <> str ".")
-
-      , "Org-ref simple citation succeeded by colon" =:
-        "cite:pandoc:" =?>
-        let citation = Citation
-                       { citationId = "pandoc"
-                       , citationPrefix = mempty
-                       , citationSuffix = mempty
-                       , citationMode = AuthorInText
-                       , citationNoteNum = 0
-                       , citationHash = 0
-                       }
-        in (para $ cite [citation] "cite:pandoc" <> str ":")
-
-      , "Org-ref simple citep citation" =:
-        "citep:pandoc" =?>
-        let citation = Citation
-                       { citationId = "pandoc"
-                       , citationPrefix = mempty
-                       , citationSuffix = mempty
-                       , citationMode = NormalCitation
-                       , citationNoteNum = 0
-                       , citationHash = 0
-                       }
-        in (para $ cite [citation] "citep:pandoc")
-
-      , "Org-ref extended citation" =:
-        "[[citep:Dominik201408][See page 20::, for example]]" =?>
-        let citation = Citation
-                       { citationId = "Dominik201408"
-                       , citationPrefix = toList "See page 20"
-                       , citationSuffix = toList ", for example"
-                       , citationMode = NormalCitation
-                       , citationNoteNum = 0
-                       , citationHash = 0
-                       }
-        in (para $ cite [citation] "[[citep:Dominik201408][See page 20::, for example]]")
-
-      , testGroup "Berkeley-style citations" $
-        let pandocCite = Citation
-              { citationId = "Pandoc"
-              , citationPrefix = mempty
-              , citationSuffix = mempty
-              , citationMode = NormalCitation
-              , citationNoteNum = 0
-              , citationHash = 0
-              }
-            pandocInText = pandocCite { citationMode = AuthorInText }
-            dominikCite = Citation
-              { citationId = "Dominik201408"
-              , citationPrefix = mempty
-              , citationSuffix = mempty
-              , citationMode = NormalCitation
-              , citationNoteNum = 0
-              , citationHash = 0
-              }
-            dominikInText = dominikCite { citationMode = AuthorInText }
-        in [
-            "Berkeley-style in-text citation" =:
-              "See @Dominik201408." =?>
-                (para $ "See "
-                      <> cite [dominikInText] "@Dominik201408"
-                      <> ".")
-
-          , "Berkeley-style parenthetical citation list" =:
-              "[(cite): see; @Dominik201408;also @Pandoc; and others]" =?>
-              let pandocCite'  = pandocCite {
-                                   citationPrefix = toList "also"
-                                 , citationSuffix = toList "and others"
-                                 }
-                  dominikCite' = dominikCite {
-                                   citationPrefix = toList "see"
-                                 }
-              in (para $ cite [dominikCite', pandocCite'] "")
-
-          , "Berkeley-style plain citation list" =:
-              "[cite: See; @Dominik201408; and @Pandoc; and others]" =?>
-              let pandocCite' = pandocInText {
-                                  citationPrefix = toList "and"
-                                }
-              in (para $ "See "
-                      <> cite [dominikInText] ""
-                      <> "," <> space
-                      <> cite [pandocCite'] ""
-                      <> "," <> space <> "and others")
-        ]
-
-      , "Inline LaTeX symbol" =:
-          "\\dots" =?>
-          para "…"
-
-      , "Inline LaTeX command" =:
-          "\\textit{Emphasised}" =?>
-          para (emph "Emphasised")
-
-      , "Inline LaTeX command with spaces" =:
-          "\\emph{Emphasis mine}" =?>
-          para (emph "Emphasis mine")
-
-      , "Inline LaTeX math symbol" =:
-          "\\tau" =?>
-          para (emph "τ")
-
-      , "Unknown inline LaTeX command" =:
-          "\\notacommand{foo}" =?>
-          para (rawInline "latex" "\\notacommand{foo}")
-
-      , "Export snippet" =:
-          "@@html:<kbd>M-x org-agenda</kbd>@@" =?>
-          para (rawInline "html" "<kbd>M-x org-agenda</kbd>")
-
-      , "MathML symbol in LaTeX-style" =:
-          "There is a hackerspace in Lübeck, Germany, called nbsp (unicode symbol: '\\nbsp')." =?>
-          para ("There is a hackerspace in Lübeck, Germany, called nbsp (unicode symbol: ' ').")
-
-      , "MathML symbol in LaTeX-style, including braces" =:
-          "\\Aacute{}stor" =?>
-          para "Ástor"
-
-      , "MathML copy sign" =:
-          "\\copy" =?>
-          para "©"
-
-      , "MathML symbols, space separated" =:
-          "\\ForAll \\Auml" =?>
-          para "∀ Ä"
-
-      , "LaTeX citation" =:
-          "\\cite{Coffee}" =?>
-          let citation = Citation
-                         { citationId = "Coffee"
-                         , citationPrefix = []
-                         , citationSuffix = []
-                         , citationMode = NormalCitation
-                         , citationNoteNum = 0
-                         , citationHash = 0}
-          in (para . cite [citation] $ rawInline "latex" "\\cite{Coffee}")
-
-      , "Macro" =:
-          T.unlines [ "#+MACRO: HELLO /Hello, $1/"
-                    , "{{{HELLO(World)}}}"
-                    ] =?>
-          para (emph "Hello, World")
-
-      , "Macro repeting its argument" =:
-          T.unlines [ "#+MACRO: HELLO $1$1"
-                    , "{{{HELLO(moin)}}}"
-                    ] =?>
-          para "moinmoin"
-
-      , "Macro called with too few arguments" =:
-          T.unlines [ "#+MACRO: HELLO Foo $1 $2 Bar"
-                    , "{{{HELLO()}}}"
-                    ] =?>
-          para "Foo Bar"
-      ]
-
-  , testGroup "Meta Information" $
-      [ "Comment" =:
-          "# Nothing to see here" =?>
-          (mempty::Blocks)
-
-      , "Not a comment" =:
-          "#-tag" =?>
-          para "#-tag"
-
-      , "Comment surrounded by Text" =:
-          T.unlines [ "Before"
-                    , "# Comment"
-                    , "After"
-                    ] =?>
-          mconcat [ para "Before"
-                  , para "After"
-                  ]
-
-      , "Title" =:
-        "#+TITLE: Hello, World" =?>
-        let titleInline = toList $ "Hello," <> space <> "World"
-            meta = setMeta "title" (MetaInlines titleInline) $ nullMeta
-        in Pandoc meta mempty
-
-      , "Author" =:
-        "#+author: Albert /Emacs-Fanboy/ Krewinkel" =?>
-        let author = toList . spcSep $ [ "Albert", emph "Emacs-Fanboy", "Krewinkel" ]
-            meta = setMeta "author" (MetaList [MetaInlines author]) $ nullMeta
-        in Pandoc meta mempty
-
-      , "Multiple authors" =:
-        "#+author: James Dewey Watson, Francis Harry Compton Crick " =?>
-        let watson = MetaInlines $ toList "James Dewey Watson"
-            crick = MetaInlines $ toList "Francis Harry Compton Crick"
-            meta = setMeta "author" (MetaList [watson, crick]) $ nullMeta
-        in Pandoc meta mempty
-
-      , "Date" =:
-        "#+Date: Feb. *28*, 2014" =?>
-        let date = toList . spcSep $ [ "Feb.", (strong "28") <> ",", "2014" ]
-            meta = setMeta "date" (MetaInlines date) $ nullMeta
-        in Pandoc meta mempty
-
-      , "Description" =:
-        "#+DESCRIPTION: Explanatory text" =?>
-        let description = "Explanatory text"
-            meta = setMeta "description" (MetaString description) $ nullMeta
-        in Pandoc meta mempty
-
-      , "Properties drawer" =:
-          T.unlines [ "  :PROPERTIES:"
-                    , "  :setting: foo"
-                    , "  :END:"
-                    ] =?>
-          (mempty::Blocks)
-
-      , "LaTeX_headers options are translated to header-includes" =:
-          "#+LaTeX_header: \\usepackage{tikz}" =?>
-          let latexInlines = rawInline "latex" "\\usepackage{tikz}"
-              inclList = MetaList [MetaInlines (toList latexInlines)]
-              meta = setMeta "header-includes" inclList nullMeta
-          in Pandoc meta mempty
-
-      , "LaTeX_class option is translated to documentclass" =:
-          "#+LATEX_CLASS: article" =?>
-          let meta = setMeta "documentclass" (MetaString "article") nullMeta
-          in Pandoc meta mempty
-
-      , "LaTeX_class_options is translated to classoption" =:
-          "#+LATEX_CLASS_OPTIONS: [a4paper]" =?>
-          let meta = setMeta "classoption" (MetaString "a4paper") nullMeta
-          in Pandoc meta mempty
-
-      , "LaTeX_class_options is translated to classoption" =:
-          "#+html_head: <meta/>" =?>
-          let html = rawInline "html" "<meta/>"
-              inclList = MetaList [MetaInlines (toList html)]
-              meta = setMeta "header-includes" inclList nullMeta
-          in Pandoc meta mempty
-
-      , "later meta definitions take precedence" =:
-          T.unlines [ "#+AUTHOR: this will not be used"
-                    , "#+author: Max"
-                    ] =?>
-          let author = MetaInlines [Str "Max"]
-              meta = setMeta "author" (MetaList [author]) $ nullMeta
-          in Pandoc meta mempty
-
-      , "Logbook drawer" =:
-          T.unlines [ "  :LogBook:"
-                    , "  - State \"DONE\"       from \"TODO\"       [2014-03-03 Mon 11:00]"
-                    , "  :END:"
-                    ] =?>
-          (mempty::Blocks)
-
-      , "Drawer surrounded by text" =:
-          T.unlines [ "Before"
-                    , ":PROPERTIES:"
-                    , ":END:"
-                    , "After"
-                    ] =?>
-          para "Before" <> para "After"
-
-      , "Drawer markers must be the only text in the line" =:
-          T.unlines [ "  :LOGBOOK: foo"
-                    , "  :END: bar"
-                    ] =?>
-          para (":LOGBOOK: foo" <> softbreak <> ":END: bar")
-
-      , "Drawers can be arbitrary" =:
-          T.unlines [ ":FOO:"
-                    , "/bar/"
-                    , ":END:"
-                    ] =?>
-          divWith (mempty, ["FOO", "drawer"], mempty) (para $ emph "bar")
-
-      , "Anchor reference" =:
-          T.unlines [ "<<link-here>> Target."
-                    , ""
-                    , "[[link-here][See here!]]"
-                    ] =?>
-          (para (spanWith ("link-here", [], []) mempty <> "Target.") <>
-           para (link "#link-here" "" ("See" <> space <> "here!")))
-
-      , "Search links are read as emph" =:
-          "[[Wally][Where's Wally?]]" =?>
-          (para (emph $ "Where's" <> space <> "Wally?"))
-
-      , "Link to nonexistent anchor" =:
-          T.unlines [ "<<link-here>> Target."
-                    , ""
-                    , "[[link$here][See here!]]"
-                    ] =?>
-          (para (spanWith ("link-here", [], []) mempty <> "Target.") <>
-           para (emph ("See" <> space <> "here!")))
-
-      , "Link abbreviation" =:
-          T.unlines [ "#+LINK: wp https://en.wikipedia.org/wiki/%s"
-                    , "[[wp:Org_mode][Wikipedia on Org-mode]]"
-                    ] =?>
-          (para (link "https://en.wikipedia.org/wiki/Org_mode" ""
-                      ("Wikipedia" <> space <> "on" <> space <> "Org-mode")))
-
-      , "Link abbreviation, defined after first use" =:
-          T.unlines [ "[[zl:non-sense][Non-sense articles]]"
-                    , "#+LINK: zl http://zeitlens.com/tags/%s.html"
-                    ] =?>
-          (para (link "http://zeitlens.com/tags/non-sense.html" ""
-                      ("Non-sense" <> space <> "articles")))
-
-      , "Link abbreviation, URL encoded arguments" =:
-          T.unlines [ "#+link: expl http://example.com/%h/foo"
-                    , "[[expl:Hello, World!][Moin!]]"
-                    ] =?>
-          (para (link "http://example.com/Hello%2C%20World%21/foo" "" "Moin!"))
-
-      , "Link abbreviation, append arguments" =:
-          T.unlines [ "#+link: expl http://example.com/"
-                    , "[[expl:foo][bar]]"
-                    ] =?>
-          (para (link "http://example.com/foo" "" "bar"))
-
-
-      , testGroup "export options"
-
-          [ "disable simple sub/superscript syntax" =:
-              T.unlines [ "#+OPTIONS: ^:nil"
-                        , "a^b"
-                        ] =?>
-              para "a^b"
-
-          , "directly select drawers to be exported" =:
-              T.unlines [ "#+OPTIONS: d:(\"IMPORTANT\")"
-                        , ":IMPORTANT:"
-                        , "23"
-                        , ":END:"
-                        , ":BORING:"
-                        , "very boring"
-                        , ":END:"
-                        ] =?>
-              divWith (mempty, ["IMPORTANT", "drawer"], mempty) (para "23")
-
-          , "exclude drawers from being exported" =:
-              T.unlines [ "#+OPTIONS: d:(not \"BORING\")"
-                        , ":IMPORTANT:"
-                        , "5"
-                        , ":END:"
-                        , ":BORING:"
-                        , "very boring"
-                        , ":END:"
-                        ] =?>
-              divWith (mempty, ["IMPORTANT", "drawer"], mempty) (para "5")
-
-          , "don't include archive trees" =:
-              T.unlines [ "#+OPTIONS: arch:nil"
-                        , "* old  :ARCHIVE:"
-                        ] =?>
-              (mempty ::Blocks)
-
-          , "include complete archive trees" =:
-              T.unlines [ "#+OPTIONS: arch:t"
-                        , "* old  :ARCHIVE:"
-                        , "  boring"
-                        ] =?>
-              mconcat [ headerWith ("old", [], mempty) 1
-                                   ("old" <> space <> tagSpan "ARCHIVE")
-                      , para "boring"
-                      ]
-
-          , "include archive tree header only" =:
-              T.unlines [ "#+OPTIONS: arch:headline"
-                        , "* old  :ARCHIVE:"
-                        , "  boring"
-                        ] =?>
-              headerWith ("old", [], mempty) 1 ("old" <> space <> tagSpan "ARCHIVE")
-
-          , "limit headline depth" =:
-              T.unlines [ "#+OPTIONS: H:2"
-                        , "* top-level section"
-                        , "** subsection"
-                        , "*** list item 1"
-                        , "*** list item 2"
-                        ] =?>
-              mconcat [ headerWith ("top-level-section", [], [])    1 "top-level section"
-                      , headerWith ("subsection", [], []) 2 "subsection"
-                      , orderedList [ para "list item 1", para "list item 2" ]
-                      ]
-
-          , "turn all headlines into lists" =:
-              T.unlines [ "#+OPTIONS: H:0"
-                        , "first block"
-                        , "* top-level section 1"
-                        , "** subsection"
-                        , "* top-level section 2"
-                        ] =?>
-              mconcat [ para "first block"
-                      , orderedList
-                        [ (para "top-level section 1" <>
-                           orderedList [ para "subsection" ])
-                        , para "top-level section 2" ]
-                      ]
-
-          , "preserve linebreaks as hard breaks" =:
-              T.unlines [ "#+OPTIONS: \\n:t"
-                        , "first"
-                        , "second"
-                        ] =?>
-              para ("first" <> linebreak <> "second")
-
-          , "disable author export" =:
-              T.unlines [ "#+OPTIONS: author:nil"
-                        , "#+AUTHOR: ShyGuy"
-                        ] =?>
-              Pandoc nullMeta mempty
-
-          , "disable creator export" =:
-              T.unlines [ "#+OPTIONS: creator:nil"
-                        , "#+creator: The Architect"
-                        ] =?>
-              Pandoc nullMeta mempty
-
-          , "disable email export" =:
-              T.unlines [ "#+OPTIONS: email:nil"
-                        , "#+email: no-mail-please@example.com"
-                        ] =?>
-              Pandoc nullMeta mempty
-
-          , "disable inclusion of todo keywords" =:
-              T.unlines [ "#+OPTIONS: todo:nil"
-                        , "** DONE todo export"
-                        ] =?>
-              headerWith ("todo-export", [], []) 2 "todo export"
-
-          , "remove tags from headlines" =:
-              T.unlines [ "#+OPTIONS: tags:nil"
-                        , "* Headline :hello:world:"
-                        ] =?>
-              headerWith ("headline", [], mempty) 1 "Headline"
-          ]
-      ]
-
-  , testGroup "Basic Blocks" $
-      [ "Paragraph" =:
-          "Paragraph\n" =?>
-          para "Paragraph"
-
-      , testGroup "headers" $
-        [ "First Level Header" =:
-            "* Headline\n" =?>
-            headerWith ("headline", [], []) 1 "Headline"
-
-        , "Third Level Header" =:
-            "*** Third Level Headline\n" =?>
-            headerWith ("third-level-headline", [], [])
-                       3
-                       ("Third" <> space <> "Level" <> space <> "Headline")
-
-        , "Compact Headers with Paragraph" =:
-            T.unlines [ "* First Level"
-                      , "** Second Level"
-                      , "   Text"
-                      ] =?>
-            mconcat [ headerWith ("first-level", [], [])
-                                 1
-                                 ("First" <> space <> "Level")
-                    , headerWith ("second-level", [], [])
-                                 2
-                                 ("Second" <> space <> "Level")
-                    , para "Text"
-                    ]
-
-        , "Separated Headers with Paragraph" =:
-            T.unlines [ "* First Level"
-                      , ""
-                      , "** Second Level"
-                      , ""
-                      , "   Text"
-                      ] =?>
-            mconcat [ headerWith ("first-level", [], [])
-                                 1
-                                 ("First" <> space <> "Level")
-                    , headerWith ("second-level", [], [])
-                                 2
-                                 ("Second" <> space <> "Level")
-                    , para "Text"
-                    ]
-
-        , "Headers not preceded by a blank line" =:
-            T.unlines [ "** eat dinner"
-                      , "Spaghetti and meatballs tonight."
-                      , "** walk dog"
-                      ] =?>
-            mconcat [ headerWith ("eat-dinner", [], [])
-                                 2
-                                 ("eat" <> space <> "dinner")
-                    , para $ spcSep [ "Spaghetti", "and", "meatballs", "tonight." ]
-                    , headerWith ("walk-dog", [], [])
-                                 2
-                                 ("walk" <> space <> "dog")
-                    ]
-
-        , testGroup "Todo keywords"
-          [ "Header with known todo keyword" =:
-              "* TODO header" =?>
-              let todoSpan = spanWith ("", ["todo", "TODO"], []) "TODO"
-              in headerWith ("header", [], []) 1 (todoSpan <> space <> "header")
-
-          , "Header marked as done" =:
-              "* DONE header" =?>
-              let todoSpan = spanWith ("", ["done", "DONE"], []) "DONE"
-              in headerWith ("header", [], []) 1 (todoSpan <> space <> "header")
-
-          , "Header with unknown todo keyword" =:
-              "* WAITING header" =?>
-              headerWith ("waiting-header", [], []) 1 "WAITING header"
-
-          , "Custom todo keywords" =:
-              T.unlines [ "#+TODO: WAITING CANCELLED"
-                        , "* WAITING compile"
-                        , "* CANCELLED lunch"
-                        ] =?>
-              let todoSpan = spanWith ("", ["todo", "WAITING"], []) "WAITING"
-                  doneSpan = spanWith ("", ["done", "CANCELLED"], []) "CANCELLED"
-              in headerWith ("compile", [], []) 1 (todoSpan <> space <> "compile")
-              <> headerWith ("lunch", [], []) 1 (doneSpan <> space <> "lunch")
-
-          , "Custom todo keywords with multiple done-states" =:
-              T.unlines [ "#+TODO: WAITING | DONE CANCELLED "
-                        , "* WAITING compile"
-                        , "* CANCELLED lunch"
-                        , "* DONE todo-feature"
-                        ] =?>
-              let waiting = spanWith ("", ["todo", "WAITING"], []) "WAITING"
-                  cancelled = spanWith ("", ["done", "CANCELLED"], []) "CANCELLED"
-                  done = spanWith ("", ["done", "DONE"], []) "DONE"
-              in headerWith ("compile", [], []) 1 (waiting <> space <> "compile")
-              <> headerWith ("lunch", [], []) 1 (cancelled <> space <> "lunch")
-              <> headerWith ("todo-feature", [], []) 1 (done <> space <> "todo-feature")
-          ]
-
-        , "Tagged headers" =:
-            T.unlines [ "* Personal       :PERSONAL:"
-                      , "** Call Mom      :@PHONE:"
-                      , "** Call John     :@PHONE:JOHN: "
-                      ] =?>
-            mconcat [ headerWith ("personal", [], [])
-                                 1
-                                 ("Personal " <> tagSpan "PERSONAL")
-                    , headerWith ("call-mom", [], [])
-                                 2
-                                 ("Call Mom " <> tagSpan "@PHONE")
-                    , headerWith ("call-john", [], [])
-                                 2
-                                 ("Call John " <> tagSpan "@PHONE" <> "\160" <> tagSpan "JOHN")
-                    ]
-
-        , "Untagged header containing colons" =:
-            "* This: is not: tagged" =?>
-            headerWith ("this-is-not-tagged", [], []) 1 "This: is not: tagged"
-
-        , "Header starting with strokeout text" =:
-            T.unlines [ "foo"
-                      , ""
-                      , "* +thing+ other thing"
-                      ] =?>
-            mconcat [ para "foo"
-                    , headerWith ("thing-other-thing", [], [])
-                                 1
-                                 ((strikeout "thing") <> " other thing")
-                    ]
-
-        , "Comment Trees" =:
-            T.unlines [ "* COMMENT A comment tree"
-                      , "  Not much going on here"
-                      , "** This will be dropped"
-                      , "* Comment tree above"
-                      ] =?>
-            headerWith ("comment-tree-above", [], []) 1 "Comment tree above"
-
-        , "Nothing but a COMMENT header" =:
-            "* COMMENT Test" =?>
-            (mempty::Blocks)
-
-        , "Tree with :noexport:" =:
-            T.unlines [ "* Should be ignored :archive:noexport:old:"
-                      , "** Old stuff"
-                      , "   This is not going to be exported"
-                      ] =?>
-            (mempty::Blocks)
-
-        , "Subtree with :noexport:" =:
-            T.unlines [ "* Exported"
-                      , "** This isn't exported :noexport:"
-                      , "*** This neither"
-                      , "** But this is"
-                      ] =?>
-            mconcat [ headerWith ("exported", [], []) 1 "Exported"
-                    , headerWith ("but-this-is", [], []) 2 "But this is"
-                    ]
-
-        , "Preferences are treated as header attributes" =:
-            T.unlines [ "* foo"
-                      , "  :PROPERTIES:"
-                      , "  :custom_id: fubar"
-                      , "  :bar: baz"
-                      , "  :END:"
-                      ] =?>
-            headerWith ("fubar", [], [("bar", "baz")]) 1 "foo"
-
-
-        , "Headers marked with a unnumbered property get a class of the same name" =:
-            T.unlines [ "* Not numbered"
-                      , "  :PROPERTIES:"
-                      , "  :UNNUMBERED: t"
-                      , "  :END:"
-                      ] =?>
-            headerWith ("not-numbered", ["unnumbered"], []) 1 "Not numbered"
-      ]
-      , "Paragraph starting with an asterisk" =:
-          "*five" =?>
-          para "*five"
-
-      , "Paragraph containing asterisk at beginning of line" =:
-          T.unlines [ "lucky"
-                    , "*star"
-                    ] =?>
-          para ("lucky" <> softbreak <> "*star")
-
-      , "Example block" =:
-          T.unlines [ ": echo hello"
-                    , ": echo dear tester"
-                    ] =?>
-          codeBlockWith ("", ["example"], []) "echo hello\necho dear tester\n"
-
-      , "Example block surrounded by text" =:
-          T.unlines [ "Greetings"
-                    , ": echo hello"
-                    , ": echo dear tester"
-                    , "Bye"
-                    ] =?>
-          mconcat [ para "Greetings"
-                  , codeBlockWith ("", ["example"], [])
-                                  "echo hello\necho dear tester\n"
-                  , para "Bye"
-                  ]
-
-      , "Horizontal Rule" =:
-          T.unlines [ "before"
-                    , "-----"
-                    , "after"
-                    ] =?>
-          mconcat [ para "before"
-                  , horizontalRule
-                  , para "after"
-                  ]
-
-      , "Not a Horizontal Rule" =:
-          "----- em and en dash" =?>
-          para "\8212\8211 em and en dash"
-
-      , "Comment Block" =:
-          T.unlines [ "#+BEGIN_COMMENT"
-                    , "stuff"
-                    , "bla"
-                    , "#+END_COMMENT"] =?>
-          (mempty::Blocks)
-
-      , testGroup "Figures" $
-        [ "Figure" =:
-            T.unlines [ "#+caption: A very courageous man."
-                      , "#+name: goodguy"
-                      , "[[file:edward.jpg]]"
-                      ] =?>
-            para (image "edward.jpg" "fig:goodguy" "A very courageous man.")
-
-        , "Figure with no name" =:
-            T.unlines [ "#+caption: I've been through the desert on this"
-                      , "[[file:horse.png]]"
-                      ] =?>
-            para (image "horse.png" "fig:" "I've been through the desert on this")
-
-        , "Figure with `fig:` prefix in name" =:
-            T.unlines [ "#+caption: Used as a metapher in evolutionary biology."
-                      , "#+name: fig:redqueen"
-                      , "[[./the-red-queen.jpg]]"
-                      ] =?>
-            para (image "./the-red-queen.jpg" "fig:redqueen"
-                        "Used as a metapher in evolutionary biology.")
-
-        , "Figure with HTML attributes" =:
-            T.unlines [ "#+CAPTION: mah brain just explodid"
-                      , "#+NAME: lambdacat"
-                      , "#+ATTR_HTML: :style color: blue :role button"
-                      , "[[file:lambdacat.jpg]]"
-                      ] =?>
-            let kv = [("style", "color: blue"), ("role", "button")]
-                name = "fig:lambdacat"
-                caption = "mah brain just explodid"
-            in para (imageWith (mempty, mempty, kv) "lambdacat.jpg" name caption)
-
-        , "Labelled figure" =:
-            T.unlines [ "#+CAPTION: My figure"
-                      , "#+LABEL: fig:myfig"
-                      , "[[file:blub.png]]"
-                      ] =?>
-            let attr = ("fig:myfig", mempty, mempty)
-            in para (imageWith attr "blub.png" "fig:" "My figure")
-
-        , "Figure with empty caption" =:
-            T.unlines [ "#+CAPTION:"
-                      , "[[file:guess.jpg]]"
-                      ] =?>
-            para (image "guess.jpg" "fig:" "")
-        ]
-
-      , testGroup "Footnotes"
-        [ "Footnote" =:
-            T.unlines [ "A footnote[1]"
-                      , ""
-                      , "[1] First paragraph"
-                      , ""
-                      , "second paragraph"
-                      ] =?>
-            para (mconcat
-                  [ "A", space, "footnote"
-                  , note $ mconcat [ para ("First" <> space <> "paragraph")
-                                   , para ("second" <> space <> "paragraph")
-                                   ]
-                  ])
-
-        , "Two footnotes" =:
-            T.unlines [ "Footnotes[fn:1][fn:2]"
-                      , ""
-                      , "[fn:1] First note."
-                      , ""
-                      , "[fn:2] Second note."
-                      ] =?>
-            para (mconcat
-                  [ "Footnotes"
-                  , note $ para ("First" <> space <> "note.")
-                  , note $ para ("Second" <> space <> "note.")
-                  ])
-
-        , "Emphasized text before footnote" =:
-            T.unlines [ "/text/[fn:1]"
-                      , ""
-                      , "[fn:1] unicorn"
-                      ] =?>
-            para (mconcat
-                 [ emph "text"
-                 , note . para $ "unicorn"
-                 ])
-
-        , "Footnote that starts with emphasized text" =:
-            T.unlines [ "text[fn:1]"
-                      , ""
-                      , "[fn:1] /emphasized/"
-                      ] =?>
-            para (mconcat
-                 [ "text"
-                 , note . para $ emph "emphasized"
-                 ])
-
-        , "Footnote followed by header" =:
-            T.unlines [ "Another note[fn:yay]"
-                      , ""
-                      , "[fn:yay] This is great!"
-                      , ""
-                      , "** Headline"
-                      ] =?>
-            mconcat
-            [ para (mconcat
-                    [ "Another", space, "note"
-                    , note $ para ("This" <> space <> "is" <> space <> "great!")
-                    ])
-            , headerWith ("headline", [], []) 2 "Headline"
-            ]
-
-        , "Footnote followed by two blank lines" =:
-            T.unlines [ "footnote[fn:blanklines]"
-                      , ""
-                      , "[fn:blanklines] followed by blank lines"
-                      , ""
-                      , ""
-                      , "next"
-                      ] =?>
-            mconcat
-            [ para ("footnote" <> note (para "followed by blank lines"))
-            , para "next"
-            ]
-        ]
-      ]
-
-  , testGroup "Lists" $
-      [ "Simple Bullet Lists" =:
-          ("- Item1\n" <>
-           "- Item2\n") =?>
-          bulletList [ plain "Item1"
-                     , plain "Item2"
-                     ]
-
-      , "Indented Bullet Lists" =:
-          ("   - Item1\n" <>
-           "   - Item2\n") =?>
-          bulletList [ plain "Item1"
-                     , plain "Item2"
-                     ]
-
-      , "Unindented *" =:
-          ("- Item1\n" <>
-           "* Item2\n") =?>
-          bulletList [ plain "Item1"
-                     ] <>
-          headerWith ("item2", [], []) 1 "Item2"
-
-      , "Multi-line Bullet Lists" =:
-          ("- *Fat\n" <>
-           "  Tony*\n" <>
-           "- /Sideshow\n" <>
-           " Bob/") =?>
-          bulletList [ plain $ strong ("Fat" <> softbreak <> "Tony")
-                     , plain $ emph ("Sideshow" <> softbreak <> "Bob")
-                     ]
-
-      , "Nested Bullet Lists" =:
-          ("- Discovery\n" <>
-           "  + One More Time\n" <>
-           "  + Harder, Better, Faster, Stronger\n" <>
-           "- Homework\n" <>
-           "  + Around the World\n"<>
-           "- Human After All\n" <>
-           "  + Technologic\n" <>
-           "  + Robot Rock\n") =?>
-          bulletList [ mconcat
-                       [ plain "Discovery"
-                       , bulletList [ plain ("One" <> space <>
-                                             "More" <> space <>
-                                             "Time")
-                                    , plain ("Harder," <> space <>
-                                             "Better," <> space <>
-                                             "Faster," <> space <>
-                                             "Stronger")
-                                    ]
-                       ]
-                     , mconcat
-                       [ plain "Homework"
-                       , bulletList [ plain ("Around" <> space <>
-                                             "the" <> space <>
-                                             "World")
-                                    ]
-                       ]
-                     , mconcat
-                       [ plain ("Human" <> space <> "After" <> space <> "All")
-                       , bulletList [ plain "Technologic"
-                                    , plain ("Robot" <> space <> "Rock")
-                                    ]
-                       ]
-                     ]
-
-      , "Bullet List with Decreasing Indent" =:
-           ("  - Discovery\n\
-            \ - Human After All\n") =?>
-           mconcat [ bulletList [ plain "Discovery" ]
-                   , bulletList [ plain ("Human" <> space <> "After" <> space <> "All")]
-                   ]
-
-      , "Header follows Bullet List" =:
-          ("  - Discovery\n\
-           \  - Human After All\n\
-           \* Homework") =?>
-          mconcat [ bulletList [ plain "Discovery"
-                               , plain ("Human" <> space <> "After" <> space <> "All")
-                               ]
-                  , headerWith ("homework", [], []) 1 "Homework"
-                  ]
-
-      , "Bullet List Unindented with trailing Header" =:
-          ("- Discovery\n\
-           \- Homework\n\
-           \* NotValidListItem") =?>
-          mconcat [ bulletList [ plain "Discovery"
-                               , plain "Homework"
-                               ]
-                  , headerWith ("notvalidlistitem", [], []) 1 "NotValidListItem"
-                  ]
-
-      , "Empty bullet points" =:
-          T.unlines [ "-"
-                    , "- "
-                    ] =?>
-          bulletList [ plain "", plain "" ]
-
-      , "Simple Ordered List" =:
-          ("1. Item1\n" <>
-           "2. Item2\n") =?>
-          let listStyle = (1, DefaultStyle, DefaultDelim)
-              listStructure = [ plain "Item1"
-                              , plain "Item2"
-                              ]
-          in orderedListWith listStyle listStructure
-
-      , "Simple Ordered List with Parens" =:
-          ("1) Item1\n" <>
-           "2) Item2\n") =?>
-          let listStyle = (1, DefaultStyle, DefaultDelim)
-              listStructure = [ plain "Item1"
-                              , plain "Item2"
-                              ]
-          in orderedListWith listStyle listStructure
-
-      , "Indented Ordered List" =:
-          (" 1. Item1\n" <>
-           " 2. Item2\n") =?>
-          let listStyle = (1, DefaultStyle, DefaultDelim)
-              listStructure = [ plain "Item1"
-                              , plain "Item2"
-                              ]
-          in orderedListWith listStyle listStructure
-
-      , "Empty ordered list item" =:
-          T.unlines [ "1."
-                    , "3. "
-                    ] =?>
-          orderedList [ plain "", plain "" ]
-
-      , "Nested Ordered Lists" =:
-          ("1. One\n" <>
-           "   1. One-One\n" <>
-           "   2. One-Two\n" <>
-           "2. Two\n" <>
-           "   1. Two-One\n"<>
-           "   2. Two-Two\n") =?>
-          let listStyle = (1, DefaultStyle, DefaultDelim)
-              listStructure = [ mconcat
-                                [ plain "One"
-                                , orderedList [ plain "One-One"
-                                              , plain "One-Two"
-                                              ]
-                                ]
-                              , mconcat
-                                [ plain "Two"
-                                , orderedList [ plain "Two-One"
-                                              , plain "Two-Two"
-                                              ]
-                                ]
-                              ]
-          in orderedListWith listStyle listStructure
-
-      , "Ordered List in Bullet List" =:
-          ("- Emacs\n" <>
-           "  1. Org\n") =?>
-          bulletList [ (plain "Emacs") <>
-                       (orderedList [ plain "Org"])
-                     ]
-
-      , "Bullet List in Ordered List" =:
-          ("1. GNU\n" <>
-           "   - Freedom\n") =?>
-          orderedList [ (plain "GNU") <> bulletList [ (plain "Freedom") ] ]
-
-      , "Definition List" =:
-          T.unlines [ "- PLL :: phase-locked loop"
-                    , "- TTL ::"
-                    , "  transistor-transistor logic"
-                    , "- PSK :: phase-shift keying"
-                    , ""
-                    , "  a digital modulation scheme"
-                    ] =?>
-          definitionList [ ("PLL", [ plain $ "phase-locked" <> space <> "loop" ])
-                         , ("TTL", [ plain $ "transistor-transistor" <> space <>
-                                               "logic" ])
-                         , ("PSK", [ mconcat
-                                     [ para $ "phase-shift" <> space <> "keying"
-                                     , para $ spcSep [ "a", "digital"
-                                                     , "modulation", "scheme" ]
-                                     ]
-                                   ])
-                         ]
-      , "Definition list with multi-word term" =:
-        " - Elijah Wood :: He plays Frodo" =?>
-         definitionList [ ("Elijah" <> space <> "Wood", [plain $ "He" <> space <> "plays" <> space <> "Frodo"])]
-      , "Compact definition list" =:
-           T.unlines [ "- ATP :: adenosine 5' triphosphate"
-                     , "- DNA :: deoxyribonucleic acid"
-                     , "- PCR :: polymerase chain reaction"
-                     , ""
-                     ] =?>
-          definitionList
-          [ ("ATP", [ plain $ spcSep [ "adenosine", "5'", "triphosphate" ] ])
-          , ("DNA", [ plain $ spcSep [ "deoxyribonucleic", "acid" ] ])
-          , ("PCR", [ plain $ spcSep [ "polymerase", "chain", "reaction" ] ])
-          ]
-
-      , "Definition List With Trailing Header" =:
-          "- definition :: list\n\
-          \- cool :: defs\n\
-          \* header" =?>
-          mconcat [ definitionList [ ("definition", [plain "list"])
-                                   , ("cool", [plain "defs"])
-                                   ]
-                  , headerWith ("header", [], []) 1 "header"
-                  ]
-
-      , "Definition lists double-colon markers must be surrounded by whitespace" =:
-          "- std::cout" =?>
-          bulletList [ plain "std::cout" ]
-
-      , "Loose bullet list" =:
-         T.unlines [ "- apple"
-                   , ""
-                   , "- orange"
-                   , ""
-                   , "- peach"
-                   ] =?>
-          bulletList [ para "apple"
-                     , para "orange"
-                     , para "peach"
-                     ]
-
-      , "Recognize preceding paragraphs in non-list contexts" =:
-          T.unlines [ "CLOSED: [2015-10-19 Mon 15:03]"
-                    , "- Note taken on [2015-10-19 Mon 13:24]"
-                    ] =?>
-          mconcat [ para "CLOSED: [2015-10-19 Mon 15:03]"
-                  , bulletList [ plain "Note taken on [2015-10-19 Mon 13:24]" ]
-                  ]
-      ]
-
-  , testGroup "Tables"
-      [ "Single cell table" =:
-          "|Test|" =?>
-          simpleTable' 1 mempty [[plain "Test"]]
-
-      , "Multi cell table" =:
-          "| One | Two |" =?>
-           simpleTable' 2 mempty [ [ plain "One", plain "Two" ] ]
-
-      , "Multi line table" =:
-          T.unlines [ "| One   |"
-                    , "| Two   |"
-                    , "| Three |"
-                    ] =?>
-           simpleTable' 1 mempty
-                        [ [ plain "One" ]
-                        , [ plain "Two" ]
-                        , [ plain "Three" ]
-                        ]
-
-      , "Empty table" =:
-          "||" =?>
-          simpleTable' 1 mempty [[mempty]]
-
-      , "Glider Table" =:
-          T.unlines [ "| 1 | 0 | 0 |"
-                    , "| 0 | 1 | 1 |"
-                    , "| 1 | 1 | 0 |"
-                    ] =?>
-          simpleTable' 3 mempty
-                       [ [ plain "1", plain "0", plain "0" ]
-                       , [ plain "0", plain "1", plain "1" ]
-                       , [ plain "1", plain "1", plain "0" ]
-                       ]
-
-      , "Table between Paragraphs" =:
-          T.unlines [ "Before"
-                    , "| One | Two |"
-                    , "After"
-                    ] =?>
-          mconcat [ para "Before"
-                  , simpleTable' 2 mempty [ [ plain "One", plain "Two" ] ]
-                  , para "After"
-                  ]
-
-      , "Table with Header" =:
-          T.unlines [ "| Species      | Status       |"
-                    , "|--------------+--------------|"
-                    , "| cervisiae    | domesticated |"
-                    , "| paradoxus    | wild         |"
-                    ] =?>
-          simpleTable [ plain "Species", plain "Status" ]
-                      [ [ plain "cervisiae", plain "domesticated" ]
-                      , [ plain "paradoxus", plain "wild" ]
-                      ]
-
-      , "Table with final hline" =:
-          T.unlines [ "| cervisiae    | domesticated |"
-                    , "| paradoxus    | wild         |"
-                    , "|--------------+--------------|"
-                    ] =?>
-          simpleTable' 2 mempty
-                [ [ plain "cervisiae", plain "domesticated" ]
-                 , [ plain "paradoxus", plain "wild" ]
-                ]
-
-      , "Table in a box" =:
-          T.unlines [ "|---------|---------|"
-                    , "| static  | Haskell |"
-                    , "| dynamic | Lisp    |"
-                    , "|---------+---------|"
-                    ] =?>
-          simpleTable' 2 mempty
-                [ [ plain "static", plain "Haskell" ]
-                , [ plain "dynamic", plain "Lisp" ]
-                ]
-
-      , "Table with empty cells" =:
-          "|||c|" =?>
-          simpleTable' 3 mempty [[mempty, mempty, plain "c"]]
-
-      , "Table with empty rows" =:
-          T.unlines [ "| first  |"
-                    , "|        |"
-                    , "| third  |"
-                    ] =?>
-          simpleTable' 1 mempty [[plain "first"], [mempty], [plain "third"]]
-
-      , "Table with alignment row" =:
-          T.unlines [ "| Numbers | Text | More |"
-                    , "| <c>     | <r>  |      |"
-                    , "| 1       | One  | foo  |"
-                    , "| 2       | Two  | bar  |"
-                    ] =?>
-          table "" (zip [AlignCenter, AlignRight, AlignDefault] [0, 0, 0])
-                []
-                [ [ plain "Numbers", plain "Text", plain "More" ]
-                , [ plain "1"      , plain "One" , plain "foo"  ]
-                , [ plain "2"      , plain "Two" , plain "bar"  ]
-                ]
-
-      , "Pipe within text doesn't start a table" =:
-          "Ceci n'est pas une | pipe " =?>
-          para (spcSep [ "Ceci", "n'est", "pas", "une", "|", "pipe" ])
-
-      , "Missing pipe at end of row" =:
-          "|incomplete-but-valid" =?>
-          simpleTable' 1 mempty [ [ plain "incomplete-but-valid" ] ]
-
-      , "Table with differing row lengths" =:
-          T.unlines [ "| Numbers | Text "
-                    , "|-"
-                    , "| <c>     | <r>  |"
-                    , "| 1       | One  | foo  |"
-                    , "| 2"
-                    ] =?>
-          table "" (zip [AlignCenter, AlignRight] [0, 0])
-                [ plain "Numbers", plain "Text" ]
-                [ [ plain "1" , plain "One" , plain "foo" ]
-                , [ plain "2" ]
-                ]
-
-      , "Table with caption" =:
-          T.unlines [ "#+CAPTION: Hitchhiker's Multiplication Table"
-                    , "| x |  6 |"
-                    , "| 9 | 42 |"
-                    ] =?>
-          table "Hitchhiker's Multiplication Table"
-                [(AlignDefault, 0), (AlignDefault, 0)]
-                []
-                [ [ plain "x", plain "6" ]
-                , [ plain "9", plain "42" ]
-                ]
-      ]
-
-    , testGroup "Blocks and fragments"
-      [ "Source block" =:
-           T.unlines [ "  #+BEGIN_SRC haskell"
-                     , "  main = putStrLn greeting"
-                     , "    where greeting = \"moin\""
-                     , "  #+END_SRC" ] =?>
-           let attr' = ("", ["haskell"], [])
-               code' = "main = putStrLn greeting\n" <>
-                       "  where greeting = \"moin\"\n"
-           in codeBlockWith attr' code'
-
-      , "Source block with indented code" =:
-           T.unlines [ "  #+BEGIN_SRC haskell"
-                     , "    main = putStrLn greeting"
-                     , "      where greeting = \"moin\""
-                     , "  #+END_SRC" ] =?>
-           let attr' = ("", ["haskell"], [])
-               code' = "main = putStrLn greeting\n" <>
-                       "  where greeting = \"moin\"\n"
-           in codeBlockWith attr' code'
-
-      , "Source block with tab-indented code" =:
-           T.unlines [ "\t#+BEGIN_SRC haskell"
-                     , "\tmain = putStrLn greeting"
-                     , "\t  where greeting = \"moin\""
-                     , "\t#+END_SRC" ] =?>
-           let attr' = ("", ["haskell"], [])
-               code' = "main = putStrLn greeting\n" <>
-                       "  where greeting = \"moin\"\n"
-           in codeBlockWith attr' code'
-
-      , "Empty source block" =:
-           T.unlines [ "  #+BEGIN_SRC haskell"
-                     , "  #+END_SRC" ] =?>
-           let attr' = ("", ["haskell"], [])
-               code' = ""
-           in codeBlockWith attr' code'
-
-      , "Source block between paragraphs" =:
-           T.unlines [ "Low German greeting"
-                     , "  #+BEGIN_SRC haskell"
-                     , "  main = putStrLn greeting"
-                     , "    where greeting = \"Moin!\""
-                     , "  #+END_SRC" ] =?>
-           let attr' = ("", ["haskell"], [])
-               code' = "main = putStrLn greeting\n" <>
-                        "  where greeting = \"Moin!\"\n"
-           in mconcat [ para $ spcSep [ "Low", "German", "greeting"  ]
-                      , codeBlockWith attr' code'
-                      ]
-      , "Source block with babel arguments" =:
-           T.unlines [ "#+BEGIN_SRC emacs-lisp :exports both"
-                     , "(progn (message \"Hello, World!\")"
-                     , "       (+ 23 42))"
-                     , "#+END_SRC" ] =?>
-           let classes = [ "commonlisp" ] -- as kate doesn't know emacs-lisp syntax
-               params = [ ("org-language", "emacs-lisp")
-                        , ("exports", "both")
-                        ]
-               code' = unlines [ "(progn (message \"Hello, World!\")"
-                               , "       (+ 23 42))" ]
-           in codeBlockWith ("", classes, params) code'
-
-      , "Source block with results and :exports both" =:
-           T.unlines [ "#+BEGIN_SRC emacs-lisp :exports both"
-                     , "(progn (message \"Hello, World!\")"
-                     , "       (+ 23 42))"
-                     , "#+END_SRC"
-                     , ""
-                     , "#+RESULTS:"
-                     , ": 65"] =?>
-           let classes = [ "commonlisp" ]
-               params = [ ("org-language", "emacs-lisp")
-                        , ("exports", "both")
-                        ]
-               code' = unlines [ "(progn (message \"Hello, World!\")"
-                               , "       (+ 23 42))" ]
-               results' = "65\n"
-           in codeBlockWith ("", classes, params) code'
-              <>
-              codeBlockWith ("", ["example"], []) results'
-
-      , "Source block with results and :exports code" =:
-           T.unlines [ "#+BEGIN_SRC emacs-lisp :exports code"
-                     , "(progn (message \"Hello, World!\")"
-                     , "       (+ 23 42))"
-                     , "#+END_SRC"
-                     , ""
-                     , "#+RESULTS:"
-                     , ": 65" ] =?>
-           let classes = [ "commonlisp" ]
-               params = [ ("org-language", "emacs-lisp")
-                        , ("exports", "code")
-                        ]
-               code' = unlines [ "(progn (message \"Hello, World!\")"
-                               , "       (+ 23 42))" ]
-           in codeBlockWith ("", classes, params) code'
-
-      , "Source block with results and :exports results" =:
-           T.unlines [ "#+BEGIN_SRC emacs-lisp :exports results"
-                     , "(progn (message \"Hello, World!\")"
-                     , "       (+ 23 42))"
-                     , "#+END_SRC"
-                     , ""
-                     , "#+RESULTS:"
-                     , ": 65" ] =?>
-           let results' = "65\n"
-           in codeBlockWith ("", ["example"], []) results'
-
-      , "Source block with results and :exports none" =:
-           T.unlines [ "#+BEGIN_SRC emacs-lisp :exports none"
-                     , "(progn (message \"Hello, World!\")"
-                     , "       (+ 23 42))"
-                     , "#+END_SRC"
-                     , ""
-                     , "#+RESULTS:"
-                     , ": 65" ] =?>
-           (mempty :: Blocks)
-
-      , "Source block with toggling header arguments" =:
-        T.unlines [ "#+BEGIN_SRC sh :noeval"
-                  , "echo $HOME"
-                  , "#+END_SRC"
-                  ] =?>
-        let classes = [ "bash" ]
-            params = [ ("org-language", "sh"), ("noeval", "yes") ]
-        in codeBlockWith ("", classes, params) "echo $HOME\n"
-
-      , "Source block with line number switch" =:
-        T.unlines [ "#+BEGIN_SRC sh -n 10"
-                  , ":() { :|:& };:"
-                  , "#+END_SRC"
-                  ] =?>
-        let classes = [ "bash", "numberLines" ]
-            params = [ ("org-language", "sh"), ("startFrom", "10") ]
-        in codeBlockWith ("", classes, params) ":() { :|:& };:\n"
-
-      , "Source block with multi-word parameter values" =:
-        T.unlines [ "#+BEGIN_SRC dot :cmdline -Kdot -Tpng "
-                  , "digraph { id [label=\"ID\"] }"
-                  , "#+END_SRC"
-                  ] =?>
-        let classes = [ "dot" ]
-            params = [ ("cmdline", "-Kdot -Tpng") ]
-        in codeBlockWith ("", classes, params) "digraph { id [label=\"ID\"] }\n"
-
-      , "Example block" =:
-           T.unlines [ "#+begin_example"
-                     , "A chosen representation of"
-                     , "a rule."
-                     , "#+eND_exAMPle"
-                     ] =?>
-           codeBlockWith ("", ["example"], [])
-                         "A chosen representation of\na rule.\n"
-
-      , "HTML block" =:
-           T.unlines [ "#+BEGIN_HTML"
-                     , "<aside>HTML5 is pretty nice.</aside>"
-                     , "#+END_HTML"
-                     ] =?>
-           rawBlock "html" "<aside>HTML5 is pretty nice.</aside>\n"
-
-      , "Quote block" =:
-           T.unlines [ "#+BEGIN_QUOTE"
-                     , "/Niemand/ hat die Absicht, eine Mauer zu errichten!"
-                     , "#+END_QUOTE"
-                     ] =?>
-           blockQuote (para (spcSep [ emph "Niemand", "hat", "die", "Absicht,"
-                                    , "eine", "Mauer", "zu", "errichten!"
-                                    ]))
-
-      , "Verse block" =:
-          T.unlines [ "The first lines of Goethe's /Faust/:"
-                    , "#+begin_verse"
-                    , "Habe nun, ach! Philosophie,"
-                    , "Juristerei und Medizin,"
-                    , "Und leider auch Theologie!"
-                    , "Durchaus studiert, mit heißem Bemühn."
-                    , "#+end_verse"
-                    ] =?>
-          mconcat
-          [ para $ spcSep [ "The", "first", "lines", "of"
-                          , "Goethe's", emph "Faust" <> ":"]
-          , lineBlock
-              [ "Habe nun, ach! Philosophie,"
-              , "Juristerei und Medizin,"
-              , "Und leider auch Theologie!"
-              , "Durchaus studiert, mit heißem Bemühn."
-              ]
-          ]
-
-      , "Verse block with blank lines" =:
-          T.unlines [ "#+BEGIN_VERSE"
-                    , "foo"
-                    , ""
-                    , "bar"
-                    , "#+END_VERSE"
-                    ] =?>
-          lineBlock [ "foo", mempty, "bar" ]
-
-      , "Verse block with varying indentation" =:
-          T.unlines [ "#+BEGIN_VERSE"
-                    , "  hello darkness"
-                    , "my old friend"
-                    , "#+END_VERSE"
-                    ] =?>
-          lineBlock [ "\160\160hello darkness", "my old friend" ]
-
-      , "Raw block LaTeX" =:
-          T.unlines [ "#+BEGIN_LaTeX"
-                    , "The category $\\cat{Set}$ is adhesive."
-                    , "#+END_LaTeX"
-                    ] =?>
-          rawBlock "latex" "The category $\\cat{Set}$ is adhesive.\n"
-
-      , "Raw LaTeX line" =:
-          "#+LATEX: \\let\\foo\\bar" =?>
-          rawBlock "latex" "\\let\\foo\\bar"
-
-      , "Raw Beamer line" =:
-          "#+beamer: \\pause" =?>
-          rawBlock "beamer" "\\pause"
-
-      , "Raw HTML line" =:
-          "#+HTML: <aside>not important</aside>" =?>
-          rawBlock "html" "<aside>not important</aside>"
-
-      , "Export block HTML" =:
-          T.unlines [ "#+BEGIN_export html"
-                    , "<samp>Hello, World!</samp>"
-                    , "#+END_export"
-                    ] =?>
-          rawBlock "html" "<samp>Hello, World!</samp>\n"
-
-      , "LaTeX fragment" =:
-          T.unlines [ "\\begin{equation}"
-                    , "X_i = \\begin{cases}"
-                    , "      G_{\\alpha(i)} & \\text{if }\\alpha(i-1) = \\alpha(i)\\\\"
-                    , "      C_{\\alpha(i)} & \\text{otherwise}"
-                    , "      \\end{cases}"
-                    , "\\end{equation}"
-                    ] =?>
-          rawBlock "latex"
-                   (unlines [ "\\begin{equation}"
-                            , "X_i = \\begin{cases}"
-                            , "      G_{\\alpha(i)} & \\text{if }\\alpha(i-1) =" <>
-                              " \\alpha(i)\\\\"
-                            , "      C_{\\alpha(i)} & \\text{otherwise}"
-                            , "      \\end{cases}"
-                            , "\\end{equation}"
-                            ])
-
-      , "Code block with caption" =:
-          T.unlines [ "#+CAPTION: Functor laws in Haskell"
-                    , "#+NAME: functor-laws"
-                    , "#+BEGIN_SRC haskell"
-                    , "fmap id = id"
-                    , "fmap (p . q) = (fmap p) . (fmap q)"
-                    , "#+END_SRC"
-                    ] =?>
-          divWith
-             nullAttr
-             (mappend
-              (plain $ spanWith ("", ["label"], [])
-                                (spcSep [ "Functor", "laws", "in", "Haskell" ]))
-              (codeBlockWith ("functor-laws", ["haskell"], [])
-                             (unlines [ "fmap id = id"
-                                      , "fmap (p . q) = (fmap p) . (fmap q)"
-                                      ])))
-
-      , "Convert blank lines in blocks to single newlines" =:
-          T.unlines [ "#+begin_html"
-                    , ""
-                    , "<span>boring</span>"
-                    , ""
-                    , "#+end_html"
-                    ] =?>
-          rawBlock "html" "\n<span>boring</span>\n\n"
-
-      , "Accept `ATTR_HTML` attributes for generic block" =:
-          T.unlines [ "#+ATTR_HTML: :title hello, world :id test :class fun code"
-                    , "#+BEGIN_TEST"
-                    , "nonsense"
-                    , "#+END_TEST"
-                    ] =?>
-          let attr = ("test", ["fun", "code", "TEST"], [("title", "hello, world")])
-          in divWith attr (para "nonsense")
-
-      , "Non-letter chars in source block parameters" =:
-          T.unlines [ "#+BEGIN_SRC C :tangle xxxx.c :city Zürich"
-                    , "code body"
-                    , "#+END_SRC"
-                    ] =?>
-          let params  = [ ("org-language", "C")
-                        , ("tangle", "xxxx.c")
-                        , ("city", "Zürich")
-                        ]
-          in codeBlockWith ( "", ["c"], params) "code body\n"
-      ]
-
-    , testGroup "Smart punctuation"
-      [ test orgSmart "quote before ellipses"
-        ("'...hi'"
-         =?> para (singleQuoted "…hi"))
-
-      , test orgSmart "apostrophe before emph"
-        ("D'oh! A l'/aide/!"
-         =?> para ("D’oh! A l’" <> emph "aide" <> "!"))
-
-      , test orgSmart "apostrophe in French"
-        ("À l'arrivée de la guerre, le thème de l'«impossibilité du socialisme»"
-         =?> para "À l’arrivée de la guerre, le thème de l’«impossibilité du socialisme»")
-
-      , test orgSmart "Quotes cannot occur at the end of emphasized text"
-        ("/say \"yes\"/" =?>
-         para ("/say" <> space <> doubleQuoted "yes" <> "/"))
-
-      , test orgSmart "Dashes are allowed at the borders of emphasis'"
-        ("/foo---/" =?>
-         para (emph "foo—"))
-
-      , test orgSmart "Single quotes can be followed by emphasized text"
-        ("Singles on the '/meat market/'" =?>
-         para ("Singles on the " <> (singleQuoted $ emph "meat market")))
-
-      , test orgSmart "Double quotes can be followed by emphasized text"
-        ("Double income, no kids: \"/DINK/\"" =?>
-         para ("Double income, no kids: " <> (doubleQuoted $ emph "DINK")))
-      ]
+import Test.Tasty (TestTree, testGroup)
+import qualified Tests.Readers.Org.Block as Block
+import qualified Tests.Readers.Org.Directive as Directive
+import qualified Tests.Readers.Org.Inline as Inline
+import qualified Tests.Readers.Org.Meta as Meta
+
+tests :: [TestTree]
+tests =
+  [ testGroup "Inlines" Inline.tests
+  , testGroup "Basic Blocks" Block.tests
+  , testGroup "Meta Information" Meta.tests
+  , testGroup "Directives" Directive.tests
   ]
diff --git a/test/Tests/Readers/Org/Block.hs b/test/Tests/Readers/Org/Block.hs
new file mode 100644
--- /dev/null
+++ b/test/Tests/Readers/Org/Block.hs
@@ -0,0 +1,192 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.Org.Block (tests) where
+
+import Test.Tasty (TestTree, testGroup)
+import Tests.Helpers ((=?>))
+import Tests.Readers.Org.Shared ((=:), spcSep)
+import Text.Pandoc.Builder
+import qualified Data.Text as T
+import qualified Tests.Readers.Org.Block.CodeBlock as CodeBlock
+import qualified Tests.Readers.Org.Block.Figure as Figure
+import qualified Tests.Readers.Org.Block.Header as Header
+import qualified Tests.Readers.Org.Block.List as List
+import qualified Tests.Readers.Org.Block.Table as Table
+
+tests :: [TestTree]
+tests =
+  [ "Paragraph" =:
+      "Paragraph\n" =?>
+      para "Paragraph"
+
+  , "Paragraph starting with an asterisk" =:
+      "*five" =?>
+      para "*five"
+
+  , "Paragraph containing asterisk at beginning of line" =:
+      T.unlines [ "lucky"
+                , "*star"
+                ] =?>
+      para ("lucky" <> softbreak <> "*star")
+
+  , "Example block" =:
+      T.unlines [ ": echo hello"
+                , ": echo dear tester"
+                ] =?>
+      codeBlockWith ("", ["example"], []) "echo hello\necho dear tester\n"
+
+  , "Example block surrounded by text" =:
+      T.unlines [ "Greetings"
+                , ": echo hello"
+                , ": echo dear tester"
+                , "Bye"
+                ] =?>
+      mconcat [ para "Greetings"
+              , codeBlockWith ("", ["example"], [])
+                              "echo hello\necho dear tester\n"
+              , para "Bye"
+              ]
+
+  , "Horizontal Rule" =:
+      T.unlines [ "before"
+                , "-----"
+                , "after"
+                ] =?>
+      mconcat [ para "before"
+              , horizontalRule
+              , para "after"
+              ]
+
+  , "Not a Horizontal Rule" =:
+      "----- em and en dash" =?>
+      para "\8212\8211 em and en dash"
+
+  , "Comment Block" =:
+      T.unlines [ "#+BEGIN_COMMENT"
+                , "stuff"
+                , "bla"
+                , "#+END_COMMENT"] =?>
+      (mempty::Blocks)
+
+  , testGroup "Blocks and fragments"
+    [ "HTML block" =:
+      T.unlines [ "#+BEGIN_HTML"
+                , "<aside>HTML5 is pretty nice.</aside>"
+                , "#+END_HTML"
+                ] =?>
+      rawBlock "html" "<aside>HTML5 is pretty nice.</aside>\n"
+
+    , "Quote block" =:
+      T.unlines [ "#+BEGIN_QUOTE"
+                , "/Niemand/ hat die Absicht, eine Mauer zu errichten!"
+                , "#+END_QUOTE"
+                ] =?>
+      blockQuote (para (spcSep [ emph "Niemand", "hat", "die", "Absicht,"
+                               , "eine", "Mauer", "zu", "errichten!"
+                               ]))
+
+    , "Verse block" =:
+      T.unlines [ "The first lines of Goethe's /Faust/:"
+                , "#+begin_verse"
+                , "Habe nun, ach! Philosophie,"
+                , "Juristerei und Medizin,"
+                , "Und leider auch Theologie!"
+                , "Durchaus studiert, mit heißem Bemühn."
+                , "#+end_verse"
+                ] =?>
+      mconcat
+        [ para $ spcSep [ "The", "first", "lines", "of"
+                        , "Goethe's", emph "Faust" <> ":"]
+        , lineBlock
+          [ "Habe nun, ach! Philosophie,"
+          , "Juristerei und Medizin,"
+          , "Und leider auch Theologie!"
+          , "Durchaus studiert, mit heißem Bemühn."
+          ]
+        ]
+
+    , "Verse block with blank lines" =:
+      T.unlines [ "#+BEGIN_VERSE"
+                , "foo"
+                , ""
+                , "bar"
+                , "#+END_VERSE"
+                ] =?>
+      lineBlock [ "foo", mempty, "bar" ]
+
+    , "Verse block with varying indentation" =:
+      T.unlines [ "#+BEGIN_VERSE"
+                , "  hello darkness"
+                , "my old friend"
+                , "#+END_VERSE"
+                ] =?>
+      lineBlock [ "\160\160hello darkness", "my old friend" ]
+
+    , "Raw block LaTeX" =:
+      T.unlines [ "#+BEGIN_LaTeX"
+                , "The category $\\cat{Set}$ is adhesive."
+                , "#+END_LaTeX"
+                ] =?>
+      rawBlock "latex" "The category $\\cat{Set}$ is adhesive.\n"
+
+    , "Raw LaTeX line" =:
+      "#+LATEX: \\let\\foo\\bar" =?>
+      rawBlock "latex" "\\let\\foo\\bar"
+
+    , "Raw Beamer line" =:
+      "#+beamer: \\pause" =?>
+      rawBlock "beamer" "\\pause"
+
+    , "Raw HTML line" =:
+      "#+HTML: <aside>not important</aside>" =?>
+      rawBlock "html" "<aside>not important</aside>"
+
+    , "Export block HTML" =:
+      T.unlines [ "#+BEGIN_export html"
+                , "<samp>Hello, World!</samp>"
+                , "#+END_export"
+                ] =?>
+      rawBlock "html" "<samp>Hello, World!</samp>\n"
+
+    , "LaTeX fragment" =:
+      T.unlines [ "\\begin{equation}"
+                , "X_i = \\begin{cases}"
+                , "      G_{\\alpha(i)} & \\text{if }\\alpha(i-1) = \\alpha(i)\\\\"
+                , "      C_{\\alpha(i)} & \\text{otherwise}"
+                , "      \\end{cases}"
+                , "\\end{equation}"
+                ] =?>
+      rawBlock "latex"
+      (unlines [ "\\begin{equation}"
+               , "X_i = \\begin{cases}"
+               , "      G_{\\alpha(i)} & \\text{if }\\alpha(i-1) =" <>
+                 " \\alpha(i)\\\\"
+               , "      C_{\\alpha(i)} & \\text{otherwise}"
+               , "      \\end{cases}"
+               , "\\end{equation}"
+               ])
+
+    , "Convert blank lines in blocks to single newlines" =:
+      T.unlines [ "#+begin_html"
+                , ""
+                , "<span>boring</span>"
+                , ""
+                , "#+end_html"
+                ] =?>
+      rawBlock "html" "\n<span>boring</span>\n\n"
+
+    , "Accept `ATTR_HTML` attributes for generic block" =:
+      T.unlines [ "#+ATTR_HTML: :title hello, world :id test :class fun code"
+                , "#+BEGIN_TEST"
+                , "nonsense"
+                , "#+END_TEST"
+                ] =?>
+      let attr = ("test", ["fun", "code", "TEST"], [("title", "hello, world")])
+      in divWith attr (para "nonsense")
+    ]
+
+  , testGroup "Headers" Header.tests
+  , testGroup "Figures" Figure.tests
+  , testGroup "Lists" List.tests
+  , testGroup "CodeBlocks" CodeBlock.tests
+  , testGroup "Tables" Table.tests
+  ]
diff --git a/test/Tests/Readers/Org/Block/CodeBlock.hs b/test/Tests/Readers/Org/Block/CodeBlock.hs
new file mode 100644
--- /dev/null
+++ b/test/Tests/Readers/Org/Block/CodeBlock.hs
@@ -0,0 +1,194 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.Org.Block.CodeBlock (tests) where
+
+import Test.Tasty (TestTree)
+import Tests.Helpers ((=?>))
+import Tests.Readers.Org.Shared ((=:), spcSep)
+import Text.Pandoc.Builder
+import qualified Data.Text as T
+
+tests :: [TestTree]
+tests =
+  [ "Source block" =:
+       T.unlines [ "  #+BEGIN_SRC haskell"
+                 , "  main = putStrLn greeting"
+                 , "    where greeting = \"moin\""
+                 , "  #+END_SRC" ] =?>
+       let attr' = ("", ["haskell"], [])
+           code' = "main = putStrLn greeting\n" <>
+                   "  where greeting = \"moin\"\n"
+       in codeBlockWith attr' code'
+
+  , "Source block with indented code" =:
+       T.unlines [ "  #+BEGIN_SRC haskell"
+                 , "    main = putStrLn greeting"
+                 , "      where greeting = \"moin\""
+                 , "  #+END_SRC" ] =?>
+       let attr' = ("", ["haskell"], [])
+           code' = "main = putStrLn greeting\n" <>
+                   "  where greeting = \"moin\"\n"
+       in codeBlockWith attr' code'
+
+  , "Source block with tab-indented code" =:
+       T.unlines [ "\t#+BEGIN_SRC haskell"
+                 , "\tmain = putStrLn greeting"
+                 , "\t  where greeting = \"moin\""
+                 , "\t#+END_SRC" ] =?>
+       let attr' = ("", ["haskell"], [])
+           code' = "main = putStrLn greeting\n" <>
+                   "  where greeting = \"moin\"\n"
+       in codeBlockWith attr' code'
+
+  , "Empty source block" =:
+       T.unlines [ "  #+BEGIN_SRC haskell"
+                 , "  #+END_SRC" ] =?>
+       let attr' = ("", ["haskell"], [])
+           code' = ""
+       in codeBlockWith attr' code'
+
+  , "Source block between paragraphs" =:
+       T.unlines [ "Low German greeting"
+                 , "  #+BEGIN_SRC haskell"
+                 , "  main = putStrLn greeting"
+                 , "    where greeting = \"Moin!\""
+                 , "  #+END_SRC" ] =?>
+       let attr' = ("", ["haskell"], [])
+           code' = "main = putStrLn greeting\n" <>
+                    "  where greeting = \"Moin!\"\n"
+       in mconcat [ para $ spcSep [ "Low", "German", "greeting"  ]
+                  , codeBlockWith attr' code'
+                  ]
+  , "Source block with babel arguments" =:
+       T.unlines [ "#+BEGIN_SRC emacs-lisp :exports both"
+                 , "(progn (message \"Hello, World!\")"
+                 , "       (+ 23 42))"
+                 , "#+END_SRC" ] =?>
+       let classes = [ "commonlisp" ] -- as kate doesn't know emacs-lisp syntax
+           params = [ ("org-language", "emacs-lisp")
+                    , ("exports", "both")
+                    ]
+           code' = unlines [ "(progn (message \"Hello, World!\")"
+                           , "       (+ 23 42))" ]
+       in codeBlockWith ("", classes, params) code'
+
+  , "Source block with results and :exports both" =:
+       T.unlines [ "#+BEGIN_SRC emacs-lisp :exports both"
+                 , "(progn (message \"Hello, World!\")"
+                 , "       (+ 23 42))"
+                 , "#+END_SRC"
+                 , ""
+                 , "#+RESULTS:"
+                 , ": 65"] =?>
+       let classes = [ "commonlisp" ]
+           params = [ ("org-language", "emacs-lisp")
+                    , ("exports", "both")
+                    ]
+           code' = unlines [ "(progn (message \"Hello, World!\")"
+                           , "       (+ 23 42))" ]
+           results' = "65\n"
+       in codeBlockWith ("", classes, params) code'
+          <>
+          codeBlockWith ("", ["example"], []) results'
+
+  , "Source block with results and :exports code" =:
+       T.unlines [ "#+BEGIN_SRC emacs-lisp :exports code"
+                 , "(progn (message \"Hello, World!\")"
+                 , "       (+ 23 42))"
+                 , "#+END_SRC"
+                 , ""
+                 , "#+RESULTS:"
+                 , ": 65" ] =?>
+       let classes = [ "commonlisp" ]
+           params = [ ("org-language", "emacs-lisp")
+                    , ("exports", "code")
+                    ]
+           code' = unlines [ "(progn (message \"Hello, World!\")"
+                           , "       (+ 23 42))" ]
+       in codeBlockWith ("", classes, params) code'
+
+  , "Source block with results and :exports results" =:
+       T.unlines [ "#+BEGIN_SRC emacs-lisp :exports results"
+                 , "(progn (message \"Hello, World!\")"
+                 , "       (+ 23 42))"
+                 , "#+END_SRC"
+                 , ""
+                 , "#+RESULTS:"
+                 , ": 65" ] =?>
+       let results' = "65\n"
+       in codeBlockWith ("", ["example"], []) results'
+
+  , "Source block with results and :exports none" =:
+       T.unlines [ "#+BEGIN_SRC emacs-lisp :exports none"
+                 , "(progn (message \"Hello, World!\")"
+                 , "       (+ 23 42))"
+                 , "#+END_SRC"
+                 , ""
+                 , "#+RESULTS:"
+                 , ": 65" ] =?>
+       (mempty :: Blocks)
+
+  , "Source block with toggling header arguments" =:
+    T.unlines [ "#+BEGIN_SRC sh :noeval"
+              , "echo $HOME"
+              , "#+END_SRC"
+              ] =?>
+    let classes = [ "bash" ]
+        params = [ ("org-language", "sh"), ("noeval", "yes") ]
+    in codeBlockWith ("", classes, params) "echo $HOME\n"
+
+  , "Source block with line number switch" =:
+    T.unlines [ "#+BEGIN_SRC sh -n 10"
+              , ":() { :|:& };:"
+              , "#+END_SRC"
+              ] =?>
+    let classes = [ "bash", "numberLines" ]
+        params = [ ("org-language", "sh"), ("startFrom", "10") ]
+    in codeBlockWith ("", classes, params) ":() { :|:& };:\n"
+
+  , "Source block with multi-word parameter values" =:
+    T.unlines [ "#+BEGIN_SRC dot :cmdline -Kdot -Tpng "
+              , "digraph { id [label=\"ID\"] }"
+              , "#+END_SRC"
+              ] =?>
+    let classes = [ "dot" ]
+        params = [ ("cmdline", "-Kdot -Tpng") ]
+    in codeBlockWith ("", classes, params) "digraph { id [label=\"ID\"] }\n"
+
+  , "Example block" =:
+       T.unlines [ "#+begin_example"
+                 , "A chosen representation of"
+                 , "a rule."
+                 , "#+eND_exAMPle"
+                 ] =?>
+       codeBlockWith ("", ["example"], [])
+                     "A chosen representation of\na rule.\n"
+
+  , "Code block with caption" =:
+      T.unlines [ "#+CAPTION: Functor laws in Haskell"
+                , "#+NAME: functor-laws"
+                , "#+BEGIN_SRC haskell"
+                , "fmap id = id"
+                , "fmap (p . q) = (fmap p) . (fmap q)"
+                , "#+END_SRC"
+                ] =?>
+      divWith
+         nullAttr
+         (mappend
+          (plain $ spanWith ("", ["label"], [])
+                            (spcSep [ "Functor", "laws", "in", "Haskell" ]))
+          (codeBlockWith ("functor-laws", ["haskell"], [])
+                         (unlines [ "fmap id = id"
+                                  , "fmap (p . q) = (fmap p) . (fmap q)"
+                                  ])))
+
+  , "Non-letter chars in source block parameters" =:
+      T.unlines [ "#+BEGIN_SRC C :tangle xxxx.c :city Zürich"
+                , "code body"
+                , "#+END_SRC"
+                ] =?>
+      let params  = [ ("org-language", "C")
+                    , ("tangle", "xxxx.c")
+                    , ("city", "Zürich")
+                    ]
+      in codeBlockWith ( "", ["c"], params) "code body\n"
+  ]
diff --git a/test/Tests/Readers/Org/Block/Figure.hs b/test/Tests/Readers/Org/Block/Figure.hs
new file mode 100644
--- /dev/null
+++ b/test/Tests/Readers/Org/Block/Figure.hs
@@ -0,0 +1,57 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.Org.Block.Figure (tests) where
+
+import Test.Tasty (TestTree)
+import Tests.Helpers ((=?>))
+import Tests.Readers.Org.Shared ((=:))
+import Text.Pandoc.Builder (image, imageWith, para)
+import qualified Data.Text as T
+
+tests :: [TestTree]
+tests =
+  [ "Figure" =:
+      T.unlines [ "#+caption: A very courageous man."
+                , "#+name: goodguy"
+                , "[[file:edward.jpg]]"
+                ] =?>
+      para (image "edward.jpg" "fig:goodguy" "A very courageous man.")
+
+  , "Figure with no name" =:
+      T.unlines [ "#+caption: I've been through the desert on this"
+                , "[[file:horse.png]]"
+                ] =?>
+      para (image "horse.png" "fig:" "I've been through the desert on this")
+
+  , "Figure with `fig:` prefix in name" =:
+      T.unlines [ "#+caption: Used as a metapher in evolutionary biology."
+                , "#+name: fig:redqueen"
+                , "[[./the-red-queen.jpg]]"
+                ] =?>
+      para (image "./the-red-queen.jpg" "fig:redqueen"
+                  "Used as a metapher in evolutionary biology.")
+
+  , "Figure with HTML attributes" =:
+      T.unlines [ "#+CAPTION: mah brain just explodid"
+                , "#+NAME: lambdacat"
+                , "#+ATTR_HTML: :style color: blue :role button"
+                , "[[file:lambdacat.jpg]]"
+                ] =?>
+      let kv = [("style", "color: blue"), ("role", "button")]
+          name = "fig:lambdacat"
+          caption = "mah brain just explodid"
+      in para (imageWith (mempty, mempty, kv) "lambdacat.jpg" name caption)
+
+  , "Labelled figure" =:
+      T.unlines [ "#+CAPTION: My figure"
+                , "#+LABEL: fig:myfig"
+                , "[[file:blub.png]]"
+                ] =?>
+      let attr = ("fig:myfig", mempty, mempty)
+      in para (imageWith attr "blub.png" "fig:" "My figure")
+
+  , "Figure with empty caption" =:
+      T.unlines [ "#+CAPTION:"
+                , "[[file:guess.jpg]]"
+                ] =?>
+      para (image "guess.jpg" "fig:" "")
+  ]
diff --git a/test/Tests/Readers/Org/Block/Header.hs b/test/Tests/Readers/Org/Block/Header.hs
new file mode 100644
--- /dev/null
+++ b/test/Tests/Readers/Org/Block/Header.hs
@@ -0,0 +1,182 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.Org.Block.Header (tests) where
+
+import Test.Tasty (TestTree, testGroup)
+import Tests.Helpers ((=?>))
+import Tests.Readers.Org.Shared ((=:), spcSep, tagSpan)
+import Text.Pandoc.Builder
+import qualified Data.Text as T
+
+tests :: [TestTree]
+tests =
+  [ "First Level Header" =:
+      "* Headline\n" =?>
+      headerWith ("headline", [], []) 1 "Headline"
+
+  , "Third Level Header" =:
+      "*** Third Level Headline\n" =?>
+      headerWith ("third-level-headline", [], [])
+                 3
+                 ("Third" <> space <> "Level" <> space <> "Headline")
+
+  , "Compact Headers with Paragraph" =:
+      T.unlines [ "* First Level"
+                , "** Second Level"
+                , "   Text"
+                ] =?>
+      mconcat [ headerWith ("first-level", [], [])
+                           1
+                           ("First" <> space <> "Level")
+              , headerWith ("second-level", [], [])
+                           2
+                           ("Second" <> space <> "Level")
+              , para "Text"
+              ]
+
+  , "Separated Headers with Paragraph" =:
+      T.unlines [ "* First Level"
+                , ""
+                , "** Second Level"
+                , ""
+                , "   Text"
+                ] =?>
+      mconcat [ headerWith ("first-level", [], [])
+                           1
+                           ("First" <> space <> "Level")
+              , headerWith ("second-level", [], [])
+                           2
+                           ("Second" <> space <> "Level")
+              , para "Text"
+              ]
+
+  , "Headers not preceded by a blank line" =:
+      T.unlines [ "** eat dinner"
+                , "Spaghetti and meatballs tonight."
+                , "** walk dog"
+                ] =?>
+      mconcat [ headerWith ("eat-dinner", [], [])
+                           2
+                           ("eat" <> space <> "dinner")
+              , para $ spcSep [ "Spaghetti", "and", "meatballs", "tonight." ]
+              , headerWith ("walk-dog", [], [])
+                           2
+                           ("walk" <> space <> "dog")
+              ]
+
+  , testGroup "Todo keywords"
+    [ "Header with known todo keyword" =:
+        "* TODO header" =?>
+        let todoSpan = spanWith ("", ["todo", "TODO"], []) "TODO"
+        in headerWith ("header", [], []) 1 (todoSpan <> space <> "header")
+
+    , "Header marked as done" =:
+        "* DONE header" =?>
+        let todoSpan = spanWith ("", ["done", "DONE"], []) "DONE"
+        in headerWith ("header", [], []) 1 (todoSpan <> space <> "header")
+
+    , "Header with unknown todo keyword" =:
+        "* WAITING header" =?>
+        headerWith ("waiting-header", [], []) 1 "WAITING header"
+
+    , "Custom todo keywords" =:
+        T.unlines [ "#+TODO: WAITING CANCELLED"
+                  , "* WAITING compile"
+                  , "* CANCELLED lunch"
+                  ] =?>
+        let todoSpan = spanWith ("", ["todo", "WAITING"], []) "WAITING"
+            doneSpan = spanWith ("", ["done", "CANCELLED"], []) "CANCELLED"
+        in headerWith ("compile", [], []) 1 (todoSpan <> space <> "compile")
+        <> headerWith ("lunch", [], []) 1 (doneSpan <> space <> "lunch")
+
+    , "Custom todo keywords with multiple done-states" =:
+        T.unlines [ "#+TODO: WAITING | DONE CANCELLED "
+                  , "* WAITING compile"
+                  , "* CANCELLED lunch"
+                  , "* DONE todo-feature"
+                  ] =?>
+        let waiting = spanWith ("", ["todo", "WAITING"], []) "WAITING"
+            cancelled = spanWith ("", ["done", "CANCELLED"], []) "CANCELLED"
+            done = spanWith ("", ["done", "DONE"], []) "DONE"
+        in headerWith ("compile", [], []) 1 (waiting <> space <> "compile")
+        <> headerWith ("lunch", [], []) 1 (cancelled <> space <> "lunch")
+        <> headerWith ("todo-feature", [], []) 1 (done <> space <> "todo-feature")
+    ]
+
+  , "Tagged headers" =:
+      T.unlines [ "* Personal       :PERSONAL:"
+                , "** Call Mom      :@PHONE:"
+                , "** Call John     :@PHONE:JOHN: "
+                ] =?>
+      mconcat [ headerWith ("personal", [], [])
+                           1
+                           ("Personal " <> tagSpan "PERSONAL")
+              , headerWith ("call-mom", [], [])
+                           2
+                           ("Call Mom " <> tagSpan "@PHONE")
+              , headerWith ("call-john", [], [])
+                           2
+                           ("Call John " <> tagSpan "@PHONE" <> "\160" <> tagSpan "JOHN")
+              ]
+
+  , "Untagged header containing colons" =:
+      "* This: is not: tagged" =?>
+      headerWith ("this-is-not-tagged", [], []) 1 "This: is not: tagged"
+
+  , "Header starting with strokeout text" =:
+      T.unlines [ "foo"
+                , ""
+                , "* +thing+ other thing"
+                ] =?>
+      mconcat [ para "foo"
+              , headerWith ("thing-other-thing", [], [])
+                           1
+                           ((strikeout "thing") <> " other thing")
+              ]
+
+  , "Comment Trees" =:
+      T.unlines [ "* COMMENT A comment tree"
+                , "  Not much going on here"
+                , "** This will be dropped"
+                , "* Comment tree above"
+                ] =?>
+      headerWith ("comment-tree-above", [], []) 1 "Comment tree above"
+
+  , "Nothing but a COMMENT header" =:
+      "* COMMENT Test" =?>
+      (mempty::Blocks)
+
+  , "Tree with :noexport:" =:
+      T.unlines [ "* Should be ignored :archive:noexport:old:"
+                , "** Old stuff"
+                , "   This is not going to be exported"
+                ] =?>
+      (mempty::Blocks)
+
+  , "Subtree with :noexport:" =:
+      T.unlines [ "* Exported"
+                , "** This isn't exported :noexport:"
+                , "*** This neither"
+                , "** But this is"
+                ] =?>
+      mconcat [ headerWith ("exported", [], []) 1 "Exported"
+              , headerWith ("but-this-is", [], []) 2 "But this is"
+              ]
+
+  , "Preferences are treated as header attributes" =:
+      T.unlines [ "* foo"
+                , "  :PROPERTIES:"
+                , "  :custom_id: fubar"
+                , "  :bar: baz"
+                , "  :END:"
+                ] =?>
+      headerWith ("fubar", [], [("bar", "baz")]) 1 "foo"
+
+
+  , "Headers marked with a unnumbered property get a class of the same name" =:
+      T.unlines [ "* Not numbered"
+                , "  :PROPERTIES:"
+                , "  :UNNUMBERED: t"
+                , "  :END:"
+                ] =?>
+      headerWith ("not-numbered", ["unnumbered"], []) 1 "Not numbered"
+  ]
diff --git a/test/Tests/Readers/Org/Block/List.hs b/test/Tests/Readers/Org/Block/List.hs
new file mode 100644
--- /dev/null
+++ b/test/Tests/Readers/Org/Block/List.hs
@@ -0,0 +1,244 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.Org.Block.List (tests) where
+
+import Test.Tasty (TestTree)
+import Tests.Helpers ((=?>))
+import Tests.Readers.Org.Shared ((=:), spcSep)
+import Text.Pandoc.Builder
+import qualified Data.Text as T
+
+tests :: [TestTree]
+tests =
+  [ "Simple Bullet Lists" =:
+      ("- Item1\n" <>
+       "- Item2\n") =?>
+      bulletList [ plain "Item1"
+                 , plain "Item2"
+                 ]
+
+  , "Indented Bullet Lists" =:
+      ("   - Item1\n" <>
+       "   - Item2\n") =?>
+      bulletList [ plain "Item1"
+                 , plain "Item2"
+                 ]
+
+  , "Unindented *" =:
+      ("- Item1\n" <>
+       "* Item2\n") =?>
+      bulletList [ plain "Item1"
+                 ] <>
+      headerWith ("item2", [], []) 1 "Item2"
+
+  , "Multi-line Bullet Lists" =:
+      ("- *Fat\n" <>
+       "  Tony*\n" <>
+       "- /Sideshow\n" <>
+       " Bob/") =?>
+      bulletList [ plain $ strong ("Fat" <> softbreak <> "Tony")
+                 , plain $ emph ("Sideshow" <> softbreak <> "Bob")
+                 ]
+
+  , "Nested Bullet Lists" =:
+      ("- Discovery\n" <>
+       "  + One More Time\n" <>
+       "  + Harder, Better, Faster, Stronger\n" <>
+       "- Homework\n" <>
+       "  + Around the World\n"<>
+       "- Human After All\n" <>
+       "  + Technologic\n" <>
+       "  + Robot Rock\n") =?>
+      bulletList [ mconcat
+                   [ plain "Discovery"
+                   , bulletList [ plain ("One" <> space <>
+                                         "More" <> space <>
+                                         "Time")
+                                , plain ("Harder," <> space <>
+                                         "Better," <> space <>
+                                         "Faster," <> space <>
+                                         "Stronger")
+                                ]
+                   ]
+                 , mconcat
+                   [ plain "Homework"
+                   , bulletList [ plain ("Around" <> space <>
+                                         "the" <> space <>
+                                         "World")
+                                ]
+                   ]
+                 , mconcat
+                   [ plain ("Human" <> space <> "After" <> space <> "All")
+                   , bulletList [ plain "Technologic"
+                                , plain ("Robot" <> space <> "Rock")
+                                ]
+                   ]
+                 ]
+
+  , "Bullet List with Decreasing Indent" =:
+       ("  - Discovery\n\
+        \ - Human After All\n") =?>
+       mconcat [ bulletList [ plain "Discovery" ]
+               , bulletList [ plain ("Human" <> space <> "After" <> space <> "All")]
+               ]
+
+  , "Header follows Bullet List" =:
+      ("  - Discovery\n\
+       \  - Human After All\n\
+       \* Homework") =?>
+      mconcat [ bulletList [ plain "Discovery"
+                           , plain ("Human" <> space <> "After" <> space <> "All")
+                           ]
+              , headerWith ("homework", [], []) 1 "Homework"
+              ]
+
+  , "Bullet List Unindented with trailing Header" =:
+      ("- Discovery\n\
+       \- Homework\n\
+       \* NotValidListItem") =?>
+      mconcat [ bulletList [ plain "Discovery"
+                           , plain "Homework"
+                           ]
+              , headerWith ("notvalidlistitem", [], []) 1 "NotValidListItem"
+              ]
+
+  , "Empty bullet points" =:
+      T.unlines [ "-"
+                , "- "
+                ] =?>
+      bulletList [ plain "", plain "" ]
+
+  , "Simple Ordered List" =:
+      ("1. Item1\n" <>
+       "2. Item2\n") =?>
+      let listStyle = (1, DefaultStyle, DefaultDelim)
+          listStructure = [ plain "Item1"
+                          , plain "Item2"
+                          ]
+      in orderedListWith listStyle listStructure
+
+  , "Simple Ordered List with Parens" =:
+      ("1) Item1\n" <>
+       "2) Item2\n") =?>
+      let listStyle = (1, DefaultStyle, DefaultDelim)
+          listStructure = [ plain "Item1"
+                          , plain "Item2"
+                          ]
+      in orderedListWith listStyle listStructure
+
+  , "Indented Ordered List" =:
+      (" 1. Item1\n" <>
+       " 2. Item2\n") =?>
+      let listStyle = (1, DefaultStyle, DefaultDelim)
+          listStructure = [ plain "Item1"
+                          , plain "Item2"
+                          ]
+      in orderedListWith listStyle listStructure
+
+  , "Empty ordered list item" =:
+      T.unlines [ "1."
+                , "3. "
+                ] =?>
+      orderedList [ plain "", plain "" ]
+
+  , "Nested Ordered Lists" =:
+      ("1. One\n" <>
+       "   1. One-One\n" <>
+       "   2. One-Two\n" <>
+       "2. Two\n" <>
+       "   1. Two-One\n"<>
+       "   2. Two-Two\n") =?>
+      let listStyle = (1, DefaultStyle, DefaultDelim)
+          listStructure = [ mconcat
+                            [ plain "One"
+                            , orderedList [ plain "One-One"
+                                          , plain "One-Two"
+                                          ]
+                            ]
+                          , mconcat
+                            [ plain "Two"
+                            , orderedList [ plain "Two-One"
+                                          , plain "Two-Two"
+                                          ]
+                            ]
+                          ]
+      in orderedListWith listStyle listStructure
+
+  , "Ordered List in Bullet List" =:
+      ("- Emacs\n" <>
+       "  1. Org\n") =?>
+      bulletList [ (plain "Emacs") <>
+                   (orderedList [ plain "Org"])
+                 ]
+
+  , "Bullet List in Ordered List" =:
+      ("1. GNU\n" <>
+       "   - Freedom\n") =?>
+      orderedList [ (plain "GNU") <> bulletList [ (plain "Freedom") ] ]
+
+  , "Definition List" =:
+      T.unlines [ "- PLL :: phase-locked loop"
+                , "- TTL ::"
+                , "  transistor-transistor logic"
+                , "- PSK :: phase-shift keying"
+                , ""
+                , "  a digital modulation scheme"
+                ] =?>
+      definitionList [ ("PLL", [ plain $ "phase-locked" <> space <> "loop" ])
+                     , ("TTL", [ plain $ "transistor-transistor" <> space <>
+                                           "logic" ])
+                     , ("PSK", [ mconcat
+                                 [ para $ "phase-shift" <> space <> "keying"
+                                 , para $ spcSep [ "a", "digital"
+                                                 , "modulation", "scheme" ]
+                                 ]
+                               ])
+                     ]
+  , "Definition list with multi-word term" =:
+    " - Elijah Wood :: He plays Frodo" =?>
+     definitionList [ ("Elijah" <> space <> "Wood", [plain $ "He" <> space <> "plays" <> space <> "Frodo"])]
+  , "Compact definition list" =:
+       T.unlines [ "- ATP :: adenosine 5' triphosphate"
+                 , "- DNA :: deoxyribonucleic acid"
+                 , "- PCR :: polymerase chain reaction"
+                 , ""
+                 ] =?>
+      definitionList
+      [ ("ATP", [ plain $ spcSep [ "adenosine", "5'", "triphosphate" ] ])
+      , ("DNA", [ plain $ spcSep [ "deoxyribonucleic", "acid" ] ])
+      , ("PCR", [ plain $ spcSep [ "polymerase", "chain", "reaction" ] ])
+      ]
+
+  , "Definition List With Trailing Header" =:
+      "- definition :: list\n\
+      \- cool :: defs\n\
+      \* header" =?>
+      mconcat [ definitionList [ ("definition", [plain "list"])
+                               , ("cool", [plain "defs"])
+                               ]
+              , headerWith ("header", [], []) 1 "header"
+              ]
+
+  , "Definition lists double-colon markers must be surrounded by whitespace" =:
+      "- std::cout" =?>
+      bulletList [ plain "std::cout" ]
+
+  , "Loose bullet list" =:
+     T.unlines [ "- apple"
+               , ""
+               , "- orange"
+               , ""
+               , "- peach"
+               ] =?>
+      bulletList [ para "apple"
+                 , para "orange"
+                 , para "peach"
+                 ]
+
+  , "Recognize preceding paragraphs in non-list contexts" =:
+      T.unlines [ "CLOSED: [2015-10-19 Mon 15:03]"
+                , "- Note taken on [2015-10-19 Mon 13:24]"
+                ] =?>
+      mconcat [ para "CLOSED: [2015-10-19 Mon 15:03]"
+              , bulletList [ plain "Note taken on [2015-10-19 Mon 13:24]" ]
+              ]
+  ]
diff --git a/test/Tests/Readers/Org/Block/Table.hs b/test/Tests/Readers/Org/Block/Table.hs
new file mode 100644
--- /dev/null
+++ b/test/Tests/Readers/Org/Block/Table.hs
@@ -0,0 +1,150 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.Org.Block.Table (tests) where
+
+import Test.Tasty (TestTree)
+import Tests.Helpers ((=?>))
+import Tests.Readers.Org.Shared ((=:), spcSep)
+import Text.Pandoc.Builder
+import qualified Data.Text as T
+
+simpleTable' :: Int
+             -> [Blocks]
+             -> [[Blocks]]
+             -> Blocks
+simpleTable' n = table "" (replicate n (AlignDefault, 0.0))
+
+tests :: [TestTree]
+tests =
+  [ "Single cell table" =:
+      "|Test|" =?>
+      simpleTable' 1 mempty [[plain "Test"]]
+
+  , "Multi cell table" =:
+      "| One | Two |" =?>
+       simpleTable' 2 mempty [ [ plain "One", plain "Two" ] ]
+
+  , "Multi line table" =:
+      T.unlines [ "| One   |"
+                , "| Two   |"
+                , "| Three |"
+                ] =?>
+       simpleTable' 1 mempty
+                    [ [ plain "One" ]
+                    , [ plain "Two" ]
+                    , [ plain "Three" ]
+                    ]
+
+  , "Empty table" =:
+      "||" =?>
+      simpleTable' 1 mempty [[mempty]]
+
+  , "Glider Table" =:
+      T.unlines [ "| 1 | 0 | 0 |"
+                , "| 0 | 1 | 1 |"
+                , "| 1 | 1 | 0 |"
+                ] =?>
+      simpleTable' 3 mempty
+                   [ [ plain "1", plain "0", plain "0" ]
+                   , [ plain "0", plain "1", plain "1" ]
+                   , [ plain "1", plain "1", plain "0" ]
+                   ]
+
+  , "Table between Paragraphs" =:
+      T.unlines [ "Before"
+                , "| One | Two |"
+                , "After"
+                ] =?>
+      mconcat [ para "Before"
+              , simpleTable' 2 mempty [ [ plain "One", plain "Two" ] ]
+              , para "After"
+              ]
+
+  , "Table with Header" =:
+      T.unlines [ "| Species      | Status       |"
+                , "|--------------+--------------|"
+                , "| cervisiae    | domesticated |"
+                , "| paradoxus    | wild         |"
+                ] =?>
+      simpleTable [ plain "Species", plain "Status" ]
+                  [ [ plain "cervisiae", plain "domesticated" ]
+                  , [ plain "paradoxus", plain "wild" ]
+                  ]
+
+  , "Table with final hline" =:
+      T.unlines [ "| cervisiae    | domesticated |"
+                , "| paradoxus    | wild         |"
+                , "|--------------+--------------|"
+                ] =?>
+      simpleTable' 2 mempty
+            [ [ plain "cervisiae", plain "domesticated" ]
+             , [ plain "paradoxus", plain "wild" ]
+            ]
+
+  , "Table in a box" =:
+      T.unlines [ "|---------|---------|"
+                , "| static  | Haskell |"
+                , "| dynamic | Lisp    |"
+                , "|---------+---------|"
+                ] =?>
+      simpleTable' 2 mempty
+            [ [ plain "static", plain "Haskell" ]
+            , [ plain "dynamic", plain "Lisp" ]
+            ]
+
+  , "Table with empty cells" =:
+      "|||c|" =?>
+      simpleTable' 3 mempty [[mempty, mempty, plain "c"]]
+
+  , "Table with empty rows" =:
+      T.unlines [ "| first  |"
+                , "|        |"
+                , "| third  |"
+                ] =?>
+      simpleTable' 1 mempty [[plain "first"], [mempty], [plain "third"]]
+
+  , "Table with alignment row" =:
+      T.unlines [ "| Numbers | Text | More |"
+                , "| <c>     | <r>  |      |"
+                , "| 1       | One  | foo  |"
+                , "| 2       | Two  | bar  |"
+                ] =?>
+      table "" (zip [AlignCenter, AlignRight, AlignDefault] [0, 0, 0])
+            []
+            [ [ plain "Numbers", plain "Text", plain "More" ]
+            , [ plain "1"      , plain "One" , plain "foo"  ]
+            , [ plain "2"      , plain "Two" , plain "bar"  ]
+            ]
+
+  , "Pipe within text doesn't start a table" =:
+      "Ceci n'est pas une | pipe " =?>
+      para (spcSep [ "Ceci", "n'est", "pas", "une", "|", "pipe" ])
+
+  , "Missing pipe at end of row" =:
+      "|incomplete-but-valid" =?>
+      simpleTable' 1 mempty [ [ plain "incomplete-but-valid" ] ]
+
+  , "Table with differing row lengths" =:
+      T.unlines [ "| Numbers | Text "
+                , "|-"
+                , "| <c>     | <r>  |"
+                , "| 1       | One  | foo  |"
+                , "| 2"
+                ] =?>
+      table "" (zip [AlignCenter, AlignRight] [0, 0])
+            [ plain "Numbers", plain "Text" ]
+            [ [ plain "1" , plain "One" , plain "foo" ]
+            , [ plain "2" ]
+            ]
+
+  , "Table with caption" =:
+      T.unlines [ "#+CAPTION: Hitchhiker's Multiplication Table"
+                , "| x |  6 |"
+                , "| 9 | 42 |"
+                ] =?>
+      table "Hitchhiker's Multiplication Table"
+            [(AlignDefault, 0), (AlignDefault, 0)]
+            []
+            [ [ plain "x", plain "6" ]
+            , [ plain "9", plain "42" ]
+            ]
+  ]
diff --git a/test/Tests/Readers/Org/Directive.hs b/test/Tests/Readers/Org/Directive.hs
new file mode 100644
--- /dev/null
+++ b/test/Tests/Readers/Org/Directive.hs
@@ -0,0 +1,199 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.Org.Directive (tests) where
+
+import Data.Time (UTCTime (UTCTime), secondsToDiffTime)
+import Data.Time.Calendar (Day (ModifiedJulianDay))
+import Test.Tasty (TestTree, testGroup)
+import Tests.Helpers ((=?>), ToString, purely, test)
+import Tests.Readers.Org.Shared ((=:), tagSpan)
+import Text.Pandoc
+import Text.Pandoc.Builder
+import qualified Data.ByteString as BS
+import qualified Data.Text as T
+
+testWithFiles :: (ToString c)
+              => [(FilePath, BS.ByteString)]
+              -> String         -- ^ name of test case
+              -> (T.Text, c)    -- ^ (input, expected value)
+              -> TestTree
+testWithFiles fileDefs = test (orgWithFiles fileDefs)
+  where
+orgWithFiles :: [(FilePath, BS.ByteString)] -> T.Text -> Pandoc
+orgWithFiles fileDefs input =
+  let readOrg' = readOrg def{ readerExtensions = getDefaultExtensions "org" }
+  in flip purely input $ \inp -> do
+    modifyPureState (\st -> st { stFiles = files fileDefs })
+    readOrg' inp
+
+
+files :: [(FilePath, BS.ByteString)] -> FileTree
+files fileDefs =
+  let dummyTime = UTCTime (ModifiedJulianDay 125) (secondsToDiffTime 0)
+  in foldr (\(fp, bs) -> insertInFileTree fp (FileInfo dummyTime bs))
+      mempty fileDefs
+
+tests :: [TestTree]
+tests =
+  [ testGroup "export options"
+    [ "disable simple sub/superscript syntax" =:
+        T.unlines [ "#+OPTIONS: ^:nil"
+                  , "a^b"
+                  ] =?>
+        para "a^b"
+
+    , "directly select drawers to be exported" =:
+        T.unlines [ "#+OPTIONS: d:(\"IMPORTANT\")"
+                  , ":IMPORTANT:"
+                  , "23"
+                  , ":END:"
+                  , ":BORING:"
+                  , "very boring"
+                  , ":END:"
+                  ] =?>
+        divWith (mempty, ["IMPORTANT", "drawer"], mempty) (para "23")
+
+    , "exclude drawers from being exported" =:
+        T.unlines [ "#+OPTIONS: d:(not \"BORING\")"
+                  , ":IMPORTANT:"
+                  , "5"
+                  , ":END:"
+                  , ":BORING:"
+                  , "very boring"
+                  , ":END:"
+                  ] =?>
+        divWith (mempty, ["IMPORTANT", "drawer"], mempty) (para "5")
+
+    , "don't include archive trees" =:
+        T.unlines [ "#+OPTIONS: arch:nil"
+                  , "* old  :ARCHIVE:"
+                  ] =?>
+        (mempty ::Blocks)
+
+    , "include complete archive trees" =:
+        T.unlines [ "#+OPTIONS: arch:t"
+                  , "* old  :ARCHIVE:"
+                  , "  boring"
+                  ] =?>
+        mconcat [ headerWith ("old", [], mempty) 1
+                             ("old" <> space <> tagSpan "ARCHIVE")
+                , para "boring"
+                ]
+
+    , "include archive tree header only" =:
+        T.unlines [ "#+OPTIONS: arch:headline"
+                  , "* old  :ARCHIVE:"
+                  , "  boring"
+                  ] =?>
+        headerWith ("old", [], mempty) 1 ("old" <> space <> tagSpan "ARCHIVE")
+
+    , "limit headline depth" =:
+        T.unlines [ "#+OPTIONS: H:2"
+                  , "* top-level section"
+                  , "** subsection"
+                  , "*** list item 1"
+                  , "*** list item 2"
+                  ] =?>
+        mconcat [ headerWith ("top-level-section", [], [])    1 "top-level section"
+                , headerWith ("subsection", [], []) 2 "subsection"
+                , orderedList [ para "list item 1", para "list item 2" ]
+                ]
+
+    , "turn all headlines into lists" =:
+        T.unlines [ "#+OPTIONS: H:0"
+                  , "first block"
+                  , "* top-level section 1"
+                  , "** subsection"
+                  , "* top-level section 2"
+                  ] =?>
+        mconcat [ para "first block"
+                , orderedList
+                  [ (para "top-level section 1" <>
+                     orderedList [ para "subsection" ])
+                  , para "top-level section 2" ]
+                ]
+
+    , "preserve linebreaks as hard breaks" =:
+        T.unlines [ "#+OPTIONS: \\n:t"
+                  , "first"
+                  , "second"
+                  ] =?>
+        para ("first" <> linebreak <> "second")
+
+    , "disable author export" =:
+        T.unlines [ "#+OPTIONS: author:nil"
+                  , "#+AUTHOR: ShyGuy"
+                  ] =?>
+        Pandoc nullMeta mempty
+
+    , "disable creator export" =:
+        T.unlines [ "#+OPTIONS: creator:nil"
+                  , "#+creator: The Architect"
+                  ] =?>
+        Pandoc nullMeta mempty
+
+    , "disable email export" =:
+        T.unlines [ "#+OPTIONS: email:nil"
+                  , "#+email: no-mail-please@example.com"
+                  ] =?>
+        Pandoc nullMeta mempty
+
+    , "disable inclusion of todo keywords" =:
+        T.unlines [ "#+OPTIONS: todo:nil"
+                  , "** DONE todo export"
+                  ] =?>
+        headerWith ("todo-export", [], []) 2 "todo export"
+
+    , "remove tags from headlines" =:
+        T.unlines [ "#+OPTIONS: tags:nil"
+                  , "* Headline :hello:world:"
+                  ] =?>
+        headerWith ("headline", [], mempty) 1 "Headline"
+    ]
+
+  , testGroup "Include"
+    [ testWithFiles [("./other.org", "content of other file\n")]
+      "file inclusion"
+      (T.unlines [ "#+include: \"other.org\"" ] =?>
+       plain "content of other file")
+
+    , testWithFiles [("./world.org", "World\n\n")]
+      "Included file belongs to item"
+      (T.unlines [ "- Hello,\n  #+include: \"world.org\"" ] =?>
+       bulletList [para "Hello," <> para "World"])
+
+    , testWithFiles [("./level3.org", "*** Level3\n\n")]
+      "Default include preserves level"
+      (T.unlines [ "#+include: \"level3.org\"" ] =?>
+       headerWith ("level3", [], []) 3 "Level3")
+
+    , testWithFiles [("./level3.org", "*** Level3\n\n")]
+      "Minlevel shifts level"
+      (T.unlines [ "#+include: \"level3.org\" :minlevel 1" ] =?>
+       headerWith ("level3", [], []) 1 "Level3")
+
+    , testWithFiles [("./src.hs", "putStrLn outString\n")]
+      "Include file as source code snippet"
+      (T.unlines [ "#+include: \"src.hs\" src haskell" ] =?>
+       codeBlockWith ("", ["haskell"], []) "putStrLn outString\n")
+
+    , testWithFiles [("./export-latex.org", "\\emph{Hello}\n")]
+      "Include file as export snippet"
+      (T.unlines [ "#+include: \"export-latex.org\" export latex" ] =?>
+       rawBlock "latex" "\\emph{Hello}\n")
+
+    , testWithFiles [("./subdir/foo-bar.latex", "foo\n"),
+                     ("./hello.lisp", "(print \"Hello!\")\n")
+                    ]
+      "include directive is limited to one line"
+      (T.unlines [ "#+INCLUDE: \"hello.lisp\" src lisp"
+                 , "#+include: \"subdir/foo-bar.latex\" export latex"
+                 , "bar"
+                 ] =?>
+       mconcat
+         [ codeBlockWith ("", ["lisp"], []) "(print \"Hello!\")\n"
+         , rawBlock "latex" "foo\n"
+         , para "bar"
+         ]
+      )
+    ]
+  ]
diff --git a/test/Tests/Readers/Org/Inline.hs b/test/Tests/Readers/Org/Inline.hs
new file mode 100644
--- /dev/null
+++ b/test/Tests/Readers/Org/Inline.hs
@@ -0,0 +1,516 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.Org.Inline (tests) where
+
+import Data.List (intersperse)
+import Test.Tasty (TestTree, testGroup)
+import Tests.Helpers ((=?>))
+import Tests.Readers.Org.Shared ((=:), spcSep)
+import Text.Pandoc
+import Text.Pandoc.Builder
+import Text.Pandoc.Shared (underlineSpan)
+import qualified Data.Text as T
+import qualified Tests.Readers.Org.Inline.Note as Note
+import qualified Tests.Readers.Org.Inline.Smart as Smart
+
+tests :: [TestTree]
+tests =
+  [ "Plain String" =:
+      "Hello, World" =?>
+      para (spcSep [ "Hello,", "World" ])
+
+  , "Emphasis" =:
+      "/Planet Punk/" =?>
+      para (emph . spcSep $ ["Planet", "Punk"])
+
+  , "Strong" =:
+      "*Cider*" =?>
+      para (strong "Cider")
+
+  , "Strong Emphasis" =:
+      "/*strength*/" =?>
+      para (emph . strong $ "strength")
+
+  , "Emphasized Strong preceded by space" =:
+      " */super/*" =?>
+      para (strong . emph $ "super")
+
+  , "Underline" =:
+      "_underline_" =?>
+      para (underlineSpan $ "underline")
+
+  , "Strikeout" =:
+      "+Kill Bill+" =?>
+      para (strikeout . spcSep $ [ "Kill", "Bill" ])
+
+  , "Verbatim" =:
+      "=Robot.rock()=" =?>
+      para (code "Robot.rock()")
+
+  , "Code" =:
+      "~word for word~" =?>
+      para (code "word for word")
+
+  , "Math $..$" =:
+      "$E=mc^2$" =?>
+       para (math "E=mc^2")
+
+  , "Math $$..$$" =:
+      "$$E=mc^2$$" =?>
+      para (displayMath "E=mc^2")
+
+  , "Math \\[..\\]" =:
+      "\\[E=ℎν\\]" =?>
+      para (displayMath "E=ℎν")
+
+  , "Math \\(..\\)" =:
+      "\\(σ_x σ_p ≥ \\frac{ℏ}{2}\\)" =?>
+      para (math "σ_x σ_p ≥ \\frac{ℏ}{2}")
+
+  , "Symbol" =:
+      "A * symbol" =?>
+      para (str "A" <> space <> str "*" <> space <> "symbol")
+
+  , "Superscript simple expression" =:
+      "2^-λ" =?>
+      para (str "2" <> superscript "-λ")
+
+  , "Superscript multi char" =:
+      "2^{n-1}" =?>
+      para (str "2" <> superscript "n-1")
+
+  , "Subscript simple expression" =:
+      "a_n" =?>
+      para (str "a" <> subscript "n")
+
+  , "Subscript multi char" =:
+      "a_{n+1}" =?>
+      para (str "a" <> subscript "n+1")
+
+  , "Linebreak" =:
+      "line \\\\ \nbreak" =?>
+      para ("line" <> linebreak <> "break")
+
+  , "Inline note" =:
+      "[fn::Schreib mir eine E-Mail]" =?>
+      para (note $ para "Schreib mir eine E-Mail")
+
+  , "Markup-chars not occuring on word break are symbols" =:
+      T.unlines [ "this+that+ +so+on"
+                , "seven*eight* nine*"
+                , "+not+funny+"
+                ] =?>
+      para ("this+that+ +so+on" <> softbreak <>
+            "seven*eight* nine*" <> softbreak <>
+            strikeout "not+funny")
+
+  , "No empty markup" =:
+      "// ** __ <> == ~~ $$" =?>
+      para (spcSep [ "//", "**", "__", "<>", "==", "~~", "$$" ])
+
+  , "Adherence to Org's rules for markup borders" =:
+      "/t/& a/ / ./r/ (*l*) /e/! /b/." =?>
+      para (spcSep [ emph $ "t/&" <> space <> "a"
+                   , "/"
+                   , "./r/"
+                   , "(" <> strong "l" <> ")"
+                   , emph "e" <> "!"
+                   , emph "b" <> "."
+                   ])
+
+  , "Quotes are allowed border chars" =:
+      "/'yep/ *sure\"*" =?>
+      para (emph "'yep" <> space <> strong "sure\"")
+
+  , "Spaces are forbidden border chars" =:
+      "/nada /" =?>
+      para "/nada /"
+
+  , "Markup should work properly after a blank line" =:
+    T.unlines ["foo", "", "/bar/"] =?>
+    (para $ text "foo") <> (para $ emph $ text "bar")
+
+  , "Inline math must stay within three lines" =:
+      T.unlines [ "$a", "b", "c$", "$d", "e", "f", "g$" ] =?>
+      para ((math "a\nb\nc") <> softbreak <>
+            "$d" <> softbreak <> "e" <> softbreak <>
+            "f" <> softbreak <> "g$")
+
+  , "Single-character math" =:
+      "$a$ $b$! $c$?" =?>
+      para (spcSep [ math "a"
+                   , "$b$!"
+                   , (math "c") <> "?"
+                   ])
+
+  , "Markup may not span more than two lines" =:
+      "/this *is +totally\nnice+ not*\nemph/" =?>
+      para ("/this" <> space <>
+              strong ("is" <> space <>
+                      strikeout ("totally" <>
+                        softbreak <> "nice") <>
+                      space <> "not") <>
+              softbreak <> "emph/")
+
+  , "Sub- and superscript expressions" =:
+     T.unlines [ "a_(a(b)(c)d)"
+               , "e^(f(g)h)"
+               , "i_(jk)l)"
+               , "m^()n"
+               , "o_{p{q{}r}}"
+               , "s^{t{u}v}"
+               , "w_{xy}z}"
+               , "1^{}2"
+               , "3_{{}}"
+               , "4^(a(*b(c*)d))"
+               ] =?>
+     para (mconcat $ intersperse softbreak
+                  [ "a" <> subscript "(a(b)(c)d)"
+                  , "e" <> superscript "(f(g)h)"
+                  , "i" <> (subscript "(jk)") <> "l)"
+                  , "m" <> (superscript "()") <> "n"
+                  , "o" <> subscript "p{q{}r}"
+                  , "s" <> superscript "t{u}v"
+                  , "w" <> (subscript "xy") <> "z}"
+                  , "1" <> (superscript "") <> "2"
+                  , "3" <> subscript "{}"
+                  , "4" <> superscript ("(a(" <> strong "b(c" <> ")d))")
+                  ])
+  , "Verbatim text can contain equal signes (=)" =:
+      "=is_subst = True=" =?>
+      para (code "is_subst = True")
+
+  , testGroup "Images"
+    [ "Image" =:
+        "[[./sunset.jpg]]" =?>
+        (para $ image "./sunset.jpg" "" "")
+
+    , "Image with explicit file: prefix" =:
+        "[[file:sunrise.jpg]]" =?>
+        (para $ image "sunrise.jpg" "" "")
+
+    , "Multiple images within a paragraph" =:
+        T.unlines [ "[[file:sunrise.jpg]]"
+                  , "[[file:sunset.jpg]]"
+                  ] =?>
+        (para $ (image "sunrise.jpg" "" "")
+             <> softbreak
+             <> (image "sunset.jpg" "" ""))
+
+    , "Image with html attributes" =:
+        T.unlines [ "#+ATTR_HTML: :width 50%"
+                  , "[[file:guinea-pig.gif]]"
+                  ] =?>
+        (para $ imageWith ("", [], [("width", "50%")]) "guinea-pig.gif" "" "")
+    ]
+
+  , "Explicit link" =:
+      "[[http://zeitlens.com/][pseudo-random /nonsense/]]" =?>
+      (para $ link "http://zeitlens.com/" ""
+                   ("pseudo-random" <> space <> emph "nonsense"))
+
+  , "Self-link" =:
+      "[[http://zeitlens.com/]]" =?>
+      (para $ link "http://zeitlens.com/" "" "http://zeitlens.com/")
+
+  , "Absolute file link" =:
+      "[[/url][hi]]" =?>
+      (para $ link "file:///url" "" "hi")
+
+  , "Link to file in parent directory" =:
+      "[[../file.txt][moin]]" =?>
+      (para $ link "../file.txt" "" "moin")
+
+  , "Empty link (for gitit interop)" =:
+      "[[][New Link]]" =?>
+      (para $ link "" "" "New Link")
+
+  , "Image link" =:
+      "[[sunset.png][file:dusk.svg]]" =?>
+      (para $ link "sunset.png" "" (image "dusk.svg" "" ""))
+
+  , "Image link with non-image target" =:
+      "[[http://example.com][./logo.png]]" =?>
+      (para $ link "http://example.com" "" (image "./logo.png" "" ""))
+
+  , "Plain link" =:
+      "Posts on http://zeitlens.com/ can be funny at times." =?>
+      (para $ spcSep [ "Posts", "on"
+                     , link "http://zeitlens.com/" "" "http://zeitlens.com/"
+                     , "can", "be", "funny", "at", "times."
+                     ])
+
+  , "Angle link" =:
+      "Look at <http://moltkeplatz.de> for fnords." =?>
+      (para $ spcSep [ "Look", "at"
+                     , link "http://moltkeplatz.de" "" "http://moltkeplatz.de"
+                     , "for", "fnords."
+                     ])
+
+  , "Absolute file link" =:
+      "[[file:///etc/passwd][passwd]]" =?>
+      (para $ link "file:///etc/passwd" "" "passwd")
+
+  , "File link" =:
+      "[[file:target][title]]" =?>
+      (para $ link "target" "" "title")
+
+  , "Anchor" =:
+      "<<anchor>> Link here later." =?>
+      (para $ spanWith ("anchor", [], []) mempty <>
+              "Link" <> space <> "here" <> space <> "later.")
+
+  , "Inline code block" =:
+      "src_emacs-lisp{(message \"Hello\")}" =?>
+      (para $ codeWith ( ""
+                       , [ "commonlisp" ]
+                       , [ ("org-language", "emacs-lisp") ])
+                       "(message \"Hello\")")
+
+  , "Inline code block with arguments" =:
+      "src_sh[:export both :results output]{echo 'Hello, World'}" =?>
+      (para $ codeWith ( ""
+                       , [ "bash" ]
+                       , [ ("org-language", "sh")
+                         , ("export", "both")
+                         , ("results", "output")
+                         ]
+                       )
+                       "echo 'Hello, World'")
+
+  , "Inline code block with toggle" =:
+      "src_sh[:toggle]{echo $HOME}" =?>
+      (para $ codeWith ( ""
+                       , [ "bash" ]
+                       , [ ("org-language", "sh")
+                         , ("toggle", "yes")
+                         ]
+                       )
+                       "echo $HOME")
+
+  , "Citation" =:
+      "[@nonexistent]" =?>
+      let citation = Citation
+                     { citationId = "nonexistent"
+                     , citationPrefix = []
+                     , citationSuffix = []
+                     , citationMode = NormalCitation
+                     , citationNoteNum = 0
+                     , citationHash = 0}
+      in (para $ cite [citation] "[@nonexistent]")
+
+  , "Citation containing text" =:
+      "[see @item1 p. 34-35]" =?>
+      let citation = Citation
+                     { citationId = "item1"
+                     , citationPrefix = [Str "see"]
+                     , citationSuffix = [Space ,Str "p.",Space,Str "34-35"]
+                     , citationMode = NormalCitation
+                     , citationNoteNum = 0
+                     , citationHash = 0}
+      in (para $ cite [citation] "[see @item1 p. 34-35]")
+
+  , "Org-ref simple citation" =:
+    "cite:pandoc" =?>
+    let citation = Citation
+                   { citationId = "pandoc"
+                   , citationPrefix = mempty
+                   , citationSuffix = mempty
+                   , citationMode = AuthorInText
+                   , citationNoteNum = 0
+                   , citationHash = 0
+                   }
+    in (para $ cite [citation] "cite:pandoc")
+
+  , "Org-ref simple citation with underscores" =:
+    "cite:pandoc_org_ref" =?>
+    let citation = Citation
+                   { citationId = "pandoc_org_ref"
+                   , citationPrefix = mempty
+                   , citationSuffix = mempty
+                   , citationMode = AuthorInText
+                   , citationNoteNum = 0
+                   , citationHash = 0
+                   }
+    in (para $ cite [citation] "cite:pandoc_org_ref")
+
+  , "Org-ref simple citation succeeded by comma" =:
+    "cite:pandoc," =?>
+    let citation = Citation
+                   { citationId = "pandoc"
+                   , citationPrefix = mempty
+                   , citationSuffix = mempty
+                   , citationMode = AuthorInText
+                   , citationNoteNum = 0
+                   , citationHash = 0
+                   }
+    in (para $ cite [citation] "cite:pandoc" <> str ",")
+
+  , "Org-ref simple citation succeeded by dot" =:
+    "cite:pandoc." =?>
+    let citation = Citation
+                   { citationId = "pandoc"
+                   , citationPrefix = mempty
+                   , citationSuffix = mempty
+                   , citationMode = AuthorInText
+                   , citationNoteNum = 0
+                   , citationHash = 0
+                   }
+    in (para $ cite [citation] "cite:pandoc" <> str ".")
+
+  , "Org-ref simple citation succeeded by colon" =:
+    "cite:pandoc:" =?>
+    let citation = Citation
+                   { citationId = "pandoc"
+                   , citationPrefix = mempty
+                   , citationSuffix = mempty
+                   , citationMode = AuthorInText
+                   , citationNoteNum = 0
+                   , citationHash = 0
+                   }
+    in (para $ cite [citation] "cite:pandoc" <> str ":")
+
+  , "Org-ref simple citep citation" =:
+    "citep:pandoc" =?>
+    let citation = Citation
+                   { citationId = "pandoc"
+                   , citationPrefix = mempty
+                   , citationSuffix = mempty
+                   , citationMode = NormalCitation
+                   , citationNoteNum = 0
+                   , citationHash = 0
+                   }
+    in (para $ cite [citation] "citep:pandoc")
+
+  , "Org-ref extended citation" =:
+    "[[citep:Dominik201408][See page 20::, for example]]" =?>
+    let citation = Citation
+                   { citationId = "Dominik201408"
+                   , citationPrefix = toList "See page 20"
+                   , citationSuffix = toList ", for example"
+                   , citationMode = NormalCitation
+                   , citationNoteNum = 0
+                   , citationHash = 0
+                   }
+    in (para $ cite [citation] "[[citep:Dominik201408][See page 20::, for example]]")
+
+  , testGroup "Berkeley-style citations" $
+    let pandocCite = Citation
+          { citationId = "Pandoc"
+          , citationPrefix = mempty
+          , citationSuffix = mempty
+          , citationMode = NormalCitation
+          , citationNoteNum = 0
+          , citationHash = 0
+          }
+        pandocInText = pandocCite { citationMode = AuthorInText }
+        dominikCite = Citation
+          { citationId = "Dominik201408"
+          , citationPrefix = mempty
+          , citationSuffix = mempty
+          , citationMode = NormalCitation
+          , citationNoteNum = 0
+          , citationHash = 0
+          }
+        dominikInText = dominikCite { citationMode = AuthorInText }
+    in [
+        "Berkeley-style in-text citation" =:
+          "See @Dominik201408." =?>
+            (para $ "See "
+                  <> cite [dominikInText] "@Dominik201408"
+                  <> ".")
+
+      , "Berkeley-style parenthetical citation list" =:
+          "[(cite): see; @Dominik201408;also @Pandoc; and others]" =?>
+          let pandocCite'  = pandocCite {
+                               citationPrefix = toList "also"
+                             , citationSuffix = toList "and others"
+                             }
+              dominikCite' = dominikCite {
+                               citationPrefix = toList "see"
+                             }
+          in (para $ cite [dominikCite', pandocCite'] "")
+
+      , "Berkeley-style plain citation list" =:
+          "[cite: See; @Dominik201408; and @Pandoc; and others]" =?>
+          let pandocCite' = pandocInText {
+                              citationPrefix = toList "and"
+                            }
+          in (para $ "See "
+                  <> cite [dominikInText] ""
+                  <> "," <> space
+                  <> cite [pandocCite'] ""
+                  <> "," <> space <> "and others")
+    ]
+
+  , "Inline LaTeX symbol" =:
+      "\\dots" =?>
+      para "…"
+
+  , "Inline LaTeX command" =:
+      "\\textit{Emphasised}" =?>
+      para (emph "Emphasised")
+
+  , "Inline LaTeX command with spaces" =:
+      "\\emph{Emphasis mine}" =?>
+      para (emph "Emphasis mine")
+
+  , "Inline LaTeX math symbol" =:
+      "\\tau" =?>
+      para (emph "τ")
+
+  , "Unknown inline LaTeX command" =:
+      "\\notacommand{foo}" =?>
+      para (rawInline "latex" "\\notacommand{foo}")
+
+  , "Export snippet" =:
+      "@@html:<kbd>M-x org-agenda</kbd>@@" =?>
+      para (rawInline "html" "<kbd>M-x org-agenda</kbd>")
+
+  , "MathML symbol in LaTeX-style" =:
+      "There is a hackerspace in Lübeck, Germany, called nbsp (unicode symbol: '\\nbsp')." =?>
+      para ("There is a hackerspace in Lübeck, Germany, called nbsp (unicode symbol: ' ').")
+
+  , "MathML symbol in LaTeX-style, including braces" =:
+      "\\Aacute{}stor" =?>
+      para "Ástor"
+
+  , "MathML copy sign" =:
+      "\\copy" =?>
+      para "©"
+
+  , "MathML symbols, space separated" =:
+      "\\ForAll \\Auml" =?>
+      para "∀ Ä"
+
+  , "LaTeX citation" =:
+      "\\cite{Coffee}" =?>
+      let citation = Citation
+                     { citationId = "Coffee"
+                     , citationPrefix = []
+                     , citationSuffix = []
+                     , citationMode = NormalCitation
+                     , citationNoteNum = 0
+                     , citationHash = 0}
+      in (para . cite [citation] $ rawInline "latex" "\\cite{Coffee}")
+
+  , "Macro" =:
+      T.unlines [ "#+MACRO: HELLO /Hello, $1/"
+                , "{{{HELLO(World)}}}"
+                ] =?>
+      para (emph "Hello, World")
+
+  , "Macro repeting its argument" =:
+      T.unlines [ "#+MACRO: HELLO $1$1"
+                , "{{{HELLO(moin)}}}"
+                ] =?>
+      para "moinmoin"
+
+  , "Macro called with too few arguments" =:
+      T.unlines [ "#+MACRO: HELLO Foo $1 $2 Bar"
+                , "{{{HELLO()}}}"
+                ] =?>
+      para "Foo Bar"
+
+  , testGroup "Footnotes" Note.tests
+  , testGroup "Smart punctuation" Smart.tests
+  ]
diff --git a/test/Tests/Readers/Org/Inline/Note.hs b/test/Tests/Readers/Org/Inline/Note.hs
new file mode 100644
--- /dev/null
+++ b/test/Tests/Readers/Org/Inline/Note.hs
@@ -0,0 +1,87 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.Org.Inline.Note (tests) where
+
+import Test.Tasty (TestTree)
+import Tests.Helpers ((=?>))
+import Tests.Readers.Org.Shared ((=:))
+import Text.Pandoc.Builder
+import qualified Data.Text as T
+
+tests :: [TestTree]
+tests =
+  [ "Footnote" =:
+      T.unlines [ "A footnote[1]"
+                , ""
+                , "[1] First paragraph"
+                , ""
+                , "second paragraph"
+                ] =?>
+      para (mconcat
+            [ "A", space, "footnote"
+            , note $ mconcat [ para ("First" <> space <> "paragraph")
+                             , para ("second" <> space <> "paragraph")
+                             ]
+            ])
+
+  , "Two footnotes" =:
+      T.unlines [ "Footnotes[fn:1][fn:2]"
+                , ""
+                , "[fn:1] First note."
+                , ""
+                , "[fn:2] Second note."
+                ] =?>
+      para (mconcat
+            [ "Footnotes"
+            , note $ para ("First" <> space <> "note.")
+            , note $ para ("Second" <> space <> "note.")
+            ])
+
+  , "Emphasized text before footnote" =:
+      T.unlines [ "/text/[fn:1]"
+                , ""
+                , "[fn:1] unicorn"
+                ] =?>
+      para (mconcat
+           [ emph "text"
+           , note . para $ "unicorn"
+           ])
+
+  , "Footnote that starts with emphasized text" =:
+      T.unlines [ "text[fn:1]"
+                , ""
+                , "[fn:1] /emphasized/"
+                ] =?>
+      para (mconcat
+           [ "text"
+           , note . para $ emph "emphasized"
+           ])
+
+  , "Footnote followed by header" =:
+      T.unlines [ "Another note[fn:yay]"
+                , ""
+                , "[fn:yay] This is great!"
+                , ""
+                , "** Headline"
+                ] =?>
+      mconcat
+      [ para (mconcat
+              [ "Another", space, "note"
+              , note $ para ("This" <> space <> "is" <> space <> "great!")
+              ])
+      , headerWith ("headline", [], []) 2 "Headline"
+      ]
+
+  , "Footnote followed by two blank lines" =:
+      T.unlines [ "footnote[fn:blanklines]"
+                , ""
+                , "[fn:blanklines] followed by blank lines"
+                , ""
+                , ""
+                , "next"
+                ] =?>
+      mconcat
+      [ para ("footnote" <> note (para "followed by blank lines"))
+      , para "next"
+      ]
+  ]
+  
diff --git a/test/Tests/Readers/Org/Inline/Smart.hs b/test/Tests/Readers/Org/Inline/Smart.hs
new file mode 100644
--- /dev/null
+++ b/test/Tests/Readers/Org/Inline/Smart.hs
@@ -0,0 +1,46 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.Org.Inline.Smart (tests) where
+
+import Data.Text (Text)
+import Test.Tasty (TestTree)
+import Tests.Helpers ((=?>), purely, test)
+import Text.Pandoc (ReaderOptions (readerExtensions),
+                    Extension (Ext_smart), def, enableExtension,
+                    getDefaultExtensions, readOrg)
+import Text.Pandoc.Builder
+
+orgSmart :: Text -> Pandoc
+orgSmart = purely $
+  let extensionsSmart = enableExtension Ext_smart (getDefaultExtensions "org")
+  in readOrg def{ readerExtensions = extensionsSmart }
+
+tests :: [TestTree]
+tests =
+  [ test orgSmart "quote before ellipses"
+    ("'...hi'"
+     =?> para (singleQuoted "…hi"))
+
+  , test orgSmart "apostrophe before emph"
+    ("D'oh! A l'/aide/!"
+     =?> para ("D’oh! A l’" <> emph "aide" <> "!"))
+
+  , test orgSmart "apostrophe in French"
+    ("À l'arrivée de la guerre, le thème de l'«impossibilité du socialisme»"
+     =?> para "À l’arrivée de la guerre, le thème de l’«impossibilité du socialisme»")
+
+  , test orgSmart "Quotes cannot occur at the end of emphasized text"
+    ("/say \"yes\"/" =?>
+     para ("/say" <> space <> doubleQuoted "yes" <> "/"))
+
+  , test orgSmart "Dashes are allowed at the borders of emphasis'"
+    ("/foo---/" =?>
+     para (emph "foo—"))
+
+  , test orgSmart "Single quotes can be followed by emphasized text"
+    ("Singles on the '/meat market/'" =?>
+     para ("Singles on the " <> (singleQuoted $ emph "meat market")))
+
+  , test orgSmart "Double quotes can be followed by emphasized text"
+    ("Double income, no kids: \"/DINK/\"" =?>
+     para ("Double income, no kids: " <> (doubleQuoted $ emph "DINK")))
+  ]
diff --git a/test/Tests/Readers/Org/Meta.hs b/test/Tests/Readers/Org/Meta.hs
new file mode 100644
--- /dev/null
+++ b/test/Tests/Readers/Org/Meta.hs
@@ -0,0 +1,173 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.Org.Meta (tests) where
+
+import Test.Tasty (TestTree)
+import Tests.Helpers ((=?>))
+import Tests.Readers.Org.Shared ((=:), spcSep)
+import Text.Pandoc
+import Text.Pandoc.Builder
+import qualified Data.Text as T
+
+tests :: [TestTree]
+tests =
+  [ "Comment" =:
+      "# Nothing to see here" =?>
+      (mempty::Blocks)
+
+  , "Not a comment" =:
+      "#-tag" =?>
+      para "#-tag"
+
+  , "Comment surrounded by Text" =:
+      T.unlines [ "Before"
+                , "# Comment"
+                , "After"
+                ] =?>
+      mconcat [ para "Before"
+              , para "After"
+              ]
+
+  , "Title" =:
+    "#+TITLE: Hello, World" =?>
+    let titleInline = toList $ "Hello," <> space <> "World"
+        meta = setMeta "title" (MetaInlines titleInline) $ nullMeta
+    in Pandoc meta mempty
+
+  , "Author" =:
+    "#+author: John /Emacs-Fanboy/ Doe" =?>
+    let author = toList . spcSep $ [ "John", emph "Emacs-Fanboy", "Doe" ]
+        meta = setMeta "author" (MetaList [MetaInlines author]) $ nullMeta
+    in Pandoc meta mempty
+
+  , "Multiple authors" =:
+    "#+author: James Dewey Watson, Francis Harry Compton Crick " =?>
+    let watson = MetaInlines $ toList "James Dewey Watson"
+        crick = MetaInlines $ toList "Francis Harry Compton Crick"
+        meta = setMeta "author" (MetaList [watson, crick]) $ nullMeta
+    in Pandoc meta mempty
+
+  , "Date" =:
+    "#+Date: Feb. *28*, 2014" =?>
+    let date = toList . spcSep $ [ "Feb.", (strong "28") <> ",", "2014" ]
+        meta = setMeta "date" (MetaInlines date) $ nullMeta
+    in Pandoc meta mempty
+
+  , "Description" =:
+    "#+DESCRIPTION: Explanatory text" =?>
+    let description = "Explanatory text"
+        meta = setMeta "description" (MetaString description) $ nullMeta
+    in Pandoc meta mempty
+
+  , "Properties drawer" =:
+      T.unlines [ "  :PROPERTIES:"
+                , "  :setting: foo"
+                , "  :END:"
+                ] =?>
+      (mempty::Blocks)
+
+  , "LaTeX_headers options are translated to header-includes" =:
+      "#+LaTeX_header: \\usepackage{tikz}" =?>
+      let latexInlines = rawInline "latex" "\\usepackage{tikz}"
+          inclList = MetaList [MetaInlines (toList latexInlines)]
+          meta = setMeta "header-includes" inclList nullMeta
+      in Pandoc meta mempty
+
+  , "LaTeX_class option is translated to documentclass" =:
+      "#+LATEX_CLASS: article" =?>
+      let meta = setMeta "documentclass" (MetaString "article") nullMeta
+      in Pandoc meta mempty
+
+  , "LaTeX_class_options is translated to classoption" =:
+      "#+LATEX_CLASS_OPTIONS: [a4paper]" =?>
+      let meta = setMeta "classoption" (MetaString "a4paper") nullMeta
+      in Pandoc meta mempty
+
+  , "LaTeX_class_options is translated to classoption" =:
+      "#+html_head: <meta/>" =?>
+      let html = rawInline "html" "<meta/>"
+          inclList = MetaList [MetaInlines (toList html)]
+          meta = setMeta "header-includes" inclList nullMeta
+      in Pandoc meta mempty
+
+  , "later meta definitions take precedence" =:
+      T.unlines [ "#+AUTHOR: this will not be used"
+                , "#+author: Max"
+                ] =?>
+      let author = MetaInlines [Str "Max"]
+          meta = setMeta "author" (MetaList [author]) $ nullMeta
+      in Pandoc meta mempty
+
+  , "Logbook drawer" =:
+      T.unlines [ "  :LogBook:"
+                , "  - State \"DONE\"       from \"TODO\"       [2014-03-03 Mon 11:00]"
+                , "  :END:"
+                ] =?>
+      (mempty::Blocks)
+
+  , "Drawer surrounded by text" =:
+      T.unlines [ "Before"
+                , ":PROPERTIES:"
+                , ":END:"
+                , "After"
+                ] =?>
+      para "Before" <> para "After"
+
+  , "Drawer markers must be the only text in the line" =:
+      T.unlines [ "  :LOGBOOK: foo"
+                , "  :END: bar"
+                ] =?>
+      para (":LOGBOOK: foo" <> softbreak <> ":END: bar")
+
+  , "Drawers can be arbitrary" =:
+      T.unlines [ ":FOO:"
+                , "/bar/"
+                , ":END:"
+                ] =?>
+      divWith (mempty, ["FOO", "drawer"], mempty) (para $ emph "bar")
+
+  , "Anchor reference" =:
+      T.unlines [ "<<link-here>> Target."
+                , ""
+                , "[[link-here][See here!]]"
+                ] =?>
+      (para (spanWith ("link-here", [], []) mempty <> "Target.") <>
+       para (link "#link-here" "" ("See" <> space <> "here!")))
+
+  , "Search links are read as emph" =:
+      "[[Wally][Where's Wally?]]" =?>
+      (para (emph $ "Where's" <> space <> "Wally?"))
+
+  , "Link to nonexistent anchor" =:
+      T.unlines [ "<<link-here>> Target."
+                , ""
+                , "[[link$here][See here!]]"
+                ] =?>
+      (para (spanWith ("link-here", [], []) mempty <> "Target.") <>
+       para (emph ("See" <> space <> "here!")))
+
+  , "Link abbreviation" =:
+      T.unlines [ "#+LINK: wp https://en.wikipedia.org/wiki/%s"
+                , "[[wp:Org_mode][Wikipedia on Org-mode]]"
+                ] =?>
+      (para (link "https://en.wikipedia.org/wiki/Org_mode" ""
+                  ("Wikipedia" <> space <> "on" <> space <> "Org-mode")))
+
+  , "Link abbreviation, defined after first use" =:
+      T.unlines [ "[[zl:non-sense][Non-sense articles]]"
+                , "#+LINK: zl http://zeitlens.com/tags/%s.html"
+                ] =?>
+      (para (link "http://zeitlens.com/tags/non-sense.html" ""
+                  ("Non-sense" <> space <> "articles")))
+
+  , "Link abbreviation, URL encoded arguments" =:
+      T.unlines [ "#+link: expl http://example.com/%h/foo"
+                , "[[expl:Hello, World!][Moin!]]"
+                ] =?>
+      (para (link "http://example.com/Hello%2C%20World%21/foo" "" "Moin!"))
+
+  , "Link abbreviation, append arguments" =:
+      T.unlines [ "#+link: expl http://example.com/"
+                , "[[expl:foo][bar]]"
+                ] =?>
+      (para (link "http://example.com/foo" "" "bar"))
+  ]
diff --git a/test/Tests/Readers/Org/Shared.hs b/test/Tests/Readers/Org/Shared.hs
new file mode 100644
--- /dev/null
+++ b/test/Tests/Readers/Org/Shared.hs
@@ -0,0 +1,29 @@
+module Tests.Readers.Org.Shared
+  ( (=:)
+  , org
+  , spcSep
+  , tagSpan
+  ) where
+
+import Data.List (intersperse)
+import Data.Text (Text)
+import Tests.Helpers (ToString, purely, test)
+import Test.Tasty (TestTree)
+import Text.Pandoc (Pandoc, ReaderOptions (readerExtensions),
+                    def, getDefaultExtensions, readOrg)
+import Text.Pandoc.Builder (Inlines, smallcaps, space, spanWith, str)
+
+org :: Text -> Pandoc
+org = purely $ readOrg def{ readerExtensions = getDefaultExtensions "org" }
+
+infix 4 =:
+(=:) :: ToString c
+     => String -> (Text, c) -> TestTree
+(=:) = test org
+
+spcSep :: [Inlines] -> Inlines
+spcSep = mconcat . intersperse space
+
+-- | Create a span for the given tag.
+tagSpan :: String -> Inlines
+tagSpan t = spanWith ("", ["tag"], [("tag-name", t)]) . smallcaps $ str t
diff --git a/test/Tests/Writers/JATS.hs b/test/Tests/Writers/JATS.hs
new file mode 100644
--- /dev/null
+++ b/test/Tests/Writers/JATS.hs
@@ -0,0 +1,124 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Writers.JATS (tests) where
+
+import Data.Text (unpack)
+import Test.Tasty
+import Tests.Helpers
+import Text.Pandoc
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder
+
+jats :: (ToPandoc a) => a -> String
+jats = unpack . purely (writeJATS def{ writerWrapText = WrapNone }) . toPandoc
+
+{-
+  "my test" =: X =?> Y
+
+is shorthand for
+
+  test jats "my test" $ X =?> Y
+
+which is in turn shorthand for
+
+  test jats "my test" (X,Y)
+-}
+
+infix 4 =:
+(=:) :: (ToString a, ToPandoc a)
+     => String -> (a, String) -> TestTree
+(=:) = test jats
+
+tests :: [TestTree]
+tests = [ testGroup "inline code"
+          [ "basic" =: code "@&" =?> "<p>\n  <monospace>@&amp;</monospace>\n</p>"
+          , "lang" =: codeWith ("", ["c"], []) "@&" =?> "<p>\n  <code language=\"c\">@&amp;</code>\n</p>"
+          ]
+        , testGroup "block code"
+          [ "basic" =: codeBlock "@&" =?> "<preformat>@&amp;</preformat>"
+          , "lang" =: codeBlockWith ("", ["c"], []) "@&" =?> "<code language=\"c\">@&amp;</code>"
+          ]
+        , testGroup "images"
+          [ "basic" =:
+            image "/url" "title" mempty
+            =?> "<graphic mimetype=\"image\" mime-subtype=\"\" xlink:href=\"/url\" xlink:title=\"title\" />"
+          ]
+        , testGroup "inlines"
+          [ "Emphasis" =: emph "emphasized"
+            =?> "<p>\n  <italic>emphasized</italic>\n</p>"
+          ]
+        , "bullet list" =: bulletList [ plain $ text "first"
+                                      , plain $ text "second"
+                                      , plain $ text "third"
+                                      ]
+            =?> "<list list-type=\"bullet\">\n\
+                \  <list-item>\n\
+                \    <p>\n\
+                \      first\n\
+                \    </p>\n\
+                \  </list-item>\n\
+                \  <list-item>\n\
+                \    <p>\n\
+                \      second\n\
+                \    </p>\n\
+                \  </list-item>\n\
+                \  <list-item>\n\
+                \    <p>\n\
+                \      third\n\
+                \    </p>\n\
+                \  </list-item>\n\
+                \</list>"
+        , testGroup "definition lists"
+          [ "with internal link" =: definitionList [(link "#go" "" (str "testing"),
+             [plain (text "hi there")])] =?>
+            "<def-list>\n\
+            \  <def-item>\n\
+            \    <term>\n\
+            \      <xref alt=\"testing\" rid=\"go\">testing</xref>\n\
+            \    </term>\n\
+            \    <def>\n\
+            \      <p>\n\
+            \        hi there\n\
+            \      </p>\n\
+            \    </def>\n\
+            \  </def-item>\n\
+            \</def-list>"
+          ]
+        , testGroup "math"
+          [ "escape |" =: para (math "\\sigma|_{\\{x\\}}") =?>
+            "<p>\n\
+            \  <inline-formula><alternatives>\n\
+            \  <tex-math><![CDATA[\\sigma|_{\\{x\\}}]]></tex-math>\n\
+            \  <mml:math display=\"inline\" xmlns:mml=\"http://www.w3.org/1998/Math/MathML\"><mml:mrow><mml:mi>σ</mml:mi><mml:msub><mml:mo stretchy=\"false\" form=\"prefix\">|</mml:mo><mml:mrow><mml:mo stretchy=\"false\" form=\"prefix\">{</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy=\"false\" form=\"postfix\">}</mml:mo></mml:mrow></mml:msub></mml:mrow></mml:math></alternatives></inline-formula>\n\
+            \</p>"
+          ]
+        , testGroup "headers"
+          [ "unnumbered header" =:
+            headerWith ("foo",["unnumbered"],[]) 1
+              (text "Header 1" <> note (plain $ text "note")) =?>
+            "<sec id=\"foo\">\n\
+            \  <title>Header 1<fn>\n\
+            \    <p>\n\
+            \      note\n\
+            \    </p>\n\
+            \  </fn></title>\n\
+            \</sec>"
+          , "unnumbered sub header" =:
+            headerWith ("foo",["unnumbered"],[]) 1
+              (text "Header")
+            <> headerWith ("foo",["unnumbered"],[]) 2
+              (text "Sub-Header") =?>
+            "<sec id=\"foo\">\n\
+            \  <title>Header</title>\n\
+            \  <sec id=\"foo\">\n\
+            \    <title>Sub-Header</title>\n\
+            \  </sec>\n\
+            \</sec>"
+          , "containing image" =:
+            header 1 (image "imgs/foo.jpg" "" (text "Alt text")) =?>
+            "<sec>\n\
+            \  <title><inline-graphic mimetype=\"image\" mime-subtype=\"jpeg\" xlink:href=\"imgs/foo.jpg\" /></title>\n\
+            \</sec>"
+          ]
+        ]
+
+
diff --git a/test/Tests/Writers/Muse.hs b/test/Tests/Writers/Muse.hs
--- a/test/Tests/Writers/Muse.hs
+++ b/test/Tests/Writers/Muse.hs
@@ -234,6 +234,11 @@
                       , ""
                       , "*** Third level"
                       ]
+            , "heading with ID" =:
+               headerWith ("bar", [], []) 2 (text "Foo") =?>
+               unlines [ "** Foo"
+                       , "#bar"
+                      ]
             ]
           , "horizontal rule" =: horizontalRule =?> "----"
           , "escape horizontal rule" =: para (text "----") =?> "<verbatim>----</verbatim>"
diff --git a/test/Tests/Writers/Powerpoint.hs b/test/Tests/Writers/Powerpoint.hs
new file mode 100644
--- /dev/null
+++ b/test/Tests/Writers/Powerpoint.hs
@@ -0,0 +1,101 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Tests.Writers.Powerpoint (tests) where
+
+import Control.Exception (throwIO)
+import Text.Pandoc
+import Text.Pandoc.Builder
+import Test.Tasty
+import Test.Tasty.HUnit
+import Codec.Archive.Zip
+import Data.List (isPrefixOf, isSuffixOf)
+
+----- Number of Slides -----------
+
+numberOfSlides :: WriterOptions -> Pandoc -> IO Int
+numberOfSlides opts pd = do
+  mbs <- runIO $
+        do setUserDataDir $ Just "../data"
+           writePowerpoint opts pd
+  case mbs of
+       Left e   -> throwIO e
+       Right bs -> do
+         let archive = toArchive bs
+         return $
+           length $
+           filter (isSuffixOf ".xml") $
+           filter (isPrefixOf "ppt/slides/slide") $
+           filesInArchive archive
+
+testNumberOfSlides :: TestName -> Int -> WriterOptions -> Pandoc -> TestTree
+testNumberOfSlides name n opts pd =
+  testCase name $ do
+    n' <- numberOfSlides opts pd
+    n' @=? n
+
+numSlideTests :: TestTree
+numSlideTests = testGroup "Number of slides in output"
+  [ testNumberOfSlides
+    "simple one-slide deck" 1
+    def
+    (doc $ para "foo")
+  , testNumberOfSlides
+    "with metadata (header slide)" 2
+    def
+    (setTitle "My Title" $ doc $ para "foo")
+  , testNumberOfSlides
+    "With h1 slide (using default slide-level)" 2
+    def
+    (doc $ header 1 "Header" <> para "foo")
+  , testNumberOfSlides
+    "With h2 slide (using default slide-level)" 2
+    def
+    (doc $ header 1 "Header" <> header 2 "subeader" <> para "foo")
+  , testNumberOfSlides
+    "With h1 slide (using default slide-level)" 2
+    def
+    (doc $ header 1 "Header" <> para "foo")
+  , testNumberOfSlides
+    "With h2 slide (using default slide-level)" 2
+    def
+    (doc $ header 1 "Header" <> header 2 "subeader" <> para "foo")
+  , testNumberOfSlides
+    "With image slide, no header" 3
+    def
+    (doc $
+      para "first slide" <>
+      (para $ image "lalune.jpg" "" "") <>
+      para "foo")
+  , testNumberOfSlides
+    "With image slide, header" 3
+    def
+    (doc $
+      para "first slide" <>
+      header 2 "image header" <>
+      (para $ image "lalune.jpg" "" "") <>
+      para "foo")
+  , testNumberOfSlides
+    "With table, no header" 3
+    def
+    (doc $
+     para "first slide" <>
+     (simpleTable [para "foo" <> para "bar"] [[para "this" <> para "that"]]) <>
+     para "foo")
+  , testNumberOfSlides
+    "With table, header" 3
+    def
+    (doc $
+     para "first slide" <>
+     header 2 "table header" <>
+     (simpleTable [para "foo" <> para "bar"] [[para "this" <> para "that"]]) <>
+     para "foo")
+  , testNumberOfSlides
+    "hrule" 2
+    def
+    (doc $
+     para "first slide" <> horizontalRule <> para "last slide")
+  ]
+
+
+tests :: [TestTree]
+tests = [numSlideTests]
diff --git a/test/command/3937.md b/test/command/3937.md
--- a/test/command/3937.md
+++ b/test/command/3937.md
@@ -3,7 +3,7 @@
 # My Great Section {#mysection}
 # Other section
 ^D
-.. mysection:
+.. _mysection:
 
 My Great Section
 ================
diff --git a/test/command/4156.md b/test/command/4156.md
new file mode 100644
--- /dev/null
+++ b/test/command/4156.md
@@ -0,0 +1,10 @@
+```
+% pandoc -f rst
+.. _`SOMEID`:
+
+foo
+^D
+<div id="SOMEID">
+<p>foo</p>
+</div>
+```
diff --git a/test/command/4159.md b/test/command/4159.md
new file mode 100644
--- /dev/null
+++ b/test/command/4159.md
@@ -0,0 +1,7 @@
+```
+% pandoc -f markdown -t native
+\newcommand{\gen}{a\ Gen\ b}
+abc
+^D
+[Para [Str "abc"]]
+```
diff --git a/test/command/4162.md b/test/command/4162.md
new file mode 100644
--- /dev/null
+++ b/test/command/4162.md
@@ -0,0 +1,10 @@
+```
+% pandoc -f html -t native
+<div class="line-block">hi<br /><br>
+ there</div>
+^D
+[LineBlock
+ [[Str "hi"]
+ ,[]
+ ,[Str "\160there"]]]
+```
diff --git a/test/command/4164.md b/test/command/4164.md
new file mode 100644
--- /dev/null
+++ b/test/command/4164.md
@@ -0,0 +1,35 @@
+```
+% pandoc -f opml -t markdown
+<?xml version="1.0"?> <opml version="1.0"> <head> <title> test </title> </head> <body> <outline text="test"> <outline text="try" _note="Here is inline html:&#xA;&#xA;&lt;div&gt; &#xA;&lt;balise&gt;&#xA;bla bla&#xA;&lt;/div&gt;"/> </outline> </body> </opml>
+^D
+test
+====
+
+try
+---
+
+Here is inline html:
+
+<div>
+
+<balise> bla bla
+
+</div>
+
+```
+
+```
+% pandoc -f opml-raw_html-native_divs -t markdown
+<?xml version="1.0"?> <opml version="1.0"> <head> <title> test </title> </head> <body> <outline text="test"> <outline text="try" _note="Here is inline html:&#xA;&#xA;&lt;div&gt; &#xA;&lt;balise&gt;&#xA;bla bla&#xA;&lt;/div&gt;"/> </outline> </body> </opml>
+^D
+test
+====
+
+try
+---
+
+Here is inline html:
+
+\<div\> \<balise\> bla bla \</div\>
+
+```
diff --git a/test/command/4171.md b/test/command/4171.md
new file mode 100644
--- /dev/null
+++ b/test/command/4171.md
@@ -0,0 +1,34 @@
+```
+% pandoc -f org -t org
+Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa [fn:1] a
+
+[fn:1] b
+^D
+Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa [fn:1]
+a
+
+[fn:1] b
+```
+
+
+```
+% pandoc -f org -t org
+Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ [fn:1] a
+
+[fn:1] b
+^D
+Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa [fn:1]
+a
+
+[fn:1] b
+```
+
+Similar bug: "-" should not be wrapped:
+```
+% pandoc -f org -t org
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - abc
+^D
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -
+abc
+```
diff --git a/test/command/4172.md b/test/command/4172.md
new file mode 100644
--- /dev/null
+++ b/test/command/4172.md
@@ -0,0 +1,29 @@
+Test that text wrapping does not move note reference [1] to the beginning of the line,
+where it would become a note.
+```
+% pandoc -f muse -t muse
+Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa [1] a
+
+[1] b
+^D
+Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa [1]
+a
+
+[1] b
+
+```
+
+SoftBreak test:
+```
+% pandoc -f muse -t muse
+Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ [1] a
+
+[1] b
+^D
+Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa [1]
+a
+
+[1] b
+
+```
diff --git a/test/command/4183.md b/test/command/4183.md
new file mode 100644
--- /dev/null
+++ b/test/command/4183.md
@@ -0,0 +1,32 @@
+```
+% pandoc -f html -t native
+<figure>
+  <img src="foo" alt="bar">
+</figure>
+^D
+[Para [Image ("",[],[]) [] ("foo","fig:")]]
+```
+
+```
+% pandoc -f html -t native
+<figure>
+  <img src="foo" alt="bar">
+  <figcaption>
+    <div>
+      baz
+    </div>
+  </figcaption>
+</figure>
+^D
+[Para [Image ("",[],[]) [Str "baz"] ("foo","fig:")]]
+```
+
+```
+% pandoc -f html -t native
+<figure>
+  <img src="foo">
+  <figcaption><p><em>baz</em></p></figcaption>
+</figure>
+^D
+[Para [Image ("",[],[]) [Emph [Str "baz"]] ("foo","fig:")]]
+```
diff --git a/test/command/4193.md b/test/command/4193.md
new file mode 100644
--- /dev/null
+++ b/test/command/4193.md
@@ -0,0 +1,10 @@
+```
+% pandoc -f rst -t native
+-
+ a
+- b
+^D
+[BulletList
+ [[Plain [Str "a"]]
+ ,[Plain [Str "b"]]]]
+```
diff --git a/test/command/4199.md b/test/command/4199.md
new file mode 100644
--- /dev/null
+++ b/test/command/4199.md
@@ -0,0 +1,6 @@
+```
+% pandoc -f latex -t native
+\foreignlanguage{ngerman}{foo}
+^D
+[Para [Span ("",[],[("lang","de-DE")]) [Str "foo"]]]
+```
diff --git a/test/command/4208.md b/test/command/4208.md
new file mode 100644
--- /dev/null
+++ b/test/command/4208.md
@@ -0,0 +1,18 @@
+```
+% pandoc -t latex
+What is a _piffle_? Mark the correct answer(s):
+
+\begin{TAB}(@)[6pt]{|l|c|}{|c|c|c|}
+(a) a subnormal woffle                      &  $\Box$  \\
+(b) an infinite-dimensional baffle          &  $\Box$  \\
+(c) an inverted first-order triffle         &  $\Box$  \\
+\end{TAB}
+^D
+What is a \emph{piffle}? Mark the correct answer(s):
+
+\begin{TAB}(@)[6pt]{|l|c|}{|c|c|c|}
+(a) a subnormal woffle                      &  $\Box$  \\
+(b) an infinite-dimensional baffle          &  $\Box$  \\
+(c) an inverted first-order triffle         &  $\Box$  \\
+\end{TAB}
+```
diff --git a/test/command/hspace.md b/test/command/hspace.md
--- a/test/command/hspace.md
+++ b/test/command/hspace.md
@@ -32,7 +32,7 @@
 F & F &\\
 \end{tabular}
 ^D
-[RawBlock (Format "latex") "\\begin{tabular}[t]{cc|c}\n\\(P\\) & \\(Q\\) & \\(P\\wedge Q\\)\\\\\n\\hline\nT & T &\\\\\nT & F &\\\\\nF & T &\\\\\nF & F &\\\\\n\\end{tabular}\\hspace{1em}\\begin{tabular}[t]{cc|c}\n\\(P\\) & \\(Q\\) & \\(P\\vee Q\\)\\\\\n\\hline\nT & T &\\\\\nT & F &\\\\\nF & T &\\\\\nF & F &\\\\\n\\end{tabular}"]
+[RawBlock (Format "latex") "\\begin{tabular}[t]{cc|c}\n\\(P\\) & \\(Q\\) & \\(P\\wedge Q\\)\\\\\n\\hline\nT & T &\\\\\nT & F &\\\\\nF & T &\\\\\nF & F &\\\\\n\\end{tabular}\n\\hspace{1em}\n\\begin{tabular}[t]{cc|c}\n\\(P\\) & \\(Q\\) & \\(P\\vee Q\\)\\\\\n\\hline\nT & T &\\\\\nT & F &\\\\\nF & T &\\\\\nF & F &\\\\\n\\end{tabular}"]
 ```
 
 ```
diff --git a/test/command/macros.md b/test/command/macros.md
--- a/test/command/macros.md
+++ b/test/command/macros.md
@@ -3,7 +3,6 @@
 \newcommand{\my}{\phi}
 $\my+\my$
 ^D
-\newcommand{\my}{\phi}
 $\phi+\phi$
 ```
 
@@ -65,4 +64,37 @@
 \emph{hi}
 
 \emph{hi--ok}
+```
+
+```
+% pandoc -f markdown+latex_macros -t markdown
+\newcommand{\my}{\phi}
+\begin{equation}
+\my+\my
+\end{equation}
+^D
+\begin{equation}
+\phi+\phi
+\end{equation}
+```
+
+```
+% pandoc -f markdown-latex_macros -t markdown
+\newcommand{\my}{\phi}
+\begin{equation}
+\my+\my
+\end{equation}
+^D
+\newcommand{\my}{\phi}
+\begin{equation}
+\my+\my
+\end{equation}
+```
+
+```
+% pandoc -f markdown+latex_macros -t markdown
+\newcommand{\my}{\emph{a}}
+\my
+^D
+\emph{a}
 ```
diff --git a/test/command/rst-links.md b/test/command/rst-links.md
new file mode 100644
--- /dev/null
+++ b/test/command/rst-links.md
@@ -0,0 +1,18 @@
+```
+% pandoc -f rst
+`*ab*`_
+
+.. _`*ab*`: foo
+^D
+<p><a href="foo">*ab*</a></p>
+```
+
+```
+% pandoc -f rst
+`A B
+c`_
+
+.. _A B C: foo
+^D
+<p><a href="foo">A B c</a></p>
+```
diff --git a/test/docx/lists_continuing.docx b/test/docx/lists_continuing.docx
new file mode 100644
Binary files /dev/null and b/test/docx/lists_continuing.docx differ
diff --git a/test/docx/lists_continuing.native b/test/docx/lists_continuing.native
new file mode 100644
--- /dev/null
+++ b/test/docx/lists_continuing.native
@@ -0,0 +1,7 @@
+[OrderedList (1,Decimal,Period)
+ [[Para [Str "Foo"]]
+ ,[Para [Str "Bar"]]
+ ,[Para [Str "Baz"]]]
+,Para [Str "Interruption."]
+,OrderedList (4,Decimal,Period)
+ [[Para [Str "Bop"]]]]
diff --git a/test/docx/lists_restarting.docx b/test/docx/lists_restarting.docx
new file mode 100644
Binary files /dev/null and b/test/docx/lists_restarting.docx differ
diff --git a/test/docx/lists_restarting.native b/test/docx/lists_restarting.native
new file mode 100644
--- /dev/null
+++ b/test/docx/lists_restarting.native
@@ -0,0 +1,8 @@
+[OrderedList (2,Decimal,Period)
+ [[Para [Str "Foo"]]
+ ,[Para [Str "Bar"]]
+ ,[Para [Str "Baz"]]]
+,BlockQuote
+ [Para [Str "Interruption"]]
+,OrderedList (1,Decimal,Period)
+ [[Para [Str "Bop."]]]]
diff --git a/test/docx/sdt_elements.docx b/test/docx/sdt_elements.docx
new file mode 100644
Binary files /dev/null and b/test/docx/sdt_elements.docx differ
diff --git a/test/docx/sdt_elements.native b/test/docx/sdt_elements.native
new file mode 100644
--- /dev/null
+++ b/test/docx/sdt_elements.native
@@ -0,0 +1,10 @@
+[Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
+ [[]
+ ,[]
+ ,[]]
+ [[[Plain [Strong [Str "col1Header"]]]
+  ,[Plain [Strong [Str "col2Header"]]]
+  ,[Plain [Strong [Str "col3Header"]]]]
+ ,[[Plain [Str "col1",Space,Str "content"]]
+  ,[Plain [Str "Body",Space,Str "copy"]]
+  ,[Plain [Str "col3",Space,Str "content"]]]]]
diff --git a/test/jats-reader.native b/test/jats-reader.native
new file mode 100644
--- /dev/null
+++ b/test/jats-reader.native
@@ -0,0 +1,422 @@
+Pandoc (Meta {unMeta = fromList [("author",MetaList [MetaInlines [Str "John",Space,Str "MacFarlane"]]),("title",MetaInlines [Str "Pandoc",Space,Str "Test",Space,Str "Suite"])]})
+[Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "set",Space,Str "of",Space,Str "tests",Space,Str "for",Space,Str "pandoc.",Space,Str "Most",Space,Str "of",Space,Str "them",Space,Str "are",Space,Str "adapted",Space,Str "from",Space,Str "John",SoftBreak,Str "Gruber's",Space,Str "markdown",Space,Str "test",Space,Str "suite."]
+,Header 1 ("headers",[],[]) [Str "Headers"]
+,Header 2 ("level-2-with-an-embedded-link",[],[]) [Str "Level",Space,Str "2",Space,Str "with",Space,Str "an",SoftBreak,Link ("",[],[]) [Str "embedded",SoftBreak,Str "link"] ("/url","")]
+,Header 3 ("level-3-with-emphasis",[],[]) [Str "Level",Space,Str "3",Space,Str "with",Space,Emph [Str "emphasis"]]
+,Header 4 ("level-4",[],[]) [Str "Level",Space,Str "4"]
+,Header 5 ("level-5",[],[]) [Str "Level",Space,Str "5"]
+,Header 1 ("level-1",[],[]) [Str "Level",Space,Str "1"]
+,Header 2 ("level-2-with-emphasis",[],[]) [Str "Level",Space,Str "2",Space,Str "with",Space,Emph [Str "emphasis"]]
+,Header 3 ("level-3",[],[]) [Str "Level",Space,Str "3"]
+,Para [Str "with",Space,Str "no",Space,Str "blank",Space,Str "line"]
+,Header 2 ("level-2",[],[]) [Str "Level",Space,Str "2"]
+,Para [Str "with",Space,Str "no",Space,Str "blank",Space,Str "line"]
+,Header 1 ("paragraphs",[],[]) [Str "Paragraphs"]
+,Para [Str "Here's",Space,Str "a",Space,Str "regular",Space,Str "paragraph."]
+,Para [Str "In",Space,Str "Markdown",Space,Str "1.0.0",Space,Str "and",Space,Str "earlier.",Space,Str "Version",Space,Str "8.",Space,Str "This",Space,Str "line",Space,Str "turns",Space,Str "into",Space,Str "a",SoftBreak,Str "list",Space,Str "item.",Space,Str "Because",Space,Str "a",Space,Str "hard-wrapped",Space,Str "line",Space,Str "in",Space,Str "the",Space,Str "middle",Space,Str "of",Space,Str "a",Space,Str "paragraph",SoftBreak,Str "looked",Space,Str "like",Space,Str "a",Space,Str "list",Space,Str "item."]
+,Para [Str "Here's",Space,Str "one",Space,Str "with",Space,Str "a",Space,Str "bullet.",Space,Str "*",Space,Str "criminey."]
+,Para [Str "There",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "hard",Space,Str "line",Space,Str "break",LineBreak,Str "here."]
+,Header 1 ("block-quotes",[],[]) [Str "Block",Space,Str "Quotes"]
+,Para [Str "E-mail",Space,Str "style:"]
+,BlockQuote
+ [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "block",Space,Str "quote.",Space,Str "It",Space,Str "is",Space,Str "pretty",Space,Str "short."]]
+,BlockQuote
+ [Para [Str "Code",Space,Str "in",Space,Str "a",Space,Str "block",Space,Str "quote:"]
+ ,CodeBlock ("",[],[]) "sub status {\n    print \"working\";\n}"
+ ,Para [Str "A",Space,Str "list:"]
+ ,OrderedList (1,DefaultStyle,DefaultDelim)
+  [[Para [Str "item",Space,Str "one"]]
+  ,[Para [Str "item",Space,Str "two"]]]
+ ,Para [Str "Nested",Space,Str "block",Space,Str "quotes:"]
+ ,BlockQuote
+  [Para [Str "nested"]]
+ ,BlockQuote
+  [Para [Str "nested"]]]
+,Para [Str "This",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "a",Space,Str "block",Space,Str "quote:",Space,Str "2",Space,Str ">",Space,Str "1."]
+,Para [Str "Box-style:"]
+,BlockQuote
+ [Para [Str "Example:"]
+ ,CodeBlock ("",[],[]) "sub status {\n    print \"working\";\n}"]
+,BlockQuote
+ [OrderedList (1,DefaultStyle,DefaultDelim)
+  [[Para [Str "do",Space,Str "laundry"]]
+  ,[Para [Str "take",Space,Str "out",Space,Str "the",Space,Str "trash"]]]]
+,Para [Str "Here's",Space,Str "a",Space,Str "nested",Space,Str "one:"]
+,BlockQuote
+ [Para [Str "Joe",Space,Str "said:"]
+ ,BlockQuote
+  [Para [Str "Don't",Space,Str "quote",Space,Str "me."]]]
+,Para [Str "And",Space,Str "a",Space,Str "following",Space,Str "paragraph."]
+,Header 1 ("code-blocks",[],[]) [Str "Code",Space,Str "Blocks"]
+,Para [Str "Code:"]
+,CodeBlock ("",[],[]) "---- (should be four hyphens)\n\nsub status {\n    print \"working\";\n}\n\nthis code block is indented by one tab"
+,Para [Str "And:"]
+,CodeBlock ("",[],[]) "    this code block is indented by two tabs\n\nThese should not be escaped:  \\$ \\\\ \\> \\[ \\{"
+,Header 1 ("lists",[],[]) [Str "Lists"]
+,Header 2 ("unordered",[],[]) [Str "Unordered"]
+,Para [Str "Asterisks",Space,Str "tight:"]
+,BulletList
+ [[Para [Str "asterisk",Space,Str "1"]]
+ ,[Para [Str "asterisk",Space,Str "2"]]
+ ,[Para [Str "asterisk",Space,Str "3"]]]
+,Para [Str "Asterisks",Space,Str "loose:"]
+,BulletList
+ [[Para [Str "asterisk",Space,Str "1"]]
+ ,[Para [Str "asterisk",Space,Str "2"]]
+ ,[Para [Str "asterisk",Space,Str "3"]]]
+,Para [Str "Pluses",Space,Str "tight:"]
+,BulletList
+ [[Para [Str "Plus",Space,Str "1"]]
+ ,[Para [Str "Plus",Space,Str "2"]]
+ ,[Para [Str "Plus",Space,Str "3"]]]
+,Para [Str "Pluses",Space,Str "loose:"]
+,BulletList
+ [[Para [Str "Plus",Space,Str "1"]]
+ ,[Para [Str "Plus",Space,Str "2"]]
+ ,[Para [Str "Plus",Space,Str "3"]]]
+,Para [Str "Minuses",Space,Str "tight:"]
+,BulletList
+ [[Para [Str "Minus",Space,Str "1"]]
+ ,[Para [Str "Minus",Space,Str "2"]]
+ ,[Para [Str "Minus",Space,Str "3"]]]
+,Para [Str "Minuses",Space,Str "loose:"]
+,BulletList
+ [[Para [Str "Minus",Space,Str "1"]]
+ ,[Para [Str "Minus",Space,Str "2"]]
+ ,[Para [Str "Minus",Space,Str "3"]]]
+,Header 2 ("ordered",[],[]) [Str "Ordered"]
+,Para [Str "Tight:"]
+,OrderedList (1,DefaultStyle,DefaultDelim)
+ [[Para [Str "First"]]
+ ,[Para [Str "Second"]]
+ ,[Para [Str "Third"]]]
+,Para [Str "and:"]
+,OrderedList (1,DefaultStyle,DefaultDelim)
+ [[Para [Str "One"]]
+ ,[Para [Str "Two"]]
+ ,[Para [Str "Three"]]]
+,Para [Str "Loose",Space,Str "using",Space,Str "tabs:"]
+,OrderedList (1,DefaultStyle,DefaultDelim)
+ [[Para [Str "First"]]
+ ,[Para [Str "Second"]]
+ ,[Para [Str "Third"]]]
+,Para [Str "and",Space,Str "using",Space,Str "spaces:"]
+,OrderedList (1,DefaultStyle,DefaultDelim)
+ [[Para [Str "One"]]
+ ,[Para [Str "Two"]]
+ ,[Para [Str "Three"]]]
+,Para [Str "Multiple",Space,Str "paragraphs:"]
+,OrderedList (1,DefaultStyle,DefaultDelim)
+ [[Para [Str "Item",Space,Str "1,",Space,Str "graf",Space,Str "one."]
+  ,Para [Str "Item",Space,Str "1.",Space,Str "graf",Space,Str "two.",Space,Str "The",Space,Str "quick",Space,Str "brown",Space,Str "fox",Space,Str "jumped",Space,Str "over",Space,Str "the",Space,Str "lazy",SoftBreak,Str "dog's",Space,Str "back."]]
+ ,[Para [Str "Item",Space,Str "2."]]
+ ,[Para [Str "Item",Space,Str "3."]]]
+,Para [Str "List",Space,Str "styles:"]
+,OrderedList (1,DefaultStyle,DefaultDelim)
+ []
+,OrderedList (1,LowerRoman,DefaultDelim)
+ []
+,Header 2 ("nested",[],[]) [Str "Nested"]
+,BulletList
+ [[Para [Str "Tab"]
+  ,BulletList
+   [[Para [Str "Tab"]
+    ,BulletList
+     [[Para [Str "Tab"]]]]]]]
+,Para [Str "Here's",Space,Str "another:"]
+,OrderedList (1,DefaultStyle,DefaultDelim)
+ [[Para [Str "First"]]
+ ,[Para [Str "Second:"]
+  ,BulletList
+   [[Para [Str "Fee"]]
+   ,[Para [Str "Fie"]]
+   ,[Para [Str "Foe"]]]]
+ ,[Para [Str "Third"]]]
+,Para [Str "Same",Space,Str "thing",Space,Str "but",Space,Str "with",Space,Str "paragraphs:"]
+,OrderedList (1,DefaultStyle,DefaultDelim)
+ [[Para [Str "First"]]
+ ,[Para [Str "Second:"]
+  ,BulletList
+   [[Para [Str "Fee"]]
+   ,[Para [Str "Fie"]]
+   ,[Para [Str "Foe"]]]]
+ ,[Para [Str "Third"]]]
+,Header 2 ("tabs-and-spaces",[],[]) [Str "Tabs",Space,Str "and",Space,Str "spaces"]
+,BulletList
+ [[Para [Str "this",Space,Str "is",Space,Str "a",Space,Str "list",Space,Str "item",Space,Str "indented",Space,Str "with",Space,Str "tabs"]]
+ ,[Para [Str "this",Space,Str "is",Space,Str "a",Space,Str "list",Space,Str "item",Space,Str "indented",Space,Str "with",Space,Str "spaces"]
+  ,BulletList
+   [[Para [Str "this",Space,Str "is",Space,Str "an",Space,Str "example",Space,Str "list",Space,Str "item",Space,Str "indented",Space,Str "with",Space,Str "tabs"]]
+   ,[Para [Str "this",Space,Str "is",Space,Str "an",Space,Str "example",Space,Str "list",Space,Str "item",Space,Str "indented",Space,Str "with",Space,Str "spaces"]]]]]
+,Header 2 ("fancy-list-markers",[],[]) [Str "Fancy",Space,Str "list",Space,Str "markers"]
+,Para [Str "Autonumbering:"]
+,OrderedList (1,DefaultStyle,DefaultDelim)
+ [[Para [Str "Autonumber."]]
+ ,[Para [Str "More."]
+  ,OrderedList (1,DefaultStyle,DefaultDelim)
+   [[Para [Str "Nested."]]]]]
+,Header 2 ("definition",[],[]) [Str "Definition"]
+,DefinitionList
+ [([Str "Violin"],
+   [[Para [Str "Stringed",Space,Str "musical",Space,Str "instrument."]
+    ,Para [Str "Torture",Space,Str "device."]]])
+ ,([Str "Cello",LineBreak,Str "Violoncello"],
+   [[Para [Str "Low-voiced",Space,Str "stringed",Space,Str "instrument."]]])]
+,Header 1 ("inline-markup",[],[]) [Str "Inline",Space,Str "Markup"]
+,Para [Str "This",Space,Str "is",Space,Emph [Str "emphasized"],Str ",",Space,Str "and",Space,Str "so",Space,Emph [Str "is",SoftBreak,Str "this"],Str "."]
+,Para [Str "This",Space,Str "is",Space,Strong [Str "strong"],Str ",",Space,Str "and",Space,Str "so",SoftBreak,Strong [Str "is",Space,Str "this"],Str "."]
+,Para [Str "Empty",Space,Strong [],Space,Str "and",Space,Emph [],Str "."]
+,Para [Str "An",SoftBreak,Emph [Link ("",[],[]) [Str "emphasized",SoftBreak,Str "link"] ("/url","")],Str "."]
+,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em."]]]
+,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word."]
+,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em."]]]
+,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word."]
+,Para [Str "This",Space,Str "is",Space,Str "code:",Space,Code ("",[],[]) ">",Str ",",Space,Code ("",[],[]) "$",Str ",",SoftBreak,Code ("",[],[]) "\\",Str ",",Space,Code ("",[],[]) "\\$",Str ",",SoftBreak,Code ("",[],[]) "<html>",Str "."]
+,Para [Str "This",Space,Str "is",Space,SmallCaps [Str "small",Space,Str "caps"],Str "."]
+,Para [Str "These",Space,Str "are",Space,Str "all",Space,Str "underlined:",Space,Str "foo",Space,Str "and",Space,Str "bar."]
+,Para [Str "These",Space,Str "are",Space,Str "all",Space,Str "strikethrough:",Space,Strikeout [Str "foo"],Str ",",SoftBreak,Strikeout [Str "bar"],Str ",",Space,Str "and",Space,Strikeout [Str "baz"],Str "."]
+,Header 1 ("smart-quotes-ellipses-dashes",[],[]) [Str "Smart",Space,Str "quotes,",Space,Str "ellipses,",Space,Str "dashes"]
+,Para [Str "\"Hello,\"",Space,Str "said",Space,Str "the",Space,Str "spider.",Space,Str "\"'Shelob'",Space,Str "is",Space,Str "my",Space,Str "name.\""]
+,Para [Str "'A',",Space,Str "'B',",Space,Str "and",Space,Str "'C'",Space,Str "are",Space,Str "letters."]
+,Para [Str "'Oak,'",Space,Str "'elm,'",Space,Str "and",Space,Str "'beech'",Space,Str "are",Space,Str "names",Space,Str "of",Space,Str "trees.",Space,Str "So",Space,Str "is",Space,Str "'pine.'"]
+,Para [Str "'He",Space,Str "said,",Space,Str "\"I",Space,Str "want",Space,Str "to",Space,Str "go.\"'",Space,Str "Were",Space,Str "you",Space,Str "alive",Space,Str "in",Space,Str "the",Space,Str "70's?"]
+,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Str "quoted",Space,Str "'",Code ("",[],[]) "code",Str "'",Space,Str "and",Space,Str "a",SoftBreak,Str "\"",Link ("",[],[]) [Str "quoted",SoftBreak,Str "link"] ("http://example.com/?foo=1&bar=2",""),Str "\"."]
+,Para [Str "Some",Space,Str "dashes:",Space,Str "one---two",Space,Str "---",Space,Str "three--four",Space,Str "--",Space,Str "five."]
+,Para [Str "Dashes",Space,Str "between",Space,Str "numbers:",Space,Str "5-7,",Space,Str "255-66,",Space,Str "1987-1999."]
+,Para [Str "Ellipses...and.",Space,Str ".",Space,Str ".and",Space,Str ".",Space,Str ".",Space,Str ".",Space,Str "."]
+,Header 1 ("latex",[],[]) [Str "LaTeX"]
+,BulletList
+ [[Para [Str "\\cite[22-23]{smith.1899}"]]
+ ,[Para [Str "\\doublespacing"]]
+ ,[Para [Str "$2+2=4$"]]
+ ,[Para [Str "$x",Space,Str "\\in",Space,Str "y$"]]
+ ,[Para [Str "$\\alpha",Space,Str "\\wedge",Space,Str "\\omega$"]]
+ ,[Para [Str "$223$"]]
+ ,[Para [Str "$p$-Tree"]]
+ ,[Para [Str "$\\frac{d}{dx}f(x)=\\lim_{h\\to",Space,Str "0}\\frac{f(x+h)-f(x)}{h}$"]]
+ ,[Para [Str "Here's",Space,Str "one",Space,Str "that",Space,Str "has",Space,Str "a",Space,Str "line",Space,Str "break",Space,Str "in",Space,Str "it:",Space,Str "$\\alpha",Space,Str "+",Space,Str "\\omega",Space,Str "\\times",SoftBreak,Str "x^2$."]]]
+,Para [Str "These",Space,Str "shouldn't",Space,Str "be",Space,Str "math:"]
+,BulletList
+ [[Para [Str "To",Space,Str "get",Space,Str "the",Space,Str "famous",Space,Str "equation,",Space,Str "write",SoftBreak,Code ("",[],[]) "$e = mc^2$",Str "."]]
+ ,[Para [Str "$22,000",Space,Str "is",Space,Str "a",Space,Emph [Str "lot"],Space,Str "of",Space,Str "money.",Space,Str "So",Space,Str "is",Space,Str "$34,000.",Space,Str "(It",SoftBreak,Str "worked",Space,Str "if",Space,Str "\"lot\"",Space,Str "is",Space,Str "emphasized.)"]]
+ ,[Para [Str "Escaped",Space,Code ("",[],[]) "$",Str ":",Space,Str "$73",Space,Emph [Str "this",Space,Str "should",Space,Str "be",SoftBreak,Str "emphasized"],Space,Str "23$."]]]
+,Para [Str "Here's",Space,Str "a",Space,Str "LaTeX",Space,Str "table:"]
+,Para [Str "\\begin{tabular}{|l|l|}\\hline",Space,Str "Animal",Space,Str "&",Space,Str "Number",Space,Str "\\\\",Space,Str "\\hline",Space,Str "Dog",Space,Str "&",SoftBreak,Str "2",Space,Str "\\\\",Space,Str "Cat",Space,Str "&",Space,Str "1",Space,Str "\\\\",Space,Str "\\hline",Space,Str "\\end{tabular}"]
+,Header 1 ("special-characters",[],[]) [Str "Special",Space,Str "Characters"]
+,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Str "unicode:"]
+,BulletList
+ [[Para [Str "I",Space,Str "hat:",Space,Str "\206"]]
+ ,[Para [Str "o",Space,Str "umlaut:",Space,Str "\246"]]
+ ,[Para [Str "section:",Space,Str "\167"]]
+ ,[Para [Str "set",Space,Str "membership:",Space,Str "elem"]]
+ ,[Para [Str "copyright:",Space,Str "\169"]]]
+,Para [Str "AT&T",Space,Str "has",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "their",Space,Str "name."]
+,Para [Str "AT&T",Space,Str "is",Space,Str "another",Space,Str "way",Space,Str "to",Space,Str "write",Space,Str "it."]
+,Para [Str "This",Space,Str "&",Space,Str "that."]
+,Para [Str "4",Space,Str "<",Space,Str "5."]
+,Para [Str "6",Space,Str ">",Space,Str "5."]
+,Para [Str "Backslash:",Space,Str "\\"]
+,Para [Str "Backtick:",Space,Str "`"]
+,Para [Str "Asterisk:",Space,Str "*"]
+,Para [Str "Underscore:",Space,Str "_"]
+,Para [Str "Left",Space,Str "brace:",Space,Str "{"]
+,Para [Str "Right",Space,Str "brace:",Space,Str "}"]
+,Para [Str "Left",Space,Str "bracket:",Space,Str "["]
+,Para [Str "Right",Space,Str "bracket:",Space,Str "]"]
+,Para [Str "Left",Space,Str "paren:",Space,Str "("]
+,Para [Str "Right",Space,Str "paren:",Space,Str ")"]
+,Para [Str "Greater-than:",Space,Str ">"]
+,Para [Str "Hash:",Space,Str "#"]
+,Para [Str "Period:",Space,Str "."]
+,Para [Str "Bang:",Space,Str "!"]
+,Para [Str "Plus:",Space,Str "+"]
+,Para [Str "Minus:",Space,Str "-"]
+,Header 1 ("links",[],[]) [Str "Links"]
+,Header 2 ("explicit",[],[]) [Str "Explicit"]
+,Para [Str "Just",Space,Str "a",SoftBreak,Link ("",[],[]) [Str "URL"] ("/url/",""),Str "."]
+,Para [Link ("",[],[]) [Str "URL",SoftBreak,Str "and",Space,Str "title"] ("/url/","title"),Str "."]
+,Para [Link ("",[],[]) [Str "URL",SoftBreak,Str "and",Space,Str "title"] ("/url/","title preceded by two spaces"),Str "."]
+,Para [Link ("",[],[]) [Str "URL",SoftBreak,Str "and",Space,Str "title"] ("/url/","title preceded by a tab"),Str "."]
+,Para [Link ("",[],[]) [Str "URL",SoftBreak,Str "and",Space,Str "title"] ("/url/","title with \"quotes\" in it")]
+,Para [Link ("",[],[]) [Str "URL",SoftBreak,Str "and",Space,Str "title"] ("/url/","title with single quotes")]
+,Para [Str "Email",Space,Str "link",Space,Str "(nobody",Space,Str "[at]",Space,Str "nowhere.net)"]
+,Para [Link ("",[],[]) [Str "Empty"] ("",""),Str "."]
+,Header 2 ("reference",[],[]) [Str "Reference"]
+,Para [Str "Foo",SoftBreak,Link ("",[],[]) [Str "bar"] ("/url/",""),Str "."]
+,Para [Str "Foo",SoftBreak,Link ("",[],[]) [Str "bar"] ("/url/",""),Str "."]
+,Para [Str "Foo",SoftBreak,Link ("",[],[]) [Str "bar"] ("/url/",""),Str "."]
+,Para [Str "With",Space,Link ("",[],[]) [Str "embedded",SoftBreak,Str "[brackets]"] ("/url/",""),Str "."]
+,Para [Link ("",[],[]) [Str "b"] ("/url/",""),Space,Str "by",SoftBreak,Str "itself",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "link."]
+,Para [Str "Indented",SoftBreak,Link ("",[],[]) [Str "once"] ("/url",""),Str "."]
+,Para [Str "Indented",SoftBreak,Link ("",[],[]) [Str "twice"] ("/url",""),Str "."]
+,Para [Str "Indented",SoftBreak,Link ("",[],[]) [Str "thrice"] ("/url",""),Str "."]
+,Para [Str "This",Space,Str "should",Space,Str "[not]",Space,Str "be",Space,Str "a",Space,Str "link."]
+,CodeBlock ("",[],[]) "[not]: /url"
+,Para [Str "Foo",SoftBreak,Link ("",[],[]) [Str "bar"] ("/url/","Title with \"quotes\" inside"),Str "."]
+,Para [Str "Foo",SoftBreak,Link ("",[],[]) [Str "biz"] ("/url/","Title with \"quote\" inside"),Str "."]
+,Header 2 ("with-ampersands",[],[]) [Str "With",Space,Str "ampersands"]
+,Para [Str "Here's",Space,Str "a",SoftBreak,Link ("",[],[]) [Str "link",SoftBreak,Str "with",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "the",Space,Str "URL"] ("http://example.com/?foo=1&bar=2",""),Str "."]
+,Para [Str "Here's",Space,Str "a",Space,Str "link",Space,Str "with",Space,Str "an",Space,Str "amersand",Space,Str "in",Space,Str "the",Space,Str "link",Space,Str "text:",SoftBreak,Link ("",[],[]) [Str "AT&T"] ("http://att.com/","AT&T"),Str "."]
+,Para [Str "Here's",Space,Str "an",SoftBreak,Link ("",[],[]) [Str "inline",SoftBreak,Str "link"] ("/script?foo=1&bar=2",""),Str "."]
+,Para [Str "Here's",Space,Str "an",SoftBreak,Link ("",[],[]) [Str "inline",SoftBreak,Str "link",Space,Str "in",Space,Str "pointy",Space,Str "braces"] ("/script?foo=1&bar=2",""),Str "."]
+,Header 2 ("autolinks",[],[]) [Str "Autolinks"]
+,Para [Str "With",Space,Str "an",Space,Str "ampersand:",SoftBreak,Link ("",[],[]) [Str "http://example.com/?foo=1&bar=2"] ("http://example.com/?foo=1&bar=2","")]
+,BulletList
+ [[Para [Str "In",Space,Str "a",Space,Str "list?"]]
+ ,[Para [Link ("",[],[]) [Str "http://example.com/"] ("http://example.com/","")]]
+ ,[Para [Str "It",Space,Str "should."]]]
+,Para [Str "An",Space,Str "e-mail",Space,Str "address:",Space,Str "nobody",Space,Str "[at]",Space,Str "nowhere.net"]
+,BlockQuote
+ [Para [Str "Blockquoted:",SoftBreak,Link ("",[],[]) [Str "http://example.com/"] ("http://example.com/","")]]
+,Para [Str "Auto-links",Space,Str "should",Space,Str "not",Space,Str "occur",Space,Str "here:",SoftBreak,Code ("",[],[]) "<http://example.com/>"]
+,CodeBlock ("",[],[]) "or here: <http://example.com/>"
+,Header 1 ("images",[],[]) [Str "Images"]
+,Para [Str "From",Space,Str "\"Voyage",Space,Str "dans",Space,Str "la",Space,Str "Lune\"",Space,Str "by",Space,Str "Georges",Space,Str "Melies",Space,Str "(1902):"]
+,Para [Image ("",[],[]) [] ("lalune.jpg","Voyage dans la Lune")]
+,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "movie",SoftBreak,Image ("",[],[]) [] ("movie.jpg",""),SoftBreak,Str "icon."]
+,Header 1 ("footnotes",[],[]) [Str "Footnotes"]
+,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "footnote",Space,Str "reference",Link ("",[],[]) [Str "(1)"] ("#note_1",""),Str ",",SoftBreak,Str "and",SoftBreak,Str "another",Link ("",[],[]) [Str "(longnote)"] ("#note_longnote",""),Str ".",SoftBreak,Str "This",Space,Str "should",Space,Emph [Str "not"],Space,Str "be",Space,Str "a",Space,Str "footnote",Space,Str "reference,",Space,Str "because",Space,Str "it",SoftBreak,Str "contains",Space,Str "a",Space,Str "space^(my",Space,Str "note)."]
+,Para [Link ("",[],[]) [Str "(1)"] ("#ref_1",""),Space,Str "Here",Space,Str "is",Space,Str "the",Space,Str "footnote.",Space,Str "It",Space,Str "can",SoftBreak,Str "go",Space,Str "anywhere",Space,Str "in",Space,Str "the",Space,Str "document,",Space,Str "not",Space,Str "just",Space,Str "at",Space,Str "the",Space,Str "end."]
+,Para [Link ("",[],[]) [Str "(longnote)"] ("#ref_longnote",""),Space,Str "Here's",SoftBreak,Str "the",Space,Str "other",Space,Str "note.",Space,Str "This",Space,Str "one",Space,Str "contains",Space,Str "multiple",Space,Str "blocks."]
+,Para [Str "Caret",Space,Str "characters",Space,Str "are",Space,Str "used",Space,Str "to",Space,Str "indicate",Space,Str "that",Space,Str "the",Space,Str "blocks",Space,Str "all",Space,Str "belong",Space,Str "to",SoftBreak,Str "a",Space,Str "single",Space,Str "footnote",Space,Str "(as",Space,Str "with",Space,Str "block",Space,Str "quotes)."]
+,CodeBlock ("",[],[]) "  { <code> }"
+,Para [Str "If",Space,Str "you",Space,Str "want,",Space,Str "you",Space,Str "can",Space,Str "use",Space,Str "a",Space,Str "caret",Space,Str "at",Space,Str "the",Space,Str "beginning",Space,Str "of",Space,Str "every",Space,Str "line,",Space,Str "as",SoftBreak,Str "with",Space,Str "blockquotes,",Space,Str "but",Space,Str "all",Space,Str "that",Space,Str "you",Space,Str "need",Space,Str "is",Space,Str "a",Space,Str "caret",Space,Str "at",Space,Str "the",Space,Str "beginning",SoftBreak,Str "of",Space,Str "the",Space,Str "first",Space,Str "line",Space,Str "of",Space,Str "the",Space,Str "block",Space,Str "and",Space,Str "any",Space,Str "preceding",Space,Str "blank",Space,Str "lines."]
+,Para [Str "text",Space,Emph [Str "Leading",Space,Str "space"]]
+,Para [Emph [Str "Trailing",Space,Str "space"],Space,Str "text"]
+,Para [Str "text",Space,Emph [Str "Leading",Space,Str "spaces"]]
+,Para [Emph [Str "Trailing",Space,Str "spaces"],Space,Str "text"]
+,Header 1 ("tables",[],[]) [Str "Tables"]
+,Header 2 ("tables-with-headers",[],[]) [Str "Tables",Space,Str "with",Space,Str "Headers"]
+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
+ [[Para [Str "X"]]
+ ,[Para [Str "Y"]]
+ ,[Para [Str "Z"]]]
+ [[[Para [Str "1"]]
+  ,[Para [Str "2"]]
+  ,[Para [Str "3"]]]
+ ,[[Para [Str "4"]]
+  ,[Para [Str "5"]]
+  ,[Para [Str "6"]]]]
+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
+ [[Para [Str "X"]]
+ ,[Para [Str "Y"]]
+ ,[Para [Str "Z"]]]
+ [[[Para [Str "1"]]
+  ,[Para [Str "2"]]
+  ,[Para [Str "3"]]]
+ ,[[Para [Str "4"]]
+  ,[Para [Str "5"]]
+  ,[Para [Str "6"]]]]
+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
+ [[Para [Str "X"]]
+ ,[Para [Str "Y"]]
+ ,[Para [Str "Z"]]]
+ [[[Para [Str "1"]]
+  ,[Para [Str "2"]]
+  ,[Para [Str "3"]]]
+ ,[[Para [Str "4"]]
+  ,[Para [Str "5"]]
+  ,[Para [Str "6"]]]]
+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
+ [[Para [Str "X"]]
+ ,[Para [Str "Y"]]
+ ,[Para [Str "Z"]]]
+ [[[Para [Str "1"]]
+  ,[Para [Str "2"]]
+  ,[Para [Str "3"]]]
+ ,[[Para [Str "4"]]
+  ,[Para [Str "5"]]
+  ,[Para [Str "6"]]]]
+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
+ [[Para [Str "X"]]
+ ,[Para [Str "Y"]]
+ ,[Para [Str "Z"]]]
+ [[[Para [Str "1"]]
+  ,[Para [Str "2"]]
+  ,[Para [Str "3"]]]
+ ,[[Para [Str "4"]]
+  ,[Para [Str "5"]]
+  ,[Para [Str "6"]]]]
+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
+ [[Para [Str "X"]]
+ ,[Para [Str "Y"]]
+ ,[Para [Str "Z"]]]
+ [[[Para [Str "1"]]
+  ,[Para [Str "2"]]
+  ,[Para [Str "3"]]]
+ ,[[Para [Str "4"]]
+  ,[Para [Str "5"]]
+  ,[Para [Str "6"]]]]
+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
+ [[Para [Str "X"]]
+ ,[Para [Str "Y"]]
+ ,[Para [Str "Z"]]]
+ [[[Para [Str "1"]]
+  ,[Para [Str "2"]]
+  ,[Para [Str "3"]]]
+ ,[[Para [Str "4"]]
+  ,[Para [Str "5"]]
+  ,[Para [Str "6"]]]]
+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
+ [[Para [Str "X"]]
+ ,[Para [Str "Y"]]
+ ,[Para [Str "Z"]]]
+ [[[Para [Str "1"]]
+  ,[Para [Str "2"]]
+  ,[Para [Str "3"]]]
+ ,[[Para [Str "4"]]
+  ,[Para [Str "5"]]
+  ,[Para [Str "6"]]]]
+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
+ [[Para [Str "X"]]
+ ,[Para [Str "Y"]]
+ ,[Para [Str "Z"]]]
+ [[[Para [Str "1"]]
+  ,[Para [Str "2"]]
+  ,[Para [Str "3"]]]
+ ,[[Para [Str "4"]]
+  ,[Para [Str "5"]]
+  ,[Para [Str "6"]]]]
+,Header 2 ("tables-without-headers",[],[]) [Str "Tables",Space,Str "without",Space,Str "Headers"]
+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
+ [[]
+ ,[]
+ ,[]]
+ [[[Para [Str "1"]]
+  ,[Para [Str "2"]]
+  ,[Para [Str "3"]]]
+ ,[[Para [Str "4"]]
+  ,[Para [Str "5"]]
+  ,[Para [Str "6"]]]]
+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
+ [[]
+ ,[]
+ ,[]]
+ [[[Para [Str "1"]]
+  ,[Para [Str "2"]]
+  ,[Para [Str "3"]]]
+ ,[[Para [Str "4"]]
+  ,[Para [Str "5"]]
+  ,[Para [Str "6"]]]]
+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
+ [[]
+ ,[]
+ ,[]]
+ [[[Para [Str "1"]]
+  ,[Para [Str "2"]]
+  ,[Para [Str "3"]]]
+ ,[[Para [Str "4"]]
+  ,[Para [Str "5"]]
+  ,[Para [Str "6"]]]]
+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
+ [[]
+ ,[]
+ ,[]]
+ [[[Para [Str "1"]]
+  ,[Para [Str "2"]]
+  ,[Para [Str "3"]]]
+ ,[[Para [Str "4"]]
+  ,[Para [Str "5"]]
+  ,[Para [Str "6"]]]]
+,Header 2 ("empty-tables",[],[]) [Str "Empty",Space,Str "Tables"]
+,Para [Str "This",Space,Str "section",Space,Str "should",Space,Str "be",Space,Str "empty."]]
diff --git a/test/jats-reader.xml b/test/jats-reader.xml
new file mode 100644
--- /dev/null
+++ b/test/jats-reader.xml
@@ -0,0 +1,1785 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Publishing DTD v1.0 20120330//EN"
+                  "JATS-journalpublishing1.dtd">
+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.0" article-type="other">
+<front>
+<journal-meta>
+<journal-title-group>
+</journal-title-group>
+<publisher>
+<publisher-name></publisher-name>
+</publisher>
+</journal-meta>
+<article-meta>
+<title-group>
+<article-title>Pandoc Test Suite</article-title>
+</title-group>
+<contrib-group>
+  <contrib contrib-type="author">
+    <name>
+      <surname>MacFarlane</surname>
+      <given-names>John</given-names>
+    </name>
+  <contrib contrib-type="author">
+    <name>
+      <surname>Anonymous</surname>
+    </name>
+  </contrib>
+</contrib-group>
+</article-meta>
+</front>
+<body>
+<p>
+  This is a set of tests for pandoc. Most of them are adapted from John
+  Gruber's markdown test suite.
+</p>
+<sec id="headers">
+  <title>Headers</title>
+  <sec id="level-2-with-an-embedded-link">
+    <title>Level 2 with an
+    <ext-link ext-link-type="uri" xlink:href="/url">embedded
+    link</ext-link></title>
+    <sec id="level-3-with-emphasis">
+      <title>Level 3 with <italic>emphasis</italic></title>
+      <sec id="level-4">
+        <title>Level 4</title>
+        <sec id="level-5">
+          <title>Level 5</title>
+        </sec>
+      </sec>
+    </sec>
+  </sec>
+</sec>
+<sec id="level-1">
+  <title>Level 1</title>
+  <sec id="level-2-with-emphasis">
+    <title>Level 2 with <italic>emphasis</italic></title>
+    <sec id="level-3">
+      <title>Level 3</title>
+      <p>
+        with no blank line
+      </p>
+    </sec>
+  </sec>
+  <sec id="level-2">
+    <title>Level 2</title>
+    <p>
+      with no blank line
+    </p>
+  </sec>
+</sec>
+<sec id="paragraphs">
+  <title>Paragraphs</title>
+  <p>
+    Here's a regular paragraph.
+  </p>
+  <p>
+    In Markdown 1.0.0 and earlier. Version 8. This line turns into a
+    list item. Because a hard-wrapped line in the middle of a paragraph
+    looked like a list item.
+  </p>
+  <p>
+    Here's one with a bullet. * criminey.
+  </p>
+  <p>
+    There should be a hard line break<break />here.
+  </p>
+</sec>
+<sec id="block-quotes">
+  <title>Block Quotes</title>
+  <p>
+    E-mail style:
+  </p>
+  <disp-quote>
+    <p>
+      This is a block quote. It is pretty short.
+    </p>
+  </disp-quote>
+  <disp-quote>
+    <p>
+      Code in a block quote:
+    </p>
+    <preformat>sub status {
+    print &quot;working&quot;;
+}</preformat>
+    <p>
+      A list:
+    </p>
+    <list list-type="order">
+      <list-item>
+        <p>
+          item one
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          item two
+        </p>
+      </list-item>
+    </list>
+    <p>
+      Nested block quotes:
+    </p>
+    <disp-quote>
+      <p>
+        nested
+      </p>
+    </disp-quote>
+    <disp-quote>
+      <p>
+        nested
+      </p>
+    </disp-quote>
+  </disp-quote>
+  <p>
+    This should not be a block quote: 2 &gt; 1.
+  </p>
+  <p>
+    Box-style:
+  </p>
+  <disp-quote>
+    <p>
+      Example:
+    </p>
+    <preformat>sub status {
+    print &quot;working&quot;;
+}</preformat>
+  </disp-quote>
+  <disp-quote>
+    <list list-type="order">
+      <list-item>
+        <p>
+          do laundry
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          take out the trash
+        </p>
+      </list-item>
+    </list>
+  </disp-quote>
+  <p>
+    Here's a nested one:
+  </p>
+  <disp-quote>
+    <p>
+      Joe said:
+    </p>
+    <disp-quote>
+      <p>
+        Don't quote me.
+      </p>
+    </disp-quote>
+  </disp-quote>
+  <p>
+    And a following paragraph.
+  </p>
+</sec>
+<sec id="code-blocks">
+  <title>Code Blocks</title>
+  <p>
+    Code:
+  </p>
+  <preformat>---- (should be four hyphens)
+
+sub status {
+    print &quot;working&quot;;
+}
+
+this code block is indented by one tab</preformat>
+  <p>
+    And:
+  </p>
+  <preformat>    this code block is indented by two tabs
+
+These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
+</sec>
+<sec id="lists">
+  <title>Lists</title>
+  <sec id="unordered">
+    <title>Unordered</title>
+    <p>
+      Asterisks tight:
+    </p>
+    <list list-type="bullet">
+      <list-item>
+        <p>
+          asterisk 1
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          asterisk 2
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          asterisk 3
+        </p>
+      </list-item>
+    </list>
+    <p>
+      Asterisks loose:
+    </p>
+    <list list-type="bullet">
+      <list-item>
+        <p>
+          asterisk 1
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          asterisk 2
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          asterisk 3
+        </p>
+      </list-item>
+    </list>
+    <p>
+      Pluses tight:
+    </p>
+    <list list-type="bullet">
+      <list-item>
+        <p>
+          Plus 1
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          Plus 2
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          Plus 3
+        </p>
+      </list-item>
+    </list>
+    <p>
+      Pluses loose:
+    </p>
+    <list list-type="bullet">
+      <list-item>
+        <p>
+          Plus 1
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          Plus 2
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          Plus 3
+        </p>
+      </list-item>
+    </list>
+    <p>
+      Minuses tight:
+    </p>
+    <list list-type="bullet">
+      <list-item>
+        <p>
+          Minus 1
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          Minus 2
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          Minus 3
+        </p>
+      </list-item>
+    </list>
+    <p>
+      Minuses loose:
+    </p>
+    <list list-type="bullet">
+      <list-item>
+        <p>
+          Minus 1
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          Minus 2
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          Minus 3
+        </p>
+      </list-item>
+    </list>
+  </sec>
+  <sec id="ordered">
+    <title>Ordered</title>
+    <p>
+      Tight:
+    </p>
+    <list list-type="order">
+      <list-item>
+        <p>
+          First
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          Second
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          Third
+        </p>
+      </list-item>
+    </list>
+    <p>
+      and:
+    </p>
+    <list list-type="order">
+      <list-item>
+        <p>
+          One
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          Two
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          Three
+        </p>
+      </list-item>
+    </list>
+    <p>
+      Loose using tabs:
+    </p>
+    <list list-type="order">
+      <list-item>
+        <p>
+          First
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          Second
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          Third
+        </p>
+      </list-item>
+    </list>
+    <p>
+      and using spaces:
+    </p>
+    <list list-type="order">
+      <list-item>
+        <p>
+          One
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          Two
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          Three
+        </p>
+      </list-item>
+    </list>
+    <p>
+      Multiple paragraphs:
+    </p>
+    <list list-type="order">
+      <list-item>
+        <p>
+          Item 1, graf one.
+        </p>
+        <p>
+          Item 1. graf two. The quick brown fox jumped over the lazy
+          dog's back.
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          Item 2.
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          Item 3.
+        </p>
+      </list-item>
+    </list>
+    <p>
+      List styles:
+    </p>
+    <list list-type="order"></list>
+    <list list-type="roman-lower"></list>
+  </sec>
+  <sec id="nested">
+    <title>Nested</title>
+    <list list-type="bullet">
+      <list-item>
+        <p>
+          Tab
+        </p>
+        <list list-type="bullet">
+          <list-item>
+            <p>
+              Tab
+            </p>
+            <list list-type="bullet">
+              <list-item>
+                <p>
+                  Tab
+                </p>
+              </list-item>
+            </list>
+          </list-item>
+        </list>
+      </list-item>
+    </list>
+    <p>
+      Here's another:
+    </p>
+    <list list-type="order">
+      <list-item>
+        <p>
+          First
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          Second:
+        </p>
+        <list list-type="bullet">
+          <list-item>
+            <p>
+              Fee
+            </p>
+          </list-item>
+          <list-item>
+            <p>
+              Fie
+            </p>
+          </list-item>
+          <list-item>
+            <p>
+              Foe
+            </p>
+          </list-item>
+        </list>
+      </list-item>
+      <list-item>
+        <p>
+          Third
+        </p>
+      </list-item>
+    </list>
+    <p>
+      Same thing but with paragraphs:
+    </p>
+    <list list-type="order">
+      <list-item>
+        <p>
+          First
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          Second:
+        </p>
+        <list list-type="bullet">
+          <list-item>
+            <p>
+              Fee
+            </p>
+          </list-item>
+          <list-item>
+            <p>
+              Fie
+            </p>
+          </list-item>
+          <list-item>
+            <p>
+              Foe
+            </p>
+          </list-item>
+        </list>
+      </list-item>
+      <list-item>
+        <p>
+          Third
+        </p>
+      </list-item>
+    </list>
+  </sec>
+  <sec id="tabs-and-spaces">
+    <title>Tabs and spaces</title>
+    <list list-type="bullet">
+      <list-item>
+        <p>
+          this is a list item indented with tabs
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          this is a list item indented with spaces
+        </p>
+        <list list-type="bullet">
+          <list-item>
+            <p>
+              this is an example list item indented with tabs
+            </p>
+          </list-item>
+          <list-item>
+            <p>
+              this is an example list item indented with spaces
+            </p>
+          </list-item>
+        </list>
+      </list-item>
+    </list>
+  </sec>
+  <sec id="fancy-list-markers">
+    <title>Fancy list markers</title>
+    <p>
+      Autonumbering:
+    </p>
+    <list list-type="order">
+      <list-item>
+        <p>
+          Autonumber.
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          More.
+        </p>
+        <list list-type="order">
+          <list-item>
+            <p>
+              Nested.
+            </p>
+          </list-item>
+        </list>
+      </list-item>
+    </list>
+  </sec>
+  <sec id="definition">
+    <title>Definition</title>
+    <def-list>
+      <def-item>
+        <term>
+          Violin
+        </term>
+        <def>
+          <p>
+            Stringed musical instrument.
+          </p>
+          <p>
+            Torture device.
+          </p>
+        </def>
+      </def-item>
+      <def-item>
+        <term>
+          Cello<break />Violoncello
+        </term>
+        <def>
+          <p>
+            Low-voiced stringed instrument.
+          </p>
+        </def>
+      </def-item>
+    </def-list>
+  </sec>
+</sec>
+<sec id="inline-markup">
+  <title>Inline Markup</title>
+  <p>
+    This is <italic>emphasized</italic>, and so <italic>is
+    this</italic>.
+  </p>
+  <p>
+    This is <bold role="strong">strong</bold>, and so
+    <bold role="strong">is this</bold>.
+  </p>
+  <p>
+    Empty <bold role="strong"></bold> and <italic></italic>.
+  </p>
+  <p>
+    An
+    <italic><ext-link ext-link-type="uri" xlink:href="/url">emphasized
+    link</ext-link></italic>.
+  </p>
+  <p>
+    <bold role="strong"><italic>This is strong and em.</italic></bold>
+  </p>
+  <p>
+    So is <bold role="strong"><italic>this</italic></bold> word.
+  </p>
+  <p>
+    <bold role="strong"><italic>This is strong and em.</italic></bold>
+  </p>
+  <p>
+    So is <bold role="strong"><italic>this</italic></bold> word.
+  </p>
+  <p>
+    This is code: <monospace>&gt;</monospace>, <monospace>$</monospace>,
+    <monospace>\</monospace>, <monospace>\$</monospace>,
+    <monospace>&lt;html&gt;</monospace>.
+  </p>
+  <p>
+    This is <sc role="smallcaps">small caps</sc>.
+  </p>
+  <p>
+    These are all underlined: foo and bar.
+  </p>
+  <p>
+    These are all strikethrough: <strike>foo</strike>,
+    <strike>bar</strike>, and <strike>baz</strike>.
+  </p>
+</sec>
+<sec id="smart-quotes-ellipses-dashes">
+  <title>Smart quotes, ellipses, dashes</title>
+  <p>
+    &quot;Hello,&quot; said the spider. &quot;'Shelob' is my name.&quot;
+  </p>
+  <p>
+    'A', 'B', and 'C' are letters.
+  </p>
+  <p>
+    'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'
+  </p>
+  <p>
+    'He said, &quot;I want to go.&quot;' Were you alive in the 70's?
+  </p>
+  <p>
+    Here is some quoted '<monospace>code</monospace>' and a
+    &quot;<ext-link ext-link-type="uri" xlink:href="http://example.com/?foo=1&amp;bar=2">quoted
+    link</ext-link>&quot;.
+  </p>
+  <p>
+    Some dashes: one---two --- three--four -- five.
+  </p>
+  <p>
+    Dashes between numbers: 5-7, 255-66, 1987-1999.
+  </p>
+  <p>
+    Ellipses...and. . .and . . . .
+  </p>
+</sec>
+<sec id="latex">
+  <title>LaTeX</title>
+  <list list-type="bullet">
+    <list-item>
+      <p>
+        \cite[22-23]{smith.1899}
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        \doublespacing
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        $2+2=4$
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        $x \in y$
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        $\alpha \wedge \omega$
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        $223$
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        $p$-Tree
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        $\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        Here's one that has a line break in it: $\alpha + \omega \times
+        x^2$.
+      </p>
+    </list-item>
+  </list>
+  <p>
+    These shouldn't be math:
+  </p>
+  <list list-type="bullet">
+    <list-item>
+      <p>
+        To get the famous equation, write
+        <monospace>$e = mc^2$</monospace>.
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        $22,000 is a <italic>lot</italic> of money. So is $34,000. (It
+        worked if &quot;lot&quot; is emphasized.)
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        Escaped <monospace>$</monospace>: $73 <italic>this should be
+        emphasized</italic> 23$.
+      </p>
+    </list-item>
+  </list>
+  <p>
+    Here's a LaTeX table:
+  </p>
+  <p>
+    \begin{tabular}{|l|l|}\hline Animal &amp; Number \\ \hline Dog &amp;
+    2 \\ Cat &amp; 1 \\ \hline \end{tabular}
+  </p>
+</sec>
+<sec id="special-characters">
+  <title>Special Characters</title>
+  <p>
+    Here is some unicode:
+  </p>
+  <list list-type="bullet">
+    <list-item>
+      <p>
+        I hat: Î
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        o umlaut: ö
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        section: §
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        set membership: elem
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        copyright: ©
+      </p>
+    </list-item>
+  </list>
+  <p>
+    AT&amp;T has an ampersand in their name.
+  </p>
+  <p>
+    AT&amp;T is another way to write it.
+  </p>
+  <p>
+    This &amp; that.
+  </p>
+  <p>
+    4 &lt; 5.
+  </p>
+  <p>
+    6 &gt; 5.
+  </p>
+  <p>
+    Backslash: \
+  </p>
+  <p>
+    Backtick: `
+  </p>
+  <p>
+    Asterisk: *
+  </p>
+  <p>
+    Underscore: _
+  </p>
+  <p>
+    Left brace: {
+  </p>
+  <p>
+    Right brace: }
+  </p>
+  <p>
+    Left bracket: [
+  </p>
+  <p>
+    Right bracket: ]
+  </p>
+  <p>
+    Left paren: (
+  </p>
+  <p>
+    Right paren: )
+  </p>
+  <p>
+    Greater-than: &gt;
+  </p>
+  <p>
+    Hash: #
+  </p>
+  <p>
+    Period: .
+  </p>
+  <p>
+    Bang: !
+  </p>
+  <p>
+    Plus: +
+  </p>
+  <p>
+    Minus: -
+  </p>
+</sec>
+<sec id="links">
+  <title>Links</title>
+  <sec id="explicit">
+    <title>Explicit</title>
+    <p>
+      Just a
+      <ext-link ext-link-type="uri" xlink:href="/url/">URL</ext-link>.
+    </p>
+    <p>
+      <ext-link ext-link-type="uri" xlink:href="/url/" xlink:title="title">URL
+      and title</ext-link>.
+    </p>
+    <p>
+      <ext-link ext-link-type="uri" xlink:href="/url/" xlink:title="title preceded by two spaces">URL
+      and title</ext-link>.
+    </p>
+    <p>
+      <ext-link ext-link-type="uri" xlink:href="/url/" xlink:title="title preceded by a tab">URL
+      and title</ext-link>.
+    </p>
+    <p>
+      <ext-link ext-link-type="uri" xlink:href="/url/" xlink:title="title with &quot;quotes&quot; in it">URL
+      and title</ext-link>
+    </p>
+    <p>
+      <ext-link ext-link-type="uri" xlink:href="/url/" xlink:title="title with single quotes">URL
+      and title</ext-link>
+    </p>
+    <p>
+      Email link (nobody [at] nowhere.net)
+    </p>
+    <p>
+      <ext-link ext-link-type="uri" xlink:href="">Empty</ext-link>.
+    </p>
+  </sec>
+  <sec id="reference">
+    <title>Reference</title>
+    <p>
+      Foo
+      <ext-link ext-link-type="uri" xlink:href="/url/">bar</ext-link>.
+    </p>
+    <p>
+      Foo
+      <ext-link ext-link-type="uri" xlink:href="/url/">bar</ext-link>.
+    </p>
+    <p>
+      Foo
+      <ext-link ext-link-type="uri" xlink:href="/url/">bar</ext-link>.
+    </p>
+    <p>
+      With <ext-link ext-link-type="uri" xlink:href="/url/">embedded
+      [brackets]</ext-link>.
+    </p>
+    <p>
+      <ext-link ext-link-type="uri" xlink:href="/url/">b</ext-link> by
+      itself should be a link.
+    </p>
+    <p>
+      Indented
+      <ext-link ext-link-type="uri" xlink:href="/url">once</ext-link>.
+    </p>
+    <p>
+      Indented
+      <ext-link ext-link-type="uri" xlink:href="/url">twice</ext-link>.
+    </p>
+    <p>
+      Indented
+      <ext-link ext-link-type="uri" xlink:href="/url">thrice</ext-link>.
+    </p>
+    <p>
+      This should [not] be a link.
+    </p>
+    <preformat>[not]: /url</preformat>
+    <p>
+      Foo
+      <ext-link ext-link-type="uri" xlink:href="/url/" xlink:title="Title with &quot;quotes&quot; inside">bar</ext-link>.
+    </p>
+    <p>
+      Foo
+      <ext-link ext-link-type="uri" xlink:href="/url/" xlink:title="Title with &quot;quote&quot; inside">biz</ext-link>.
+    </p>
+  </sec>
+  <sec id="with-ampersands">
+    <title>With ampersands</title>
+    <p>
+      Here's a
+      <ext-link ext-link-type="uri" xlink:href="http://example.com/?foo=1&amp;bar=2">link
+      with an ampersand in the URL</ext-link>.
+    </p>
+    <p>
+      Here's a link with an amersand in the link text:
+      <ext-link ext-link-type="uri" xlink:href="http://att.com/" xlink:title="AT&amp;T">AT&amp;T</ext-link>.
+    </p>
+    <p>
+      Here's an
+      <ext-link ext-link-type="uri" xlink:href="/script?foo=1&amp;bar=2">inline
+      link</ext-link>.
+    </p>
+    <p>
+      Here's an
+      <ext-link ext-link-type="uri" xlink:href="/script?foo=1&amp;bar=2">inline
+      link in pointy braces</ext-link>.
+    </p>
+  </sec>
+  <sec id="autolinks">
+    <title>Autolinks</title>
+    <p>
+      With an ampersand:
+      <ext-link ext-link-type="uri" xlink:href="http://example.com/?foo=1&amp;bar=2">http://example.com/?foo=1&amp;bar=2</ext-link>
+    </p>
+    <list list-type="bullet">
+      <list-item>
+        <p>
+          In a list?
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          <ext-link ext-link-type="uri" xlink:href="http://example.com/">http://example.com/</ext-link>
+        </p>
+      </list-item>
+      <list-item>
+        <p>
+          It should.
+        </p>
+      </list-item>
+    </list>
+    <p>
+      An e-mail address: nobody [at] nowhere.net
+    </p>
+    <disp-quote>
+      <p>
+        Blockquoted:
+        <ext-link ext-link-type="uri" xlink:href="http://example.com/">http://example.com/</ext-link>
+      </p>
+    </disp-quote>
+    <p>
+      Auto-links should not occur here:
+      <monospace>&lt;http://example.com/&gt;</monospace>
+    </p>
+    <preformat>or here: &lt;http://example.com/&gt;</preformat>
+  </sec>
+</sec>
+<sec id="images">
+  <title>Images</title>
+  <p>
+    From &quot;Voyage dans la Lune&quot; by Georges Melies (1902):
+  </p>
+  <p>
+    <inline-graphic mimetype="image" mime-subtype="jpeg" xlink:href="lalune.jpg" xlink:title="Voyage dans la Lune" />
+  </p>
+  <p>
+    Here is a movie
+    <inline-graphic mimetype="image" mime-subtype="jpeg" xlink:href="movie.jpg" />
+    icon.
+  </p>
+</sec>
+<sec id="footnotes">
+  <title>Footnotes</title>
+  <p>
+    Here is a footnote reference<xref alt="(1)" rid="note_1">(1)</xref>,
+    and
+    another<xref alt="(longnote)" rid="note_longnote">(longnote)</xref>.
+    This should <italic>not</italic> be a footnote reference, because it
+    contains a space^(my note).
+  </p>
+  <p>
+    <xref alt="(1)" rid="ref_1">(1)</xref> Here is the footnote. It can
+    go anywhere in the document, not just at the end.
+  </p>
+  <p>
+    <xref alt="(longnote)" rid="ref_longnote">(longnote)</xref> Here's
+    the other note. This one contains multiple blocks.
+  </p>
+  <p>
+    Caret characters are used to indicate that the blocks all belong to
+    a single footnote (as with block quotes).
+  </p>
+  <preformat>  { &lt;code&gt; }</preformat>
+  <p>
+    If you want, you can use a caret at the beginning of every line, as
+    with blockquotes, but all that you need is a caret at the beginning
+    of the first line of the block and any preceding blank lines.
+  </p>
+  <p>
+    text <italic>Leading space</italic>
+  </p>
+  <p>
+    <italic>Trailing space</italic> text
+  </p>
+  <p>
+    text <italic>Leading spaces</italic>
+  </p>
+  <p>
+    <italic>Trailing spaces</italic> text
+  </p>
+</sec>
+<sec id="tables">
+  <title>Tables</title>
+  <sec id="tables-with-headers">
+    <title>Tables with Headers</title>
+    <table>
+      <col align="left" />
+      <col align="left" />
+      <col align="left" />
+      <thead>
+        <tr>
+          <th>
+            <p>
+              X
+            </p>
+          </th>
+          <th>
+            <p>
+              Y
+            </p>
+          </th>
+          <th>
+            <p>
+              Z
+            </p>
+          </th>
+        </tr>
+      </thead>
+      <tbody>
+        <tr>
+          <td>
+            <p>
+              1
+            </p>
+          </td>
+          <td>
+            <p>
+              2
+            </p>
+          </td>
+          <td>
+            <p>
+              3
+            </p>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <p>
+              4
+            </p>
+          </td>
+          <td>
+            <p>
+              5
+            </p>
+          </td>
+          <td>
+            <p>
+              6
+            </p>
+          </td>
+        </tr>
+      </tbody>
+    </table>
+    <table>
+      <col align="left" />
+      <col align="left" />
+      <col align="left" />
+      <thead>
+        <tr>
+          <th>
+            <p>
+              X
+            </p>
+          </th>
+          <th>
+            <p>
+              Y
+            </p>
+          </th>
+          <th>
+            <p>
+              Z
+            </p>
+          </th>
+        </tr>
+      </thead>
+      <tbody>
+        <tr>
+          <td>
+            <p>
+              1
+            </p>
+          </td>
+          <td>
+            <p>
+              2
+            </p>
+          </td>
+          <td>
+            <p>
+              3
+            </p>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <p>
+              4
+            </p>
+          </td>
+          <td>
+            <p>
+              5
+            </p>
+          </td>
+          <td>
+            <p>
+              6
+            </p>
+          </td>
+        </tr>
+      </tbody>
+    </table>
+    <table>
+      <col align="left" />
+      <col align="left" />
+      <col align="left" />
+      <thead>
+        <tr>
+          <th>
+            <p>
+              X
+            </p>
+          </th>
+          <th>
+            <p>
+              Y
+            </p>
+          </th>
+          <th>
+            <p>
+              Z
+            </p>
+          </th>
+        </tr>
+      </thead>
+      <tbody>
+        <tr>
+          <td>
+            <p>
+              1
+            </p>
+          </td>
+          <td>
+            <p>
+              2
+            </p>
+          </td>
+          <td>
+            <p>
+              3
+            </p>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <p>
+              4
+            </p>
+          </td>
+          <td>
+            <p>
+              5
+            </p>
+          </td>
+          <td>
+            <p>
+              6
+            </p>
+          </td>
+        </tr>
+      </tbody>
+    </table>
+    <table>
+      <col align="left" />
+      <col align="left" />
+      <col align="left" />
+      <thead>
+        <tr>
+          <th>
+            <p>
+              X
+            </p>
+          </th>
+          <th>
+            <p>
+              Y
+            </p>
+          </th>
+          <th>
+            <p>
+              Z
+            </p>
+          </th>
+        </tr>
+      </thead>
+      <tbody>
+        <tr>
+          <td>
+            <p>
+              1
+            </p>
+          </td>
+          <td>
+            <p>
+              2
+            </p>
+          </td>
+          <td>
+            <p>
+              3
+            </p>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <p>
+              4
+            </p>
+          </td>
+          <td>
+            <p>
+              5
+            </p>
+          </td>
+          <td>
+            <p>
+              6
+            </p>
+          </td>
+        </tr>
+      </tbody>
+    </table>
+    <table>
+      <col align="left" />
+      <col align="left" />
+      <col align="left" />
+      <thead>
+        <tr>
+          <th>
+            <p>
+              X
+            </p>
+          </th>
+          <th>
+            <p>
+              Y
+            </p>
+          </th>
+          <th>
+            <p>
+              Z
+            </p>
+          </th>
+        </tr>
+      </thead>
+      <tbody>
+        <tr>
+          <td>
+            <p>
+              1
+            </p>
+          </td>
+          <td>
+            <p>
+              2
+            </p>
+          </td>
+          <td>
+            <p>
+              3
+            </p>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <p>
+              4
+            </p>
+          </td>
+          <td>
+            <p>
+              5
+            </p>
+          </td>
+          <td>
+            <p>
+              6
+            </p>
+          </td>
+        </tr>
+      </tbody>
+    </table>
+    <table>
+      <col align="left" />
+      <col align="left" />
+      <col align="left" />
+      <thead>
+        <tr>
+          <th>
+            <p>
+              X
+            </p>
+          </th>
+          <th>
+            <p>
+              Y
+            </p>
+          </th>
+          <th>
+            <p>
+              Z
+            </p>
+          </th>
+        </tr>
+      </thead>
+      <tbody>
+        <tr>
+          <td>
+            <p>
+              1
+            </p>
+          </td>
+          <td>
+            <p>
+              2
+            </p>
+          </td>
+          <td>
+            <p>
+              3
+            </p>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <p>
+              4
+            </p>
+          </td>
+          <td>
+            <p>
+              5
+            </p>
+          </td>
+          <td>
+            <p>
+              6
+            </p>
+          </td>
+        </tr>
+      </tbody>
+    </table>
+    <table>
+      <col align="left" />
+      <col align="left" />
+      <col align="left" />
+      <thead>
+        <tr>
+          <th>
+            <p>
+              X
+            </p>
+          </th>
+          <th>
+            <p>
+              Y
+            </p>
+          </th>
+          <th>
+            <p>
+              Z
+            </p>
+          </th>
+        </tr>
+      </thead>
+      <tbody>
+        <tr>
+          <td>
+            <p>
+              1
+            </p>
+          </td>
+          <td>
+            <p>
+              2
+            </p>
+          </td>
+          <td>
+            <p>
+              3
+            </p>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <p>
+              4
+            </p>
+          </td>
+          <td>
+            <p>
+              5
+            </p>
+          </td>
+          <td>
+            <p>
+              6
+            </p>
+          </td>
+        </tr>
+      </tbody>
+    </table>
+    <table>
+      <col align="left" />
+      <col align="left" />
+      <col align="left" />
+      <thead>
+        <tr>
+          <th>
+            <p>
+              X
+            </p>
+          </th>
+          <th>
+            <p>
+              Y
+            </p>
+          </th>
+          <th>
+            <p>
+              Z
+            </p>
+          </th>
+        </tr>
+      </thead>
+      <tbody>
+        <tr>
+          <td>
+            <p>
+              1
+            </p>
+          </td>
+          <td>
+            <p>
+              2
+            </p>
+          </td>
+          <td>
+            <p>
+              3
+            </p>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <p>
+              4
+            </p>
+          </td>
+          <td>
+            <p>
+              5
+            </p>
+          </td>
+          <td>
+            <p>
+              6
+            </p>
+          </td>
+        </tr>
+      </tbody>
+    </table>
+    <table>
+      <col width="33*" align="left" />
+      <col width="33*" align="left" />
+      <col width="33*" align="left" />
+      <thead>
+        <tr>
+          <th>
+            <p>
+              X
+            </p>
+          </th>
+          <th>
+            <p>
+              Y
+            </p>
+          </th>
+          <th>
+            <p>
+              Z
+            </p>
+          </th>
+        </tr>
+      </thead>
+      <tbody>
+        <tr>
+          <td>
+            <p>
+              1
+            </p>
+          </td>
+          <td>
+            <p>
+              2
+            </p>
+          </td>
+          <td>
+            <p>
+              3
+            </p>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <p>
+              4
+            </p>
+          </td>
+          <td>
+            <p>
+              5
+            </p>
+          </td>
+          <td>
+            <p>
+              6
+            </p>
+          </td>
+        </tr>
+      </tbody>
+    </table>
+  </sec>
+  <sec id="tables-without-headers">
+    <title>Tables without Headers</title>
+    <table>
+      <col align="left" />
+      <col align="left" />
+      <col align="left" />
+      <tbody>
+        <tr>
+          <td>
+            <p>
+              1
+            </p>
+          </td>
+          <td>
+            <p>
+              2
+            </p>
+          </td>
+          <td>
+            <p>
+              3
+            </p>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <p>
+              4
+            </p>
+          </td>
+          <td>
+            <p>
+              5
+            </p>
+          </td>
+          <td>
+            <p>
+              6
+            </p>
+          </td>
+        </tr>
+      </tbody>
+    </table>
+    <table>
+      <col align="left" />
+      <col align="left" />
+      <col align="left" />
+      <tbody>
+        <tr>
+          <td>
+            <p>
+              1
+            </p>
+          </td>
+          <td>
+            <p>
+              2
+            </p>
+          </td>
+          <td>
+            <p>
+              3
+            </p>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <p>
+              4
+            </p>
+          </td>
+          <td>
+            <p>
+              5
+            </p>
+          </td>
+          <td>
+            <p>
+              6
+            </p>
+          </td>
+        </tr>
+      </tbody>
+    </table>
+    <table>
+      <col align="left" />
+      <col align="left" />
+      <col align="left" />
+      <tbody>
+        <tr>
+          <td>
+            <p>
+              1
+            </p>
+          </td>
+          <td>
+            <p>
+              2
+            </p>
+          </td>
+          <td>
+            <p>
+              3
+            </p>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <p>
+              4
+            </p>
+          </td>
+          <td>
+            <p>
+              5
+            </p>
+          </td>
+          <td>
+            <p>
+              6
+            </p>
+          </td>
+        </tr>
+      </tbody>
+    </table>
+    <table>
+      <col align="left" />
+      <col align="left" />
+      <col align="left" />
+      <tbody>
+        <tr>
+          <td>
+            <p>
+              1
+            </p>
+          </td>
+          <td>
+            <p>
+              2
+            </p>
+          </td>
+          <td>
+            <p>
+              3
+            </p>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <p>
+              4
+            </p>
+          </td>
+          <td>
+            <p>
+              5
+            </p>
+          </td>
+          <td>
+            <p>
+              6
+            </p>
+          </td>
+        </tr>
+      </tbody>
+    </table>
+  </sec>
+  <sec id="empty-tables">
+    <title>Empty Tables</title>
+    <p>
+      This section should be empty.
+    </p>
+  </sec>
+</sec>
+</body>
+<back>
+</back>
+</article>
diff --git a/test/lhs-test.html b/test/lhs-test.html
--- a/test/lhs-test.html
+++ b/test/lhs-test.html
@@ -9,7 +9,6 @@
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
       span.underline{text-decoration: underline;}
-      div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
   </style>
   <style type="text/css">
diff --git a/test/lhs-test.html+lhs b/test/lhs-test.html+lhs
--- a/test/lhs-test.html+lhs
+++ b/test/lhs-test.html+lhs
@@ -9,7 +9,6 @@
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
       span.underline{text-decoration: underline;}
-      div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
   </style>
   <style type="text/css">
diff --git a/test/lua/test-pandoc-utils.lua b/test/lua/test-pandoc-utils.lua
new file mode 100644
--- /dev/null
+++ b/test/lua/test-pandoc-utils.lua
@@ -0,0 +1,115 @@
+utils = require 'pandoc.utils'
+
+-- hierarchicalize
+------------------------------------------------------------------------
+function test_hierarchicalize ()
+  local blks = {
+    pandoc.Header(1, {pandoc.Str 'First'}),
+    pandoc.Header(2, {pandoc.Str 'Second'}),
+    pandoc.Header(2, {pandoc.Str 'Third'}),
+  }
+  local hblks = utils.hierarchicalize(blks)
+  return hblks[1].t == "Sec"
+    and hblks[1].contents[1].t == "Sec"
+    and hblks[1].contents[2].numbering[1] == 1
+    and hblks[1].contents[2].numbering[2] == 2
+end
+
+-- SHA1
+------------------------------------------------------------------------
+function test_sha1 ()
+  local ref_hash = '0a0a9f2a6772942557ab5355d76af442f8f65e01'
+  local hash = utils.sha1 'Hello, World!'
+  return hash == ref_hash
+end
+
+-- Pipe
+------------------------------------------------------------------------
+function file_exists (filename)
+  local fh = io.open(filename, 'r')
+  return fh ~= nil and (fh:close() or true)
+end
+
+function warn (...) io.stderr:write(...) end
+
+function test_pipe ()
+  if not file_exists('/bin/sed') then
+    warn 'Did not find /bin/sed, skipping test'
+    return true
+  end
+  local pipe_result = pandoc.pipe('/bin/sed', {'-e', 's/a/b/'}, 'abc')
+  return pipe_result == 'bbc'
+end
+
+function test_failing_pipe ()
+  if not file_exists('/bin/false') then
+    warn 'Did not find /bin/false, skipping test'
+    return true
+  end
+  local res, err = pcall(pandoc.pipe, '/bin/false', {}, 'abc')
+  return not res and
+    err.command == '/bin/false' and
+    err.error_code == 1 and
+    err.output == ''
+end
+
+-- Read
+------------------------------------------------------------------------
+function test_read ()
+  local valid_markdown = '*Hello*, World!\n'
+  local res = pandoc.read(valid_markdown).blocks[1].content
+  return res[1].t == 'Emph' and res[3].t == 'Space' and res[4].t == 'Str'
+end
+
+function test_failing_read ()
+  local res, err = pcall(pandoc.read, 'foo', 'nosuchreader')
+  return not res and err:match 'Unknown reader: nosuchreader'
+end
+
+-- Stringify
+------------------------------------------------------------------------
+function test_stringify ()
+  local inline = pandoc.Emph{
+    pandoc.Str 'Cogito',
+    pandoc.Space(),
+    pandoc.Str 'ergo',
+    pandoc.Space(),
+    pandoc.Str 'sum.',
+  }
+  return utils.stringify(inline) == 'Cogito ergo sum.'
+end
+
+-- to_roman_numeral
+------------------------------------------------------------------------
+function test_to_roman_numeral ()
+  return utils.to_roman_numeral(1888) == 'MDCCCLXXXVIII'
+    -- calling with a string fails
+    and not pcall(utils.to_roman_numeral, 'not a number')
+end
+
+-- normalize_date
+------------------------------------------------------------------------
+function test_normalize_date ()
+  return utils.normalize_date("12/31/2017") == '2017-12-31'
+    and utils.normalize_date("pandoc") == nil
+end
+
+-- Return result
+------------------------------------------------------------------------
+function run(fn)
+  return fn() and "OK" or "FAIL"
+end
+
+function Para (el)
+  return {
+    pandoc.Plain{pandoc.Str("hierarchicalize: " .. run(test_hierarchicalize))},
+    pandoc.Plain{pandoc.Str("normalize_date: " .. run(test_normalize_date))},
+    pandoc.Plain{pandoc.Str("pipe: " .. run(test_pipe))},
+    pandoc.Plain{pandoc.Str("failing pipe: " .. run(test_failing_pipe))},
+    pandoc.Plain{pandoc.Str("read: " .. run(test_read))},
+    pandoc.Plain{pandoc.Str("failing read: " .. run(test_failing_read))},
+    pandoc.Plain{pandoc.Str("sha1: " .. run(test_sha1))},
+    pandoc.Plain{pandoc.Str("stringify: " .. run(test_stringify))},
+    pandoc.Plain{pandoc.Str("to_roman_numeral: " .. run(test_to_roman_numeral))},
+  }
+end
diff --git a/test/markdown-reader-more.native b/test/markdown-reader-more.native
--- a/test/markdown-reader-more.native
+++ b/test/markdown-reader-more.native
@@ -3,9 +3,7 @@
 ,Header 2 ("blank-line-before-url-in-link-reference",[],[]) [Str "Blank",Space,Str "line",Space,Str "before",Space,Str "URL",Space,Str "in",Space,Str "link",Space,Str "reference"]
 ,Para [Link ("",[],[]) [Str "foo"] ("/url",""),Space,Str "and",Space,Link ("",[],[]) [Str "bar"] ("/url","title")]
 ,Header 2 ("raw-context-environments",[],[]) [Str "Raw",Space,Str "ConTeXt",Space,Str "environments"]
-,RawBlock (Format "latex") "\\placeformula "
-,RawBlock (Format "context") "\\startformula\n   L_{1} = L_{2}\n   \\stopformula"
-,RawBlock (Format "context") "\\start[a2]\n\\start[a2]\n\\stop[a2]\n\\stop[a2]"
+,RawBlock (Format "context") "\\placeformula \\startformula\n   L_{1} = L_{2}\n   \\stopformula\n\n\\start[a2]\n\\start[a2]\n\\stop[a2]\n\\stop[a2]"
 ,Header 2 ("raw-latex-environments",[],[]) [Str "Raw",Space,Str "LaTeX",Space,Str "environments"]
 ,RawBlock (Format "latex") "\\begin{center}\n\\begin{tikzpicture}[baseline={([yshift=+-.5ex]current bounding box.center)}, level distance=24pt]\n\\Tree [.{S} [.NP John\\index{i} ] [.VP [.V likes ] [.NP himself\\index{i,*j} ]]]\n\\end{tikzpicture}\n\\end{center}"
 ,Header 2 ("urls-with-spaces-and-punctuation",[],[]) [Str "URLs",Space,Str "with",Space,Str "spaces",Space,Str "and",Space,Str "punctuation"]
@@ -56,7 +54,6 @@
 ,OrderedList (3,Example,TwoParens)
  [[Plain [Str "Third",Space,Str "example."]]]
 ,Header 2 ("macros",[],[]) [Str "Macros"]
-,RawBlock (Format "latex") "\\newcommand{\\tuple}[1]{\\langle #1 \\rangle}"
 ,Para [Math InlineMath "\\langle x,y \\rangle"]
 ,Header 2 ("case-insensitive-references",[],[]) [Str "Case-insensitive",Space,Str "references"]
 ,Para [Link ("",[],[]) [Str "Fum"] ("/fum","")]
diff --git a/test/s5-basic.html b/test/s5-basic.html
--- a/test/s5-basic.html
+++ b/test/s5-basic.html
@@ -14,7 +14,6 @@
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
       span.underline{text-decoration: underline;}
-      div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
   </style>
   <!-- configuration parameters -->
diff --git a/test/s5-fancy.html b/test/s5-fancy.html
--- a/test/s5-fancy.html
+++ b/test/s5-fancy.html
@@ -14,7 +14,6 @@
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
       span.underline{text-decoration: underline;}
-      div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
   </style>
   <!-- configuration parameters -->
diff --git a/test/s5-inserts.html b/test/s5-inserts.html
--- a/test/s5-inserts.html
+++ b/test/s5-inserts.html
@@ -12,7 +12,6 @@
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
       span.underline{text-decoration: underline;}
-      div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
   </style>
   <link rel="stylesheet" href="main.css" type="text/css" />
diff --git a/test/tables.custom b/test/tables.custom
new file mode 100644
--- /dev/null
+++ b/test/tables.custom
@@ -0,0 +1,201 @@
+<p>Simple table with caption:</p>
+
+<table>
+<caption>Demonstration of simple table syntax.</caption>
+<tr class="header">
+<th align="right">Right</th>
+<th align="left">Left</th>
+<th align="center">Center</th>
+<th align="left">Default</th>
+</tr>
+<tr class="odd">
+<td align="right">12</td>
+<td align="left">12</td>
+<td align="center">12</td>
+<td align="left">12</td>
+</tr>
+<tr class="even">
+<td align="right">123</td>
+<td align="left">123</td>
+<td align="center">123</td>
+<td align="left">123</td>
+</tr>
+<tr class="odd">
+<td align="right">1</td>
+<td align="left">1</td>
+<td align="center">1</td>
+<td align="left">1</td>
+</tr>
+</table
+
+<p>Simple table without caption:</p>
+
+<table>
+<tr class="header">
+<th align="right">Right</th>
+<th align="left">Left</th>
+<th align="center">Center</th>
+<th align="left">Default</th>
+</tr>
+<tr class="odd">
+<td align="right">12</td>
+<td align="left">12</td>
+<td align="center">12</td>
+<td align="left">12</td>
+</tr>
+<tr class="even">
+<td align="right">123</td>
+<td align="left">123</td>
+<td align="center">123</td>
+<td align="left">123</td>
+</tr>
+<tr class="odd">
+<td align="right">1</td>
+<td align="left">1</td>
+<td align="center">1</td>
+<td align="left">1</td>
+</tr>
+</table
+
+<p>Simple table indented two spaces:</p>
+
+<table>
+<caption>Demonstration of simple table syntax.</caption>
+<tr class="header">
+<th align="right">Right</th>
+<th align="left">Left</th>
+<th align="center">Center</th>
+<th align="left">Default</th>
+</tr>
+<tr class="odd">
+<td align="right">12</td>
+<td align="left">12</td>
+<td align="center">12</td>
+<td align="left">12</td>
+</tr>
+<tr class="even">
+<td align="right">123</td>
+<td align="left">123</td>
+<td align="center">123</td>
+<td align="left">123</td>
+</tr>
+<tr class="odd">
+<td align="right">1</td>
+<td align="left">1</td>
+<td align="center">1</td>
+<td align="left">1</td>
+</tr>
+</table
+
+<p>Multiline table with caption:</p>
+
+<table>
+<caption>Here’s the caption.
+It may span multiple lines.</caption>
+<col width="15%" />
+<col width="14%" />
+<col width="16%" />
+<col width="34%" />
+<tr class="header">
+<th align="center">Centered
+Header</th>
+<th align="left">Left
+Aligned</th>
+<th align="right">Right
+Aligned</th>
+<th align="left">Default aligned</th>
+</tr>
+<tr class="odd">
+<td align="center">First</td>
+<td align="left">row</td>
+<td align="right">12.0</td>
+<td align="left">Example of a row that spans
+multiple lines.</td>
+</tr>
+<tr class="even">
+<td align="center">Second</td>
+<td align="left">row</td>
+<td align="right">5.0</td>
+<td align="left">Here’s another one. Note
+the blank line between rows.</td>
+</tr>
+</table
+
+<p>Multiline table without caption:</p>
+
+<table>
+<col width="15%" />
+<col width="14%" />
+<col width="16%" />
+<col width="34%" />
+<tr class="header">
+<th align="center">Centered
+Header</th>
+<th align="left">Left
+Aligned</th>
+<th align="right">Right
+Aligned</th>
+<th align="left">Default aligned</th>
+</tr>
+<tr class="odd">
+<td align="center">First</td>
+<td align="left">row</td>
+<td align="right">12.0</td>
+<td align="left">Example of a row that spans
+multiple lines.</td>
+</tr>
+<tr class="even">
+<td align="center">Second</td>
+<td align="left">row</td>
+<td align="right">5.0</td>
+<td align="left">Here’s another one. Note
+the blank line between rows.</td>
+</tr>
+</table
+
+<p>Table without column headers:</p>
+
+<table>
+<tr class="odd">
+<td align="right">12</td>
+<td align="left">12</td>
+<td align="center">12</td>
+<td align="right">12</td>
+</tr>
+<tr class="even">
+<td align="right">123</td>
+<td align="left">123</td>
+<td align="center">123</td>
+<td align="right">123</td>
+</tr>
+<tr class="odd">
+<td align="right">1</td>
+<td align="left">1</td>
+<td align="center">1</td>
+<td align="right">1</td>
+</tr>
+</table
+
+<p>Multiline table without column headers:</p>
+
+<table>
+<col width="15%" />
+<col width="14%" />
+<col width="16%" />
+<col width="34%" />
+<tr class="odd">
+<td align="center">First</td>
+<td align="left">row</td>
+<td align="right">12.0</td>
+<td align="left">Example of a row that spans
+multiple lines.</td>
+</tr>
+<tr class="even">
+<td align="center">Second</td>
+<td align="left">row</td>
+<td align="right">5.0</td>
+<td align="left">Here’s another one. Note
+the blank line between rows.</td>
+</tr>
+</table
+
diff --git a/test/tables.jats b/test/tables.jats
--- a/test/tables.jats
+++ b/test/tables.jats
@@ -15,92 +15,60 @@
     <thead>
       <tr>
         <th>
-          <p>
-            Right
-          </p>
+          Right
         </th>
         <th>
-          <p>
-            Left
-          </p>
+          Left
         </th>
         <th>
-          <p>
-            Center
-          </p>
+          Center
         </th>
         <th>
-          <p>
-            Default
-          </p>
+          Default
         </th>
       </tr>
     </thead>
     <tbody>
       <tr>
         <td>
-          <p>
-            12
-          </p>
+          12
         </td>
         <td>
-          <p>
-            12
-          </p>
+          12
         </td>
         <td>
-          <p>
-            12
-          </p>
+          12
         </td>
         <td>
-          <p>
-            12
-          </p>
+          12
         </td>
       </tr>
       <tr>
         <td>
-          <p>
-            123
-          </p>
+          123
         </td>
         <td>
-          <p>
-            123
-          </p>
+          123
         </td>
         <td>
-          <p>
-            123
-          </p>
+          123
         </td>
         <td>
-          <p>
-            123
-          </p>
+          123
         </td>
       </tr>
       <tr>
         <td>
-          <p>
-            1
-          </p>
+          1
         </td>
         <td>
-          <p>
-            1
-          </p>
+          1
         </td>
         <td>
-          <p>
-            1
-          </p>
+          1
         </td>
         <td>
-          <p>
-            1
-          </p>
+          1
         </td>
       </tr>
     </tbody>
@@ -117,92 +85,60 @@
   <thead>
     <tr>
       <th>
-        <p>
-          Right
-        </p>
+        Right
       </th>
       <th>
-        <p>
-          Left
-        </p>
+        Left
       </th>
       <th>
-        <p>
-          Center
-        </p>
+        Center
       </th>
       <th>
-        <p>
-          Default
-        </p>
+        Default
       </th>
     </tr>
   </thead>
   <tbody>
     <tr>
       <td>
-        <p>
-          12
-        </p>
+        12
       </td>
       <td>
-        <p>
-          12
-        </p>
+        12
       </td>
       <td>
-        <p>
-          12
-        </p>
+        12
       </td>
       <td>
-        <p>
-          12
-        </p>
+        12
       </td>
     </tr>
     <tr>
       <td>
-        <p>
-          123
-        </p>
+        123
       </td>
       <td>
-        <p>
-          123
-        </p>
+        123
       </td>
       <td>
-        <p>
-          123
-        </p>
+        123
       </td>
       <td>
-        <p>
-          123
-        </p>
+        123
       </td>
     </tr>
     <tr>
       <td>
-        <p>
-          1
-        </p>
+        1
       </td>
       <td>
-        <p>
-          1
-        </p>
+        1
       </td>
       <td>
-        <p>
-          1
-        </p>
+        1
       </td>
       <td>
-        <p>
-          1
-        </p>
+        1
       </td>
     </tr>
   </tbody>
@@ -224,92 +160,60 @@
     <thead>
       <tr>
         <th>
-          <p>
-            Right
-          </p>
+          Right
         </th>
         <th>
-          <p>
-            Left
-          </p>
+          Left
         </th>
         <th>
-          <p>
-            Center
-          </p>
+          Center
         </th>
         <th>
-          <p>
-            Default
-          </p>
+          Default
         </th>
       </tr>
     </thead>
     <tbody>
       <tr>
         <td>
-          <p>
-            12
-          </p>
+          12
         </td>
         <td>
-          <p>
-            12
-          </p>
+          12
         </td>
         <td>
-          <p>
-            12
-          </p>
+          12
         </td>
         <td>
-          <p>
-            12
-          </p>
+          12
         </td>
       </tr>
       <tr>
         <td>
-          <p>
-            123
-          </p>
+          123
         </td>
         <td>
-          <p>
-            123
-          </p>
+          123
         </td>
         <td>
-          <p>
-            123
-          </p>
+          123
         </td>
         <td>
-          <p>
-            123
-          </p>
+          123
         </td>
       </tr>
       <tr>
         <td>
-          <p>
-            1
-          </p>
+          1
         </td>
         <td>
-          <p>
-            1
-          </p>
+          1
         </td>
         <td>
-          <p>
-            1
-          </p>
+          1
         </td>
         <td>
-          <p>
-            1
-          </p>
+          1
         </td>
       </tr>
     </tbody>
@@ -332,70 +236,46 @@
     <thead>
       <tr>
         <th>
-          <p>
-            Centered Header
-          </p>
+          Centered Header
         </th>
         <th>
-          <p>
-            Left Aligned
-          </p>
+          Left Aligned
         </th>
         <th>
-          <p>
-            Right Aligned
-          </p>
+          Right Aligned
         </th>
         <th>
-          <p>
-            Default aligned
-          </p>
+          Default aligned
         </th>
       </tr>
     </thead>
     <tbody>
       <tr>
         <td>
-          <p>
-            First
-          </p>
+          First
         </td>
         <td>
-          <p>
-            row
-          </p>
+          row
         </td>
         <td>
-          <p>
-            12.0
-          </p>
+          12.0
         </td>
         <td>
-          <p>
-            Example of a row that spans multiple lines.
-          </p>
+          Example of a row that spans multiple lines.
         </td>
       </tr>
       <tr>
         <td>
-          <p>
-            Second
-          </p>
+          Second
         </td>
         <td>
-          <p>
-            row
-          </p>
+          row
         </td>
         <td>
-          <p>
-            5.0
-          </p>
+          5.0
         </td>
         <td>
-          <p>
-            Here’s another one. Note the blank line between rows.
-          </p>
+          Here’s another one. Note the blank line between rows.
         </td>
       </tr>
     </tbody>
@@ -412,70 +292,46 @@
   <thead>
     <tr>
       <th>
-        <p>
-          Centered Header
-        </p>
+        Centered Header
       </th>
       <th>
-        <p>
-          Left Aligned
-        </p>
+        Left Aligned
       </th>
       <th>
-        <p>
-          Right Aligned
-        </p>
+        Right Aligned
       </th>
       <th>
-        <p>
-          Default aligned
-        </p>
+        Default aligned
       </th>
     </tr>
   </thead>
   <tbody>
     <tr>
       <td>
-        <p>
-          First
-        </p>
+        First
       </td>
       <td>
-        <p>
-          row
-        </p>
+        row
       </td>
       <td>
-        <p>
-          12.0
-        </p>
+        12.0
       </td>
       <td>
-        <p>
-          Example of a row that spans multiple lines.
-        </p>
+        Example of a row that spans multiple lines.
       </td>
     </tr>
     <tr>
       <td>
-        <p>
-          Second
-        </p>
+        Second
       </td>
       <td>
-        <p>
-          row
-        </p>
+        row
       </td>
       <td>
-        <p>
-          5.0
-        </p>
+        5.0
       </td>
       <td>
-        <p>
-          Here’s another one. Note the blank line between rows.
-        </p>
+        Here’s another one. Note the blank line between rows.
       </td>
     </tr>
   </tbody>
@@ -491,68 +347,44 @@
   <tbody>
     <tr>
       <td>
-        <p>
-          12
-        </p>
+        12
       </td>
       <td>
-        <p>
-          12
-        </p>
+        12
       </td>
       <td>
-        <p>
-          12
-        </p>
+        12
       </td>
       <td>
-        <p>
-          12
-        </p>
+        12
       </td>
     </tr>
     <tr>
       <td>
-        <p>
-          123
-        </p>
+        123
       </td>
       <td>
-        <p>
-          123
-        </p>
+        123
       </td>
       <td>
-        <p>
-          123
-        </p>
+        123
       </td>
       <td>
-        <p>
-          123
-        </p>
+        123
       </td>
     </tr>
     <tr>
       <td>
-        <p>
-          1
-        </p>
+        1
       </td>
       <td>
-        <p>
-          1
-        </p>
+        1
       </td>
       <td>
-        <p>
-          1
-        </p>
+        1
       </td>
       <td>
-        <p>
-          1
-        </p>
+        1
       </td>
     </tr>
   </tbody>
@@ -568,46 +400,30 @@
   <tbody>
     <tr>
       <td>
-        <p>
-          First
-        </p>
+        First
       </td>
       <td>
-        <p>
-          row
-        </p>
+        row
       </td>
       <td>
-        <p>
-          12.0
-        </p>
+        12.0
       </td>
       <td>
-        <p>
-          Example of a row that spans multiple lines.
-        </p>
+        Example of a row that spans multiple lines.
       </td>
     </tr>
     <tr>
       <td>
-        <p>
-          Second
-        </p>
+        Second
       </td>
       <td>
-        <p>
-          row
-        </p>
+        row
       </td>
       <td>
-        <p>
-          5.0
-        </p>
+        5.0
       </td>
       <td>
-        <p>
-          Here’s another one. Note the blank line between rows.
-        </p>
+        Here’s another one. Note the blank line between rows.
       </td>
     </tr>
   </tbody>
diff --git a/test/tables.latex b/test/tables.latex
--- a/test/tables.latex
+++ b/test/tables.latex
@@ -136,6 +136,7 @@
 
 \begin{longtable}[]{@{}rlcr@{}}
 \toprule
+\endhead
 12 & 12 & 12 & 12\tabularnewline
 123 & 123 & 123 & 123\tabularnewline
 1 & 1 & 1 & 1\tabularnewline
@@ -146,6 +147,7 @@
 
 \begin{longtable}[]{@{}clrl@{}}
 \toprule
+\endhead
 \begin{minipage}[t]{0.13\columnwidth}\centering
 First\strut
 \end{minipage} & \begin{minipage}[t]{0.12\columnwidth}\raggedright
diff --git a/test/test-pandoc.hs b/test/test-pandoc.hs
--- a/test/test-pandoc.hs
+++ b/test/test-pandoc.hs
@@ -11,6 +11,7 @@
 import qualified Tests.Readers.Docx
 import qualified Tests.Readers.EPUB
 import qualified Tests.Readers.HTML
+import qualified Tests.Readers.JATS
 import qualified Tests.Readers.LaTeX
 import qualified Tests.Readers.Markdown
 import qualified Tests.Readers.Muse
@@ -25,12 +26,14 @@
 import qualified Tests.Writers.Docx
 import qualified Tests.Writers.FB2
 import qualified Tests.Writers.HTML
+import qualified Tests.Writers.JATS
 import qualified Tests.Writers.LaTeX
 import qualified Tests.Writers.Markdown
 import qualified Tests.Writers.Muse
 import qualified Tests.Writers.Native
 import qualified Tests.Writers.Org
 import qualified Tests.Writers.Plain
+import qualified Tests.Writers.Powerpoint
 import qualified Tests.Writers.RST
 import qualified Tests.Writers.TEI
 import Text.Pandoc.Shared (inDirectory)
@@ -44,6 +47,7 @@
           , testGroup "ConTeXt" Tests.Writers.ConTeXt.tests
           , testGroup "LaTeX" Tests.Writers.LaTeX.tests
           , testGroup "HTML" Tests.Writers.HTML.tests
+          , testGroup "JATS" Tests.Writers.JATS.tests
           , testGroup "Docbook" Tests.Writers.Docbook.tests
           , testGroup "Markdown" Tests.Writers.Markdown.tests
           , testGroup "Org" Tests.Writers.Org.tests
@@ -54,11 +58,13 @@
           , testGroup "TEI" Tests.Writers.TEI.tests
           , testGroup "Muse" Tests.Writers.Muse.tests
           , testGroup "FB2" Tests.Writers.FB2.tests
+          , testGroup "PowerPoint" Tests.Writers.Powerpoint.tests
           ]
         , testGroup "Readers"
           [ testGroup "LaTeX" Tests.Readers.LaTeX.tests
           , testGroup "Markdown" Tests.Readers.Markdown.tests
           , testGroup "HTML" Tests.Readers.HTML.tests
+          , testGroup "JATS" Tests.Readers.JATS.tests
           , testGroup "Org" Tests.Readers.Org.tests
           , testGroup "RST" Tests.Readers.RST.tests
           , testGroup "Docx" Tests.Readers.Docx.tests
diff --git a/test/writer.custom b/test/writer.custom
new file mode 100644
--- /dev/null
+++ b/test/writer.custom
@@ -0,0 +1,783 @@
+<p>This is a set of tests for pandoc. Most of them are adapted from
+John Gruber’s markdown test suite.</p>
+
+<hr/>
+
+<h1 id="headers">Headers</h1>
+
+<h2 id="level-2-with-an-embedded-link">Level 2 with an <a href='/url' title=''>embedded link</a></h2>
+
+<h3 id="level-3-with-emphasis">Level 3 with <em>emphasis</em></h3>
+
+<h4 id="level-4">Level 4</h4>
+
+<h5 id="level-5">Level 5</h5>
+
+<h1 id="level-1">Level 1</h1>
+
+<h2 id="level-2-with-emphasis">Level 2 with <em>emphasis</em></h2>
+
+<h3 id="level-3">Level 3</h3>
+
+<p>with no blank line</p>
+
+<h2 id="level-2">Level 2</h2>
+
+<p>with no blank line</p>
+
+<hr/>
+
+<h1 id="paragraphs">Paragraphs</h1>
+
+<p>Here’s a regular paragraph.</p>
+
+<p>In Markdown 1.0.0 and earlier. Version
+8. This line turns into a list item.
+Because a hard-wrapped line in the
+middle of a paragraph looked like a
+list item.</p>
+
+<p>Here’s one with a bullet.
+* criminey.</p>
+
+<p>There should be a hard line break<br/>here.</p>
+
+<hr/>
+
+<h1 id="block-quotes">Block Quotes</h1>
+
+<p>E-mail style:</p>
+
+<blockquote>
+<p>This is a block quote.
+It is pretty short.</p>
+</blockquote>
+
+<blockquote>
+<p>Code in a block quote:</p>
+
+<pre><code>sub status {
+    print &quot;working&quot;;
+}</code></pre>
+
+<p>A list:</p>
+
+<ol>
+<li>item one</li>
+<li>item two</li>
+</ol>
+
+<p>Nested block quotes:</p>
+
+<blockquote>
+<p>nested</p>
+</blockquote>
+
+<blockquote>
+<p>nested</p>
+</blockquote>
+</blockquote>
+
+<p>This should not be a block quote: 2
+&gt; 1.</p>
+
+<p>And a following paragraph.</p>
+
+<hr/>
+
+<h1 id="code-blocks">Code Blocks</h1>
+
+<p>Code:</p>
+
+<pre><code>---- (should be four hyphens)
+
+sub status {
+    print &quot;working&quot;;
+}
+
+this code block is indented by one tab</code></pre>
+
+<p>And:</p>
+
+<pre><code>    this code block is indented by two tabs
+
+These should not be escaped:  \$ \\ \&gt; \[ \{</code></pre>
+
+<hr/>
+
+<h1 id="lists">Lists</h1>
+
+<h2 id="unordered">Unordered</h2>
+
+<p>Asterisks tight:</p>
+
+<ul>
+<li>asterisk 1</li>
+<li>asterisk 2</li>
+<li>asterisk 3</li>
+</ul>
+
+<p>Asterisks loose:</p>
+
+<ul>
+<li><p>asterisk 1</p></li>
+<li><p>asterisk 2</p></li>
+<li><p>asterisk 3</p></li>
+</ul>
+
+<p>Pluses tight:</p>
+
+<ul>
+<li>Plus 1</li>
+<li>Plus 2</li>
+<li>Plus 3</li>
+</ul>
+
+<p>Pluses loose:</p>
+
+<ul>
+<li><p>Plus 1</p></li>
+<li><p>Plus 2</p></li>
+<li><p>Plus 3</p></li>
+</ul>
+
+<p>Minuses tight:</p>
+
+<ul>
+<li>Minus 1</li>
+<li>Minus 2</li>
+<li>Minus 3</li>
+</ul>
+
+<p>Minuses loose:</p>
+
+<ul>
+<li><p>Minus 1</p></li>
+<li><p>Minus 2</p></li>
+<li><p>Minus 3</p></li>
+</ul>
+
+<h2 id="ordered">Ordered</h2>
+
+<p>Tight:</p>
+
+<ol>
+<li>First</li>
+<li>Second</li>
+<li>Third</li>
+</ol>
+
+<p>and:</p>
+
+<ol>
+<li>One</li>
+<li>Two</li>
+<li>Three</li>
+</ol>
+
+<p>Loose using tabs:</p>
+
+<ol>
+<li><p>First</p></li>
+<li><p>Second</p></li>
+<li><p>Third</p></li>
+</ol>
+
+<p>and using spaces:</p>
+
+<ol>
+<li><p>One</p></li>
+<li><p>Two</p></li>
+<li><p>Three</p></li>
+</ol>
+
+<p>Multiple paragraphs:</p>
+
+<ol>
+<li><p>Item 1, graf one.</p>
+
+<p>Item 1. graf two. The quick brown fox jumped over the lazy dog’s
+back.</p></li>
+<li><p>Item 2.</p></li>
+<li><p>Item 3.</p></li>
+</ol>
+
+<h2 id="nested">Nested</h2>
+
+<ul>
+<li>Tab
+
+<ul>
+<li>Tab
+
+<ul>
+<li>Tab</li>
+</ul></li>
+</ul></li>
+</ul>
+
+<p>Here’s another:</p>
+
+<ol>
+<li>First</li>
+<li>Second:
+
+<ul>
+<li>Fee</li>
+<li>Fie</li>
+<li>Foe</li>
+</ul></li>
+<li>Third</li>
+</ol>
+
+<p>Same thing but with paragraphs:</p>
+
+<ol>
+<li><p>First</p></li>
+<li><p>Second:</p>
+
+<ul>
+<li>Fee</li>
+<li>Fie</li>
+<li>Foe</li>
+</ul></li>
+<li><p>Third</p></li>
+</ol>
+
+<h2 id="tabs-and-spaces">Tabs and spaces</h2>
+
+<ul>
+<li><p>this is a list item
+indented with tabs</p></li>
+<li><p>this is a list item
+indented with spaces</p>
+
+<ul>
+<li><p>this is an example list item
+indented with tabs</p></li>
+<li><p>this is an example list item
+indented with spaces</p></li>
+</ul></li>
+</ul>
+
+<h2 id="fancy-list-markers">Fancy list markers</h2>
+
+<ol>
+<li>begins with 2</li>
+<li><p>and now 3</p>
+
+<p>with a continuation</p>
+
+<ol>
+<li>sublist with roman numerals,
+starting with 4</li>
+<li>more items
+
+<ol>
+<li>a subsublist</li>
+<li>a subsublist</li>
+</ol></li>
+</ol></li>
+</ol>
+
+<p>Nesting:</p>
+
+<ol>
+<li>Upper Alpha
+
+<ol>
+<li>Upper Roman.
+
+<ol>
+<li>Decimal start with 6
+
+<ol>
+<li>Lower alpha with paren</li>
+</ol></li>
+</ol></li>
+</ol></li>
+</ol>
+
+<p>Autonumbering:</p>
+
+<ol>
+<li>Autonumber.</li>
+<li>More.
+
+<ol>
+<li>Nested.</li>
+</ol></li>
+</ol>
+
+<p>Should not be a list item:</p>
+
+<p>M.A. 2007</p>
+
+<p>B. Williams</p>
+
+<hr/>
+
+<h1 id="definition-lists">Definition Lists</h1>
+
+<p>Tight using spaces:</p>
+
+<dl>
+<dt>apple</dt>
+<dd>red fruit</dd>
+<dt>orange</dt>
+<dd>orange fruit</dd>
+<dt>banana</dt>
+<dd>yellow fruit</dd>
+</dl>
+
+<p>Tight using tabs:</p>
+
+<dl>
+<dt>apple</dt>
+<dd>red fruit</dd>
+<dt>orange</dt>
+<dd>orange fruit</dd>
+<dt>banana</dt>
+<dd>yellow fruit</dd>
+</dl>
+
+<p>Loose:</p>
+
+<dl>
+<dt>apple</dt>
+<dd><p>red fruit</p></dd>
+<dt>orange</dt>
+<dd><p>orange fruit</p></dd>
+<dt>banana</dt>
+<dd><p>yellow fruit</p></dd>
+</dl>
+
+<p>Multiple blocks with italics:</p>
+
+<dl>
+<dt><em>apple</em></dt>
+<dd><p>red fruit</p>
+
+<p>contains seeds,
+crisp, pleasant to taste</p></dd>
+<dt><em>orange</em></dt>
+<dd><p>orange fruit</p>
+
+<pre><code>{ orange code block }</code></pre>
+
+<blockquote>
+<p>orange block quote</p>
+</blockquote></dd>
+</dl>
+
+<p>Multiple definitions, tight:</p>
+
+<dl>
+<dt>apple</dt>
+<dd>red fruit</dd>
+<dd>computer</dd>
+<dt>orange</dt>
+<dd>orange fruit</dd>
+<dd>bank</dd>
+</dl>
+
+<p>Multiple definitions, loose:</p>
+
+<dl>
+<dt>apple</dt>
+<dd><p>red fruit</p></dd>
+<dd><p>computer</p></dd>
+<dt>orange</dt>
+<dd><p>orange fruit</p></dd>
+<dd><p>bank</p></dd>
+</dl>
+
+<p>Blank line after term, indented marker, alternate markers:</p>
+
+<dl>
+<dt>apple</dt>
+<dd><p>red fruit</p></dd>
+<dd><p>computer</p></dd>
+<dt>orange</dt>
+<dd><p>orange fruit</p>
+
+<ol>
+<li>sublist</li>
+<li>sublist</li>
+</ol></dd>
+</dl>
+
+<h1 id="html-blocks">HTML Blocks</h1>
+
+<p>Simple block on one line:</p>
+
+<div>
+foo</div>
+
+<p>And nested without indentation:</p>
+
+<div>
+<div>
+<div>
+<p>foo</p></div></div>
+
+<div>
+bar</div></div>
+
+<p>Interpreted markdown in a table:</p>
+
+<table>
+
+<tr>
+
+<td>
+
+This is <em>emphasized</em>
+
+</td>
+
+<td>
+
+And this is <strong>strong</strong>
+
+</td>
+
+</tr>
+
+</table>
+
+<script type="text/javascript">document.write('This *should not* be interpreted as markdown');</script>
+
+<p>Here’s a simple block:</p>
+
+<div>
+<p>foo</p></div>
+
+<p>This should be a code block, though:</p>
+
+<pre><code>&lt;div&gt;
+    foo
+&lt;/div&gt;</code></pre>
+
+<p>As should this:</p>
+
+<pre><code>&lt;div&gt;foo&lt;/div&gt;</code></pre>
+
+<p>Now, nested:</p>
+
+<div>
+<div>
+<div>
+foo</div></div></div>
+
+<p>This should just be an HTML comment:</p>
+
+<!-- Comment -->
+
+<p>Multiline:</p>
+
+<!--
+Blah
+Blah
+-->
+
+<!--
+    This is another comment.
+-->
+
+<p>Code block:</p>
+
+<pre><code>&lt;!-- Comment --&gt;</code></pre>
+
+<p>Just plain comment, with trailing spaces on the line:</p>
+
+<!-- foo -->
+
+<p>Code:</p>
+
+<pre><code>&lt;hr /&gt;</code></pre>
+
+<p>Hr’s:</p>
+
+<hr>
+
+<hr />
+
+<hr />
+
+<hr>
+
+<hr />
+
+<hr />
+
+<hr class="foo" id="bar" />
+
+<hr class="foo" id="bar" />
+
+<hr class="foo" id="bar">
+
+<hr/>
+
+<h1 id="inline-markup">Inline Markup</h1>
+
+<p>This is <em>emphasized</em>, and so <em>is this</em>.</p>
+
+<p>This is <strong>strong</strong>, and so <strong>is this</strong>.</p>
+
+<p>An <em><a href='/url' title=''>emphasized link</a></em>.</p>
+
+<p><strong><em>This is strong and em.</em></strong></p>
+
+<p>So is <strong><em>this</em></strong> word.</p>
+
+<p><strong><em>This is strong and em.</em></strong></p>
+
+<p>So is <strong><em>this</em></strong> word.</p>
+
+<p>This is code: <code>&gt;</code>, <code>$</code>, <code>\</code>, <code>\$</code>, <code>&lt;html&gt;</code>.</p>
+
+<p><del>This is <em>strikeout</em>.</del></p>
+
+<p>Superscripts: a<sup>bc</sup>d a<sup><em>hello</em></sup> a<sup>hello there</sup>.</p>
+
+<p>Subscripts: H<sub>2</sub>O, H<sub>23</sub>O, H<sub>many of them</sub>O.</p>
+
+<p>These should not be superscripts or subscripts,
+because of the unescaped spaces: a^b c^d, a~b c~d.</p>
+
+<hr/>
+
+<h1 id="smart-quotes-ellipses-dashes">Smart quotes, ellipses, dashes</h1>
+
+<p> said the spider. </p>
+
+<p>, , and  are letters.</p>
+
+<p>  and  are names of trees.
+So is </p>
+
+<p> Were you alive in the
+70’s?</p>
+
+<p>Here is some quoted  and a .</p>
+
+<p>Some dashes: one—two — three—four — five.</p>
+
+<p>Dashes between numbers: 5–7, 255–66, 1987–1999.</p>
+
+<p>Ellipses…and…and….</p>
+
+<hr/>
+
+<h1 id="latex">LaTeX</h1>
+
+<ul>
+<li></li>
+<li>\(2+2=4\)</li>
+<li>\(x \in y\)</li>
+<li>\(\alpha \wedge \omega\)</li>
+<li>\(223\)</li>
+<li>\(p\)-Tree</li>
+<li>Here’s some display math:
+\[\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}\]</li>
+<li>Here’s one that has a line break in it: \(\alpha + \omega \times x^2\).</li>
+</ul>
+
+<p>These shouldn’t be math:</p>
+
+<ul>
+<li>To get the famous equation, write <code>$e = mc^2$</code>.</li>
+<li>$22,000 is a <em>lot</em> of money. So is $34,000.
+(It worked if  is emphasized.)</li>
+<li>Shoes ($20) and socks ($5).</li>
+<li>Escaped <code>$</code>: $73 <em>this should be emphasized</em> 23$.</li>
+</ul>
+
+<p>Here’s a LaTeX table:</p>
+
+
+
+<hr/>
+
+<h1 id="special-characters">Special Characters</h1>
+
+<p>Here is some unicode:</p>
+
+<ul>
+<li>I hat: Î</li>
+<li>o umlaut: ö</li>
+<li>section: §</li>
+<li>set membership: ∈</li>
+<li>copyright: ©</li>
+</ul>
+
+<p>AT&amp;T has an ampersand in their name.</p>
+
+<p>AT&amp;T is another way to write it.</p>
+
+<p>This &amp; that.</p>
+
+<p>4 &lt; 5.</p>
+
+<p>6 &gt; 5.</p>
+
+<p>Backslash: \</p>
+
+<p>Backtick: `</p>
+
+<p>Asterisk: *</p>
+
+<p>Underscore: _</p>
+
+<p>Left brace: {</p>
+
+<p>Right brace: }</p>
+
+<p>Left bracket: [</p>
+
+<p>Right bracket: ]</p>
+
+<p>Left paren: (</p>
+
+<p>Right paren: )</p>
+
+<p>Greater-than: &gt;</p>
+
+<p>Hash: #</p>
+
+<p>Period: .</p>
+
+<p>Bang: !</p>
+
+<p>Plus: +</p>
+
+<p>Minus: -</p>
+
+<hr/>
+
+<h1 id="links">Links</h1>
+
+<h2 id="explicit">Explicit</h2>
+
+<p>Just a <a href='/url/' title=''>URL</a>.</p>
+
+<p><a href='/url/' title='title'>URL and title</a>.</p>
+
+<p><a href='/url/' title='title preceded by two spaces'>URL and title</a>.</p>
+
+<p><a href='/url/' title='title preceded by a tab'>URL and title</a>.</p>
+
+<p><a href='/url/' title='title with &quot;quotes&quot; in it'>URL and title</a></p>
+
+<p><a href='/url/' title='title with single quotes'>URL and title</a></p>
+
+<p><a href='/url/with_underscore' title=''>with_underscore</a></p>
+
+<p><a href='mailto:nobody@nowhere.net' title=''>Email link</a></p>
+
+<p><a href='' title=''>Empty</a>.</p>
+
+<h2 id="reference">Reference</h2>
+
+<p>Foo <a href='/url/' title=''>bar</a>.</p>
+
+<p>With <a href='/url/' title=''>embedded [brackets]</a>.</p>
+
+<p><a href='/url/' title=''>b</a> by itself should be a link.</p>
+
+<p>Indented <a href='/url' title=''>once</a>.</p>
+
+<p>Indented <a href='/url' title=''>twice</a>.</p>
+
+<p>Indented <a href='/url' title=''>thrice</a>.</p>
+
+<p>This should [not][] be a link.</p>
+
+<pre><code>[not]: /url</code></pre>
+
+<p>Foo <a href='/url/' title='Title with &quot;quotes&quot; inside'>bar</a>.</p>
+
+<p>Foo <a href='/url/' title='Title with &quot;quote&quot; inside'>biz</a>.</p>
+
+<h2 id="with-ampersands">With ampersands</h2>
+
+<p>Here’s a <a href='http://example.com/?foo=1&amp;bar=2' title=''>link with an ampersand in the URL</a>.</p>
+
+<p>Here’s a link with an amersand in the link text: <a href='http://att.com/' title='AT&amp;T'>AT&amp;T</a>.</p>
+
+<p>Here’s an <a href='/script?foo=1&amp;bar=2' title=''>inline link</a>.</p>
+
+<p>Here’s an <a href='/script?foo=1&amp;bar=2' title=''>inline link in pointy braces</a>.</p>
+
+<h2 id="autolinks">Autolinks</h2>
+
+<p>With an ampersand: <a href='http://example.com/?foo=1&amp;bar=2' title=''>http://example.com/?foo=1&amp;bar=2</a></p>
+
+<ul>
+<li>In a list?</li>
+<li><a href='http://example.com/' title=''>http://example.com/</a></li>
+<li>It should.</li>
+</ul>
+
+<p>An e-mail address: <a href='mailto:nobody@nowhere.net' title=''>nobody@nowhere.net</a></p>
+
+<blockquote>
+<p>Blockquoted: <a href='http://example.com/' title=''>http://example.com/</a></p>
+</blockquote>
+
+<p>Auto-links should not occur here: <code>&lt;http://example.com/&gt;</code></p>
+
+<pre><code>or here: &lt;http://example.com/&gt;</code></pre>
+
+<hr/>
+
+<h1 id="images">Images</h1>
+
+<p>From  by Georges Melies (1902):</p>
+
+<div class="figure">
+<img src="lalune.jpg" title="fig:Voyage dans la Lune"/>
+<p class="caption">lalune</p>
+</div>
+
+<p>Here is a movie <img src='movie.jpg' title=''/> icon.</p>
+
+<hr/>
+
+<h1 id="footnotes">Footnotes</h1>
+
+<p>Here is a footnote reference,<a id="fnref1" href="#fn1"><sup>1</sup></a> and another.<a id="fnref2" href="#fn2"><sup>2</sup></a>
+This should <em>not</em> be a footnote reference, because it
+contains a space.[^my note] Here is an inline note.<a id="fnref3" href="#fn3"><sup>3</sup></a></p>
+
+<blockquote>
+<p>Notes can go in quotes.<a id="fnref4" href="#fn4"><sup>4</sup></a></p>
+</blockquote>
+
+<ol>
+<li>And in list items.<a id="fnref5" href="#fn5"><sup>5</sup></a></li>
+</ol>
+
+<p>This paragraph should not be part of the note, as it is not indented.</p>
+<ol class="footnotes">
+<li id="fn1"><p>Here is the footnote. It can go anywhere after the footnote
+reference. It need not be placed at the end of the document. <a href="#fnref1">&#8617;</a></p></li>
+<li id="fn2"><p>Here’s the long note. This one contains multiple
+blocks.</p>
+
+<p>Subsequent blocks are indented to show that they belong to the
+footnote (as with list items).</p>
+
+<pre><code>  { &lt;code&gt; }</code></pre>
+
+<p>If you want, you can indent every line, but you can also be
+lazy and just indent the first line of each block. <a href="#fnref2">&#8617;</a></p></li>
+<li id="fn3"><p>This
+is <em>easier</em> to type. Inline notes may contain
+<a href='http://google.com' title=''>links</a> and <code>]</code> verbatim characters,
+as well as [bracketed text]. <a href="#fnref3">&#8617;</a></p></li>
+<li id="fn4"><p>In quote. <a href="#fnref4">&#8617;</a></p></li>
+<li id="fn5"><p>In list. <a href="#fnref5">&#8617;</a></p></li>
+</ol>
+
diff --git a/test/writer.html4 b/test/writer.html4
--- a/test/writer.html4
+++ b/test/writer.html4
@@ -12,7 +12,6 @@
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
       span.underline{text-decoration: underline;}
-      div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
   </style>
 </head>
diff --git a/test/writer.html5 b/test/writer.html5
--- a/test/writer.html5
+++ b/test/writer.html5
@@ -12,7 +12,6 @@
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
       span.underline{text-decoration: underline;}
-      div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
   </style>
   <!--[if lt IE 9]>
diff --git a/test/writer.jats b/test/writer.jats
--- a/test/writer.jats
+++ b/test/writer.jats
@@ -1379,7 +1379,7 @@
   </p>
   <fig>
     <caption>lalune</caption>
-    <graphic mimetype="image" mime-subtype="peg" xlink:href="lalune.jpg" xlink:title="Voyage dans la Lune" />
+    <graphic mimetype="image" mime-subtype="jpeg" xlink:href="lalune.jpg" xlink:title="Voyage dans la Lune" />
   </fig>
   <p>
     Here is a movie
