diff --git a/.travis.yml b/.travis.yml
index f20042da7..ee594e6de 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -49,6 +49,10 @@ matrix:
     compiler: ": #GHC 8.2.2"
     addons: {apt: {packages: [cabal-install-2.0,ghc-8.2.2,happy-1.19.5], sources: [hvr-ghc]}}
 
+  - env: BUILD=cabal GHCVER=8.4.1 CABALVER=2.0 OPTS="-O0 -Wall -Wincomplete-record-updates -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -fno-warn-unused-do-bind -Werror" FLAGS="fast embed_data_files" CABALARGS="--enable-benchmarks"
+    compiler: ": #GHC 8.4.1"
+    addons: {apt: {packages: [cabal-install-2.0,ghc-8.4.1,happy-1.19.5], sources: [hvr-ghc]}}
+
   # Build with the newest GHC and cabal-install. This is an accepted failure,
   # see below.
   # - env: BUILD=cabal GHCVER=head  CABALVER=head CABALAGS="--allow-newer"
@@ -123,7 +127,7 @@ script:
     stack)
       ulimit -n 4096
       stack config set system-ghc --global true
-      stack --no-terminal $ARGS test --fast --flag 'aeson:fast' --flag pandoc:embed_data_files --haddock --no-haddock-deps --ghc-options="$OPTS"
+      stack --no-terminal $ARGS test --fast --flag 'aeson:fast' --flag pandoc:embed_data_files --haddock --no-haddock-deps --ghc-options="$OPTS" --test-arguments='--hide-successes'
       ;;
     cabal)
       cabal sdist --output-directory=sourcedist && \
diff --git a/AUTHORS.md b/AUTHORS.md
index a2c66d1e9..431deea10 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -1,5 +1,6 @@
 # Contributors
 
+- Anabra
 - Arata Mizuki
 - Aaron Wolen
 - Albert Krewinkel
@@ -49,8 +50,10 @@
 - Emily Eisenberg
 - Eric Kow
 - Eric Seidel
+- Étienne Bersac
 - Felix Yan
 - Florian Eitel
+- Francesco Occhipinti
 - François Gannaz
 - Freiric Barral
 - Freirich Raabe
@@ -83,6 +86,7 @@
 - Jens Getreu
 - Jens Petersen
 - Jesse Rosenthal
+- Joe Hermaszewski
 - Joe Hillenbrand
 - John MacFarlane
 - John Muccigrosso
@@ -129,6 +133,7 @@
 - Nick Bart
 - Nicolas Kaiser
 - Nikolay Yakimov
+- Nokome Bentley
 - Oliver Matthews
 - Ophir Lifshitz
 - Or Neeman
@@ -186,6 +191,7 @@
 - lwolfsonkin
 - nkalvi
 - oltolm
+- quasicomputational
 - qerub
 - robabla
 - roblabla
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 1145dd835..11a0c9c94 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -205,6 +205,10 @@ placed in the source directory):
 Profiling
 ---------
 
+To diagnose a performance issue with parsing, first try using
+the `--trace` option.  This will give you a record of when block
+parsers succeed, so you can spot backtracking issues.
+
 To use the GHC profiler with cabal:
 
     cabal clean
diff --git a/COPYRIGHT b/COPYRIGHT
index 711b8f299..320a5f72c 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -69,8 +69,9 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ----------------------------------------------------------------------
-Pandoc's templates (in `data/templates`) are dual-licensed GPL (v2 or
-higher, same as pandoc) and the BSD 3-clause license.
+Pandoc's templates (in `data/templates`) are dual-licensed as either
+GPL (v2 or higher, same as pandoc) or (at your option) the BSD
+3-clause license.
 
 Copyright (c) 2014--2018, John MacFarlane
 
@@ -118,6 +119,24 @@ Copyright (C) 2010-2018 Paul Rivier and John MacFarlane
 
 Released under the GNU General Public License version 2 or later.
 
+----------------------------------------------------------------------
+src/Text/Pandoc/Readers/TikiWiki.hs
+Copyright (C) 2017 Robin Lee Powell
+
+Released under the GNU General Public License version 2 or later.
+
+----------------------------------------------------------------------
+src/Text/Pandoc/Readers/JATS.hs
+Copyright (C) 2017-2018 Hamish Mackenzie
+
+Released under the GNU General Public License version 2 or later.
+
+----------------------------------------------------------------------
+src/Text/Pandoc/Readers/EPUB.hs
+Copyright (C) 2014-2018 Matthew Pickering
+
+Released under the GNU General Public License version 2 or later.
+
 ----------------------------------------------------------------------
 src/Text/Pandoc/Readers/Org.hs
 src/Text/Pandoc/Readers/Org/*
@@ -127,20 +146,12 @@ Copyright (C) 2014-2018 Albert Krewinkel
 Released under the GNU General Public License version 2 or later.
 
 ----------------------------------------------------------------------
-data/LaTeXMathML.js
-Adapted by Jeff Knisely and Douglas Woodall from
-ASCIIMathML.js v. 1.4.7
-Copyright (C) 2005 Peter Jipsen
+src/Text/Pandoc/Readers/FB2.hs
+Copyright (C) 2018 Alexander Krotov
 
 Released under the GNU General Public License version 2 or later.
 
 ----------------------------------------------------------------------
-data/MathMLinHTML.js
-Copyright (C) 2004 Peter Jipsen http://www.chapman.edu/~jipsen
-
-Released under the GNU General Public License version 2 or later.
-
-------------------------------------------------------------------------
 data/pandoc.lua
 Copyright (C) 2017-2018 Albert Krewinkel
 
diff --git a/INSTALL.md b/INSTALL.md
index 7e983d1c0..b299653d2 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -125,7 +125,7 @@ The easiest way to build pandoc from source is to use [stack]:
 2.  Change to the pandoc source directory and issue the following commands:
 
         stack setup
-        stack install --test
+        stack install
 
     `stack setup` will automatically download the ghc compiler
     if you don't have it.  `stack install` will install the
@@ -145,7 +145,7 @@ The easiest way to build pandoc from source is to use [stack]:
 
 3.  Use `cabal` to install pandoc and its dependencies:
 
-        cabal install pandoc --enable-tests
+        cabal install pandoc
 
     This procedure will install the released version of pandoc,
     which will be downloaded automatically from HackageDB.
@@ -272,6 +272,7 @@ test`.
 To run particular tests (pattern-matching on their names), use
 the `-p` option:
 
+    cabal install pandoc --enable-tests
     cabal test --test-options='-p markdown'
 
 Or with stack:
diff --git a/MANUAL.txt b/MANUAL.txt
index 144ec8494..42b658af9 100644
--- a/MANUAL.txt
+++ b/MANUAL.txt
@@ -1,6 +1,6 @@
 % Pandoc User's Guide
 % John MacFarlane
-% January 18, 2018
+% April 26, 2018
 
 Synopsis
 ========
@@ -13,37 +13,19 @@ Description
 Pandoc is a [Haskell] library for converting from one markup format to
 another, and a command-line tool that uses this library.
 
-Pandoc 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], [JATS], [Muse], [txt2tags], [Vimwiki],
-[EPUB], [ODT], and [Word docx].
-
-Pandoc 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], [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, `pdfroff`,
-`wkhtmltopdf`, `prince`, or `weasyprint` is installed.
+Pandoc can convert between numerous markup and word processing formats,
+including, but not limited to, various flavors of [Markdown], [HTML],
+[LaTeX] and [Word docx]. For the full lists of input and output formats,
+see the `--from` and `--to` [options below][General options].
+Pandoc can also produce [PDF] output: see [creating a PDF], below.
 
 Pandoc's enhanced version of Markdown includes syntax for [tables],
-[definition lists], [metadata blocks], [`Div` blocks][Extension:
-`fenced_divs`], [footnotes] and [citations], embedded
-[LaTeX][Extension: `raw_tex`] (including [math]), [Markdown inside HTML
-block elements][Extension: `markdown_in_html_blocks`], and much more.
-These enhancements, described further under [Pandoc's Markdown],
-can be disabled using the `markdown_strict` format.
+[definition lists], [metadata blocks], [footnotes], [citations], [math],
+and much more.  See below under [Pandoc's Markdown].
 
 Pandoc has a modular design: it consists of a set of readers, which parse
 text in a given format and produce a native representation of the document
-(like an _abstract syntax tree_ or AST), and a set of writers, which convert
+(an _abstract syntax tree_ or AST), and a set of writers, which convert
 this native representation into a target format. Thus, adding an input
 or output format requires only adding a reader or writer. Users can also
 run custom [pandoc filters] to modify the intermediate AST.
@@ -58,56 +40,6 @@ model.  While conversions from pandoc's Markdown to all formats aspire
 to be perfect, conversions from formats more expressive than pandoc's
 Markdown can be expected to be lossy.
 
-[Markdown]: http://daringfireball.net/projects/markdown/
-[CommonMark]: http://commonmark.org
-[PHP Markdown Extra]: https://michelf.ca/projects/php-markdown/extra/
-[GitHub-Flavored Markdown]: https://help.github.com/articles/github-flavored-markdown/
-[MultiMarkdown]: http://fletcherpenney.net/multimarkdown/
-[reStructuredText]: http://docutils.sourceforge.net/docs/ref/rst/introduction.html
-[S5]: http://meyerweb.com/eric/tools/s5/
-[Slidy]: http://www.w3.org/Talks/Tools/Slidy/
-[Slideous]: http://goessner.net/articles/slideous/
-[HTML]: http://www.w3.org/html/
-[HTML5]: http://www.w3.org/TR/html5/
-[polyglot markup]: https://www.w3.org/TR/html-polyglot/
-[XHTML]: http://www.w3.org/TR/xhtml1/
-[LaTeX]: http://latex-project.org
-[`beamer`]: https://ctan.org/pkg/beamer
-[Beamer User's Guide]: http://ctan.math.utah.edu/ctan/tex-archive/macros/latex/contrib/beamer/doc/beameruserguide.pdf
-[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
-[OpenDocument]: http://opendocument.xml.org
-[ODT]: http://en.wikipedia.org/wiki/OpenDocument
-[Textile]: http://redcloth.org/textile
-[MediaWiki markup]: https://www.mediawiki.org/wiki/Help:Formatting
-[DokuWiki markup]: https://www.dokuwiki.org/dokuwiki
-[ZimWiki markup]: http://zim-wiki.org/manual/Help/Wiki_Syntax.html
-[TWiki markup]: http://twiki.org/cgi-bin/view/TWiki/TextFormattingRules
-[TikiWiki markup]: https://doc.tiki.org/Wiki-Syntax-Text#The_Markup_Language_Wiki-Syntax
-[Haddock markup]: https://www.haskell.org/haddock/doc/html/ch03s08.html
-[Creole 1.0]: http://www.wikicreole.org/wiki/Creole1.0
-[groff man]: http://man7.org/linux/man-pages/man7/groff_man.7.html
-[groff ms]: http://man7.org/linux/man-pages/man7/groff_ms.7.html
-[Haskell]: https://www.haskell.org
-[GNU Texinfo]: http://www.gnu.org/software/texinfo/
-[Emacs Org mode]: http://orgmode.org
-[AsciiDoc]: http://www.methods.co.nz/asciidoc/
-[DZSlides]: http://paulrouget.com/dzslides/
-[Word docx]: https://en.wikipedia.org/wiki/Office_Open_XML
-[PDF]: https://www.adobe.com/pdf/
-[reveal.js]: http://lab.hakim.se/reveal-js/
-[FictionBook2]: http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1
-[InDesign ICML]: http://wwwimages.adobe.com/www.adobe.com/content/dam/acom/en/devnet/indesign/sdk/cs6/idml/idml-cookbook.pdf
-[TEI Simple]: https://github.com/TEIC/TEI-Simple
-[Muse]: https://amusewiki.org/library/manual
-[PowerPoint]: https://en.wikipedia.org/wiki/Microsoft_PowerPoint
-[Vimwiki]: https://vimwiki.github.io
-
 Using `pandoc`
 --------------
 
@@ -283,20 +215,42 @@ General options
 
 `-f` *FORMAT*, `-r` *FORMAT*, `--from=`*FORMAT*, `--read=`*FORMAT*
 
-:   Specify input format.  *FORMAT* can be `native` (native Haskell),
-    `json` (JSON version of native AST), `markdown` (pandoc's
-    extended Markdown), `markdown_strict` (original unextended
-    Markdown), `markdown_phpextra` (PHP Markdown Extra),
-    `markdown_mmd` (MultiMarkdown), `gfm` (GitHub-Flavored Markdown),
-    `commonmark` (CommonMark Markdown), `textile` (Textile), `rst`
-    (reStructuredText), `html` (HTML), `docbook` (DocBook), `t2t`
-    (txt2tags), `docx` (docx), `odt` (ODT), `epub` (EPUB), `opml` (OPML),
-    `org` (Emacs Org mode), `mediawiki` (MediaWiki markup), `twiki` (TWiki
-    markup), `tikiwiki` (TikiWiki markup), `creole` (Creole 1.0),
-    `haddock` (Haddock markup), or `latex` (LaTeX).
-    (`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`.)
+:   Specify input format.  *FORMAT* can be:
+
+    ::: {#input-formats}
+    - `commonmark` ([CommonMark] Markdown)
+    - `creole` ([Creole 1.0])
+    - `docbook` ([DocBook])
+    - `docx` ([Word docx])
+    - `epub` ([EPUB])
+    - `fb2` ([FictionBook2] e-book)
+    - `gfm` ([GitHub-Flavored Markdown]),
+      or `markdown_github`, which provides deprecated and less accurate
+      support for Github-Flavored Markdown; please use `gfm` instead,
+      unless you need to use extensions other than `smart`.
+    - `haddock` ([Haddock markup])
+    - `html` ([HTML])
+    - `jats` ([JATS] XML)
+    - `json` (JSON version of native AST)
+    - `latex` ([LaTeX])
+    - `markdown` ([Pandoc's Markdown])
+    - `markdown_mmd` ([MultiMarkdown])
+    - `markdown_phpextra` ([PHP Markdown Extra])
+    - `markdown_strict` (original unextended [Markdown])
+    - `mediawiki` ([MediaWiki markup])
+    - `muse` ([Muse])
+    - `native` (native Haskell)
+    - `odt` ([ODT])
+    - `opml` ([OPML])
+    - `org` ([Emacs Org mode])
+    - `rst` ([reStructuredText])
+    - `t2t` ([txt2tags])
+    - `textile` ([Textile])
+    - `tikiwiki` ([TikiWiki markup])
+    - `twiki` ([TWiki markup])
+    - `vimwiki` ([Vimwiki])
+    :::
+
     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
@@ -305,34 +259,64 @@ General options
 
 `-t` *FORMAT*, `-w` *FORMAT*, `--to=`*FORMAT*, `--write=`*FORMAT*
 
-:   Specify output format.  *FORMAT* can be `native` (native Haskell),
-    `json` (JSON version of native AST), `plain` (plain text),
-    `markdown` (pandoc's extended Markdown), `markdown_strict`
-    (original unextended Markdown), `markdown_phpextra` (PHP Markdown
-    Extra), `markdown_mmd` (MultiMarkdown), `gfm` (GitHub-Flavored
-    Markdown), `commonmark` (CommonMark Markdown), `rst`
-    (reStructuredText), `html4` (XHTML 1.0 Transitional), `html` or
-    `html5` (HTML5/XHTML [polyglot markup]), `latex` (LaTeX), `beamer`
-    (LaTeX beamer slide show), `context` (ConTeXt), `man` (groff man),
-    `mediawiki` (MediaWiki markup), `dokuwiki` (DokuWiki markup),
-    `zimwiki` (ZimWiki markup), `textile` (Textile), `org` (Emacs Org
-    mode), `texinfo` (GNU Texinfo), `opml` (OPML), `docbook` or
-    `docbook4` (DocBook 4), `docbook5` (DocBook 5), `jats` (JATS XML),
-    `opendocument` (OpenDocument), `odt` (OpenOffice text document),
-    `docx` (Word docx), `haddock` (Haddock markup), `rtf` (rich text
-    format), `epub2` (EPUB v2 book), `epub` or `epub3` (EPUB v3),
-    `fb2` (FictionBook2 e-book), `asciidoc` (AsciiDoc), `icml`
-    (InDesign ICML), `tei` (TEI Simple), `slidy` (Slidy HTML and
-    JavaScript slide show), `slideous` (Slideous HTML and JavaScript
-    slide show), `dzslides` (DZSlides HTML5 + JavaScript slide show),
-    `revealjs` (reveal.js HTML5 + JavaScript slide show), `s5` (S5
-    HTML and JavaScript slide show), `pptx` (PowerPoint slide show) or
-    the path of a custom lua writer (see [Custom writers],
-    below). (`markdown_github` provides deprecated and less accurate
-    support for Github-Flavored Markdown; please use `gfm` instead,
-    unless you use extensions that do not work with `gfm`.) Note that
-    `odt`, `docx`, and `epub` output will not be directed to *stdout*
-    unless forced with `-o -`. Extensions can be individually enabled or
+:   Specify output format.  *FORMAT* can be:
+
+    ::: {#output-formats}
+    - `asciidoc` ([AsciiDoc])
+    - `beamer` ([LaTeX beamer][`beamer`] slide show)
+    - `commonmark` ([CommonMark] Markdown)
+    - `context` ([ConTeXt])
+    - `docbook` or `docbook4` ([DocBook] 4)
+    - `docbook5` (DocBook 5)
+    - `docx` ([Word docx])
+    - `dokuwiki` ([DokuWiki markup])
+    - `epub` or `epub3` ([EPUB] v3 book)
+    - `epub2` (EPUB v2)
+    - `fb2` ([FictionBook2] e-book)
+    - `gfm` ([GitHub-Flavored Markdown]),
+      or `markdown_github`, which provides deprecated and less accurate
+      support for Github-Flavored Markdown; please use `gfm` instead,
+      unless you use extensions that do not work with `gfm`.
+    - `haddock` ([Haddock markup])
+    - `html` or `html5` ([HTML], i.e. [HTML5]/XHTML [polyglot markup])
+    - `html4` ([XHTML] 1.0 Transitional)
+    - `icml` ([InDesign ICML])
+    - `jats` ([JATS] XML)
+    - `json` (JSON version of native AST)
+    - `latex` ([LaTeX])
+    - `man` ([groff man])
+    - `markdown` ([Pandoc's Markdown])
+    - `markdown_mmd` ([MultiMarkdown])
+    - `markdown_phpextra` ([PHP Markdown Extra])
+    - `markdown_strict` (original unextended [Markdown])
+    - `mediawiki` ([MediaWiki markup])
+    - `ms` ([groff ms])
+    - `muse` ([Muse]),
+    - `native` (native Haskell),
+    - `odt` ([OpenOffice text document][ODT])
+    - `opml` ([OPML])
+    - `opendocument` ([OpenDocument])
+    - `org` ([Emacs Org mode])
+    - `plain` (plain text),
+    - `pptx` ([PowerPoint] slide show)
+    - `rst` ([reStructuredText])
+    - `rtf` ([Rich Text Format])
+    - `texinfo` ([GNU Texinfo])
+    - `textile` ([Textile])
+    - `slideous` ([Slideous] HTML and JavaScript slide show)
+    - `slidy` ([Slidy] HTML and JavaScript slide show)
+    - `dzslides` ([DZSlides] HTML5 + JavaScript slide show),
+    - `revealjs` ([reveal.js] HTML5 + JavaScript slide show)
+    - `s5` ([S5] HTML and JavaScript slide show)
+    - `tei` ([TEI Simple])
+    - `zimwiki` ([ZimWiki markup])
+    - the path of a custom lua writer, see [Custom writers] below
+    :::
+
+    Note that `odt`, `docx`, and `epub` output will not be directed
+    to *stdout* unless forced with `-o -`.
+
+    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.
@@ -424,6 +408,56 @@ General options
 
 :   Show usage message.
 
+[Markdown]: http://daringfireball.net/projects/markdown/
+[CommonMark]: http://commonmark.org
+[PHP Markdown Extra]: https://michelf.ca/projects/php-markdown/extra/
+[GitHub-Flavored Markdown]: https://help.github.com/articles/github-flavored-markdown/
+[MultiMarkdown]: http://fletcherpenney.net/multimarkdown/
+[reStructuredText]: http://docutils.sourceforge.net/docs/ref/rst/introduction.html
+[S5]: http://meyerweb.com/eric/tools/s5/
+[Slidy]: http://www.w3.org/Talks/Tools/Slidy/
+[Slideous]: http://goessner.net/articles/slideous/
+[HTML]: http://www.w3.org/html/
+[HTML5]: http://www.w3.org/TR/html5/
+[polyglot markup]: https://www.w3.org/TR/html-polyglot/
+[XHTML]: http://www.w3.org/TR/xhtml1/
+[LaTeX]: http://latex-project.org
+[`beamer`]: https://ctan.org/pkg/beamer
+[Beamer User's Guide]: http://ctan.math.utah.edu/ctan/tex-archive/macros/latex/contrib/beamer/doc/beameruserguide.pdf
+[ConTeXt]: http://www.contextgarden.net/
+[Rich Text Format]: 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
+[OpenDocument]: http://opendocument.xml.org
+[ODT]: http://en.wikipedia.org/wiki/OpenDocument
+[Textile]: http://redcloth.org/textile
+[MediaWiki markup]: https://www.mediawiki.org/wiki/Help:Formatting
+[DokuWiki markup]: https://www.dokuwiki.org/dokuwiki
+[ZimWiki markup]: http://zim-wiki.org/manual/Help/Wiki_Syntax.html
+[TWiki markup]: http://twiki.org/cgi-bin/view/TWiki/TextFormattingRules
+[TikiWiki markup]: https://doc.tiki.org/Wiki-Syntax-Text#The_Markup_Language_Wiki-Syntax
+[Haddock markup]: https://www.haskell.org/haddock/doc/html/ch03s08.html
+[Creole 1.0]: http://www.wikicreole.org/wiki/Creole1.0
+[groff man]: http://man7.org/linux/man-pages/man7/groff_man.7.html
+[groff ms]: http://man7.org/linux/man-pages/man7/groff_ms.7.html
+[Haskell]: https://www.haskell.org
+[GNU Texinfo]: http://www.gnu.org/software/texinfo/
+[Emacs Org mode]: http://orgmode.org
+[AsciiDoc]: http://www.methods.co.nz/asciidoc/
+[DZSlides]: http://paulrouget.com/dzslides/
+[Word docx]: https://en.wikipedia.org/wiki/Office_Open_XML
+[PDF]: https://www.adobe.com/pdf/
+[reveal.js]: http://lab.hakim.se/reveal-js/
+[FictionBook2]: http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1
+[InDesign ICML]: http://wwwimages.adobe.com/www.adobe.com/content/dam/acom/en/devnet/indesign/sdk/cs6/idml/idml-cookbook.pdf
+[TEI Simple]: https://github.com/TEIC/TEI-Simple
+[Muse]: https://amusewiki.org/library/manual
+[PowerPoint]: https://en.wikipedia.org/wiki/Microsoft_PowerPoint
+[Vimwiki]: https://vimwiki.github.io
+
 Reader options
 --------------
 
@@ -521,17 +555,27 @@ Reader options
 
         return {{Str = expand_hello_world}}
 
+    In order of preference, pandoc will look for lua filters in
+
+     1. a specified full or relative path (executable or
+     non-executable)
+
+     2. `$DATADIR/filters` (executable or non-executable)
+     where `$DATADIR` is the user data directory (see
+     `--data-dir`, above).
 
 `-M` *KEY*[`=`*VAL*], `--metadata=`*KEY*[`:`*VAL*]
 
 :   Set the metadata field *KEY* to the value *VAL*.  A value specified
-    on the command line overrides a value specified in the document.
+    on the command line overrides a value specified in the document
+    using [YAML metadata blocks][Extension: `yaml_metadata_block`].
     Values will be parsed as YAML boolean or string values. If no value is
     specified, the value will be treated as Boolean true.  Like
     `--variable`, `--metadata` causes template variables to be set.
     But unlike `--variable`, `--metadata` affects the metadata of the
     underlying document (which is accessible from filters and may be
-    printed in some output formats).
+    printed in some output formats) and metadata values will be escaped
+    when inserted into the template.
 
 `-p`, `--preserve-tabs`
 
@@ -598,7 +642,8 @@ General writer options
 :   Produce output with an appropriate header and footer (e.g. a
     standalone HTML, LaTeX, TEI, or RTF file, not a fragment).  This option
     is set automatically for `pdf`, `epub`, `epub3`, `fb2`, `docx`, and `odt`
-    output.
+    output.  For `native` output, this option causes metadata to
+    be included; otherwise, metadata is suppressed.
 
 `--template=`*FILE*
 
@@ -795,9 +840,10 @@ Options affecting specific writers
 
 `--ascii`
 
-:   Use only ASCII characters in output.  Currently supported only for
-    HTML and DocBook output (which uses numerical entities instead of
-    UTF-8 when this option is selected).
+:   Use only ASCII characters in output.  Currently supported for
+    XML and HTML formats (which use numerical entities instead of
+    UTF-8 when this option is selected) and for groff ms and man
+    (which use hexadecimal escapes).
 
 `--reference-links`
 
@@ -1171,54 +1217,8 @@ of the following options.
     not specified, a link to the KaTeX CDN will be inserted. Note that this
     option does not imply `--katex`.
 
-`-m` [*URL*], `--latexmathml`[`=`*URL*]
-
-:   *Deprecated.*
-    Use the [LaTeXMathML] script to display embedded TeX math in HTML output.
-    TeX math will be displayed between `$` or `$$` characters and put in
-    `<span>` tags with class `LaTeX`. The LaTeXMathML JavaScript will then
-    change it to MathML. Note that currently only Firefox and Safari
-    (and select e-book readers) natively support MathML.
-    To insert a link the `LaTeXMathML.js` script, provide a *URL*.
-
-`--jsmath`[`=`*URL*]
-
-:   *Deprecated.*
-    Use [jsMath] (the predecessor of MathJax) to display embedded TeX
-    math in HTML output. TeX math will be put inside `<span>` tags
-    (for inline math) or `<div>` tags (for display math) with class
-    `math` and rendered by the jsMath script. The *URL* should point to
-    the script (e.g. `jsMath/easy/load.js`); if provided, it will be linked
-    to in the header of standalone HTML documents. If a *URL* is not provided,
-    no link to the jsMath load script will be inserted; it is then
-    up to the author to provide such a link in the HTML template.
-
-`--gladtex`
-
-:   *Deprecated.*
-    Enclose TeX math in `<eq>` tags in HTML output.  The resulting HTML
-    can then be processed by [gladTeX] to produce images of the typeset
-    formulas and an HTML file with links to these images.
-    So, the procedure is:
-
-        pandoc -s --gladtex input.md -o myfile.htex
-        gladtex -d myfile-images myfile.htex
-        # produces myfile.html and images in myfile-images
-
-`--mimetex`[`=`*URL*]
-
-:   *Deprecated.*
-    Render TeX math using the [mimeTeX] CGI script, which generates an
-    image for each TeX formula. This should work in all browsers. If
-    *URL* is not specified, it is assumed that the script is at
-    `/cgi-bin/mimetex.cgi`.
-
 [MathML]: http://www.w3.org/Math/
-[LaTeXMathML]: http://math.etsu.edu/LaTeXMathML/
-[jsMath]: http://www.math.union.edu/~dpvc/jsmath/
 [MathJax]: https://www.mathjax.org
-[gladTeX]: http://ans.hsh.no/home/mgg/gladtex/
-[mimeTeX]: http://www.forkosh.com/mimetex.html
 [KaTeX]: https://github.com/Khan/KaTeX
 
 Options for wrapper scripts
@@ -1266,23 +1266,22 @@ directory (see `--data-dir`, above). *Exceptions:*
 - For `pdf` output, customize the `default.latex` template
   (or the `default.context` template, if you use `-t context`,
   or the `default.ms` template, if you use `-t ms`, or the
-  `default.html5` template, if you use `-t html5`).
+  `default.html` template, if you use `-t html`).
 - `docx` has no template (however, you can use
   `--reference-doc` to customize the output).
 
 Templates contain *variables*, which allow for the inclusion of
-arbitrary information at any point in the file. Variables may be set
-within the document using [YAML metadata blocks][Extension:
-`yaml_metadata_block`].  They may also be set at the
-command line using the `-V/--variable` option: variables set in this
-way override metadata fields with the same name.
+arbitrary information at any point in the file. They may be set at the
+command line using the `-V/--variable` option. If a variable is not set,
+pandoc will look for the key in the document's metadata – which can be set
+using either [YAML metadata blocks][Extension: `yaml_metadata_block`]
+or with the `--metadata` option.
 
 Variables set by pandoc
 -----------------------
 
 Some variables are set automatically by pandoc.  These vary somewhat
-depending on the output format, but include metadata fields as well
-as the following:
+depending on the output format, but include the following:
 
 `sourcefile`, `outputfile`
 :   source and destination filenames, as given on the command line.
@@ -1467,6 +1466,9 @@ LaTeX variables are used when [creating a PDF].
 :   option for document class, e.g. `oneside`; may be repeated
     for multiple options
 
+`beameroption`
+:   In beamer, add extra beamer option with `\setbeameroption{}`
+
 `geometry`
 :   option for [`geometry`] package, e.g. `margin=1in`;
     may be repeated for multiple options
@@ -1624,12 +1626,22 @@ Variables for ConTeXt
 `lof`, `lot`
 :   include list of figures, list of tables
 
+`pdfa`
+:   adds to the preamble the setup necessary to generate PDF/A-1b:2005.
+    To successfully generate PDF/A the required ICC color profiles have to
+    be available and the content and all included files (such as images)
+    have to be standard conforming.  The ICC profiles can be obtained
+    from [ConTeXt ICC Profiles].  See also [ConTeXt PDFA] for more
+    details.
+
 [ConTeXt Paper Setup]: http://wiki.contextgarden.net/PaperSetup
 [ConTeXt Layout]: http://wiki.contextgarden.net/Layout
 [ConTeXt Font Switching]: http://wiki.contextgarden.net/Font_Switching
 [ConTeXt Color]: http://wiki.contextgarden.net/Color
 [ConTeXt Headers and Footers]: http://wiki.contextgarden.net/Headers_and_Footers
 [ConTeXt Indentation]: http://wiki.contextgarden.net/Indentation
+[ConTeXt ICC Profiles]: http://wiki.contextgarden.net/PDFX#ICC_profiles
+[ConTeXt PDFA]: http://wiki.contextgarden.net/PDF/A
 [`setupwhitespace`]: http://wiki.contextgarden.net/Command/setupwhitespace
 [`setupinterlinespace`]: http://wiki.contextgarden.net/Command/setupinterlinespace
 [`setuppagenumbering`]: http://wiki.contextgarden.net/Command/setuppagenumbering
@@ -1689,10 +1701,24 @@ Templates may contain conditionals.  The syntax is as follows:
     Y
     $endif$
 
-This will include `X` in the template if `variable` has a non-null
-value; otherwise it will include `Y`. `X` and `Y` are placeholders for
-any valid template text, and may include interpolated variables or other
-conditionals. The `$else$` section may be omitted.
+This will include `X` in the template if `variable` has a truthy
+value; otherwise it will include `Y`. Here a truthy value is any
+of the following:
+
+- a string that is not entirely white space,
+- a non-empty array where the first value is truthy,
+- any number (including zero),
+- any object,
+- the boolean `true` (to specify the boolean `true`
+  value using YAML metadata or the `--metadata` flag,
+  use `y`, `Y`, `yes`, `Yes`, `YES`, `true`, `True`,
+  `TRUE`, `on`, `On`, or `ON`; with the `--variable`
+  flag, simply omit a value for the variable, e.g.
+  `--variable draft`).
+
+`X` and `Y` are placeholders for any valid template text,
+and may include interpolated variables or other conditionals.
+The `$else$` section may be omitted.
 
 When variables can have multiple values (for example, `author` in
 a multi-author document), you can use the `$for$` keyword:
@@ -1954,9 +1980,9 @@ ordinary HTML (without bird tracks).
 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.
+Note that GHC expects the bird tracks in the first column, so indented
+literate code blocks (e.g. inside an itemized environment) will not be
+picked up by the Haskell compiler.
 
 Other extensions
 ----------------
@@ -1972,7 +1998,7 @@ input formats
 :  `docx`, `html`
 
 output formats
-:  `markdown`, `docx`, `odt`, `opendocument`, `html`
+:  `docx`, `odt`, `opendocument`, `html`
 
 #### Extension: `styles` #### {#ext-styles}
 
@@ -3086,7 +3112,8 @@ the [`raw_attribute` extension](#extension-raw_attribute)), or it
 will be interpreted as markdown. For example:
 
     header-includes:
-    - ```{=latex}
+    - |
+      ```{=latex}
       \let\oldsection\section
       \renewcommand{\section}[1]{\clearpage\oldsection{#1}}
       ```
@@ -3405,9 +3432,24 @@ And the following produces a raw `html` inline element:
 
     This is `<a>html</a>`{=html}
 
+This can be useful to insert raw xml into `docx` documents, e.g.
+a pagebreak:
+
+    ```{=openxml}
+    <w:p>
+      <w:r>
+        <w:br w:type="page"/>
+      </w:r>
+    </w:p>
+    ```
+
 The format name should match the target format name (see
 `-t/--to`, above, for a list, or use `pandoc
---list-output-formats`).
+--list-output-formats`). Use `openxml` for `docx` output,
+`opendocument` for `odt` output, `html5` for `epub3` output,
+`html4` for `epub2` output, and `latex`, `beamer`,
+`ms`, or `html5` for `pdf` output (depending on what you
+use for `--pdf-engine`).
 
 This extension presupposes that the relevant kind of
 inline code or fenced code block is enabled.  Thus, for
@@ -4384,6 +4426,50 @@ the [Beamer User's Guide] may also be used: `allowdisplaybreaks`,
 `allowframebreaks`, `b`, `c`, `t`, `environment`, `label`, `plain`,
 `shrink`.
 
+Background in reveal.js
+-----------------------
+
+Background images can be added to self-contained reveal.js slideshows.
+
+For the same image on every slide, use the reveal.js configuration
+option `parallaxBackgroundImage` either in the YAML metadata block
+or as a command-line variable. You can also set
+`parallaxBackgroundHorizontal` and `parallaxBackgroundVertical` the same
+way and must also set `parallaxBackgroundSize` to have your values
+take effect.
+
+To set an image for a particular slide, add
+`{data-background-image="/path/to/image"}`
+to the first slide-level header on the slide (which may even be empty).
+
+In reveal.js's overview mode, the parallaxBackgroundImage will show up
+only on the first slide.
+
+Other background settings also work on individual slides, including
+`data-background-size`, `data-background-repeat`, `data-background-color`,
+`data-transition`, and `data-transition-speed`.
+
+See the [reveal.js
+documentation](https://github.com/hakimel/reveal.js#slide-backgrounds)
+for more details.
+
+For example:
+
+```
+---
+title: My Slideshow
+parallaxBackgroundImage: /path/to/my/background_image.png
+---
+
+## Slide One
+
+Slide 1 has background_image.png as its background.
+
+## {data-background-image="/path/to/special_image.jpg"}
+
+Slide 2 has a special image for its background, even though the header has no content.
+```
+
 Creating EPUBs with pandoc
 ==========================
 
@@ -4562,8 +4648,8 @@ And with the extension:
     :::
 
     ::: {custom-style="BodyText"}
-    This is text with an [*emphasized*]{custom-style="Emphatic"} text style.
-    And this is text with a [**strengthened**]{custom-style="Strengthened"}
+    This is text with an [emphasized]{custom-style="Emphatic"} text style.
+    And this is text with a [strengthened]{custom-style="Strengthened"}
     text style.
     :::
 
diff --git a/Makefile b/Makefile
index 330f83e87..8076421ad 100644
--- a/Makefile
+++ b/Makefile
@@ -54,9 +54,9 @@ debpkg: man/pandoc.1
 macospkg: man/pandoc.1
 	./macos/make_macos_package.sh
 
-winpkg: pandoc-$(version)-windows.msi pandoc-$(version)-windows.zip
+winpkg: pandoc-$(version)-windows-i386.msi pandoc-$(version)-windows-i386.zip pandoc-$(version)-windows-x86_64.msi pandoc-$(version)-windows-x86_64.zip
 
-pandoc-$(version)-windows.zip: pandoc-$(version)-windows.msi
+pandoc-$(version)-windows-%.zip: pandoc-$(version)-windows-%.msi
 	-rm -rf wintmp && \
 	msiextract -C wintmp $< && \
 	cd wintmp/"Program Files" && \
@@ -66,10 +66,17 @@ pandoc-$(version)-windows.zip: pandoc-$(version)-windows.msi
 	cd ../.. && \
 	rm -rf wintmp
 
-pandoc-$(version)-windows.msi:
-	wget 'https://ci.appveyor.com/api/projects/jgm/pandoc/artifacts/windows/pandoc-windows-i386.msi?branch=$(BRANCH)' -O pandoc.msi && \
-	osslsigncode sign -pkcs12 ~/Private/ComodoCodeSigning.exp2019.p12 -in pandoc.msi -i http://johnmacfarlane.net/ -t http://timestamp.comodoca.com/ -out $@ -askpass
-	rm pandoc.msi
+pandoc-$(version)-windows-%.msi: pandoc-windows-%.msi
+	osslsigncode sign -pkcs12 ~/Private/ComodoCodeSigning.exp2019.p12 -in $< -i http://johnmacfarlane.net/ -t http://timestamp.comodoca.com/ -out $@ -askpass
+	rm $<
+
+pandoc-windows-i386.msi:
+	JOBID=$(shell curl 'https://ci.appveyor.com/api/projects/jgm/pandoc' | jq -r '.build.jobs[0].jobId') && \
+	wget "https://ci.appveyor.com/api/buildjobs/$$JOBID/artifacts/windows%2F$@" -O $@
+
+pandoc-windows-x86_64.msi:
+	JOBID=$(shell curl 'https://ci.appveyor.com/api/projects/jgm/pandoc' | jq -r '.build.jobs[1].jobId') && \
+	wget "https://ci.appveyor.com/api/buildjobs/$$JOBID/artifacts/windows%2F$@" -O $@
 
 man/pandoc.1: MANUAL.txt man/pandoc.1.template
 	pandoc $< -f markdown-smart -t man -s --template man/pandoc.1.template \
diff --git a/README.md b/README.md
index 3f57b05aa..dc64421f1 100644
--- a/README.md
+++ b/README.md
@@ -22,93 +22,153 @@ groups](https://img.shields.io/badge/pandoc-discuss-red.svg?style=social)](https
 
 ## The universal markup converter
 
-<div id="description">
+Pandoc is a [Haskell](http://haskell.org) library for converting from
+one markup format to another, and a command-line tool that uses this
+library. It can convert *from*
 
-Pandoc is a [Haskell](https://www.haskell.org) library for converting
-from one markup format to another, and a command-line tool that uses
-this library.
+<div id="input-formats">
 
-Pandoc can read
-[Markdown](http://daringfireball.net/projects/markdown/),
-[CommonMark](http://commonmark.org), [PHP Markdown
-Extra](https://michelf.ca/projects/php-markdown/extra/),
-[GitHub-Flavored
-Markdown](https://help.github.com/articles/github-flavored-markdown/),
-[MultiMarkdown](http://fletcherpenney.net/multimarkdown/), and (subsets
-of) [Textile](http://redcloth.org/textile),
-[reStructuredText](http://docutils.sourceforge.net/docs/ref/rst/introduction.html),
-[HTML](http://www.w3.org/html/), [LaTeX](http://latex-project.org),
-[MediaWiki markup](https://www.mediawiki.org/wiki/Help:Formatting),
-[TWiki markup](http://twiki.org/cgi-bin/view/TWiki/TextFormattingRules),
-[TikiWiki
-markup](https://doc.tiki.org/Wiki-Syntax-Text#The_Markup_Language_Wiki-Syntax),
-[Creole 1.0](http://www.wikicreole.org/wiki/Creole1.0), [Haddock
-markup](https://www.haskell.org/haddock/doc/html/ch03s08.html),
-[OPML](http://dev.opml.org/spec2.html), [Emacs Org
-mode](http://orgmode.org), [DocBook](http://docbook.org),
-[JATS](https://jats.nlm.nih.gov),
-[Muse](https://amusewiki.org/library/manual),
-[txt2tags](http://txt2tags.org), [Vimwiki](https://vimwiki.github.io),
-[EPUB](http://idpf.org/epub),
-[ODT](http://en.wikipedia.org/wiki/OpenDocument), and [Word
-docx](https://en.wikipedia.org/wiki/Office_Open_XML).
+  - `commonmark` ([CommonMark](http://commonmark.org) Markdown)
+  - `creole` ([Creole 1.0](http://www.wikicreole.org/wiki/Creole1.0))
+  - `docbook` ([DocBook](http://docbook.org))
+  - `docx` ([Word docx](https://en.wikipedia.org/wiki/Office_Open_XML))
+  - `epub` ([EPUB](http://idpf.org/epub))
+  - `fb2`
+    ([FictionBook2](http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1)
+    e-book)
+  - `gfm` ([GitHub-Flavored
+    Markdown](https://help.github.com/articles/github-flavored-markdown/)),
+    or `markdown_github`, which provides deprecated and less accurate
+    support for Github-Flavored Markdown; please use `gfm` instead,
+    unless you need to use extensions other than `smart`.
+  - `haddock` ([Haddock
+    markup](https://www.haskell.org/haddock/doc/html/ch03s08.html))
+  - `html` ([HTML](http://www.w3.org/html/))
+  - `jats` ([JATS](https://jats.nlm.nih.gov) XML)
+  - `json` (JSON version of native AST)
+  - `latex` ([LaTeX](http://latex-project.org))
+  - `markdown` ([Pandoc’s Markdown](#pandocs-markdown))
+  - `markdown_mmd`
+    ([MultiMarkdown](http://fletcherpenney.net/multimarkdown/))
+  - `markdown_phpextra` ([PHP Markdown
+    Extra](https://michelf.ca/projects/php-markdown/extra/))
+  - `markdown_strict` (original unextended
+    [Markdown](http://daringfireball.net/projects/markdown/))
+  - `mediawiki` ([MediaWiki
+    markup](https://www.mediawiki.org/wiki/Help:Formatting))
+  - `muse` ([Muse](https://amusewiki.org/library/manual))
+  - `native` (native Haskell)
+  - `odt` ([ODT](http://en.wikipedia.org/wiki/OpenDocument))
+  - `opml` ([OPML](http://dev.opml.org/spec2.html))
+  - `org` ([Emacs Org mode](http://orgmode.org))
+  - `rst`
+    ([reStructuredText](http://docutils.sourceforge.net/docs/ref/rst/introduction.html))
+  - `t2t` ([txt2tags](http://txt2tags.org))
+  - `textile` ([Textile](http://redcloth.org/textile))
+  - `tikiwiki` ([TikiWiki
+    markup](https://doc.tiki.org/Wiki-Syntax-Text#The_Markup_Language_Wiki-Syntax))
+  - `twiki` ([TWiki
+    markup](http://twiki.org/cgi-bin/view/TWiki/TextFormattingRules))
+  - `vimwiki` ([Vimwiki](https://vimwiki.github.io))
 
-Pandoc can write plain text,
-[Markdown](http://daringfireball.net/projects/markdown/),
-[CommonMark](http://commonmark.org), [PHP Markdown
-Extra](https://michelf.ca/projects/php-markdown/extra/),
-[GitHub-Flavored
-Markdown](https://help.github.com/articles/github-flavored-markdown/),
-[MultiMarkdown](http://fletcherpenney.net/multimarkdown/),
-[reStructuredText](http://docutils.sourceforge.net/docs/ref/rst/introduction.html),
-[XHTML](http://www.w3.org/TR/xhtml1/),
-[HTML5](http://www.w3.org/TR/html5/), [LaTeX](http://latex-project.org)
-(including [`beamer`](https://ctan.org/pkg/beamer) slide shows),
-[ConTeXt](http://www.contextgarden.net/),
-[RTF](http://en.wikipedia.org/wiki/Rich_Text_Format),
-[OPML](http://dev.opml.org/spec2.html), [DocBook](http://docbook.org),
-[JATS](https://jats.nlm.nih.gov),
-[OpenDocument](http://opendocument.xml.org),
-[ODT](http://en.wikipedia.org/wiki/OpenDocument), [Word
-docx](https://en.wikipedia.org/wiki/Office_Open_XML), [GNU
-Texinfo](http://www.gnu.org/software/texinfo/), [MediaWiki
-markup](https://www.mediawiki.org/wiki/Help:Formatting), [DokuWiki
-markup](https://www.dokuwiki.org/dokuwiki), [ZimWiki
-markup](http://zim-wiki.org/manual/Help/Wiki_Syntax.html), [Haddock
-markup](https://www.haskell.org/haddock/doc/html/ch03s08.html),
-[EPUB](http://idpf.org/epub) (v2 or v3),
-[FictionBook2](http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1),
-[Textile](http://redcloth.org/textile), [groff
-man](http://man7.org/linux/man-pages/man7/groff_man.7.html), [groff
-ms](http://man7.org/linux/man-pages/man7/groff_ms.7.html), [Emacs Org
-mode](http://orgmode.org),
-[AsciiDoc](http://www.methods.co.nz/asciidoc/), [InDesign
-ICML](http://wwwimages.adobe.com/www.adobe.com/content/dam/acom/en/devnet/indesign/sdk/cs6/idml/idml-cookbook.pdf),
-[TEI Simple](https://github.com/TEIC/TEI-Simple),
-[Muse](https://amusewiki.org/library/manual),
-[PowerPoint](https://en.wikipedia.org/wiki/Microsoft_PowerPoint) slide
-shows and [Slidy](http://www.w3.org/Talks/Tools/Slidy/),
-[Slideous](http://goessner.net/articles/slideous/),
-[DZSlides](http://paulrouget.com/dzslides/),
-[reveal.js](http://lab.hakim.se/reveal-js/) or
-[S5](http://meyerweb.com/eric/tools/s5/) HTML slide shows. It can also
-produce [PDF](https://www.adobe.com/pdf/) output on systems where LaTeX,
-ConTeXt, `pdfroff`, `wkhtmltopdf`, `prince`, or `weasyprint` is
-installed.
+</div>
+
+It can convert *to*
+
+<div id="output-formats">
+
+  - `asciidoc` ([AsciiDoc](http://www.methods.co.nz/asciidoc/))
+  - `beamer` ([LaTeX beamer](https://ctan.org/pkg/beamer) slide show)
+  - `commonmark` ([CommonMark](http://commonmark.org) Markdown)
+  - `context` ([ConTeXt](http://www.contextgarden.net/))
+  - `docbook` or `docbook4` ([DocBook](http://docbook.org) 4)
+  - `docbook5` (DocBook 5)
+  - `docx` ([Word docx](https://en.wikipedia.org/wiki/Office_Open_XML))
+  - `dokuwiki` ([DokuWiki markup](https://www.dokuwiki.org/dokuwiki))
+  - `epub` or `epub3` ([EPUB](http://idpf.org/epub) v3 book)
+  - `epub2` (EPUB v2)
+  - `fb2`
+    ([FictionBook2](http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1)
+    e-book)
+  - `gfm` ([GitHub-Flavored
+    Markdown](https://help.github.com/articles/github-flavored-markdown/)),
+    or `markdown_github`, which provides deprecated and less accurate
+    support for Github-Flavored Markdown; please use `gfm` instead,
+    unless you use extensions that do not work with `gfm`.
+  - `haddock` ([Haddock
+    markup](https://www.haskell.org/haddock/doc/html/ch03s08.html))
+  - `html` or `html5` ([HTML](http://www.w3.org/html/), i.e.
+    [HTML5](http://www.w3.org/TR/html5/)/XHTML [polyglot
+    markup](https://www.w3.org/TR/html-polyglot/))
+  - `html4` ([XHTML](http://www.w3.org/TR/xhtml1/) 1.0 Transitional)
+  - `icml` ([InDesign
+    ICML](http://wwwimages.adobe.com/www.adobe.com/content/dam/acom/en/devnet/indesign/sdk/cs6/idml/idml-cookbook.pdf))
+  - `jats` ([JATS](https://jats.nlm.nih.gov) XML)
+  - `json` (JSON version of native AST)
+  - `latex` ([LaTeX](http://latex-project.org))
+  - `man` ([groff
+    man](http://man7.org/linux/man-pages/man7/groff_man.7.html))
+  - `markdown` ([Pandoc’s Markdown](#pandocs-markdown))
+  - `markdown_mmd`
+    ([MultiMarkdown](http://fletcherpenney.net/multimarkdown/))
+  - `markdown_phpextra` ([PHP Markdown
+    Extra](https://michelf.ca/projects/php-markdown/extra/))
+  - `markdown_strict` (original unextended
+    [Markdown](http://daringfireball.net/projects/markdown/))
+  - `mediawiki` ([MediaWiki
+    markup](https://www.mediawiki.org/wiki/Help:Formatting))
+  - `ms` ([groff
+    ms](http://man7.org/linux/man-pages/man7/groff_ms.7.html))
+  - `muse` ([Muse](https://amusewiki.org/library/manual)),
+  - `native` (native Haskell),
+  - `odt` ([OpenOffice text
+    document](http://en.wikipedia.org/wiki/OpenDocument))
+  - `opml` ([OPML](http://dev.opml.org/spec2.html))
+  - `opendocument` ([OpenDocument](http://opendocument.xml.org))
+  - `org` ([Emacs Org mode](http://orgmode.org))
+  - `plain` (plain text),
+  - `pptx`
+    ([PowerPoint](https://en.wikipedia.org/wiki/Microsoft_PowerPoint)
+    slide show)
+  - `rst`
+    ([reStructuredText](http://docutils.sourceforge.net/docs/ref/rst/introduction.html))
+  - `rtf` ([Rich Text
+    Format](http://en.wikipedia.org/wiki/Rich_Text_Format))
+  - `texinfo` ([GNU Texinfo](http://www.gnu.org/software/texinfo/))
+  - `textile` ([Textile](http://redcloth.org/textile))
+  - `slideous` ([Slideous](http://goessner.net/articles/slideous/) HTML
+    and JavaScript slide show)
+  - `slidy` ([Slidy](http://www.w3.org/Talks/Tools/Slidy/) HTML and
+    JavaScript slide show)
+  - `dzslides` ([DZSlides](http://paulrouget.com/dzslides/) HTML5 +
+    JavaScript slide show),
+  - `revealjs` ([reveal.js](http://lab.hakim.se/reveal-js/) HTML5 +
+    JavaScript slide show)
+  - `s5` ([S5](http://meyerweb.com/eric/tools/s5/) HTML and JavaScript
+    slide show)
+  - `tei` ([TEI Simple](https://github.com/TEIC/TEI-Simple))
+  - `zimwiki` ([ZimWiki
+    markup](http://zim-wiki.org/manual/Help/Wiki_Syntax.html))
+  - the path of a custom lua writer, see [Custom
+    writers](#custom-writers) below
+
+</div>
+
+Pandoc can also produce PDF output via LaTeX, Groff ms, or HTML.
 
 Pandoc’s enhanced version of Markdown includes syntax for tables,
-definition lists, metadata blocks, `Div` blocks, footnotes and
-citations, embedded LaTeX (including math), Markdown inside HTML block
-elements, and much more. These enhancements, described further under
-Pandoc’s Markdown, can be disabled using the `markdown_strict` format.
+definition lists, metadata blocks, footnotes, citations, math, and much
+more. See the User’s Manual below under [Pandoc’s
+Markdown](https://pandoc.org/MANUAL.html#pandocs-markdown).
 
 Pandoc has a modular design: it consists of a set of readers, which
 parse text in a given format and produce a native representation of the
-document (like an *abstract syntax tree* or AST), and a set of writers,
-which convert this native representation into a target format. Thus,
-adding an input or output format requires only adding a reader or
-writer. Users can also run custom [pandoc
-filters](http://pandoc.org/filters.html) to modify the intermediate AST.
+document (an *abstract syntax tree* or AST), and a set of writers, which
+convert this native representation into a target format. Thus, adding an
+input or output format requires only adding a reader or writer. Users
+can also run custom pandoc filters to modify the intermediate AST (see
+the documentation for [filters](https://pandoc.org/filters.html) and
+[lua filters](https://pandoc.org/lua-filters.html)).
 
 Because pandoc’s intermediate representation of a document is less
 expressive than many of the formats it converts between, one should not
@@ -120,8 +180,6 @@ While conversions from pandoc’s Markdown to all formats aspire to be
 perfect, conversions from formats more expressive than pandoc’s Markdown
 can be expected to be lossy.
 
-</div>
-
 ## Installing
 
 Here’s [how to install pandoc](INSTALL.md).
diff --git a/README.template b/README.template
index cf664647a..7b5d0b7b9 100644
--- a/README.template
+++ b/README.template
@@ -19,9 +19,44 @@ Pandoc
 The universal markup converter
 ------------------------------
 
-::: 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 convert *from*
+
+::: {#input-formats}
 :::
 
+It can convert *to*
+
+::: {#output-formats}
+:::
+
+Pandoc can also produce PDF output via LaTeX, Groff ms, or HTML.
+
+Pandoc's enhanced version of Markdown includes syntax for tables,
+definition lists, metadata blocks, footnotes, citations, math,
+and much more.  See the User's Manual below under
+[Pandoc's Markdown](https://pandoc.org/MANUAL.html#pandocs-markdown).
+
+Pandoc has a modular design: it consists of a set of readers, which parse
+text in a given format and produce a native representation of the document
+(an _abstract syntax tree_ or AST), and a set of writers, which convert
+this native representation into a target format. Thus, adding an input
+or output format requires only adding a reader or writer. Users can also
+run custom pandoc filters to modify the intermediate AST (see
+the documentation for [filters](https://pandoc.org/filters.html)
+and [lua filters](https://pandoc.org/lua-filters.html)).
+
+Because pandoc's intermediate representation of a document is less
+expressive than many of the formats it converts between, one should
+not expect perfect conversions between every format and every other.
+Pandoc attempts to preserve the structural elements of a document, but
+not formatting details such as margin size.  And some document elements,
+such as complex tables, may not fit into pandoc's simple document
+model.  While conversions from pandoc's Markdown to all formats aspire
+to be perfect, conversions from formats more expressive than pandoc's
+Markdown can be expected to be lossy.
+
+
 Installing
 ----------
 
@@ -52,3 +87,4 @@ License
 any kind.  (See COPYRIGHT for full copyright and warranty notices.)
 
 [GPL]: http://www.gnu.org/copyleft/gpl.html "GNU General Public License"
+[Haskell]: http://haskell.org
diff --git a/appveyor.yml b/appveyor.yml
index 0df7abf32..f0d4975f9 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,3 +1,4 @@
+image: Visual Studio 2013
 clone_folder: "c:\\pandoc"
 environment:
   global:
@@ -10,10 +11,10 @@ environment:
     STACK_ROOT: "c:\\sr32"
     STACK: "%STACK_ROOT%\\stack.exe"
     STACK_FLAGS: "--flag=hslua:lua_32bits"
-#  - STACK_VERSION: "windows-x86_64"
-#    STACK_ROOT: "c:\\sr64"
-#    STACK: "%STACK_ROOT%\\stack.exe"
-#    STACK_FLAGS: ""
+  - STACK_VERSION: "windows-x86_64"
+    STACK_ROOT: "c:\\sr64"
+    STACK: "%STACK_ROOT%\\stack.exe"
+    STACK_FLAGS: ""
 
 skip_commits:
   files:
diff --git a/benchmark/benchmark-pandoc.hs b/benchmark/benchmark-pandoc.hs
index 489d5c39b..db6c2eb9c 100644
--- a/benchmark/benchmark-pandoc.hs
+++ b/benchmark/benchmark-pandoc.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE TupleSections #-}
 {-
 Copyright (C) 2012-2018 John MacFarlane <jgm@berkeley.edu>
@@ -16,6 +17,7 @@ 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
 -}
+import Prelude
 import Text.Pandoc
 import qualified Text.Pandoc.UTF8 as UTF8
 import qualified Data.ByteString as B
diff --git a/benchmark/weigh-pandoc.hs b/benchmark/weigh-pandoc.hs
index d3cada8c0..efc446404 100644
--- a/benchmark/weigh-pandoc.hs
+++ b/benchmark/weigh-pandoc.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+import Prelude
 import Weigh
 import Text.Pandoc
 import Data.Text (Text)
diff --git a/changelog b/changelog
index d79a2094a..6f7b2419a 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,708 @@
+pandoc (2.2)
+
+  * New input format: `fb2` (FictionBook2) (Alexander Krotov).
+
+  * Make `--ascii` work for all XML formats (ICML, OPML, JATS,...),
+    and for `ms` and `man`.
+
+  * Remove deprecated `--latexmathml`, `--gladtex`, `--mimetex`, `--jsmath`, `-m`,
+    `--asciimathml` options.
+
+  * New module Text.Pandoc.Readers.FB2, exporting readFB2 (Alexander
+    Krotov, API change).
+
+  * Markdown reader:
+
+    + Allow empty key-value attributes, like `title=""` (#2944).
+    + Handle table w/o following blank line in fenced div (#4560).
+    + Remove "fallback" for `doubleQuote` parser.  Previously the
+      parser tried to be efficient -- if no end double quote was found,
+      it would just return the contents.  But this could backfire in a
+      case `**this should "be bold**`, since the fallback would return
+      the content `"be bold**` and the closing boldface delimiter
+      would never be encountered.
+    + Improve computation of the relative width of the last column in a
+      multiline table, so we can round-trip tables without constantly
+      shrinking the last column.
+
+  * EPUB reader:
+
+    + Fix images with space in file path (#4344).
+
+  * LaTeX reader:
+
+    + Properly resolve section numbers with `\ref` and chapters (#4529).
+    + Parse sloppypar environment (#4517, Marc Schreiber).
+    + Improve handling of raw LaTeX (for markdown etc.) (#4589, #4594).
+      Previously there were some bugs in how macros were handled.
+    + Support `\MakeUppercase`, `\MakeLowercase', `\uppercase`, `\lowercase`,
+      and also `\MakeTextUppercase` and `\MakeTextLowercase` from textcase
+      (#4959).
+
+  * Textile reader:
+
+    + Fixed tables with no body rows (#4513).
+      Previously these raised an exception.
+
+  * Mediawiki reader:
+
+    + Improve table parsing (#4508).  This fixes detection of table
+      attributes and also handles `!` characters in cells.
+
+  * DocBook reader:
+
+    + Properly handle title in `section` element (#4526).
+      Previously we just got `section_title` for `section` (though `sect1`,
+      `sect2`, etc. were handled properly).
+    + Read tex math as output by asciidoctor (#4569, Joe Hermaszewski).
+
+  * Docx reader:
+
+    + Combine adjacent CodeBlocks with the same attributes into
+      a single CodeBlock.  This prevents a multiline codeblock in
+      Word from being read as different paragraphs.
+
+  * RST reader:
+
+    + Allow < 3 spaces indent under directives (#4579).
+    + Fix anonymous redirects with backticks (#4598).
+
+  * Muse reader (Alexander Krotov):
+
+    + Add support for Text::Amuse multiline headings.
+    + Add `<math>` tag support.
+    + Add support for `<biblio>` and `<play>` tags.
+    + Allow links to have empty descriptions.
+    + Require block `<literal>` tags to be on separate lines.
+    + Allow `-` in anchors.
+    + Allow verse to be indented.
+    + Allow nested footnotes.
+    + Internal improvements.
+
+  * Muse writer (Alexander Krotov):
+
+    + Escape `>` only at the beginning of a line.
+    + Escape `]` in image title.
+    + Escape `]` brackets in URLs as `%5D`.
+    + Only escape brackets when necessary.
+    + Escape ordered list markers.
+    + Do not escape list markers unless preceded by space.
+    + Escape strings starting with space.
+    + Escape semicolons and markers after line break.
+    + Escape `;` to avoid accidental comments.
+    + Don't break headers, line blocks and tables with line breaks.
+    + Correctly output empty headings.
+    + Escape horizontal rule only if at the beginning of the line.
+    + Escape definition list terms starting with list markers.
+    + Place header IDs before header.
+    + Improve span writing.
+    + Do not join Spans in normalization.
+    + Don't align ordered list items.
+    + Remove key-value pairs from attributes before normalization.
+    + Enable `--wrap=preserve` for all tests by default.
+    + Reduced `<verbatim>` tags in output.
+    + Internal changes.
+
+  * RST writer:
+
+    + Use more consistent indentation (#4563).  Previously we
+      used an odd mix of 3- and 4-space indentation.  Now we use 3-space
+      indentation, except for ordered lists, where indentation must
+      depend on the width of the list marker.
+    + Flatten nested inlines (#4368, Francesco Occhipinti).
+      Nested inlines are not valid RST syntax, so we flatten them following
+      some readability criteria discussed in #4368.
+
+  * EPUB writer:
+
+    + Ensure that `pagetitle` is always set, even when structured titles
+      are used.  This prevents spurious warnings about empty title
+      elements (#4486).
+
+  * FB2 writer (Alexander Krotov):
+
+    + Output links inline instead of producing notes.  Previously all links
+      were turned into footnotes with unclickable URLs inside.
+    + Allow emphasis and notes in titles.
+    + Don't intersperse paragraph with empty lines.
+    + Convert metadata value `abstract` to book annotation.
+    + Use `<empty-line />` for `HorizontalRule` rather than `LineBreak`.
+      FB2 does not have a way to represent line breaks inside paragraphs;
+      previously we used `<empty-line />` elements, but these are not allowed
+      inside paragraphs.
+
+  * Powerpoint writer (Jesse Rosenthal):
+
+    + Handle Quoted Inlines (#4532).
+    + Simplify code with `ParseXml`.
+    + Allow fallback options when looking for placeholder type.
+    + Check reference-doc for all layouts.
+    + Simplify speaker notes logic.
+    + Change notes state to a simpler per-slide value.
+    + Remove `Maybe` from `SpeakerNotes` in `Slide`. `mempty`
+      means no speaker notes.
+    + Add tests for improved speaker notes.
+    + Handle speaker notes earlier in the conversion process.
+    + Keep notes with related blocks (#4477).  Some blocks automatically
+      split slides (imgs, tables, `column` divs). We assume that any
+      speaker notes immediately following these are connected to these
+      elements, and keep them with the related blocks, splitting after them.
+    + Remove `docProps/thumbnail.jpeg` in data dir (Jesse Rosenthal, #4588).
+      It contained a nonfree ICC color calibration profile and is not needed
+      for production of a powerpoint document.
+
+  * Markdown writer:
+
+    + Include a blank line at the end of the row in a single-row multiline
+      table, to prevent it from being interpreted as a simple table (#4578).
+
+  * CommonMark writer:
+
+    + Correctly ignore LaTeX raw blocks when `raw_tex` is not
+      enabled (#4527, quasicomputational).
+
+  * EPUB writer:
+
+    + Add `epub:type="footnotes"` to notes section in EPUB3 (#4489).
+
+  * LaTeX writer:
+
+    + In beamer, don't use format specifier for default ordered lists
+      (#4556).  This gives better results for styles that put ordered list
+      markers in boxes or circles.
+    + Update `\lstinline` delimiters (#4369, Tim Parenti).
+
+  * Ms writer:
+
+    + Use `\f[R]` rather than `\f[]` to reset font (#4552).
+    + Use `\f[BI]` and `\f[CB]` in headers, instead of `\f[I]` and `\f[C]`,
+      since the header font is automatically bold (#4552).
+    + Use `\f[CB]` rather than `\f[BC]` for monospace bold (#4552).
+    + Create pdf anchor for a Div with an identifier (#4515).
+    + Escape `/` character in anchor ids (#4515).
+    + Improve escaping for anchor ids: we now use _uNNN_ instead of uNNN
+      to avoid ambiguity.
+
+  * Man writer:
+
+    + Don't escape U+2019 as `'` (#4550).
+
+  * Text.Pandoc.Options:
+
+    + Removed `JsMath`, `LaTeXMathML`, and `GladTeX` constructors from
+    `Text.Pandoc.Options.HTMLMathMethod` [API change].
+
+  * Text.Pandoc.Class:
+
+    + `writeMedia`: unescape URI-escaping in file path.  This avoids
+      writing things like `file%20one.png` to the file system.
+
+  * Text.Pandoc.Parsing:
+
+    + Fix `romanNumeral` parser (#4480).  We previously accepted 'DDC'
+      as 1100.
+    + `uri`: don't treat `*` characters at end as part of URI (#4561).
+
+  * Text.Pandoc.MIME:
+
+    + Use the alias `application/eps` for EPS (#2067).
+      This will ensure that we retain the eps extension after reading the
+      image into a mediabag and writing it again.
+
+  * Text.Pandoc.PDF:
+
+    + Use `withTempDir` in `html2pdf`.
+    + With `xelatex`, don't compress images til the last run (#4484).
+      This saves time for image-heavy documents.
+    + Don't try to convert EPS files (#2067).  `pdflatex` converts them
+      itself, and JuicyPixels can't do it.
+    + For `pdflatex`, use a temp directory in the working directory.
+      Otherwise we can have problems with the EPS conversion pdflatex
+      tries to do, which can't operate on a file above the working
+      directory without `--shell-escape`.
+
+  * Changes to tests to accommodate changes in pandoc-types.
+    In <https://github.com/jgm/pandoc-types/pull/36> we changed
+    the table builder to pad cells.  This commit changes tests
+    (and two readers) to accord with this behavior.
+
+  * Set default extensions for `beamer` same as `latex`.
+
+  * LaTeX template:
+
+    + Add `beameroption` variable (#4359, Étienne Bersac).
+    + Use `pgfpages` package; this is needed for notes on second
+      screen in beamer (Étienne Bersac).
+    + Add `background-image` variable (#4601, John Muccigrosso).
+
+  * reveal.js template: Add `background-image` variable (#4600,
+    John Muccigrosso).
+
+  * ms template: Fix date.  Previously `.ND` was used, but this only
+    works if you have a title page, which we don't.  Thanks to @teoric.
+
+  * Removed pragmas for unused extensions (#4506, Anabra).
+
+  * Fix bash completion for `--print-default-data-file` (#4549).
+    Previously this looked in the filesystem, even if pandoc
+    was compiled with `embed_data_files` (and sometimes it looked
+    in a nonexistent build directory).  Now the bash completion
+    script just includes a hard-coded list of data file names.
+
+  * MANUAL:
+
+    + Clarify template vs metadata variables (#4501, Mauro Bieg).
+    + Fix raw content example (#4479, Mauro Bieg).
+    + Specify that you use html for raw output in epub.
+    + Add examples for raw docx blocks (#4472, Tristan Stenner).
+      The documentation states that the target format name should match
+      the output format, which isn't the case for `docx`/`openxml` and
+      some others.
+    + Don't say that `empty_paragraphs` affects markdown output (#4540).
+    + Consolidate input/output format documentation (#4577, Mauro Bieg).
+
+  * New README template. Take in/out formats from manual.
+
+  * Fix example in lua-filters docs (#4459, HeirOfNorton).
+
+  * Use the `-threaded` GHC flag when building benchmarks (#4587,
+    Francesco Occhipinti).
+
+  * Bump temporary upper bound to 1.4.
+
+  * Use pandoc-citeproc 0.14.3.1.
+
+  * Use texmath-0.10.1.2 (fixes escapes in math in ms, #4597).
+
+  * Removed old lib directory.  This was used for something long ago,
+    but plays no role now.
+
+  * Removed unneeded data file `LaTeXMathML.js`.
+
+  * Create 64- and 32-bit versions of Windows binary packages.
+
+pandoc (2.1.3)
+
+  * Docx reader (Jesse Rosenthal):
+
+    + Add tests for nested smart tags.
+    + Parse nested smart tags.
+    + Make unwrapSDT into a general `unwrap` function that can unwrap both
+      nested SDT tags and smartTags. This makes the SmartTags constructor in
+      the Docx type unnecessary, so we remove it (#4446).
+    + Remove unused `docxWarnings` (Alexander Krotov).
+
+  * RST reader: Allow unicode bullet characters (#4454).
+
+  * Haddock reader:  Better table handling, using haddock-library's
+    new table support, if compiled against a version that
+    includes it.  Note that tables with col/rowspans will not
+    translate well into Pandoc.
+
+  * Muse reader (Alexander Krotov):
+
+    + Require closing tag to have the same indentation as opening.
+    + Do not reparse blocks inside unclosed block tag (#4425).
+    + Parse `<class>` tag (supported by Emacs Muse).
+    + Do not produce empty Str element for unindented verse lines.
+    + Don't allow footnote references inside links.
+    + Allow URL to be empty.
+    + Require that comment semicolons are in the first column (#4551).
+    + Various internal improvements.
+
+  * LaTeX reader:
+
+    + Add support to parse unit string of `\SI` command (closes #4296,
+      Marc Schreiber).
+
+  * Haddock writer:  In the writer, we now render tables always as
+    grid tables, since Haddock supports these.
+
+  * DokuWiki writer: rewrite backSlashLineBreaks (#4445, Mauro Bieg).
+
+  * Docx writer: Fixed formatting of `DefaultStyle` ordered lists in
+    docx writer.  We want decimal for the top level, not lower roman.
+
+  * RST writer:
+
+    + Strip whitespace at beginning and ending of inline containers
+      (#4327, Francesco Occhipinti).
+    + Filter out empty inline containers (#4434).  There is nothing in
+      RST that corresponds to e.g. `Emph []`, so we just ignore elements
+      like this (Francesco Occhipinti).
+
+  * Muse writer (Alexander Krotov):
+
+    + Support spans with anchors.
+    + Replace smallcaps with emphasis before normalization.
+    + Output smallcaps as emphasis.
+    + Expand Cite before list normalization.
+    + Write empty inline lists as `<verbatim></verbatim>`.
+    + Remove empty Str from the beginning of inline lists during normalization.
+    + Escape "-" to avoid creating bullet lists.
+    + Fix math expansion for more than one expression per paragraph.
+    + Expand math before inline list normalization.
+
+  * Dokuwiki writer: fix LineBreaks in Tables (#4313, Mauro Bieg).
+
+  * Ms writer:
+
+    + Asciify pdf anchors, since unicode anchors don't work (#4436).
+      Internal links should be converted automatically, so this shouldn't
+      affect users directly.
+    + Don't escape hyphens as `\-`; that's for a minus sign (#4467).
+
+  * Beamer writer: put hyperlink after `\begin{frame}` and not in the title
+    (#4307).  If it's in the title, then we get a titlebar on slides with
+    the `plain` attribute, when the id is non-null.  This fixes a regression
+    in 2.0.
+
+  * EPUB writer: Remove notes from TOC in nav.xhtml (#4453, Mauro Bieg).
+
+  * JATS writer: Remove extraneous, significant whitespace (#4335,
+    Nokome Bentley).
+
+  * html2pdf: inject base tag wih current working directory (#4413, Mauro
+    Bieg).  This helps ensure that linked resources are included.
+
+  * Add Semigroup instances for everything for which we defined a
+    Monoid instance previously (API change):
+
+    + Text.Pandoc.Class.FileTree.
+    + Text.Pandoc.Translations.Translations.
+    + Text.Pandoc.Extensions.Extensions.
+    + Text.Pandoc.Readers.Odt.StyleReader.Styles.
+    + Text.Pandoc.Pretty.Doc.
+    + Text.Pandoc.MediaBag.MediaBag.
+
+  * Add custom Prelude to give clean code for Monoid and Semigroup
+    that works with ghc 7.10-8.4.  The custom Prelude (`prelude/Prelude`)
+    is used for ghc versions < 8.4.  `NoImplicitPrelude` is used
+    in all source files, and Prelude is explicitly imported
+    (this is necessary for ghci to work properly with the custom prelude).
+
+  * Text.Pandoc.Writers.Shared (Francesco Occhipinti):
+
+    + Export `stripLeadingTrailingSpace`.
+    + Don't wrap lines in grid tables when `--wrap=none` (#4320).
+    + `gridTable`: Don't wrap lines in tables when `--wrap=none`.  Instead,
+      expand cells, even if it results in cells that don't respect relative
+      widths or surpass page column width.  This change affects RST,
+      Markdown, and Haddock writers.
+
+  * Raise error if someone tries to print docx, odt, etc. template (#4441).
+
+  * LaTeX template: Provide `bidi` package's option using
+    `\PassOptionsToPackage`  (#4357, Václav Haisman).  This avoid a
+    clash when   `polyglossia` loads it first and then it is loaded again
+    for XeLaTeX.
+
+  * ConTeXt template: Added `pdfa` variable to generate PDF/A (#4294, Henri
+    Menke).  Instructions on how to install the ICC profiles on ConTeXt
+    standalone can be found in the wiki:
+    <http://wiki.contextgarden.net/PDFX#ICC_profiles>.
+    If the ICC profiles are not available the log will contain error
+    messages.
+
+  * Use latest pandoc-types, skylighting
+
+  * Use latest pandoc-citeproc in binary package.
+
+  * Bump upper bound for time, criterion, haddock-library, exceptions,
+    http-types, aeson, haddock-library.
+
+  * Bump upper bound tasty-quickcheck 0.10 (#4429, Felix Yan).
+
+  * pandoc.cabal:  fix up other-extensions and language fields.
+    Language is now consistently `Haskell2010`, and other-extensions
+    is consistently `NoImplicitPrelude`. Everything else to be specified
+    in the module header as needed.
+
+  * Removed `old-locale` flag and Text.Pandoc.Compat.Time.
+    This is no longer necessary since we no longer support ghc 7.8.
+
+  * Make `weigh-pandoc` into a benchmark program.
+    Remove `weigh-pandoc` flag.  `weigh-pandoc` is now built (and run)
+    automatically when you build (and run) benchmarks.
+
+  * MANUAL: add instructions for background images reveal.js (#4325, John
+    Muccigrosso).
+
+  * appveyor: use VS 2013 environment instead of VS 2015 for Windows builds.
+
+
+pandoc (2.1.2)
+
+  * Markdown reader:
+
+    + Fix parsing bug with nested fenced divs (#4281).  Previously we allowed
+      "nonindent spaces" before the opening and closing `:::`, but this
+      interfered with list parsing, so now we require the fences to be flush with
+      the margin of the containing block.
+
+  * Commonmark reader:
+
+    + `raw_html` is now on by default.  It can be disabled explicitly
+      using `-f commonmark-raw_html`.
+
+  * Org reader (Albert Krewinkel):
+
+    + Move citation tests to separate module.
+    + Allow changing emphasis syntax (#4378).  The characters allowed before
+      and after emphasis can be configured via `#+pandoc-emphasis-pre` and
+      `#+pandoc-emphasis-post`, respectively. This allows to change which
+      strings are recognized as emphasized text on a per-document or even
+      per-paragraph basis.  Example:
+
+          #+pandoc-emphasis-pre: "-\t ('\"{"
+          #+pandoc-emphasis-post: "-\t\n .,:!?;'\")}["
+
+  * LaTeX reader:
+
+    + Fixed comments inside citations (#4374).
+    + Fix regression in package options including underscore (#4424).
+    + Make `--trace` work.
+    + Fixed parsing of `tabular*` environment (#4279).
+
+  * RST reader:
+
+    + Fix regression in parsing of headers with trailing space (#4280).
+
+  * Muse reader (Alexander Krotov):
+
+    + Enable `<literal>` tags even if amuse extension is enabled.
+      Amusewiki disables <literal> tags for security reasons.
+      If user wants similar behavior in pandoc, RawBlocks and RawInlines
+      can be removed or replaced with filters.
+    + Remove space prefix from `<literal>` tag contents.
+    + Do not consume whitespace while looking for closing end tag.
+    + Convert alphabetical list markers to decimal in round-trip test.
+      Alphabetical lists are an addition of Text::Amuse.
+      They are not present in Emacs Muse and can be ambiguous
+      when list starts with "i.", "c." etc.
+    + Allow `<quote>` and other tags to be indented.
+    + Allow single colon in definition list term.
+    + Fix parsing of verse in lists.
+    + Improved parsing efficiency.  Avoid `parseFromString`.
+      Lists are parsed in linear instead of exponential time now.
+    + Replace ParserState with MuseState.
+    + Prioritize lists with roman numerals over alphabetical lists.
+      This is to make sure "i." starts a roman numbered list,
+      instead of a list with letter "i" (followed by "j", "k", ...").
+    + Fix directive parsing.
+    + Parse definition lists with multiple descriptions.
+    + Parse next list item before parsing more item contents.
+    + Fixed a bug: headers did not terminate lists.
+    + Move indentation parsing from `definitionListItem` to `definitionList`.
+    + Paragraph indentation does not indicate nested quote.
+      Muse allows indentation to indicate quotation or alignment,
+      but only on the top level, not within a <quote> or list.
+    + Require that block tags are on separate lines.
+      Text::Amuse already explicitly requires it anyway.
+    + Fix matching of closing inline tags.
+    + Various internal changes.
+    + Fix parsing of nested definition lists.
+    + Require only one space for nested definition list indentation.
+    + Do not remove trailing whitespace from `<code>`.
+    + Fix parsing of trailing whitespace.  Newline after whitespace now
+      results in softbreak instead of space.
+
+  * Docx reader (Jesse Rosenthal, except where noted):
+
+    + Handle nested sdt tags (#4415).
+    + Don't look up dependant run styles if `+styles` is enabled.
+    + Move pandoc inline styling inside custom-style span.
+    + Read custom styles (#1843).  This will read all paragraph and
+      character classes as divs and spans, respectively. Dependent styles
+      will still be resolved, but will be wrapped with appropriate style
+      tags. It is controlled by the `+styles` extension (`-f docx+styles`).
+      This can be used in conjunction with the `custom-style` feature in the
+      docx writer for a pandoc-docx editing workflow. Users can convert from
+      an input docx, reading the custom-styles, and then use that same input
+      docx file as a reference-doc for producing an output docx file. Styles
+      will be maintained across the conversion, even if pandoc doesn't
+      understand them.
+    + Small change to Fields hyperlink parser.  Previously, unquoted string
+      required a space at the end of the line (and consumed it). Now we
+      either take a space (and don't consume it), or end of input.
+    + Pick table width from the longest row or header (Francesco Occhipinti,
+      #4360).
+
+  * Muse writer (Alexander Krotov):
+
+    + Change verse markup: `> ` instead of `<verse>` tag.
+    + Remove empty strings during inline normalization.
+    + Don't indent nested definition lists.
+    + Use unicode quotes for quoted text.
+    + Write image width specified in percent in Text::Amuse mode.
+    + Don't wrap displayMath into `<verse>`.
+    + Escape nonbreaking space (`~~`).
+    + Join code with different attributes during normalization.
+    + Indent lists inside Div.
+    + Support definitions with multiple descriptions.
+
+  * Powerpoint writer (Jesse Rosenthal):
+
+    + Use table styles This will use the default table style in the
+      reference-doc file. As a result they will be easier when using
+      in a template, and match the color scheme.
+    + Remove empty slides.  Because of the way that slides were split, these
+      could be accidentally produced by comments after images.  When animations
+      are added, there will be a way to add an empty slide with either
+      incremental lists or pauses.
+    + Implement syntax highlighting.  Note that background colors can't
+      be implemented in PowerPoint, so highlighting styles that require
+      these will be incomplete.
+    + New test framework for pptx.  We now compare the output of the
+      Powerpoint writer with files that we know to (a) not be corrupt,
+      and (b) to show the desired output behavior (details below).
+    + Add `notesMaster` to `presentation.xml` if necessary.
+    + Ignore links and (end)notes in speaker notes.
+    + Output speaker notes.
+    + Read speaker note templates conditionally.  If there are speaker
+      notes in the presentation, we read in the notesMasters templates
+      from the reference pptx file.
+    + Fix deletion track changes (#4303, Jesse Rosenthal).
+
+  * Markdown writer: properly escape @ to avoid capture as citation
+    (#4366).
+
+  * LaTeX writer:
+
+    + Put hypertarget inside figure environment (#4388).
+      This works around a problem with the endfloat package and
+      makes pandoc's output compatible with it.
+    + Fix image height with percentage (#4389).  This previously caused
+      the image to be resized to a percentage of textwidth, rather than
+      textheight.
+
+  * ConTeXt writer (Henri Menke):
+
+    + New section syntax and support `--section-divs` (#2609).
+      `\section[my-header]{My Header}` ->
+      `\section[title={My Header},reference={my-header}]`.
+      The ConTeXt writer now supports the `--section-divs` option to
+      write sections in the fenced style, with `\startsection` and
+      `\stopsection`.
+    + xtables: correct wrong usage of caption (Henri Menke).
+
+  * Docx writer:
+
+    + Fix image resizing with multiple images (#3930, Andrew Pritchard).
+    + Use new golden framework (Jesse Rosenthal).
+    + Make more deterministic to facilitate testing (Jesse Rosenthal).
+      - `getUniqueId` now calls to the state to get an incremented digit,
+        instead of calling to P.uniqueHash.
+      - we always start the PRNG in mkNumbering/mkAbstractNum with the same
+        seed (1848), so our randoms should be the same each time.
+    + Fix ids in comment writing (Jesse Rosenthal).  Comments from
+      `--track-changes=all` were producing corrupt docx, because the
+      writer was trying to get id from the `(ID,_,_)` field of
+      the attributes, and ignoring the "id" entry in the key-value pairs. We
+      now check both.
+
+  * Ms writer: Added papersize variable.
+
+  * TEI writer:
+
+    + Use `height` instead of `depth` for images (#4331).
+    + Ensure that id prefix is always used.
+    + Don't emit `role` attribute; that was a leftover from the
+      Docbook writer.
+    + Use 'xml:id', not 'id' attribute (#4371).
+
+  * AsciiDoc writer:
+
+    + Do not output implicit heading IDs (#4363, Alexander
+      Krotov).  Convert to `asciidoc-auto_identifiers` for old behaviour.
+
+  * RST writer:
+
+    + Remove `blockToRST'` moving its logic into `fixBlocks`
+      (Francesco Occhipinti).
+    + Insert comment between lists and quotes (#4248, Francesco Occchipinti).
+
+  * RST template: remove definition of 'math' role as raw.
+    This used to be needed prior to v 0.8 of docutils, but
+    now math support is built-in.
+
+  * Slides: Use divs to set incremental/non-incremental (#4381,
+    Jesse Rosenthal).  The old method (list inside blockquote) still
+    works, but we are encouraging the use of divs with class
+    `incremental` or `nonincremental`.
+
+  * Text.Pandoc.ImageSize:
+
+    + Make image size detection for PDFs more robust (#4322).
+    + Determine image size for PDFs (#4322).
+    + EMF Image size support (#4375, Andrew Pritchard).
+
+  * Text.Pandoc.Extensions:
+
+    + Add `Ext_styles` (Jesse Rosenthal, API change).  This will be used in
+      the docx reader (defaulting to off) to read pargraph and character
+      styles not understood by pandoc (as divs and spans, respectively).
+    + Made `Ext_raw_html` default for `commonmark` format.
+
+  * Text.Pandoc.Parsing:
+
+    + Export `manyUntil` (Alexander Krotov, API change).
+    + Export improved `sepBy1` (Alexander Krotov).
+    + Export list marker parsers: `upperRoman`, `lowerRoman`,
+      `decimal`, `lowerAlpha`, `upperAlpha` (Alexander Krotov, API change).
+
+  * Tests/Lua: fix tests on windows (Albert Krewinkel).
+
+  * Lua: register script name in global variable (#4393).  The name of the Lua
+    script which is executed is made available in the global Lua variable
+    `PANDOC_SCRIPT_FILE`, both for Lua filters and custom writers.
+
+  * Tests: Abstract powerpoint tests out to OOXML tests (Jesse Rosenthal).
+    There is very little pptx-specific in these tests, so we abstract out
+    the basic testing function so it can be used for docx as well. This
+    should allow us to catch some errors in the docx writer that slipped
+    by the roundtrip testing.
+
+  * Lua filters: store constructors in registry (Albert Krewinkel).  Lua
+    functions used to construct AST element values are stored in the Lua
+    registry for quicker access. Getting a value from the registry is much
+    faster than getting a global value (partly to idiosyncrasies of hslua);
+    this change results in a considerable performance boost.
+
+  * Documentation:
+
+    + `doc/org.md` Add draft of Org-mode documentation (Albert Krewinkel).
+    + `doc/lua-filters.md`: document global vars set for filters
+      (Albert Krewinkel).
+    + INSTALL.md: mention Stack version. (#4343, Adam Brandizzi).
+    + MANUAL: add documentation on custom styles (Jesse Rosenthal).
+    + MANUAL.txt: Document incremental and nonincremental divs (Jesse
+      Rosenthal).  Blockquoted lists are still described, but fenced divs are
+      presented in preference.
+    + MANUAL.txt: document header and footer variables (newmana).
+    + MANUAL.txt: self-contained implies standalone (#4304, Daniel Lublin).
+    + CONTRIBUTING.md: label was renamed. (#4310, Alexander Brandizzi).
+
+  * Require tagsoup 0.14.3 (#4282), fixing HTML tokenization bug.
+
+  * Use latest texmath.
+
+  * Use latest pandoc-citeproc.
+
+  * Allow exceptions 0.9.
+
+  * Require aeson-pretty 0.8.5 (#4394).
+
+  * Bump blaze-markup, blaze-html lower bounds to 0.8, 0.9 (#4334).
+
+  * Update tagsoup to 0.14.6 (Alexander Krotov, #4282).
+
+  * Removed ghc-prof-options.  As of cabal 1.24, sensible defaults are used.
+
+  * Update default.nix to current nixpkgs-unstable for hslua-0.9.5 (#4348,
+    jarlg).
+
+
 pandoc (2.1.1)
 
   * Markdown reader:
@@ -1299,7 +2004,7 @@ pandoc (2.0)
     directory.  However, the working directory must be explicitly
     specified if the `--resource-path` option is used.
 
-  * Added --abbreviations=FILE option for custom abbreviations file
+  * Added `--abbreviations=FILE` option for custom abbreviations file
     (#256).  Default abbreviations file (`data/abbreviations`) contains
     a list of strings that will be recognized by pandoc's
     Markdown parser as abbreviations.  (A nonbreaking space will
@@ -1704,7 +2409,7 @@ pandoc (2.0)
   * HTML reader: parse a span with class `smallcaps` as `SmallCaps`.
 
   * LaTeX reader:
- 
+
     + Implemented `\graphicspath` (#736).
     + Properly handle column prefixes/suffixes.  For example, in
       `\begin{tabular}{>{$}l<{$}>{$}l<{$} >{$}l<{$}}`
diff --git a/data/LaTeXMathML.js b/data/LaTeXMathML.js
deleted file mode 100644
index 4957624de..000000000
--- a/data/LaTeXMathML.js
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
-LaTeXMathML.js from http://math.etsu.edu/LaTeXMathML/
-Adapted by Jeff Knisely and Douglas Woodall from ASCIIMathML.js v. 1.4.7,
-(c) 2005 Peter Jipsen http://www.chapman.edu/~jipsen.
-Released under the GNU General Public License version 2 or later.
-See the GNU General Public License (at http://www.gnu.org/copyleft/gpl.html)
-for more details.
-*/
-var checkForMathML=true;var notifyIfNoMathML=true;var alertIfNoMathML=false;var mathcolor="";var mathfontfamily="";var showasciiformulaonhover=true;var isIE=document.createElementNS==null;if(document.getElementById==null)
-alert("This webpage requires a recent browser such as \nMozilla/Netscape 7+ or Internet Explorer 6+MathPlayer")
-function AMcreateElementXHTML(t){if(isIE)return document.createElement(t);else return document.createElementNS("http://www.w3.org/1999/xhtml",t);}
-function AMnoMathMLNote(){var nd=AMcreateElementXHTML("h3");nd.setAttribute("align","center")
-nd.appendChild(AMcreateElementXHTML("p"));nd.appendChild(document.createTextNode("To view the "));var an=AMcreateElementXHTML("a");an.appendChild(document.createTextNode("LaTeXMathML"));an.setAttribute("href","http://www.maths.nott.ac.uk/personal/drw/lm.html");nd.appendChild(an);nd.appendChild(document.createTextNode(" notation use Internet Explorer 6+"));an=AMcreateElementXHTML("a");an.appendChild(document.createTextNode("MathPlayer"));an.setAttribute("href","http://www.dessci.com/en/products/mathplayer/download.htm");nd.appendChild(an);nd.appendChild(document.createTextNode(" or Netscape/Mozilla/Firefox"));nd.appendChild(AMcreateElementXHTML("p"));return nd;}
-function AMisMathMLavailable(){if(navigator.appName.slice(0,8)=="Netscape")
-if(navigator.appVersion.slice(0,1)>="5")return null;else return AMnoMathMLNote();else if(navigator.appName.slice(0,9)=="Microsoft")
-try{var ActiveX=new ActiveXObject("MathPlayer.Factory.1");return null;}catch(e){return AMnoMathMLNote();}
-else return AMnoMathMLNote();}
-var AMcal=[0xEF35,0x212C,0xEF36,0xEF37,0x2130,0x2131,0xEF38,0x210B,0x2110,0xEF39,0xEF3A,0x2112,0x2133,0xEF3B,0xEF3C,0xEF3D,0xEF3E,0x211B,0xEF3F,0xEF40,0xEF41,0xEF42,0xEF43,0xEF44,0xEF45,0xEF46];var AMfrk=[0xEF5D,0xEF5E,0x212D,0xEF5F,0xEF60,0xEF61,0xEF62,0x210C,0x2111,0xEF63,0xEF64,0xEF65,0xEF66,0xEF67,0xEF68,0xEF69,0xEF6A,0x211C,0xEF6B,0xEF6C,0xEF6D,0xEF6E,0xEF6F,0xEF70,0xEF71,0x2128];var AMbbb=[0xEF8C,0xEF8D,0x2102,0xEF8E,0xEF8F,0xEF90,0xEF91,0x210D,0xEF92,0xEF93,0xEF94,0xEF95,0xEF96,0x2115,0xEF97,0x2119,0x211A,0x211D,0xEF98,0xEF99,0xEF9A,0xEF9B,0xEF9C,0xEF9D,0xEF9E,0x2124];var CONST=0,UNARY=1,BINARY=2,INFIX=3,LEFTBRACKET=4,RIGHTBRACKET=5,SPACE=6,UNDEROVER=7,DEFINITION=8,TEXT=9,BIG=10,LONG=11,STRETCHY=12,MATRIX=13;var AMsqrt={input:"\\sqrt",tag:"msqrt",output:"sqrt",ttype:UNARY},AMroot={input:"\\root",tag:"mroot",output:"root",ttype:BINARY},AMfrac={input:"\\frac",tag:"mfrac",output:"/",ttype:BINARY},AMover={input:"\\stackrel",tag:"mover",output:"stackrel",ttype:BINARY},AMatop={input:"\\atop",tag:"mfrac",output:"",ttype:INFIX},AMchoose={input:"\\choose",tag:"mfrac",output:"",ttype:INFIX},AMsub={input:"_",tag:"msub",output:"_",ttype:INFIX},AMsup={input:"^",tag:"msup",output:"^",ttype:INFIX},AMtext={input:"\\mathrm",tag:"mtext",output:"text",ttype:TEXT},AMmbox={input:"\\mbox",tag:"mtext",output:"mbox",ttype:TEXT};var AMsymbols=[{input:"\\alpha",tag:"mi",output:"\u03B1",ttype:CONST},{input:"\\beta",tag:"mi",output:"\u03B2",ttype:CONST},{input:"\\gamma",tag:"mi",output:"\u03B3",ttype:CONST},{input:"\\delta",tag:"mi",output:"\u03B4",ttype:CONST},{input:"\\epsilon",tag:"mi",output:"\u03B5",ttype:CONST},{input:"\\varepsilon",tag:"mi",output:"\u025B",ttype:CONST},{input:"\\zeta",tag:"mi",output:"\u03B6",ttype:CONST},{input:"\\eta",tag:"mi",output:"\u03B7",ttype:CONST},{input:"\\theta",tag:"mi",output:"\u03B8",ttype:CONST},{input:"\\vartheta",tag:"mi",output:"\u03D1",ttype:CONST},{input:"\\iota",tag:"mi",output:"\u03B9",ttype:CONST},{input:"\\kappa",tag:"mi",output:"\u03BA",ttype:CONST},{input:"\\lambda",tag:"mi",output:"\u03BB",ttype:CONST},{input:"\\mu",tag:"mi",output:"\u03BC",ttype:CONST},{input:"\\nu",tag:"mi",output:"\u03BD",ttype:CONST},{input:"\\xi",tag:"mi",output:"\u03BE",ttype:CONST},{input:"\\pi",tag:"mi",output:"\u03C0",ttype:CONST},{input:"\\varpi",tag:"mi",output:"\u03D6",ttype:CONST},{input:"\\rho",tag:"mi",output:"\u03C1",ttype:CONST},{input:"\\varrho",tag:"mi",output:"\u03F1",ttype:CONST},{input:"\\varsigma",tag:"mi",output:"\u03C2",ttype:CONST},{input:"\\sigma",tag:"mi",output:"\u03C3",ttype:CONST},{input:"\\tau",tag:"mi",output:"\u03C4",ttype:CONST},{input:"\\upsilon",tag:"mi",output:"\u03C5",ttype:CONST},{input:"\\phi",tag:"mi",output:"\u03C6",ttype:CONST},{input:"\\varphi",tag:"mi",output:"\u03D5",ttype:CONST},{input:"\\chi",tag:"mi",output:"\u03C7",ttype:CONST},{input:"\\psi",tag:"mi",output:"\u03C8",ttype:CONST},{input:"\\omega",tag:"mi",output:"\u03C9",ttype:CONST},{input:"\\Gamma",tag:"mo",output:"\u0393",ttype:CONST},{input:"\\Delta",tag:"mo",output:"\u0394",ttype:CONST},{input:"\\Theta",tag:"mo",output:"\u0398",ttype:CONST},{input:"\\Lambda",tag:"mo",output:"\u039B",ttype:CONST},{input:"\\Xi",tag:"mo",output:"\u039E",ttype:CONST},{input:"\\Pi",tag:"mo",output:"\u03A0",ttype:CONST},{input:"\\Sigma",tag:"mo",output:"\u03A3",ttype:CONST},{input:"\\Upsilon",tag:"mo",output:"\u03A5",ttype:CONST},{input:"\\Phi",tag:"mo",output:"\u03A6",ttype:CONST},{input:"\\Psi",tag:"mo",output:"\u03A8",ttype:CONST},{input:"\\Omega",tag:"mo",output:"\u03A9",ttype:CONST},{input:"\\frac12",tag:"mo",output:"\u00BD",ttype:CONST},{input:"\\frac14",tag:"mo",output:"\u00BC",ttype:CONST},{input:"\\frac34",tag:"mo",output:"\u00BE",ttype:CONST},{input:"\\frac13",tag:"mo",output:"\u2153",ttype:CONST},{input:"\\frac23",tag:"mo",output:"\u2154",ttype:CONST},{input:"\\frac15",tag:"mo",output:"\u2155",ttype:CONST},{input:"\\frac25",tag:"mo",output:"\u2156",ttype:CONST},{input:"\\frac35",tag:"mo",output:"\u2157",ttype:CONST},{input:"\\frac45",tag:"mo",output:"\u2158",ttype:CONST},{input:"\\frac16",tag:"mo",output:"\u2159",ttype:CONST},{input:"\\frac56",tag:"mo",output:"\u215A",ttype:CONST},{input:"\\frac18",tag:"mo",output:"\u215B",ttype:CONST},{input:"\\frac38",tag:"mo",output:"\u215C",ttype:CONST},{input:"\\frac58",tag:"mo",output:"\u215D",ttype:CONST},{input:"\\frac78",tag:"mo",output:"\u215E",ttype:CONST},{input:"\\pm",tag:"mo",output:"\u00B1",ttype:CONST},{input:"\\mp",tag:"mo",output:"\u2213",ttype:CONST},{input:"\\triangleleft",tag:"mo",output:"\u22B2",ttype:CONST},{input:"\\triangleright",tag:"mo",output:"\u22B3",ttype:CONST},{input:"\\cdot",tag:"mo",output:"\u22C5",ttype:CONST},{input:"\\star",tag:"mo",output:"\u22C6",ttype:CONST},{input:"\\ast",tag:"mo",output:"\u002A",ttype:CONST},{input:"\\times",tag:"mo",output:"\u00D7",ttype:CONST},{input:"\\div",tag:"mo",output:"\u00F7",ttype:CONST},{input:"\\circ",tag:"mo",output:"\u2218",ttype:CONST},{input:"\\bullet",tag:"mo",output:"\u2022",ttype:CONST},{input:"\\oplus",tag:"mo",output:"\u2295",ttype:CONST},{input:"\\ominus",tag:"mo",output:"\u2296",ttype:CONST},{input:"\\otimes",tag:"mo",output:"\u2297",ttype:CONST},{input:"\\bigcirc",tag:"mo",output:"\u25CB",ttype:CONST},{input:"\\oslash",tag:"mo",output:"\u2298",ttype:CONST},{input:"\\odot",tag:"mo",output:"\u2299",ttype:CONST},{input:"\\land",tag:"mo",output:"\u2227",ttype:CONST},{input:"\\wedge",tag:"mo",output:"\u2227",ttype:CONST},{input:"\\lor",tag:"mo",output:"\u2228",ttype:CONST},{input:"\\vee",tag:"mo",output:"\u2228",ttype:CONST},{input:"\\cap",tag:"mo",output:"\u2229",ttype:CONST},{input:"\\cup",tag:"mo",output:"\u222A",ttype:CONST},{input:"\\sqcap",tag:"mo",output:"\u2293",ttype:CONST},{input:"\\sqcup",tag:"mo",output:"\u2294",ttype:CONST},{input:"\\uplus",tag:"mo",output:"\u228E",ttype:CONST},{input:"\\amalg",tag:"mo",output:"\u2210",ttype:CONST},{input:"\\bigtriangleup",tag:"mo",output:"\u25B3",ttype:CONST},{input:"\\bigtriangledown",tag:"mo",output:"\u25BD",ttype:CONST},{input:"\\dag",tag:"mo",output:"\u2020",ttype:CONST},{input:"\\dagger",tag:"mo",output:"\u2020",ttype:CONST},{input:"\\ddag",tag:"mo",output:"\u2021",ttype:CONST},{input:"\\ddagger",tag:"mo",output:"\u2021",ttype:CONST},{input:"\\lhd",tag:"mo",output:"\u22B2",ttype:CONST},{input:"\\rhd",tag:"mo",output:"\u22B3",ttype:CONST},{input:"\\unlhd",tag:"mo",output:"\u22B4",ttype:CONST},{input:"\\unrhd",tag:"mo",output:"\u22B5",ttype:CONST},{input:"\\sum",tag:"mo",output:"\u2211",ttype:UNDEROVER},{input:"\\prod",tag:"mo",output:"\u220F",ttype:UNDEROVER},{input:"\\bigcap",tag:"mo",output:"\u22C2",ttype:UNDEROVER},{input:"\\bigcup",tag:"mo",output:"\u22C3",ttype:UNDEROVER},{input:"\\bigwedge",tag:"mo",output:"\u22C0",ttype:UNDEROVER},{input:"\\bigvee",tag:"mo",output:"\u22C1",ttype:UNDEROVER},{input:"\\bigsqcap",tag:"mo",output:"\u2A05",ttype:UNDEROVER},{input:"\\bigsqcup",tag:"mo",output:"\u2A06",ttype:UNDEROVER},{input:"\\coprod",tag:"mo",output:"\u2210",ttype:UNDEROVER},{input:"\\bigoplus",tag:"mo",output:"\u2A01",ttype:UNDEROVER},{input:"\\bigotimes",tag:"mo",output:"\u2A02",ttype:UNDEROVER},{input:"\\bigodot",tag:"mo",output:"\u2A00",ttype:UNDEROVER},{input:"\\biguplus",tag:"mo",output:"\u2A04",ttype:UNDEROVER},{input:"\\int",tag:"mo",output:"\u222B",ttype:CONST},{input:"\\oint",tag:"mo",output:"\u222E",ttype:CONST},{input:":=",tag:"mo",output:":=",ttype:CONST},{input:"\\lt",tag:"mo",output:"<",ttype:CONST},{input:"\\gt",tag:"mo",output:">",ttype:CONST},{input:"\\ne",tag:"mo",output:"\u2260",ttype:CONST},{input:"\\neq",tag:"mo",output:"\u2260",ttype:CONST},{input:"\\le",tag:"mo",output:"\u2264",ttype:CONST},{input:"\\leq",tag:"mo",output:"\u2264",ttype:CONST},{input:"\\leqslant",tag:"mo",output:"\u2264",ttype:CONST},{input:"\\ge",tag:"mo",output:"\u2265",ttype:CONST},{input:"\\geq",tag:"mo",output:"\u2265",ttype:CONST},{input:"\\geqslant",tag:"mo",output:"\u2265",ttype:CONST},{input:"\\equiv",tag:"mo",output:"\u2261",ttype:CONST},{input:"\\ll",tag:"mo",output:"\u226A",ttype:CONST},{input:"\\gg",tag:"mo",output:"\u226B",ttype:CONST},{input:"\\doteq",tag:"mo",output:"\u2250",ttype:CONST},{input:"\\prec",tag:"mo",output:"\u227A",ttype:CONST},{input:"\\succ",tag:"mo",output:"\u227B",ttype:CONST},{input:"\\preceq",tag:"mo",output:"\u227C",ttype:CONST},{input:"\\succeq",tag:"mo",output:"\u227D",ttype:CONST},{input:"\\subset",tag:"mo",output:"\u2282",ttype:CONST},{input:"\\supset",tag:"mo",output:"\u2283",ttype:CONST},{input:"\\subseteq",tag:"mo",output:"\u2286",ttype:CONST},{input:"\\supseteq",tag:"mo",output:"\u2287",ttype:CONST},{input:"\\sqsubset",tag:"mo",output:"\u228F",ttype:CONST},{input:"\\sqsupset",tag:"mo",output:"\u2290",ttype:CONST},{input:"\\sqsubseteq",tag:"mo",output:"\u2291",ttype:CONST},{input:"\\sqsupseteq",tag:"mo",output:"\u2292",ttype:CONST},{input:"\\sim",tag:"mo",output:"\u223C",ttype:CONST},{input:"\\simeq",tag:"mo",output:"\u2243",ttype:CONST},{input:"\\approx",tag:"mo",output:"\u2248",ttype:CONST},{input:"\\cong",tag:"mo",output:"\u2245",ttype:CONST},{input:"\\Join",tag:"mo",output:"\u22C8",ttype:CONST},{input:"\\bowtie",tag:"mo",output:"\u22C8",ttype:CONST},{input:"\\in",tag:"mo",output:"\u2208",ttype:CONST},{input:"\\ni",tag:"mo",output:"\u220B",ttype:CONST},{input:"\\owns",tag:"mo",output:"\u220B",ttype:CONST},{input:"\\propto",tag:"mo",output:"\u221D",ttype:CONST},{input:"\\vdash",tag:"mo",output:"\u22A2",ttype:CONST},{input:"\\dashv",tag:"mo",output:"\u22A3",ttype:CONST},{input:"\\models",tag:"mo",output:"\u22A8",ttype:CONST},{input:"\\perp",tag:"mo",output:"\u22A5",ttype:CONST},{input:"\\smile",tag:"mo",output:"\u2323",ttype:CONST},{input:"\\frown",tag:"mo",output:"\u2322",ttype:CONST},{input:"\\asymp",tag:"mo",output:"\u224D",ttype:CONST},{input:"\\notin",tag:"mo",output:"\u2209",ttype:CONST},{input:"\\begin{eqnarray}",output:"X",ttype:MATRIX,invisible:true},{input:"\\begin{array}",output:"X",ttype:MATRIX,invisible:true},{input:"\\\\",output:"}&{",ttype:DEFINITION},{input:"\\end{eqnarray}",output:"}}",ttype:DEFINITION},{input:"\\end{array}",output:"}}",ttype:DEFINITION},{input:"\\big",tag:"mo",output:"X",atval:"1.2",ieval:"2.2",ttype:BIG},{input:"\\Big",tag:"mo",output:"X",atval:"1.6",ieval:"2.6",ttype:BIG},{input:"\\bigg",tag:"mo",output:"X",atval:"2.2",ieval:"3.2",ttype:BIG},{input:"\\Bigg",tag:"mo",output:"X",atval:"2.9",ieval:"3.9",ttype:BIG},{input:"\\left",tag:"mo",output:"X",ttype:LEFTBRACKET},{input:"\\right",tag:"mo",output:"X",ttype:RIGHTBRACKET},{input:"{",output:"{",ttype:LEFTBRACKET,invisible:true},{input:"}",output:"}",ttype:RIGHTBRACKET,invisible:true},{input:"(",tag:"mo",output:"(",atval:"1",ttype:STRETCHY},{input:"[",tag:"mo",output:"[",atval:"1",ttype:STRETCHY},{input:"\\lbrack",tag:"mo",output:"[",atval:"1",ttype:STRETCHY},{input:"\\{",tag:"mo",output:"{",atval:"1",ttype:STRETCHY},{input:"\\lbrace",tag:"mo",output:"{",atval:"1",ttype:STRETCHY},{input:"\\langle",tag:"mo",output:"\u2329",atval:"1",ttype:STRETCHY},{input:"\\lfloor",tag:"mo",output:"\u230A",atval:"1",ttype:STRETCHY},{input:"\\lceil",tag:"mo",output:"\u2308",atval:"1",ttype:STRETCHY},{input:")",tag:"mo",output:")",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"]",tag:"mo",output:"]",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"\\rbrack",tag:"mo",output:"]",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"\\}",tag:"mo",output:"}",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"\\rbrace",tag:"mo",output:"}",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"\\rangle",tag:"mo",output:"\u232A",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"\\rfloor",tag:"mo",output:"\u230B",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"\\rceil",tag:"mo",output:"\u2309",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"|",tag:"mo",output:"\u2223",atval:"1",ttype:STRETCHY},{input:"\\|",tag:"mo",output:"\u2225",atval:"1",ttype:STRETCHY},{input:"\\vert",tag:"mo",output:"\u2223",atval:"1",ttype:STRETCHY},{input:"\\Vert",tag:"mo",output:"\u2225",atval:"1",ttype:STRETCHY},{input:"\\mid",tag:"mo",output:"\u2223",atval:"1",ttype:STRETCHY},{input:"\\parallel",tag:"mo",output:"\u2225",atval:"1",ttype:STRETCHY},{input:"/",tag:"mo",output:"/",atval:"1.01",ttype:STRETCHY},{input:"\\backslash",tag:"mo",output:"\u2216",atval:"1",ttype:STRETCHY},{input:"\\setminus",tag:"mo",output:"\\",ttype:CONST},{input:"\\!",tag:"mspace",atname:"width",atval:"-0.167em",ttype:SPACE},{input:"\\,",tag:"mspace",atname:"width",atval:"0.167em",ttype:SPACE},{input:"\\>",tag:"mspace",atname:"width",atval:"0.222em",ttype:SPACE},{input:"\\:",tag:"mspace",atname:"width",atval:"0.222em",ttype:SPACE},{input:"\\;",tag:"mspace",atname:"width",atval:"0.278em",ttype:SPACE},{input:"~",tag:"mspace",atname:"width",atval:"0.333em",ttype:SPACE},{input:"\\quad",tag:"mspace",atname:"width",atval:"1em",ttype:SPACE},{input:"\\qquad",tag:"mspace",atname:"width",atval:"2em",ttype:SPACE},{input:"\\prime",tag:"mo",output:"\u2032",ttype:CONST},{input:"'",tag:"mo",output:"\u02B9",ttype:CONST},{input:"''",tag:"mo",output:"\u02BA",ttype:CONST},{input:"'''",tag:"mo",output:"\u2034",ttype:CONST},{input:"''''",tag:"mo",output:"\u2057",ttype:CONST},{input:"\\ldots",tag:"mo",output:"\u2026",ttype:CONST},{input:"\\cdots",tag:"mo",output:"\u22EF",ttype:CONST},{input:"\\vdots",tag:"mo",output:"\u22EE",ttype:CONST},{input:"\\ddots",tag:"mo",output:"\u22F1",ttype:CONST},{input:"\\forall",tag:"mo",output:"\u2200",ttype:CONST},{input:"\\exists",tag:"mo",output:"\u2203",ttype:CONST},{input:"\\Re",tag:"mo",output:"\u211C",ttype:CONST},{input:"\\Im",tag:"mo",output:"\u2111",ttype:CONST},{input:"\\aleph",tag:"mo",output:"\u2135",ttype:CONST},{input:"\\hbar",tag:"mo",output:"\u210F",ttype:CONST},{input:"\\ell",tag:"mo",output:"\u2113",ttype:CONST},{input:"\\wp",tag:"mo",output:"\u2118",ttype:CONST},{input:"\\emptyset",tag:"mo",output:"\u2205",ttype:CONST},{input:"\\infty",tag:"mo",output:"\u221E",ttype:CONST},{input:"\\surd",tag:"mo",output:"\\sqrt{}",ttype:DEFINITION},{input:"\\partial",tag:"mo",output:"\u2202",ttype:CONST},{input:"\\nabla",tag:"mo",output:"\u2207",ttype:CONST},{input:"\\triangle",tag:"mo",output:"\u25B3",ttype:CONST},{input:"\\therefore",tag:"mo",output:"\u2234",ttype:CONST},{input:"\\angle",tag:"mo",output:"\u2220",ttype:CONST},{input:"\\diamond",tag:"mo",output:"\u22C4",ttype:CONST},{input:"\\Diamond",tag:"mo",output:"\u25C7",ttype:CONST},{input:"\\neg",tag:"mo",output:"\u00AC",ttype:CONST},{input:"\\lnot",tag:"mo",output:"\u00AC",ttype:CONST},{input:"\\bot",tag:"mo",output:"\u22A5",ttype:CONST},{input:"\\top",tag:"mo",output:"\u22A4",ttype:CONST},{input:"\\square",tag:"mo",output:"\u25AB",ttype:CONST},{input:"\\Box",tag:"mo",output:"\u25A1",ttype:CONST},{input:"\\wr",tag:"mo",output:"\u2240",ttype:CONST},{input:"\\arccos",tag:"mi",output:"arccos",ttype:UNARY,func:true},{input:"\\arcsin",tag:"mi",output:"arcsin",ttype:UNARY,func:true},{input:"\\arctan",tag:"mi",output:"arctan",ttype:UNARY,func:true},{input:"\\arg",tag:"mi",output:"arg",ttype:UNARY,func:true},{input:"\\cos",tag:"mi",output:"cos",ttype:UNARY,func:true},{input:"\\cosh",tag:"mi",output:"cosh",ttype:UNARY,func:true},{input:"\\cot",tag:"mi",output:"cot",ttype:UNARY,func:true},{input:"\\coth",tag:"mi",output:"coth",ttype:UNARY,func:true},{input:"\\csc",tag:"mi",output:"csc",ttype:UNARY,func:true},{input:"\\deg",tag:"mi",output:"deg",ttype:UNARY,func:true},{input:"\\det",tag:"mi",output:"det",ttype:UNARY,func:true},{input:"\\dim",tag:"mi",output:"dim",ttype:UNARY,func:true},{input:"\\exp",tag:"mi",output:"exp",ttype:UNARY,func:true},{input:"\\gcd",tag:"mi",output:"gcd",ttype:UNARY,func:true},{input:"\\hom",tag:"mi",output:"hom",ttype:UNARY,func:true},{input:"\\inf",tag:"mo",output:"inf",ttype:UNDEROVER},{input:"\\ker",tag:"mi",output:"ker",ttype:UNARY,func:true},{input:"\\lg",tag:"mi",output:"lg",ttype:UNARY,func:true},{input:"\\lim",tag:"mo",output:"lim",ttype:UNDEROVER},{input:"\\liminf",tag:"mo",output:"liminf",ttype:UNDEROVER},{input:"\\limsup",tag:"mo",output:"limsup",ttype:UNDEROVER},{input:"\\ln",tag:"mi",output:"ln",ttype:UNARY,func:true},{input:"\\log",tag:"mi",output:"log",ttype:UNARY,func:true},{input:"\\max",tag:"mo",output:"max",ttype:UNDEROVER},{input:"\\min",tag:"mo",output:"min",ttype:UNDEROVER},{input:"\\Pr",tag:"mi",output:"Pr",ttype:UNARY,func:true},{input:"\\sec",tag:"mi",output:"sec",ttype:UNARY,func:true},{input:"\\sin",tag:"mi",output:"sin",ttype:UNARY,func:true},{input:"\\sinh",tag:"mi",output:"sinh",ttype:UNARY,func:true},{input:"\\sup",tag:"mo",output:"sup",ttype:UNDEROVER},{input:"\\tan",tag:"mi",output:"tan",ttype:UNARY,func:true},{input:"\\tanh",tag:"mi",output:"tanh",ttype:UNARY,func:true},{input:"\\gets",tag:"mo",output:"\u2190",ttype:CONST},{input:"\\leftarrow",tag:"mo",output:"\u2190",ttype:CONST},{input:"\\to",tag:"mo",output:"\u2192",ttype:CONST},{input:"\\rightarrow",tag:"mo",output:"\u2192",ttype:CONST},{input:"\\leftrightarrow",tag:"mo",output:"\u2194",ttype:CONST},{input:"\\uparrow",tag:"mo",output:"\u2191",ttype:CONST},{input:"\\downarrow",tag:"mo",output:"\u2193",ttype:CONST},{input:"\\updownarrow",tag:"mo",output:"\u2195",ttype:CONST},{input:"\\Leftarrow",tag:"mo",output:"\u21D0",ttype:CONST},{input:"\\Rightarrow",tag:"mo",output:"\u21D2",ttype:CONST},{input:"\\Leftrightarrow",tag:"mo",output:"\u21D4",ttype:CONST},{input:"\\iff",tag:"mo",output:"~\\Longleftrightarrow~",ttype:DEFINITION},{input:"\\Uparrow",tag:"mo",output:"\u21D1",ttype:CONST},{input:"\\Downarrow",tag:"mo",output:"\u21D3",ttype:CONST},{input:"\\Updownarrow",tag:"mo",output:"\u21D5",ttype:CONST},{input:"\\mapsto",tag:"mo",output:"\u21A6",ttype:CONST},{input:"\\longleftarrow",tag:"mo",output:"\u2190",ttype:LONG},{input:"\\longrightarrow",tag:"mo",output:"\u2192",ttype:LONG},{input:"\\longleftrightarrow",tag:"mo",output:"\u2194",ttype:LONG},{input:"\\Longleftarrow",tag:"mo",output:"\u21D0",ttype:LONG},{input:"\\Longrightarrow",tag:"mo",output:"\u21D2",ttype:LONG},{input:"\\Longleftrightarrow",tag:"mo",output:"\u21D4",ttype:LONG},{input:"\\longmapsto",tag:"mo",output:"\u21A6",ttype:CONST},AMsqrt,AMroot,AMfrac,AMover,AMsub,AMsup,AMtext,AMmbox,AMatop,AMchoose,{input:"\\acute",tag:"mover",output:"\u00B4",ttype:UNARY,acc:true},{input:"\\grave",tag:"mover",output:"\u0060",ttype:UNARY,acc:true},{input:"\\breve",tag:"mover",output:"\u02D8",ttype:UNARY,acc:true},{input:"\\check",tag:"mover",output:"\u02C7",ttype:UNARY,acc:true},{input:"\\dot",tag:"mover",output:".",ttype:UNARY,acc:true},{input:"\\ddot",tag:"mover",output:"..",ttype:UNARY,acc:true},{input:"\\mathring",tag:"mover",output:"\u00B0",ttype:UNARY,acc:true},{input:"\\vec",tag:"mover",output:"\u20D7",ttype:UNARY,acc:true},{input:"\\overrightarrow",tag:"mover",output:"\u20D7",ttype:UNARY,acc:true},{input:"\\overleftarrow",tag:"mover",output:"\u20D6",ttype:UNARY,acc:true},{input:"\\hat",tag:"mover",output:"\u005E",ttype:UNARY,acc:true},{input:"\\widehat",tag:"mover",output:"\u0302",ttype:UNARY,acc:true},{input:"\\tilde",tag:"mover",output:"~",ttype:UNARY,acc:true},{input:"\\widetilde",tag:"mover",output:"\u02DC",ttype:UNARY,acc:true},{input:"\\bar",tag:"mover",output:"\u203E",ttype:UNARY,acc:true},{input:"\\overbrace",tag:"mover",output:"\uFE37",ttype:UNARY,acc:true},{input:"\\overbracket",tag:"mover",output:"\u23B4",ttype:UNARY,acc:true},{input:"\\overline",tag:"mover",output:"\u00AF",ttype:UNARY,acc:true},{input:"\\underbrace",tag:"munder",output:"\uFE38",ttype:UNARY,acc:true},{input:"\\underbracket",tag:"munder",output:"\u23B5",ttype:UNARY,acc:true},{input:"\\underline",tag:"munder",output:"\u00AF",ttype:UNARY,acc:true},{input:"\\displaystyle",tag:"mstyle",atname:"displaystyle",atval:"true",ttype:UNARY},{input:"\\textstyle",tag:"mstyle",atname:"displaystyle",atval:"false",ttype:UNARY},{input:"\\scriptstyle",tag:"mstyle",atname:"scriptlevel",atval:"1",ttype:UNARY},{input:"\\scriptscriptstyle",tag:"mstyle",atname:"scriptlevel",atval:"2",ttype:UNARY},{input:"\\textrm",tag:"mstyle",output:"\\mathrm",ttype:DEFINITION},{input:"\\mathbf",tag:"mstyle",atname:"mathvariant",atval:"bold",ttype:UNARY},{input:"\\textbf",tag:"mstyle",atname:"mathvariant",atval:"bold",ttype:UNARY},{input:"\\mathit",tag:"mstyle",atname:"mathvariant",atval:"italic",ttype:UNARY},{input:"\\textit",tag:"mstyle",atname:"mathvariant",atval:"italic",ttype:UNARY},{input:"\\mathtt",tag:"mstyle",atname:"mathvariant",atval:"monospace",ttype:UNARY},{input:"\\texttt",tag:"mstyle",atname:"mathvariant",atval:"monospace",ttype:UNARY},{input:"\\mathsf",tag:"mstyle",atname:"mathvariant",atval:"sans-serif",ttype:UNARY},{input:"\\mathbb",tag:"mstyle",atname:"mathvariant",atval:"double-struck",ttype:UNARY,codes:AMbbb},{input:"\\mathcal",tag:"mstyle",atname:"mathvariant",atval:"script",ttype:UNARY,codes:AMcal},{input:"\\mathfrak",tag:"mstyle",atname:"mathvariant",atval:"fraktur",ttype:UNARY,codes:AMfrk},{input:"\\textcolor",tag:"mstyle",atname:"mathvariant",atval:"mathcolor",ttype:BINARY},{input:"\\colorbox",tag:"mstyle",atname:"mathvariant",atval:"background",ttype:BINARY}];function compareNames(s1,s2){if(s1.input>s2.input)return 1
-else return-1;}
-var AMnames=[];function AMinitSymbols(){AMsymbols.sort(compareNames);for(i=0;i<AMsymbols.length;i++)AMnames[i]=AMsymbols[i].input;}
-var AMmathml="http://www.w3.org/1998/Math/MathML";function AMcreateElementMathML(t){if(isIE)return document.createElement("m:"+t);else return document.createElementNS(AMmathml,t);}
-function AMcreateMmlNode(t,frag){if(isIE)var node=document.createElement("m:"+t);else var node=document.createElementNS(AMmathml,t);node.appendChild(frag);return node;}
-function newcommand(oldstr,newstr){AMsymbols=AMsymbols.concat([{input:oldstr,tag:"mo",output:newstr,ttype:DEFINITION}]);}
-function AMremoveCharsAndBlanks(str,n){var st;st=str.slice(n);for(var i=0;i<st.length&&st.charCodeAt(i)<=32;i=i+1);return st.slice(i);}
-function AMposition(arr,str,n){if(n==0){var h,m;n=-1;h=arr.length;while(n+1<h){m=(n+h)>>1;if(arr[m]<str)n=m;else h=m;}
-return h;}else
-for(var i=n;i<arr.length&&arr[i]<str;i++);return i;}
-function AMgetSymbol(str){var k=0;var j=0;var mk;var st;var tagst;var match="";var more=true;for(var i=1;i<=str.length&&more;i++){st=str.slice(0,i);j=k;k=AMposition(AMnames,st,j);if(k<AMnames.length&&str.slice(0,AMnames[k].length)==AMnames[k]){match=AMnames[k];mk=k;i=match.length;}
-more=k<AMnames.length&&str.slice(0,AMnames[k].length)>=AMnames[k];}
-AMpreviousSymbol=AMcurrentSymbol;if(match!=""){AMcurrentSymbol=AMsymbols[mk].ttype;return AMsymbols[mk];}
-AMcurrentSymbol=CONST;k=1;st=str.slice(0,1);if("0"<=st&&st<="9")tagst="mn";else tagst=(("A">st||st>"Z")&&("a">st||st>"z")?"mo":"mi");return{input:st,tag:tagst,output:st,ttype:CONST};}
-var AMpreviousSymbol,AMcurrentSymbol;function AMparseSexpr(str){var symbol,node,result,result2,i,st,newFrag=document.createDocumentFragment();str=AMremoveCharsAndBlanks(str,0);symbol=AMgetSymbol(str);if(symbol==null||symbol.ttype==RIGHTBRACKET)
-return[null,str,null];if(symbol.ttype==DEFINITION){str=symbol.output+AMremoveCharsAndBlanks(str,symbol.input.length);symbol=AMgetSymbol(str);if(symbol==null||symbol.ttype==RIGHTBRACKET)
-return[null,str,null];}
-str=AMremoveCharsAndBlanks(str,symbol.input.length);switch(symbol.ttype){case SPACE:node=AMcreateElementMathML(symbol.tag);node.setAttribute(symbol.atname,symbol.atval);return[node,str,symbol.tag];case UNDEROVER:if(isIE){if(symbol.input.substr(0,4)=="\\big"){str="\\"+symbol.input.substr(4)+str;symbol=AMgetSymbol(str);symbol.ttype=UNDEROVER;str=AMremoveCharsAndBlanks(str,symbol.input.length);}}
-return[AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)),str,symbol.tag];case CONST:var output=symbol.output;if(isIE){if(symbol.input=="'")
-output="\u2032";else if(symbol.input=="''")
-output="\u2033";else if(symbol.input=="'''")
-output="\u2033\u2032";else if(symbol.input=="''''")
-output="\u2033\u2033";else if(symbol.input=="\\square")
-output="\u25A1";else if(symbol.input.substr(0,5)=="\\frac"){var denom=symbol.input.substr(6,1);if(denom=="5"||denom=="6"){str=symbol.input.replace(/\\frac/,"\\frac ")+str;return[node,str,symbol.tag];}}}
-node=AMcreateMmlNode(symbol.tag,document.createTextNode(output));return[node,str,symbol.tag];case LONG:node=AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output));node.setAttribute("minsize","1.5");node.setAttribute("maxsize","1.5");node=AMcreateMmlNode("mover",node);node.appendChild(AMcreateElementMathML("mspace"));return[node,str,symbol.tag];case STRETCHY:if(isIE&&symbol.input=="\\backslash")
-symbol.output="\\";node=AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output));if(symbol.input=="|"||symbol.input=="\\vert"||symbol.input=="\\|"||symbol.input=="\\Vert"){node.setAttribute("lspace","0em");node.setAttribute("rspace","0em");}
-node.setAttribute("maxsize",symbol.atval);if(symbol.rtag!=null)
-return[node,str,symbol.rtag];else
-return[node,str,symbol.tag];case BIG:var atval=symbol.atval;if(isIE)
-atval=symbol.ieval;symbol=AMgetSymbol(str);if(symbol==null)
-return[null,str,null];str=AMremoveCharsAndBlanks(str,symbol.input.length);node=AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output));if(isIE){var space=AMcreateElementMathML("mspace");space.setAttribute("height",atval+"ex");node=AMcreateMmlNode("mrow",node);node.appendChild(space);}else{node.setAttribute("minsize",atval);node.setAttribute("maxsize",atval);}
-return[node,str,symbol.tag];case LEFTBRACKET:if(symbol.input=="\\left"){symbol=AMgetSymbol(str);if(symbol!=null){if(symbol.input==".")
-symbol.invisible=true;str=AMremoveCharsAndBlanks(str,symbol.input.length);}}
-result=AMparseExpr(str,true,false);if(symbol==null||(typeof symbol.invisible=="boolean"&&symbol.invisible))
-node=AMcreateMmlNode("mrow",result[0]);else{node=AMcreateMmlNode("mo",document.createTextNode(symbol.output));node=AMcreateMmlNode("mrow",node);node.appendChild(result[0]);}
-return[node,result[1],result[2]];case MATRIX:if(symbol.input=="\\begin{array}"){var mask="";symbol=AMgetSymbol(str);str=AMremoveCharsAndBlanks(str,0);if(symbol==null)
-mask="l";else{str=AMremoveCharsAndBlanks(str,symbol.input.length);if(symbol.input!="{")
-mask="l";else do{symbol=AMgetSymbol(str);if(symbol!=null){str=AMremoveCharsAndBlanks(str,symbol.input.length);if(symbol.input!="}")
-mask=mask+symbol.input;}}while(symbol!=null&&symbol.input!=""&&symbol.input!="}");}
-result=AMparseExpr("{"+str,true,true);node=AMcreateMmlNode("mtable",result[0]);mask=mask.replace(/l/g,"left ");mask=mask.replace(/r/g,"right ");mask=mask.replace(/c/g,"center ");node.setAttribute("columnalign",mask);node.setAttribute("displaystyle","false");if(isIE)
-return[node,result[1],null];var lspace=AMcreateElementMathML("mspace");lspace.setAttribute("width","0.167em");var rspace=AMcreateElementMathML("mspace");rspace.setAttribute("width","0.167em");var node1=AMcreateMmlNode("mrow",lspace);node1.appendChild(node);node1.appendChild(rspace);return[node1,result[1],null];}else{result=AMparseExpr("{"+str,true,true);node=AMcreateMmlNode("mtable",result[0]);if(isIE)
-node.setAttribute("columnspacing","0.25em");else
-node.setAttribute("columnspacing","0.167em");node.setAttribute("columnalign","right center left");node.setAttribute("displaystyle","true");node=AMcreateMmlNode("mrow",node);return[node,result[1],null];}
-case TEXT:if(str.charAt(0)=="{")i=str.indexOf("}");else i=0;if(i==-1)
-i=str.length;st=str.slice(1,i);if(st.charAt(0)==" "){node=AMcreateElementMathML("mspace");node.setAttribute("width","0.33em");newFrag.appendChild(node);}
-newFrag.appendChild(AMcreateMmlNode(symbol.tag,document.createTextNode(st)));if(st.charAt(st.length-1)==" "){node=AMcreateElementMathML("mspace");node.setAttribute("width","0.33em");newFrag.appendChild(node);}
-str=AMremoveCharsAndBlanks(str,i+1);return[AMcreateMmlNode("mrow",newFrag),str,null];case UNARY:result=AMparseSexpr(str);if(result[0]==null)return[AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)),str];if(typeof symbol.func=="boolean"&&symbol.func){st=str.charAt(0);if(st=="^"||st=="_"||st==","){return[AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)),str,symbol.tag];}else{node=AMcreateMmlNode("mrow",AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)));if(isIE){var space=AMcreateElementMathML("mspace");space.setAttribute("width","0.167em");node.appendChild(space);}
-node.appendChild(result[0]);return[node,result[1],symbol.tag];}}
-if(symbol.input=="\\sqrt"){if(isIE){var space=AMcreateElementMathML("mspace");space.setAttribute("height","1.2ex");space.setAttribute("width","0em");node=AMcreateMmlNode(symbol.tag,result[0])
-node.appendChild(space);return[node,result[1],symbol.tag];}else
-return[AMcreateMmlNode(symbol.tag,result[0]),result[1],symbol.tag];}else if(typeof symbol.acc=="boolean"&&symbol.acc){node=AMcreateMmlNode(symbol.tag,result[0]);var output=symbol.output;if(isIE){if(symbol.input=="\\hat")
-output="\u0302";else if(symbol.input=="\\widehat")
-output="\u005E";else if(symbol.input=="\\bar")
-output="\u00AF";else if(symbol.input=="\\grave")
-output="\u0300";else if(symbol.input=="\\tilde")
-output="\u0303";}
-var node1=AMcreateMmlNode("mo",document.createTextNode(output));if(symbol.input=="\\vec"||symbol.input=="\\check")
-node1.setAttribute("maxsize","1.2");if(isIE&&symbol.input=="\\bar")
-node1.setAttribute("maxsize","0.5");if(symbol.input=="\\underbrace"||symbol.input=="\\underline")
-node1.setAttribute("accentunder","true");else
-node1.setAttribute("accent","true");node.appendChild(node1);if(symbol.input=="\\overbrace"||symbol.input=="\\underbrace")
-node.ttype=UNDEROVER;return[node,result[1],symbol.tag];}else{if(!isIE&&typeof symbol.codes!="undefined"){for(i=0;i<result[0].childNodes.length;i++)
-if(result[0].childNodes[i].nodeName=="mi"||result[0].nodeName=="mi"){st=(result[0].nodeName=="mi"?result[0].firstChild.nodeValue:result[0].childNodes[i].firstChild.nodeValue);var newst=[];for(var j=0;j<st.length;j++)
-if(st.charCodeAt(j)>64&&st.charCodeAt(j)<91)newst=newst+
-String.fromCharCode(symbol.codes[st.charCodeAt(j)-65]);else newst=newst+st.charAt(j);if(result[0].nodeName=="mi")
-result[0]=AMcreateElementMathML("mo").appendChild(document.createTextNode(newst));else result[0].replaceChild(AMcreateElementMathML("mo").appendChild(document.createTextNode(newst)),result[0].childNodes[i]);}}
-node=AMcreateMmlNode(symbol.tag,result[0]);node.setAttribute(symbol.atname,symbol.atval);if(symbol.input=="\\scriptstyle"||symbol.input=="\\scriptscriptstyle")
-node.setAttribute("displaystyle","false");return[node,result[1],symbol.tag];}
-case BINARY:result=AMparseSexpr(str);if(result[0]==null)return[AMcreateMmlNode("mo",document.createTextNode(symbol.input)),str,null];result2=AMparseSexpr(result[1]);if(result2[0]==null)return[AMcreateMmlNode("mo",document.createTextNode(symbol.input)),str,null];if(symbol.input=="\\textcolor"||symbol.input=="\\colorbox"){var tclr=str.match(/\{\s*([#\w]+)\s*\}/);str=str.replace(/\{\s*[#\w]+\s*\}/,"");if(tclr!=null){if(IsColorName.test(tclr[1].toLowerCase())){tclr=LaTeXColor[tclr[1].toLowerCase()];}else{tclr=tclr[1];}
-node=AMcreateElementMathML("mstyle");node.setAttribute(symbol.atval,tclr);node.appendChild(result2[0]);return[node,result2[1],symbol.tag];}}
-if(symbol.input=="\\root"||symbol.input=="\\stackrel")newFrag.appendChild(result2[0]);newFrag.appendChild(result[0]);if(symbol.input=="\\frac")newFrag.appendChild(result2[0]);return[AMcreateMmlNode(symbol.tag,newFrag),result2[1],symbol.tag];case INFIX:str=AMremoveCharsAndBlanks(str,symbol.input.length);return[AMcreateMmlNode("mo",document.createTextNode(symbol.output)),str,symbol.tag];default:return[AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)),str,symbol.tag];}}
-function AMparseIexpr(str){var symbol,sym1,sym2,node,result,tag,underover;str=AMremoveCharsAndBlanks(str,0);sym1=AMgetSymbol(str);result=AMparseSexpr(str);node=result[0];str=result[1];tag=result[2];symbol=AMgetSymbol(str);if(symbol.ttype==INFIX){str=AMremoveCharsAndBlanks(str,symbol.input.length);result=AMparseSexpr(str);if(result[0]==null)
-result[0]=AMcreateMmlNode("mo",document.createTextNode("\u25A1"));str=result[1];tag=result[2];if(symbol.input=="_"||symbol.input=="^"){sym2=AMgetSymbol(str);tag=null;underover=((sym1.ttype==UNDEROVER)||(node.ttype==UNDEROVER));if(symbol.input=="_"&&sym2.input=="^"){str=AMremoveCharsAndBlanks(str,sym2.input.length);var res2=AMparseSexpr(str);str=res2[1];tag=res2[2];node=AMcreateMmlNode((underover?"munderover":"msubsup"),node);node.appendChild(result[0]);node.appendChild(res2[0]);}else if(symbol.input=="_"){node=AMcreateMmlNode((underover?"munder":"msub"),node);node.appendChild(result[0]);}else{node=AMcreateMmlNode((underover?"mover":"msup"),node);node.appendChild(result[0]);}
-node=AMcreateMmlNode("mrow",node);}else{node=AMcreateMmlNode(symbol.tag,node);if(symbol.input=="\\atop"||symbol.input=="\\choose")
-node.setAttribute("linethickness","0ex");node.appendChild(result[0]);if(symbol.input=="\\choose")
-node=AMcreateMmlNode("mfenced",node);}}
-return[node,str,tag];}
-function AMparseExpr(str,rightbracket,matrix){var symbol,node,result,i,tag,newFrag=document.createDocumentFragment();do{str=AMremoveCharsAndBlanks(str,0);result=AMparseIexpr(str);node=result[0];str=result[1];tag=result[2];symbol=AMgetSymbol(str);if(node!=undefined){if((tag=="mn"||tag=="mi")&&symbol!=null&&typeof symbol.func=="boolean"&&symbol.func){var space=AMcreateElementMathML("mspace");space.setAttribute("width","0.167em");node=AMcreateMmlNode("mrow",node);node.appendChild(space);}
-newFrag.appendChild(node);}}while((symbol.ttype!=RIGHTBRACKET)&&symbol!=null&&symbol.output!="");tag=null;if(symbol.ttype==RIGHTBRACKET){if(symbol.input=="\\right"){str=AMremoveCharsAndBlanks(str,symbol.input.length);symbol=AMgetSymbol(str);if(symbol!=null&&symbol.input==".")
-symbol.invisible=true;if(symbol!=null)
-tag=symbol.rtag;}
-if(symbol!=null)
-str=AMremoveCharsAndBlanks(str,symbol.input.length);var len=newFrag.childNodes.length;if(matrix&&len>0&&newFrag.childNodes[len-1].nodeName=="mrow"&&len>1&&newFrag.childNodes[len-2].nodeName=="mo"&&newFrag.childNodes[len-2].firstChild.nodeValue=="&"){var pos=[];var m=newFrag.childNodes.length;for(i=0;matrix&&i<m;i=i+2){pos[i]=[];node=newFrag.childNodes[i];for(var j=0;j<node.childNodes.length;j++)
-if(node.childNodes[j].firstChild.nodeValue=="&")
-pos[i][pos[i].length]=j;}
-var row,frag,n,k,table=document.createDocumentFragment();for(i=0;i<m;i=i+2){row=document.createDocumentFragment();frag=document.createDocumentFragment();node=newFrag.firstChild;n=node.childNodes.length;k=0;for(j=0;j<n;j++){if(typeof pos[i][k]!="undefined"&&j==pos[i][k]){node.removeChild(node.firstChild);row.appendChild(AMcreateMmlNode("mtd",frag));k++;}else frag.appendChild(node.firstChild);}
-row.appendChild(AMcreateMmlNode("mtd",frag));if(newFrag.childNodes.length>2){newFrag.removeChild(newFrag.firstChild);newFrag.removeChild(newFrag.firstChild);}
-table.appendChild(AMcreateMmlNode("mtr",row));}
-return[table,str];}
-if(typeof symbol.invisible!="boolean"||!symbol.invisible){node=AMcreateMmlNode("mo",document.createTextNode(symbol.output));newFrag.appendChild(node);}}
-return[newFrag,str,tag];}
-function AMparseMath(str){var result,node=AMcreateElementMathML("mstyle");var cclr=str.match(/\\color\s*\{\s*([#\w]+)\s*\}/);str=str.replace(/\\color\s*\{\s*[#\w]+\s*\}/g,"");if(cclr!=null){if(IsColorName.test(cclr[1].toLowerCase())){cclr=LaTeXColor[cclr[1].toLowerCase()];}else{cclr=cclr[1];}
-node.setAttribute("mathcolor",cclr);}else{if(mathcolor!="")node.setAttribute("mathcolor",mathcolor);};if(mathfontfamily!="")node.setAttribute("fontfamily",mathfontfamily);node.appendChild(AMparseExpr(str.replace(/^\s+/g,""),false,false)[0]);node=AMcreateMmlNode("math",node);if(showasciiformulaonhover)
-node.setAttribute("title",str.replace(/\s+/g," "));if(false){var fnode=AMcreateElementXHTML("font");fnode.setAttribute("face",mathfontfamily);fnode.appendChild(node);return fnode;}
-return node;}
-function AMstrarr2docFrag(arr,linebreaks){var newFrag=document.createDocumentFragment();var expr=false;for(var i=0;i<arr.length;i++){if(expr)newFrag.appendChild(AMparseMath(arr[i]));else{var arri=(linebreaks?arr[i].split("\n\n"):[arr[i]]);newFrag.appendChild(AMcreateElementXHTML("span").appendChild(document.createTextNode(arri[0])));for(var j=1;j<arri.length;j++){newFrag.appendChild(AMcreateElementXHTML("p"));newFrag.appendChild(AMcreateElementXHTML("span").appendChild(document.createTextNode(arri[j])));}}
-expr=!expr;}
-return newFrag;}
-function AMprocessNodeR(n,linebreaks){var mtch,str,arr,frg,i;if(n.childNodes.length==0){if((n.nodeType!=8||linebreaks)&&n.parentNode.nodeName!="form"&&n.parentNode.nodeName!="FORM"&&n.parentNode.nodeName!="textarea"&&n.parentNode.nodeName!="TEXTAREA"&&n.parentNode.nodeName!="pre"&&n.parentNode.nodeName!="PRE"){str=n.nodeValue;if(!(str==null)){str=str.replace(/\r\n\r\n/g,"\n\n");str=str.replace(/\x20+/g," ");str=str.replace(/\s*\r\n/g," ");mtch=(str.indexOf("\$")==-1?false:true);str=str.replace(/([^\\])\$/g,"$1 \$");str=str.replace(/^\$/," \$");arr=str.split(" \$");for(i=0;i<arr.length;i++)
-arr[i]=arr[i].replace(/\\\$/g,"\$");if(arr.length>1||mtch){if(checkForMathML){checkForMathML=false;var nd=AMisMathMLavailable();AMnoMathML=nd!=null;if(AMnoMathML&&notifyIfNoMathML)
-if(alertIfNoMathML)
-alert("To view the ASCIIMathML notation use Internet Explorer 6 +\nMathPlayer (free from www.dessci.com)\nor Firefox/Mozilla/Netscape");else AMbody.insertBefore(nd,AMbody.childNodes[0]);}
-if(!AMnoMathML){frg=AMstrarr2docFrag(arr,n.nodeType==8);var len=frg.childNodes.length;n.parentNode.replaceChild(frg,n);return len-1;}else return 0;}}}else return 0;}else if(n.nodeName!="math"){for(i=0;i<n.childNodes.length;i++)
-i+=AMprocessNodeR(n.childNodes[i],linebreaks);}
-return 0;}
-function AMprocessNode(n,linebreaks,spanclassAM){var frag,st;if(spanclassAM!=null){frag=document.getElementsByTagName("span")
-for(var i=0;i<frag.length;i++)
-if(frag[i].className=="AM")
-AMprocessNodeR(frag[i],linebreaks);}else{try{st=n.innerHTML;}catch(err){}
-if(st==null||st.indexOf("\$")!=-1)
-AMprocessNodeR(n,linebreaks);}
-if(isIE){frag=document.getElementsByTagName('math');for(var i=0;i<frag.length;i++)frag[i].update()}}
-var inAppendix=false;var sectionCntr=0;var IEcommentWarning=true;var biblist=[];var bibcntr=0;var LaTeXCounter=[];LaTeXCounter["definition"]=0;LaTeXCounter["proposition"]=0;LaTeXCounter["lemma"]=0;LaTeXCounter["theorem"]=0;LaTeXCounter["corollary"]=0;LaTeXCounter["example"]=0;LaTeXCounter["exercise"]=0;LaTeXCounter["subsection"]=0;LaTeXCounter["subsubsection"]=0;LaTeXCounter["figure"]=0;LaTeXCounter["equation"]=0;LaTeXCounter["table"]=0;var LaTeXColor=[];LaTeXColor["greenyellow"]="#D9FF4F";LaTeXColor["yellow"]="#FFFF00";LaTeXColor["goldenrod"]="#FFE529";LaTeXColor["dandelion"]="#FFB529";LaTeXColor["apricot"]="#FFAD7A";LaTeXColor["peach"]="#FF804D";LaTeXColor["melon"]="#FF8A80";LaTeXColor["yelloworange"]="#FF9400";LaTeXColor["orange"]="#FF6321";LaTeXColor["burntorange"]="#FF7D00";LaTeXColor["bittersweet"]="#C20300";LaTeXColor["redorange"]="#FF3B21";LaTeXColor["mahogany"]="#A60000";LaTeXColor["maroon"]="#AD0000";LaTeXColor["brickred"]="#B80000";LaTeXColor["red"]="#FF0000";LaTeXColor["orangered"]="#FF0080";LaTeXColor["rubinered"]="#FF00DE";LaTeXColor["wildstrawberry"]="#FF0A9C";LaTeXColor["salmon"]="#FF789E";LaTeXColor["carnationpink"]="#FF5EFF";LaTeXColor["magenta"]="#FF00FF";LaTeXColor["violetred"]="#FF30FF";LaTeXColor["rhodamine"]="#FF2EFF";LaTeXColor["mulberry"]="#A314FA";LaTeXColor["redviolet"]="#9600A8";LaTeXColor["fuchsia"]="#7303EB";LaTeXColor["lavender"]="#FF85FF";LaTeXColor["thistle"]="#E069FF";LaTeXColor["orchid"]="#AD5CFF";LaTeXColor["darkorchid"]="#9933CC";LaTeXColor["purple"]="#8C24FF";LaTeXColor["plum"]="#8000FF";LaTeXColor["violet"]="#361FFF";LaTeXColor["royalpurple"]="#401AFF";LaTeXColor["blueviolet"]="#1A0DF5";LaTeXColor["periwinkle"]="#6E73FF";LaTeXColor["cadetblue"]="#616EC4";LaTeXColor["cornflowerblue"]="#59DEFF";LaTeXColor["midnightblue"]="#007091";LaTeXColor["navyblue"]="#0F75FF";LaTeXColor["royalblue"]="#0080FF";LaTeXColor["blue"]="#0000FF";LaTeXColor["cerulean"]="#0FE3FF";LaTeXColor["cyan"]="#00FFFF";LaTeXColor["processblue"]="#0AFFFF";LaTeXColor["skyblue"]="#61FFE0";LaTeXColor["turquoise"]="#26FFCC";LaTeXColor["tealblue"]="#1FFAA3";LaTeXColor["aquamarine"]="#2EFFB2";LaTeXColor["bluegreen"]="#26FFAB";LaTeXColor["emerald"]="#00FF80";LaTeXColor["junglegreen"]="#03FF7A";LaTeXColor["seagreen"]="#4FFF80";LaTeXColor["green"]="#00FF00";LaTeXColor["forestgreen"]="#00E000";LaTeXColor["pinegreen"]="#00BF29";LaTeXColor["limegreen"]="#80FF00";LaTeXColor["yellowgreen"]="#8FFF42";LaTeXColor["springgreen"]="#BDFF3D";LaTeXColor["olivegreen"]="#009900";LaTeXColor["rawsienna"]="#8C0000";LaTeXColor["sepia"]="#4D0000";LaTeXColor["brown"]="#660000";LaTeXColor["tan"]="#DB9470";LaTeXColor["gray"]="#808080";LaTeXColor["grey"]="#808080";LaTeXColor["black"]="#000000";LaTeXColor["white"]="#FFFFFF";var IsColorName=/^(?:greenyellow|yellow|goldenrod|dandelion|apricot|peach|melon|yelloworange|orange|burntorange|bittersweet|redorange|mahogany|maroon|brickred|red|orangered|rubinered|wildstrawberry|salmon|carnationpink|magenta|violetred|rhodamine|mulberry|redviolet|fuchsia|lavender|thistle|orchid|darkorchid|purple|plum|violet|royalpurple|blueviolet|periwinkle|cadetblue|cornflowerblue|midnightblue|navyblue|royalblue|blue|cerulean|cyan|processblue|skyblue|turquoise|tealblue|aquamarine|bluegreen|emerald|junglegreen|seagreen|green|forestgreen|pinegreen|limegreen|yellowgreen|springgreen|olivegreen|rawsienna|sepia|brown|tan|gray|grey|black|white)$/;var IsCounter=/^(?:definition|proposition|lemma|theorem|corollary|example|exercise|subsection|subsubsection|figure|equation|table)$/;var IsLaTeXElement=/^(?:displayequation|title|author|address|date|abstract|keyword|section|subsection|subsubsection|ref|cite|thebibliography|definition|proposition|lemma|theorem|corollary|example|exercise|itemize|enumerate|enddefinition|endproposition|endlemma|endtheorem|endcorollary|endexample|endexercise|enditemize|endenumerate|LaTeXMathMLlabel|LaTeXMathML|smallskip|medskip|bigskip|quote|quotation|endquote|endquotation|center|endcenter|description|enddescription|inlinemath)$/;var IsTextOnlyArea=/^(?:form|textarea|pre)$/i;var tableid=0;function makeNumberString(cntr){if(sectionCntr>0){if(inAppendix){return"A"+sectionCntr+"."+cntr;}else{return sectionCntr+"."+cntr;}}else{return""+cntr;}};function LaTeXpreProcess(thebody){var TheBody=thebody;if(TheBody.hasChildNodes()){if(!(IsLaTeXElement.test(TheBody.className)))
-{for(var i=0;i<TheBody.childNodes.length;i++){LaTeXpreProcess(TheBody.childNodes[i])}}}
-else{if(TheBody.nodeType==3&&!(IsTextOnlyArea.test(TheBody.parentNode.nodeName)))
-{var str=TheBody.nodeValue;if(!(str==null)){str=str.replace(/\\%/g,"<per>");str=str.replace(/%[^\n]*(?=\n)/g,"");str=str.replace(/%[^\r]*(?=\r)/g,"");str=str.replace(/%[^\n]*$/,"")
-if(isIE&&str.match(/%/g)!=null&&IEcommentWarning){alert("Comments may not have parsed properly.  Try putting in <pre class='LaTeX><div>..</div></pre> structure.");IEcommentWarning=false;}
-str=str.replace(/<per>/g,"%");if(str.match(/XXX[\s\S]*/)!=null){var tmp=str.match(/XXX[\s\S]*/)[0];var tmpstr=tmp.charCodeAt(7)+"::"+tmp.charCodeAt(8)+"::"+tmp.charCodeAt(9)+"::"+tmp.charCodeAt(10)+"::"+tmp.charCodeAt(11)+"::"+tmp.charCodeAt(12)+"::"+tmp.charCodeAt(13);alert(tmpstr);}
-str=str.replace(/([^\\])\\(\s)/g,"$1\u00A0$2");str=str.replace(/\\quad/g,"\u2001");str=str.replace(/\\qquad/g,"\u2001\u2001");str=str.replace(/\\enspace/g,"\u2002");str=str.replace(/\\;/g,"\u2004");str=str.replace(/\\:/g,"\u2005");str=str.replace(/\\,/g,"\u2006");str=str.replace(/\\thinspace/g,"\u200A");str=str.replace(/([^\\])~/g,"$1\u00A0");str=str.replace(/\\~/g,"~");str=str.replace(/\\\[/g," <DEQ> $\\displaystyle{");str=str.replace(/\\\]/g,"}$ <DEQ> ");str=str.replace(/\$\$/g,"${$<DEQ>$}$");str=str.replace(/\\begin\s*\{\s*array\s*\}/g,"\\begin{array}");str=str.replace(/\\end\s*\{\s*array\s*\}/g,"\\end{array}");str=str.replace(/\\begin\s*\{\s*eqnarray\s*\}/g,"  <DEQ>eqno$\\begin{eqnarray}");str=str.replace(/\\end\s*\{\s*eqnarray\s*\}/g,"\\end{eqnarray}$<DEQ>  ");str=str.replace(/\\begin\s*\{\s*eqnarray\*\s*\}/g,"  <DEQ>$\\begin{eqnarray}");str=str.replace(/\\end\s*\{\s*eqnarray\*\s*\}/g,"\\end{eqnarray}$<DEQ>  ");str=str.replace(/\\begin\s*\{\s*displaymath\s*\}/g," <DEQ> $\\displaystyle{");str=str.replace(/\\end\s*\{\s*displaymath\s*\}/g,"}$ <DEQ> ");str=str.replace(/\\begin\s*\{\s*equation\s*\*\s*\}/g," <DEQ> $\\displaystyle{");str=str.replace(/\\end\s*\{\s*equation\s*\*\s*\}/g,"}$ <DEQ> ");str=str.replace(/\\begin\s*\{\s*equation\s*\}/g," <DEQ>eqno$\\displaystyle{");str=str.replace(/\\end\s*\{\s*equation\s*\}/g,"}$ <DEQ> ");str=str.split("<DEQ>");var newFrag=document.createDocumentFragment();for(var i=0;i<str.length;i++){if(i%2){var DEQtable=document.createElement("table");DEQtable.className='displayequation';var DEQtbody=document.createElement("tbody");var DEQtr=document.createElement("tr");var DEQtdeq=document.createElement("td");DEQtdeq.className='eq';str[i]=str[i].replace(/\$\}\$/g,"$\\displaystyle{");str[i]=str[i].replace(/\$\{\$/g,"}");var lbl=str[i].match(/\\label\s*\{\s*(\w+)\s*\}/);var ISeqno=str[i].match(/^eqno/);str[i]=str[i].replace(/^eqno/," ");str[i]=str[i].replace(/\\label\s*\{\s*\w+\s*\}/," ");DEQtdeq.appendChild(document.createTextNode(str[i]));DEQtr.appendChild(DEQtdeq);str[i]=str[i].replace(/\\nonumber/g,"");if(ISeqno!=null||lbl!=null){var DEQtdno=document.createElement("td");DEQtdno.className='eqno';LaTeXCounter["equation"]++;var eqnoString=makeNumberString(LaTeXCounter["equation"]);var DEQanchor=document.createElement("a");if(lbl!=null){DEQanchor.id=lbl[1]};DEQanchor.className="eqno";var anchorSpan=document.createElement("span");anchorSpan.className="eqno";anchorSpan.style.display="none";anchorSpan.appendChild(document.createTextNode(eqnoString));DEQanchor.appendChild(anchorSpan);DEQtdno.appendChild(DEQanchor);var DEQspan=document.createElement("span");DEQspan.className="eqno";DEQspan.appendChild(document.createTextNode("("+eqnoString+")"));DEQtdno.appendChild(DEQspan);DEQtr.appendChild(DEQtdno);}
-DEQtbody.appendChild(DEQtr);DEQtable.appendChild(DEQtbody);newFrag.appendChild(DEQtable);}
-else{str[i]=str[i].replace(/\$\}\$/g,"");str[i]=str[i].replace(/\$\{\$/g,"");str[i]=str[i].replace(/\\maketitle/g,"");str[i]=str[i].replace(/\\begin\s*\{\s*document\s*\}/g,"");str[i]=str[i].replace(/\\end\s*\{\s*document\s*\}/g,"");str[i]=str[i].replace(/\\documentclass[^\}]*?\}/g,"");str[i]=str[i].replace(/\\usepackage[^\}]*?\}/g,"");str[i]=str[i].replace(/\\noindent/g,"");str[i]=str[i].replace(/\\notag/g,"");str[i]=str[i].replace(/\\ref\s*\{\s*(\w+)\}/g," \\[ref\\]$1\\[ ");str[i]=str[i].replace(/\\url\s*\{\s*([^\}\n]+)\}/g," \\[url\\]$1\\[ ");str[i]=str[i].replace(/\\href\s*\{\s*([^\}]+)\}\s*\{\s*([^\}]+)\}/g," \\[href\\]$1\\]$2\\[ ");str[i]=str[i].replace(/\\cite\s*\{\s*(\w+)\}/g," \\[cite\\]$1\\[ ");str[i]=str[i].replace(/\\qed/g,"\u220E");str[i]=str[i].replace(/\\endproof/g,"\u220E");str[i]=str[i].replace(/\\proof/g,"\\textbf{Proof: }");str[i]=str[i].replace(/\\n(?=\s)/g," \\[br\\] \\[ ");str[i]=str[i].replace(/\\newline/g," \\[br\\] \\[ ");str[i]=str[i].replace(/\\linebreak/g," \\[br\\] \\[ ");str[i]=str[i].replace(/\\smallskip/g," \\[logicalbreak\\]smallskip\\[ ");str[i]=str[i].replace(/\\medskip/g," \\[logicalbreak\\]medskip\\[ ");str[i]=str[i].replace(/\\bigskip/g," \\[logicalbreak\\]bigskip\\[ ");str[i]=str[i].replace(/[\n\r]+[ \f\n\r\t\v\u2028\u2029]*[\n\r]+/g," \\[logicalbreak\\]LaTeXMathML\\[ ");if(isIE){str[i]=str[i].replace(/\r/g," ");}
-str[i]=str[i].replace(/\\bibitem\s*([^\{]*\{\s*\w*\s*\})/g," \\[bibitem\\]$1\\[ ");str[i]=str[i].replace(/\\bibitem\s*/g," \\[bibitem\\] \\[ ");str[i]=str[i].replace(/\\item\s*\[\s*(\w+)\s*\]/g," \\[alistitem\\]$1\\[ ");str[i]=str[i].replace(/\\item\s*/g," \\[alistitem\\] \\[ ");str[i]=str[i].replace(/\\appendix/g," \\[appendix\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*figure\s*\}([\s\S]+?)\\end\s*\{\s*figure\s*\}/g," \\[figure\\]$1\\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*table\s*\}([\s\S]+?)\\end\s*\{\s*table\s*\}/g," \\[table\\]$1\\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*theorem\s*\}/g," \\[theorem\\]Theorem \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*theorem\s*\}/g," \\[endtheorem\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*definition\s*\}/g," \\[definition\\]Definition \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*definition\s*\}/g," \\[enddefinition\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*lemma\s*\}/g," \\[lemma\\]Lemma \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*lemma\s*\}/g," \\[endlemma\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*corollary\s*\}/g," \\[corollary\\]Corollary \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*corollary\s*\}/g," \\[endcorollary\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*proposition\s*\}/g," \\[proposition\\]Proposition \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*proposition\s*\}/g," \\[endproposition\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*example\s*\}/g," \\[example\\]Example \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*example\s*\}/g," \\[endexample\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*exercise\s*\}/g," \\[exercise\\]Exercise \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*exercise\s*\}/g," \\[endexercise\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*thebibliography\s*\}\s*\{\s*\w+\s*\}/g," \\[thebibliography\\]References \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*thebibliography\s*\}/g," \\[thebibliography\\]References \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*thebibliography\s*\}/g," \\[endthebibliography\\]References \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*proof\s*\}/g," \\[proof\\]Proof: \\[ ");if(isIE){str[i]=str[i].replace(/\\end\s*\{\s*proof\s*\}/g,"\u220E \\[endproof\\] \\[ ");}else{str[i]=str[i].replace(/\\end\s*\{\s*proof\s*\}/g," \\[endproof\\] \\[ ");}
-str[i]=str[i].replace(/\\title\s*\{\s*([^\}]+)\}/g," \\[title\\] \\[$1 \\[endtitle\\] \\[ ");str[i]=str[i].replace(/\\author\s*\{\s*([^\}]+)\}/g," \\[author\\] \\[$1 \\[endauthor\\] \\[ ");str[i]=str[i].replace(/\\address\s*\{\s*([^\}]+)\}/g," \\[address\\] \\[$1 \\[endaddress\\] \\[ ");str[i]=str[i].replace(/\\date\s*\{\s*([^\}]+)\}/g," \\[date\\] \\[$1 \\[enddate\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*keyword\s*\}/g," \\[keyword\\] \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*keyword\s*\}/g," \\[endkeyword\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*abstract\s*\}/g," \\[abstract\\] \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*abstract\s*\}/g," \\[endabstract\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*(?!array|tabular)(\w+)\s*\}/g," \\[$1\\] \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*(?!array|tabular)(\w+)\s*\}/g," \\[end$1\\] \\[ ");var sectionIndex=str[i].search(/\\section\s*\{\s*[\s\S]+\}/);while(sectionIndex>=0){str[i]=str[i].replace(/\\section\s*\{/," \\[section\\]");var delimcnt=1;for(var ii=sectionIndex;ii<str[i].length;ii++){if(str[i].charAt(ii)=="{"){delimcnt++};if(str[i].charAt(ii)=="}"){delimcnt--};if(delimcnt==0){str[i]=str[i].substring(0,ii)+"\\[ "+str[i].substring(ii+1,str[i].length);break;}};sectionIndex=str[i].search(/\\section\s*\{\s*[\s\S]+\}/);}
-sectionIndex=str[i].search(/\\subsection\s*\{\s*[\s\S]+\}/);while(sectionIndex>=0){str[i]=str[i].replace(/\\subsection\s*\{/," \\[subsection\\]");var delimcnt=1;for(var ii=sectionIndex;ii<str[i].length;ii++){if(str[i].charAt(ii)=="{"){delimcnt++};if(str[i].charAt(ii)=="}"){delimcnt--};if(delimcnt==0){str[i]=str[i].substring(0,ii)+"\\[ "+str[i].substring(ii+1,str[i].length);break;}};sectionIndex=str[i].search(/\\subsection\s*\{\s*[\s\S]+\}/);}
-sectionIndex=str[i].search(/\\subsubsection\s*\{\s*[\s\S]+\}/);while(sectionIndex>=0){str[i]=str[i].replace(/\\subsubsection\s*\{/," \\[subsubsection\\]");var delimcnt=1;for(var ii=sectionIndex;ii<str[i].length;ii++){if(str[i].charAt(ii)=="{"){delimcnt++};if(str[i].charAt(ii)=="}"){delimcnt--};if(delimcnt==0){str[i]=str[i].substring(0,ii)+"\\[ "+str[i].substring(ii+1,str[i].length);break;}};sectionIndex=str[i].search(/\\subsubsection\s*\{\s*[\s\S]+\}/);}
-var CatToNextEven="";var strtmp=str[i].split("\\[");for(var j=0;j<strtmp.length;j++){if(j%2){var strtmparray=strtmp[j].split("\\]");switch(strtmparray[0]){case"section":var nodeTmp=document.createElement("H2");nodeTmp.className='section';sectionCntr++;for(var div in LaTeXCounter){LaTeXCounter[div]=0};var nodeAnchor=document.createElement("a");if(inAppendix){nodeAnchor.className='appendixsection';}else{nodeAnchor.className='section';}
-var nodeNumString=makeNumberString("");var anchorSpan=document.createElement("span");anchorSpan.className="section";anchorSpan.style.display="none";anchorSpan.appendChild(document.createTextNode(nodeNumString));nodeAnchor.appendChild(anchorSpan);nodeTmp.appendChild(nodeAnchor);var nodeSpan=document.createElement("span");nodeSpan.className='section';nodeSpan.appendChild(document.createTextNode(nodeNumString+" "));nodeTmp.appendChild(nodeSpan);nodeTmp.appendChild(document.createTextNode(strtmparray[1]));newFrag.appendChild(nodeTmp);break;case"subsection":var nodeTmp=document.createElement("H3");nodeTmp.className='subsection';LaTeXCounter["subsection"]++;LaTeXCounter["subsubsection"]=0;var nodeAnchor=document.createElement("a");nodeAnchor.className='subsection';var nodeNumString=makeNumberString(LaTeXCounter["subsection"]);var anchorSpan=document.createElement("span");anchorSpan.className="subsection";anchorSpan.style.display="none";anchorSpan.appendChild(document.createTextNode(nodeNumString));nodeAnchor.appendChild(anchorSpan);nodeTmp.appendChild(nodeAnchor);var nodeSpan=document.createElement("span");nodeSpan.className='subsection';nodeSpan.appendChild(document.createTextNode(nodeNumString+". "));nodeTmp.appendChild(nodeSpan);nodeTmp.appendChild(document.createTextNode(strtmparray[1]));newFrag.appendChild(nodeTmp);break;case"subsubsection":var nodeTmp=document.createElement("H4");nodeTmp.className='subsubsection';LaTeXCounter["subsubsection"]++;var nodeAnchor=document.createElement("a");nodeAnchor.className='subsubsection';var nodeNumString=makeNumberString(LaTeXCounter["subsection"]+"."+LaTeXCounter["subsubsection"]);var anchorSpan=document.createElement("span");anchorSpan.className="subsubsection";anchorSpan.style.display="none";anchorSpan.appendChild(document.createTextNode(nodeNumString));nodeAnchor.appendChild(anchorSpan);nodeTmp.appendChild(nodeAnchor);var nodeSpan=document.createElement("span");nodeSpan.className='subsubsection';nodeSpan.appendChild(document.createTextNode(nodeNumString+". "));nodeTmp.appendChild(nodeSpan);nodeTmp.appendChild(document.createTextNode(strtmparray[1]));newFrag.appendChild(nodeTmp);break;case"href":var nodeTmp=document.createElement("a");nodeTmp.className='LaTeXMathML';nodeTmp.href=strtmparray[1];nodeTmp.appendChild(document.createTextNode(strtmparray[2]));newFrag.appendChild(nodeTmp);break;case"url":var nodeTmp=document.createElement("a");nodeTmp.className='LaTeXMathML';nodeTmp.href=strtmparray[1];nodeTmp.appendChild(document.createTextNode(strtmparray[1]));newFrag.appendChild(nodeTmp);break;case"figure":var nodeTmp=document.createElement("table");nodeTmp.className='figure';var FIGtbody=document.createElement("tbody");var FIGlbl=strtmparray[1].match(/\\label\s*\{\s*(\w+)\s*\}/);strtmparray[1]=strtmparray[1].replace(/\\label\s*\{\w+\}/g,"");var capIndex=strtmparray[1].search(/\\caption\s*\{[\s\S]+\}/);var FIGcap="";if(capIndex>=0){var tmp=strtmparray[1];var delimcnt=0;var capstart=-1;for(var pos=capIndex;pos<tmp.length;pos++){if(tmp.charAt(pos)=="{"){delimcnt++};if(tmp.charAt(pos)=="}"){delimcnt--};if(delimcnt==1&&capstart<0){capstart=pos+1};if(delimcnt==0&&capstart>0){capend=pos-1;FIGcap=tmp.substring(capstart,pos);break}}}
-var FIGtr2=document.createElement("tr");var FIGtd2=document.createElement("td");FIGtd2.className="caption";var FIGanchor=document.createElement("a");FIGanchor.className="figure";if(FIGlbl!=null){FIGanchor.id=FIGlbl[1];}
-LaTeXCounter["figure"]++;var fignmbr=makeNumberString(LaTeXCounter["figure"]);var anchorSpan=document.createElement("span");anchorSpan.className="figure";anchorSpan.style.display="none";anchorSpan.appendChild(document.createTextNode(fignmbr));FIGanchor.appendChild(anchorSpan);FIGtd2.appendChild(FIGanchor);var FIGspan=document.createElement("span");FIGspan.className="figure";FIGspan.appendChild(document.createTextNode("Figure "+fignmbr+". "));FIGtd2.appendChild(FIGspan);FIGtd2.appendChild(document.createTextNode(""+FIGcap));FIGtr2.appendChild(FIGtd2);FIGtbody.appendChild(FIGtr2);var IsSpecial=false;var FIGinfo=strtmparray[1].match(/\\includegraphics\s*\{([^\}]+)\}/);if(FIGinfo==null){FIGinfo=strtmparray[1].match(/\\includegraphics\s*\[[^\]]*\]\s*\{\s*([^\}]+)\s*\}/);}
-if(FIGinfo==null){FIGinfo=strtmparray[1].match(/\\special\s*\{\s*([^\}]+)\}/);IsSpecial=true};if(FIGinfo!=null){var FIGtr1=document.createElement("tr");var FIGtd1=document.createElement("td");FIGtd1.className="image";var FIGimg=document.createElement("img");var FIGsrc=FIGinfo[1];FIGimg.src=FIGsrc;FIGimg.alt="Figure "+FIGsrc+" did not load";FIGimg.title="Figure "+fignmbr+". "+FIGcap;FIGimg.id="figure"+fignmbr;FIGtd1.appendChild(FIGimg);FIGtr1.appendChild(FIGtd1);FIGtbody.appendChild(FIGtr1);}
-nodeTmp.appendChild(FIGtbody);newFrag.appendChild(nodeTmp);break;case"table":var nodeTmp=document.createElement("table");if(strtmparray[1].search(/\\centering/)>=0){nodeTmp.className='LaTeXtable centered';nodeTmp.align="center";}else{nodeTmp.className='LaTeXtable';};tableid++;nodeTmp.id="LaTeXtable"+tableid;var TABlbl=strtmparray[1].match(/\\label\s*\{\s*(\w+)\s*\}/);strtmparray[1]=strtmparray[1].replace(/\\label\s*\{\w+\}/g,"");var capIndex=strtmparray[1].search(/\\caption\s*\{[\s\S]+\}/);var TABcap="";if(capIndex>=0){var tmp=strtmparray[1];var delimcnt=0;var capstart=-1;for(var pos=capIndex;pos<tmp.length;pos++){if(tmp.charAt(pos)=="{"){delimcnt++};if(tmp.charAt(pos)=="}"){delimcnt--};if(delimcnt==1&&capstart<0){capstart=pos+1};if(delimcnt==0&&capstart>0){capend=pos-1;TABcap=tmp.substring(capstart,pos);break}}}
-if(TABcap!=""){var TABtbody=document.createElement("tbody");var TABcaption=document.createElement("caption");TABcaption.className="LaTeXtable centered";var TABanchor=document.createElement("a");TABanchor.className="LaTeXtable";if(TABlbl!=null){TABanchor.id=TABlbl[1];}
-LaTeXCounter["table"]++;var tabnmbr=makeNumberString(LaTeXCounter["table"]);var anchorSpan=document.createElement("span");anchorSpan.className="LaTeXtable";anchorSpan.style.display="none";anchorSpan.appendChild(document.createTextNode(tabnmbr));TABanchor.appendChild(anchorSpan);TABcaption.appendChild(TABanchor);var TABspan=document.createElement("span");TABspan.className="LaTeXtable";TABspan.appendChild(document.createTextNode("Table "+tabnmbr+". "));TABcaption.appendChild(TABspan);TABcaption.appendChild(document.createTextNode(""+TABcap));nodeTmp.appendChild(TABcaption);}
-var TABinfo=strtmparray[1].match(/\\begin\s*\{\s*tabular\s*\}([\s\S]+)\\end\s*\{\s*tabular\s*\}/);if(TABinfo!=null){var TABtbody=document.createElement('tbody');var TABrow=null;var TABcell=null;var row=0;var col=0;var TABalign=TABinfo[1].match(/^\s*\{([^\}]+)\}/);TABinfo=TABinfo[1].replace(/^\s*\{[^\}]+\}/,"");TABinfo=TABinfo.replace(/\\hline/g,"");TABalign[1]=TABalign[1].replace(/\|/g,"");TABalign[1]=TABalign[1].replace(/\s/g,"");TABinfo=TABinfo.split("\\\\");for(row=0;row<TABinfo.length;row++){TABrow=document.createElement("tr");TABinfo[row]=TABinfo[row].split("&");for(col=0;col<TABinfo[row].length;col++){TABcell=document.createElement("td");switch(TABalign[1].charAt(col)){case"l":TABcell.align="left";break;case"c":TABcell.align="center";break;case"r":TABcell.align="right";break;default:TABcell.align="left";};TABcell.appendChild(document.createTextNode(TABinfo[row][col]));TABrow.appendChild(TABcell);}
-TABtbody.appendChild(TABrow);}
-nodeTmp.appendChild(TABtbody);}
-newFrag.appendChild(nodeTmp);break;case"logicalbreak":var nodeTmp=document.createElement("p");nodeTmp.className=strtmparray[1];nodeTmp.appendChild(document.createTextNode("\u00A0"));newFrag.appendChild(nodeTmp);break;case"appendix":inAppendix=true;sectionCntr=0;break;case"alistitem":var EndDiv=document.createElement("div");EndDiv.className="endlistitem";newFrag.appendChild(EndDiv);var BegDiv=document.createElement("div");BegDiv.className="listitem";if(strtmparray[1]!=" "){var BegSpan=document.createElement("span");BegSpan.className="listitemmarker";var boldBegSpan=document.createElement("b");boldBegSpan.appendChild(document.createTextNode(strtmparray[1]+" "));BegSpan.appendChild(boldBegSpan);BegDiv.appendChild(BegSpan);}
-newFrag.appendChild(BegDiv);break;case"br":newFrag.appendChild(document.createElement("br"));break;case"bibitem":newFrag.appendChild(document.createElement("br"));var nodeTmp=document.createElement("a");nodeTmp.className='bibitem';var nodeSpan=document.createElement("span");nodeSpan.className='bibitem';bibcntr++;var lbl=strtmparray[1].match(/\{\s*(\w+)\s*\}/);strtmparray[1]=strtmparray[1].replace(/\s*\{\s*\w+\s*\}/g,"");strtmparray[1]=strtmparray[1].replace(/^\s*\[/,"");strtmparray[1]=strtmparray[1].replace(/\s*\]$/,"");strtmparray[1]=strtmparray[1].replace(/^\s+|\s+$/g,"");if(lbl==null){biblist[bibcntr]="bibitem"+bibcntr}else{biblist[bibcntr]=lbl[1];};nodeTmp.name=biblist[bibcntr];nodeTmp.id=biblist[bibcntr];if(strtmparray[1]!=""){nodeSpan.appendChild(document.createTextNode(strtmparray[1]));}else{nodeSpan.appendChild(document.createTextNode("["+bibcntr+"]"));}
-nodeTmp.appendChild(nodeSpan);newFrag.appendChild(nodeTmp);break;case"cite":var nodeTmp=document.createElement("a");nodeTmp.className='cite';nodeTmp.name='cite';nodeTmp.href="#"+strtmparray[1];newFrag.appendChild(nodeTmp);break;case"ref":var nodeTmp=document.createElement("a");nodeTmp.className='ref';nodeTmp.name='ref';nodeTmp.href="#"+strtmparray[1];newFrag.appendChild(nodeTmp);break;default:var nodeTmp=document.createElement("div");nodeTmp.className=strtmparray[0];if(IsCounter.test(strtmparray[0])){LaTeXCounter[strtmparray[0]]++;var nodeAnchor=document.createElement("a");nodeAnchor.className=strtmparray[0];var divnum=makeNumberString(LaTeXCounter[strtmparray[0]]);var anchorSpan=document.createElement("span");anchorSpan.className=strtmparray[0];anchorSpan.appendChild(document.createTextNode(divnum));anchorSpan.style.display="none";nodeAnchor.appendChild(anchorSpan);nodeTmp.appendChild(nodeAnchor);var nodeSpan=document.createElement("span");nodeSpan.className=strtmparray[0];nodeSpan.appendChild(document.createTextNode(strtmparray[1]+" "+divnum+". "));nodeTmp.appendChild(nodeSpan);}
-if(isIE){if(strtmparray[0]==("thebibliography"||"abstract"||"keyword"||"proof")){var nodeSpan=document.createElement("span");nodeSpan.className=strtmparray[0];nodeSpan.appendChild(document.createTextNode(strtmparray[1]));nodeTmp.appendChild(nodeSpan);}}
-if(strtmparray[0]=="endenumerate"||strtmparray[0]=="enditemize"||strtmparray[0]=="enddescription"){var endDiv=document.createElement("div");endDiv.className="endlistitem";newFrag.appendChild(endDiv);}
-newFrag.appendChild(nodeTmp);if(strtmparray[0]=="enumerate"||strtmparray[0]=="itemize"||strtmparray[0]=="description"){var endDiv=document.createElement("div");endDiv.className="listitem";newFrag.appendChild(endDiv);}}}else{strtmp[j]=strtmp[j].replace(/\\\$/g,"<per>");strtmp[j]=strtmp[j].replace(/\$([^\$]+)\$/g," \\[$1\\[ ");strtmp[j]=strtmp[j].replace(/<per>/g,"\\$");strtmp[j]=strtmp[j].replace(/\\begin\s*\{\s*math\s*\}([\s\S]+?)\\end\s*\{\s*math\s*\}/g," \\[$1\\[ ");var strtmptmp=strtmp[j].split("\\[");for(var jjj=0;jjj<strtmptmp.length;jjj++){if(jjj%2){var nodeTmp=document.createElement("span");nodeTmp.className='inlinemath';nodeTmp.appendChild(document.createTextNode("$"+strtmptmp[jjj]+"$"));newFrag.appendChild(nodeTmp);}else{var TagIndex=strtmptmp[jjj].search(/\\\w+/);var tmpIndex=TagIndex;while(tmpIndex>-1){if(/^\\textcolor/.test(strtmptmp[jjj].substring(TagIndex,strtmptmp[jjj].length))){strtmptmp[jjj]=strtmptmp[jjj].replace(/\\textcolor\s*\{\s*(\w+)\s*\}\s*/," \\[textcolor\\]$1\\]|");}else{if(/^\\colorbox/.test(strtmptmp[jjj].substring(TagIndex,strtmptmp[jjj].length))){strtmptmp[jjj]=strtmptmp[jjj].replace(/\\colorbox\s*\{\s*(\w+)\s*\}\s*/," \\[colorbox\\]$1\\]|");}else{strtmptmp[jjj]=strtmptmp[jjj].substring(0,TagIndex)+strtmptmp[jjj].substring(TagIndex,strtmptmp[jjj].length).replace(/\\\s*(\w+)\s*/," \\[$1\\]|");}}
-TagIndex+=strtmptmp[jjj].substring(TagIndex,strtmptmp[jjj].length).search(/\|/);TagIndex++;strtmptmp[jjj]=strtmptmp[jjj].replace(/\\\]\|/,"\\] ");if(strtmptmp[jjj].charAt(TagIndex)=="{"){strtmptmp[jjj]=strtmptmp[jjj].substring(0,TagIndex)+strtmptmp[jjj].substring(TagIndex+1,strtmptmp[jjj].length);var delimcnt=1;for(var kk=TagIndex;kk<strtmptmp[jjj].length;kk++){if(strtmptmp[jjj].charAt(kk)=="{"){delimcnt++};if(strtmptmp[jjj].charAt(kk)=="}"){delimcnt--};if(delimcnt==0){break;}}
-strtmptmp[jjj]=strtmptmp[jjj].substring(0,kk)+"\\[ "+strtmptmp[jjj].substring(kk+1,strtmptmp[jjj].length);TagIndex=kk+3;}else{strtmptmp[jjj]=strtmptmp[jjj].substring(0,TagIndex)+"\\[ "+strtmptmp[jjj].substring(TagIndex+1,strtmptmp[jjj].length);TagIndex=TagIndex+3;}
-if(TagIndex<strtmptmp[jjj].length){tmpIndex=strtmptmp[jjj].substring(TagIndex,strtmptmp[jjj].length).search(/\\\w+/);}
-else{tmpIndex=-1};TagIndex+=tmpIndex;}
-strtmptmp[jjj]=strtmptmp[jjj].replace(/\\\\\s*\\\\/g,"\\\\");strtmptmp[jjj]=strtmptmp[jjj].replace(/\\\\/g," \\[br\\] \\[ ");strtmptmp[jjj]=strtmptmp[jjj].replace(/\\label\s*\{\s*(\w+)\s*\}/g," \\[a\\]$1\\[ ");var strlbls=strtmptmp[jjj].split("\\[");for(var jj=0;jj<strlbls.length;jj++){if(jj%2){var strtmparray=strlbls[jj].split("\\]");switch(strtmparray[0]){case"textcolor":var nodeTmp=document.createElement("span");nodeTmp.className='LaTeXColor';if(IsColorName.test(strtmparray[1].toLowerCase())){nodeTmp.style.color=LaTeXColor[strtmparray[1].toLowerCase()];}else{nodeTmp.style.color=strtmparray[1];};nodeTmp.appendChild(document.createTextNode(strtmparray[2]));newFrag.appendChild(nodeTmp);break;case"colorbox":var nodeTmp=document.createElement("span");nodeTmp.className='LaTeXColor';if(IsColorName.test(strtmparray[1].toLowerCase())){nodeTmp.style.background=LaTeXColor[strtmparray[1].toLowerCase()];}else{nodeTmp.style.background=strtmparray[1];};nodeTmp.appendChild(document.createTextNode(strtmparray[2]));newFrag.appendChild(nodeTmp);break;case"br":newFrag.appendChild(document.createElement("br"));break;case"a":var nodeTmp=document.createElement("a");nodeTmp.className='LaTeXMathMLlabel';nodeTmp.id=strtmparray[1];nodeTmp.style.display="none";newFrag.appendChild(nodeTmp);break;default:var nodeTmp=document.createElement("span");nodeTmp.className=strtmparray[0];nodeTmp.appendChild(document.createTextNode(strtmparray[1]))
-newFrag.appendChild(nodeTmp);}}else{newFrag.appendChild(document.createTextNode(strlbls[jj]));}}}}}}}};TheBody.parentNode.replaceChild(newFrag,TheBody);}}}
-return TheBody;}
-function LaTeXDivsAndRefs(thebody){var TheBody=thebody;var EndDivClass=null;var AllDivs=TheBody.getElementsByTagName("div");var lbl2id="";var lblnode=null;for(var i=AllDivs.length-1;i>=0;i--){EndDivClass=AllDivs[i].className.match(/end\w+/);if(EndDivClass!=null){EndDivClass=EndDivClass[0];var DivClass=EndDivClass.substring(3,EndDivClass.length);var EndDivNode=AllDivs[i];break;}}
-while(EndDivClass!=null){var newFrag=document.createDocumentFragment();var RootNode=EndDivNode.parentNode;var ClassCount=1;while(EndDivNode.previousSibling!=null&&ClassCount>0){switch(EndDivNode.previousSibling.className){case EndDivClass:ClassCount++;newFrag.insertBefore(EndDivNode.previousSibling,newFrag.firstChild);break;case DivClass:if(EndDivNode.previousSibling.nodeName=="DIV"){ClassCount--;if(lbl2id!=""){EndDivNode.previousSibling.id=lbl2id;lbl2id=""}
-if(ClassCount==0){RootNode=EndDivNode.previousSibling;}else{newFrag.insertBefore(EndDivNode.previousSibling,newFrag.firstChild);}};break;case'LaTeXMathMLlabel':lbl2id=EndDivNode.previousSibling.id;EndDivNode.parentNode.removeChild(EndDivNode.previousSibling);break;default:newFrag.insertBefore(EndDivNode.previousSibling,newFrag.firstChild);}}
-RootNode.appendChild(newFrag);EndDivNode.parentNode.removeChild(EndDivNode);AllDivs=TheBody.getElementsByTagName("DIV");for(i=AllDivs.length-1;i>=0;i--){EndDivClass=AllDivs[i].className.match(/end\w+/);if(EndDivClass!=null){ClassCount=0;EndDivClass=EndDivClass[0];DivClass=EndDivClass.substring(3,EndDivClass.length);EndDivNode=AllDivs[i];RootNode=EndDivNode.parentNode;break;}}}
-var AllDivs=TheBody.getElementsByTagName("div");var DIV2LI=null;for(var i=0;i<AllDivs.length;i++){if(AllDivs[i].className=="itemize"||AllDivs[i].className=="enumerate"||AllDivs[i].className=="description"){if(AllDivs[i].className=="itemize"){RootNode=document.createElement("UL");}else{RootNode=document.createElement("OL");}
-RootNode.className='LaTeXMathML';if(AllDivs[i].hasChildNodes()){AllDivs[i].removeChild(AllDivs[i].firstChild)};while(AllDivs[i].hasChildNodes()){if(AllDivs[i].firstChild.hasChildNodes()){DIV2LI=document.createElement("LI");while(AllDivs[i].firstChild.hasChildNodes()){DIV2LI.appendChild(AllDivs[i].firstChild.firstChild);}
-if(DIV2LI.firstChild.className=="listitemmarker"){DIV2LI.style.listStyleType="none";}
-RootNode.appendChild(DIV2LI)}
-AllDivs[i].removeChild(AllDivs[i].firstChild);}
-AllDivs[i].appendChild(RootNode);}}
-var AllAnchors=TheBody.getElementsByTagName("a");for(var i=0;i<AllAnchors.length;i++){if(AllAnchors[i].className=="ref"||AllAnchors[i].className=="cite"){var label=AllAnchors[i].href.match(/\#(\w+)/);if(label!=null){var labelNode=document.getElementById(label[1]);if(labelNode!=null){var TheSpans=labelNode.getElementsByTagName("SPAN");if(TheSpans!=null){var refNode=TheSpans[0].cloneNode(true);refNode.style.display="inline"
-refNode.className=AllAnchors[i].className;AllAnchors[i].appendChild(refNode);}}}}}
-return TheBody;}
-var AMbody;var AMnoMathML=false,AMtranslated=false;function translate(spanclassAM){if(!AMtranslated){AMtranslated=true;AMinitSymbols();var LaTeXContainers=[];var AllContainers=document.getElementsByTagName('*');var ExtendName="";for(var k=0,l=0;k<AllContainers.length;k++){ExtendName=" "+AllContainers[k].className+" ";if(ExtendName.match(/\sLaTeX\s/)!=null){LaTeXContainers[l]=AllContainers[k];l++;}};if(LaTeXContainers.length>0){for(var m=0;m<LaTeXContainers.length;m++){AMbody=LaTeXContainers[m];try{AMbody=LaTeXDivsAndRefs(LaTeXpreProcess(AMbody));}catch(err){alert("Unknown Error: Defaulting to Original LaTeXMathML");}
-if(AMbody.tagName=="PRE"){var PreChilds=document.createDocumentFragment();var DivChilds=document.createElement("DIV");while(AMbody.hasChildNodes()){DivChilds.appendChild(AMbody.firstChild);}
-PreChilds.appendChild(DivChilds);AMbody.parentNode.replaceChild(PreChilds,AMbody);AMbody=DivChilds;}
-AMprocessNode(AMbody,false,spanclassAM);}}else{AMbody=document.getElementsByTagName("body")[0];try{AMbody=LaTeXDivsAndRefs(LaTeXpreProcess(AMbody));}catch(err){alert("Unknown Error: Defaulting to Original LaTeXMathML");}
-AMprocessNode(AMbody,false,spanclassAM);}}}
-if(isIE){document.write("<object id=\"mathplayer\" classid=\"clsid:32F66A20-7614-11D4-BD11-00104BD3F987\"></object>");document.write("<?import namespace=\"m\" implementation=\"#mathplayer\"?>");}
-function generic()
-{translate();};if(typeof window.addEventListener!='undefined')
-{window.addEventListener('load',generic,false);}
-else if(typeof document.addEventListener!='undefined')
-{document.addEventListener('load',generic,false);}
-else if(typeof window.attachEvent!='undefined')
-{window.attachEvent('onload',generic);}
-else
-{if(typeof window.onload=='function')
-{var existing=onload;window.onload=function()
-{existing();generic();};}
-else
-{window.onload=generic;}}
diff --git a/data/bash_completion.tpl b/data/bash_completion.tpl
index c9145c06c..60140a1e4 100644
--- a/data/bash_completion.tpl
+++ b/data/bash_completion.tpl
@@ -4,7 +4,7 @@
 
 _pandoc()
 {
-    local cur prev opts lastc informats outformats datadir
+    local cur prev opts lastc informats outformats datafiles
     COMPREPLY=()
     cur="${COMP_WORDS[COMP_CWORD]}"
     prev="${COMP_WORDS[COMP_CWORD-1]}"
@@ -14,7 +14,7 @@ _pandoc()
     informats="%s"
     outformats="%s"
     highlight_styles="%s"
-    datadir="%s"
+    datafiles="%s"
 
     case "${prev}" in
          --from|-f|--read|-r)
@@ -34,7 +34,7 @@ _pandoc()
              return 0
              ;;
          --print-default-data-file)
-             COMPREPLY=( $(compgen -W "reference.odt reference.docx $(find ${datadir} | sed -e 's/.*\/data\///')" -- ${cur}) )
+             COMPREPLY=( $(compgen -W "${datafiles}" -- ${cur}) )
              return 0
              ;;
          --wrap)
diff --git a/data/pptx/docProps/thumbnail.jpeg b/data/pptx/docProps/thumbnail.jpeg
deleted file mode 100644
index 07aa48f19..000000000
Binary files a/data/pptx/docProps/thumbnail.jpeg and /dev/null differ
diff --git a/data/templates/default.context b/data/templates/default.context
index 56f4e9cf7..879269394 100644
--- a/data/templates/default.context
+++ b/data/templates/default.context
@@ -38,6 +38,13 @@ $endif$
 $if(pagenumbering)$
 \setuppagenumbering[$for(pagenumbering)$$pagenumbering$$sep$,$endfor$]
 $endif$
+$if(pdfa)$
+% attempt to generate PDF/A
+\setupbackend
+  [format=PDF/A-1b:2005,
+   intent=sRGB IEC61966-2.1,
+   profile=sRGB.icc]
+$endif$
 
 % use microtypography
 \definefontfeature[default][default][script=latn, protrusion=quality, expansion=quality, itlc=yes, textitalics=yes, onum=yes, pnum=yes]
@@ -47,7 +54,7 @@ $endif$
 
 \setupbodyfontenvironment[default][em=italic] % use italic as em, not slanted
 
-\definefallbackfamily[mainface][rm][DejaVu Serif][preset=range:greek, force=yes]
+\definefallbackfamily[mainface][rm][CMU Serif][preset=range:greek, force=yes]
 \definefontfamily[mainface][rm][$if(mainfont)$$mainfont$$else$Latin Modern Roman$endif$]
 \definefontfamily[mainface][mm][$if(mathfont)$$mathfont$$else$Latin Modern Math$endif$]
 \definefontfamily[mainface][ss][$if(sansfont)$$sansfont$$else$Latin Modern Sans$endif$]
diff --git a/data/templates/default.html5 b/data/templates/default.html5
index 5c484f376..9c15107c0 100644
--- a/data/templates/default.html5
+++ b/data/templates/default.html5
@@ -29,7 +29,7 @@ $highlighting-css$
   </style>
 $endif$
 $for(css)$
-  <link rel="stylesheet" href="$css$">
+  <link rel="stylesheet" href="$css$" />
 $endfor$
 $if(math)$
   $math$
diff --git a/data/templates/default.latex b/data/templates/default.latex
index c36bf8576..31093374f 100644
--- a/data/templates/default.latex
+++ b/data/templates/default.latex
@@ -2,14 +2,24 @@
 \PassOptionsToPackage{hyphens}{url}
 $if(colorlinks)$
 \PassOptionsToPackage{dvipsnames,svgnames*,x11names*}{xcolor}
-$endif$
-%
+$endif$$if(dir)$$if(latex-dir-rtl)$
+\PassOptionsToPackage{RTLdocument}{bidi}
+$endif$$endif$%
 \documentclass[$if(fontsize)$$fontsize$,$endif$$if(lang)$$babel-lang$,$endif$$if(papersize)$$papersize$paper,$endif$$if(beamer)$ignorenonframetext,$if(handout)$handout,$endif$$if(aspectratio)$aspectratio=$aspectratio$,$endif$$endif$$for(classoption)$$classoption$$sep$,$endfor$]{$documentclass$}
 $if(beamer)$
+$if(background-image)$
+\usebackgroundtemplate{%
+\includegraphics[width=\paperwidth]{$background-image$}%
+}
+$endif$
+\usepackage{pgfpages}
 \setbeamertemplate{caption}[numbered]
 \setbeamertemplate{caption label separator}{: }
 \setbeamercolor{caption name}{fg=normal text.fg}
 \beamertemplatenavigationsymbols$if(navigation)$$navigation$$else$empty$endif$
+$for(beameroption)$
+\setbeameroption{$beameroption$}
+$endfor$
 $endif$
 $if(beamerarticle)$
 \usepackage{beamerarticle} % needs to be loaded first
@@ -287,11 +297,7 @@ $endif$
 $if(dir)$
 \ifxetex
   % load bidi as late as possible as it modifies e.g. graphicx
-  $if(latex-dir-rtl)$
-  \usepackage[RTLdocument]{bidi}
-  $else$
   \usepackage{bidi}
-  $endif$
 \fi
 \ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex
   \TeXXeTstate=1
diff --git a/data/templates/default.ms b/data/templates/default.ms
index f4204338a..02bbc626a 100644
--- a/data/templates/default.ms
+++ b/data/templates/default.ms
@@ -90,7 +90,10 @@ $for(author)$
 $author$
 $endfor$
 $if(date)$
-.ND "$date$"
+.AU
+.sp 0.5
+.ft R
+$date$
 $endif$
 $if(abstract)$
 .AB
diff --git a/data/templates/default.revealjs b/data/templates/default.revealjs
index 65ab09049..6f847e23a 100644
--- a/data/templates/default.revealjs
+++ b/data/templates/default.revealjs
@@ -197,6 +197,11 @@ $endif$
 $if(parallaxBackgroundImage)$
         // Parallax background image
         parallaxBackgroundImage: '$parallaxBackgroundImage$', // e.g. "'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg'"
+$else$
+$if(background-image)$
+       // Parallax background image
+       parallaxBackgroundImage: '$background-image$', // e.g. "'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg'"
+$endif$
 $endif$
 $if(parallaxBackgroundSize)$
         // Parallax background size
diff --git a/doc/lua-filters.md b/doc/lua-filters.md
index 6f03360bb..170aaa8f5 100644
--- a/doc/lua-filters.md
+++ b/doc/lua-filters.md
@@ -135,9 +135,42 @@ Elements without matching functions are left untouched.
 See [module documentation](#module-pandoc) for a list of pandoc
 elements.
 
-The global `FORMAT` is set to the format of the pandoc writer
-being used (`html5`, `latex`, etc.), so the behavior of a filter
-can be made conditional on the eventual output format.
+
+## Global variables
+
+Pandoc passes additional data to Lua filters by setting global
+variables.
+
+`FORMAT`
+:   The global `FORMAT` is set to the format of the pandoc
+    writer being used (`html5`, `latex`, etc.), so the behavior
+    of a filter can be made conditional on the eventual output
+    format.
+
+`PANDOC_READER_OPTIONS`
+:   Table of the options which were provided to the parser.
+
+`PANDOC_VERSION`
+:   Contains the pandoc version as a numerically indexed table,
+    most significant number first. E.g., for pandoc 2.1.1, the
+    value of the variable is a table `{2, 1, 1}`. Use
+    `table.concat(PANDOC_VERSION, '.')` to produce a version
+    string. This variable is also set in custom writers.
+
+`PANDOC_API_VERSION`
+:   Contains the version of the pandoc-types API against which
+    pandoc was compiled. It is given as a numerically indexed
+    table, most significant number first. E.g., if pandoc was
+    compiled against pandoc-types 1.17.3, then the value of the
+    variable will be a table `{1, 17, 3}`. Use
+    `table.concat(PANDOC_API_VERSION, '.')` to produce a version
+    string from this table. This variable is also set in custom
+    writers.
+
+`PANDOC_SCRIPT_FILE`
+:   The name used to involve the filter. This value can be used
+    to find files relative to the script file. This variable is
+    also set in custom writers.
 
 # Pandoc Module
 
@@ -318,7 +351,7 @@ local vars = {}
 function get_vars (meta)
   for k, v in pairs(meta) do
     if v.t == 'MetaInlines' then
-      vars["$" .. k .. "$"] = v
+      vars["$" .. k .. "$"] = {table.unpack(v)}
     end
   end
 end
diff --git a/doc/org.md b/doc/org.md
new file mode 100644
index 000000000..2a87f826c
--- /dev/null
+++ b/doc/org.md
@@ -0,0 +1,95 @@
+---
+title: Org-mode features and differences
+author: Albert Krewinkel
+---
+
+Pandoc handles org files very similarly to Emacs org-mode.
+However, there are differences worth highlighting.
+
+
+Citations
+=========
+
+Emacs org-mode lacks an official citation syntax, leading to
+multiple syntaxes coexisting. Pandoc recognizes four different
+syntaxes for citations.
+
+Berkeley-style citations
+------------------------
+
+The semi-offical Org-mode citation syntax is based on John
+MacFarlane's Pandoc syntax and org-oriented enhancements
+contributed by Richard Lawrence and others. It's dubbed Berkeley
+syntax due the place of activity of its main contributors.
+
+Example:
+
+    See @john_doe_2006.
+    [cite: See; @Mandelkern1981; and @Watson1953]
+    [(cite): See; @Mandelkern1981; and @Watson1953]
+
+
+org-ref citations
+-----------------
+
+The [org-ref] package is in wide use to handle citations and has
+excellent tooling support in Emacs. Its citation syntax is
+geared towards users in the natural sciences but still very
+flexible regardless.
+
+    cite:doe_john_2000
+    citep:doe_jane_1989
+    [[citep:Dominik201408][See page 20 of::, for example]]
+
+
+Pandoc-Markdown-like syntax
+---------------------------
+
+Historically, Markdown-style citations syntax was the first that
+was added to pandoc's org reader. It is almost identical to
+Markdown's citation syntax.
+
+Example:
+
+    [prefix @citekey suffix]
+    [see @doe2000 p. 23-42]
+
+
+LaTeX-Syntax
+------------
+
+Use normal latex citation commands like `\cite{x}` or
+`\citet{y}`.
+
+[org-ref]: https://github.com/jkitchin/org-ref
+
+
+Emphasis rules
+==============
+
+Org-mode uses complex rules to decide whether a string
+represents emphasized text. In Emacs, this can be customized via
+the variable `org-emphasis-regexp-components`. A variable like
+this doesn't fit well with pandoc's model. Instead, it is
+possible to use special lines to change these values:
+
+    #+pandoc-emphasis-pre: "-\t ('\"{"
+    #+pandoc-emphasis-post: "-\t\n .,:!?;'\")}["
+    
+The above describes the default values of these variables. The
+arguments must be valid (Haskell) strings. If interpretation of
+the argument as string fails, the default is restored.
+
+Changing emphasis rules only affect the part of the document
+following the special lines. They must be some of the first
+lines to alter parsing behavior for the whole document. It is
+also possible to change the values temporarily for selected
+sections only. The string `test` in the following snippet will
+be read as emphasized text, while the rest of the document will
+be parsed using default emphasis rules:
+
+    #+pandoc-emphasis-pre: "["
+    #+pandoc-emphasis-post: "]"
+    [/test/]
+    #+pandoc-emphasis-pre:
+    #+pandoc-emphasis-post:
diff --git a/lib/fonts/Makefile b/lib/fonts/Makefile
deleted file mode 100644
index 5693ee054..000000000
--- a/lib/fonts/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-symbol.hs: symbol.txt
-	runghc parseUnicodeMapping.hs symbol.txt
-
-.PHONY: clean
-clean:
-	-rm symbol.hs
diff --git a/lib/fonts/parseUnicodeMapping.hs b/lib/fonts/parseUnicodeMapping.hs
deleted file mode 100644
index 4f7ff692b..000000000
--- a/lib/fonts/parseUnicodeMapping.hs
+++ /dev/null
@@ -1,40 +0,0 @@
-import System.FilePath
-import Text.Parsec
-import Data.Char
-import System.Environment
-import Control.Applicative hiding (many)
-import Data.List
-
-main :: IO ()
-main = (head <$> getArgs) >>= parseUnicodeMapping
-
-
-parseUnicodeMapping :: FilePath -> IO ()
-parseUnicodeMapping fname = do
-  fin <- readFile fname
-  let mapname = dropExtension . takeFileName $ fname
-  let res = runParse fin
-  let header = "-- Generated from " ++ fname ++ "\n" ++
-                mapname ++ " :: [(Char, Char)]\n" ++ mapname ++" =\n  [ "
-  let footer = "]"
-  writeFile (replaceExtension fname ".hs")
-    (header ++ (concat $ intersperse "\n  , " (map show res)) ++ footer)
-
-type Unicode = Char
-
-runParse :: String -> [(Char, Unicode)]
-runParse s=  either (error . show) id (parse parseMap "" s)
-
-anyline = manyTill anyChar newline
-
-getHexChar :: Parsec String () Char
-getHexChar = do
-  [(c,_)] <- readLitChar . ("\\x" ++) <$> many1 hexDigit
-  return c
-
-parseMap :: Parsec String () [(Char, Unicode)]
-parseMap = do
-  skipMany (char '#' >> anyline)
-  many (flip (,) <$> getHexChar <* tab <*> getHexChar <* anyline)
-
-
diff --git a/lib/fonts/symbol.txt b/lib/fonts/symbol.txt
deleted file mode 100644
index b98baf6cf..000000000
--- a/lib/fonts/symbol.txt
+++ /dev/null
@@ -1,256 +0,0 @@
-#
-#  Name:             Adobe Symbol Encoding to Unicode
-#  Unicode version:  2.0
-#  Table version:    1.0
-#  Date:             2011 July 12
-#  
-#  Copyright (c) 1991-2011 Unicode, Inc. All Rights reserved.
-#  
-#  This file is provided as-is by Unicode, Inc. (The Unicode Consortium). No
-#  claims are made as to fitness for any particular purpose. No warranties of
-#  any kind are expressed or implied. The recipient agrees to determine
-#  applicability of information provided. If this file has been provided on
-#  magnetic media by Unicode, Inc., the sole remedy for any claim will be
-#  exchange of defective media within 90 days of receipt.
-#  
-#  Unicode, Inc. hereby grants the right to freely use the information
-#  supplied in this file in the creation of products supporting the
-#  Unicode Standard, and to make copies of this file in any form for
-#  internal or external distribution as long as this notice remains
-#  attached.
-#  
-#  Format: 4 tab-delimited fields:
-#
-#    (1) The Unicode value (in hexadecimal)
-#    (2) The Symbol Encoding code point (in hexadecimal)
-#    (3) # Unicode name
-#    (4) # PostScript character name
-#  
-#  General Notes:
-# 
-#    The Unicode values in this table were produced as the result of applying
-#    the algorithm described in the section "Populating a Unicode space" in the
-#    document "Unicode and Glyph Names," at
-#    http://partners.adobe.com/asn/developer/typeforum/unicodegn.html
-#    to the characters in Symbol. Note that some characters, such as "space",
-#    are mapped to 2 Unicode values. 29 characters have assignments in the
-#    Corporate Use Subarea; these are indicated by "(CUS)" in field 4. Refer to
-#    the above document for more details.
-#
-#    2011 July 12: The above link is no longer valid. For comparable,
-#    more current information, see the document, "Glyph", at:
-#    <http://www.adobe.com/devnet/opentype/archives/glyph.html>
-#
-#  Revision History:
-#
-#    [v1.0, 2011 July 12]
-#    Updated terms of use to current wording.
-#    Updated contact information and document link.
-#    No changes to the mapping data.
-#
-#    [v0.2, 30 March 1999]
-#    Different algorithm to produce Unicode values (see notes above) results in
-#    some character codes being mapped to 2 Unicode values; use of Corporate
-#    Use subarea values; addition of the euro character; changed assignments of
-#    some characters such as the COPYRIGHT SIGNs and RADICAL EXTENDER. Updated
-#    Unicode names to Unicode 2.0 names.
-#
-#    [v0.1, 5 May 1995] First release.
-#
-#  Use the Unicode reporting form <http://www.unicode.org/reporting.html>
-#    for any questions or comments or to report errors in the data.
-#
-0020	20	# SPACE	# space
-00A0	20	# NO-BREAK SPACE	# space
-0021	21	# EXCLAMATION MARK	# exclam
-2200	22	# FOR ALL	# universal
-0023	23	# NUMBER SIGN	# numbersign
-2203	24	# THERE EXISTS	# existential
-0025	25	# PERCENT SIGN	# percent
-0026	26	# AMPERSAND	# ampersand
-220B	27	# CONTAINS AS MEMBER	# suchthat
-0028	28	# LEFT PARENTHESIS	# parenleft
-0029	29	# RIGHT PARENTHESIS	# parenright
-2217	2A	# ASTERISK OPERATOR	# asteriskmath
-002B	2B	# PLUS SIGN	# plus
-002C	2C	# COMMA	# comma
-2212	2D	# MINUS SIGN	# minus
-002E	2E	# FULL STOP	# period
-002F	2F	# SOLIDUS	# slash
-0030	30	# DIGIT ZERO	# zero
-0031	31	# DIGIT ONE	# one
-0032	32	# DIGIT TWO	# two
-0033	33	# DIGIT THREE	# three
-0034	34	# DIGIT FOUR	# four
-0035	35	# DIGIT FIVE	# five
-0036	36	# DIGIT SIX	# six
-0037	37	# DIGIT SEVEN	# seven
-0038	38	# DIGIT EIGHT	# eight
-0039	39	# DIGIT NINE	# nine
-003A	3A	# COLON	# colon
-003B	3B	# SEMICOLON	# semicolon
-003C	3C	# LESS-THAN SIGN	# less
-003D	3D	# EQUALS SIGN	# equal
-003E	3E	# GREATER-THAN SIGN	# greater
-003F	3F	# QUESTION MARK	# question
-2245	40	# APPROXIMATELY EQUAL TO	# congruent
-0391	41	# GREEK CAPITAL LETTER ALPHA	# Alpha
-0392	42	# GREEK CAPITAL LETTER BETA	# Beta
-03A7	43	# GREEK CAPITAL LETTER CHI	# Chi
-0394	44	# GREEK CAPITAL LETTER DELTA	# Delta
-2206	44	# INCREMENT	# Delta
-0395	45	# GREEK CAPITAL LETTER EPSILON	# Epsilon
-03A6	46	# GREEK CAPITAL LETTER PHI	# Phi
-0393	47	# GREEK CAPITAL LETTER GAMMA	# Gamma
-0397	48	# GREEK CAPITAL LETTER ETA	# Eta
-0399	49	# GREEK CAPITAL LETTER IOTA	# Iota
-03D1	4A	# GREEK THETA SYMBOL	# theta1
-039A	4B	# GREEK CAPITAL LETTER KAPPA	# Kappa
-039B	4C	# GREEK CAPITAL LETTER LAMDA	# Lambda
-039C	4D	# GREEK CAPITAL LETTER MU	# Mu
-039D	4E	# GREEK CAPITAL LETTER NU	# Nu
-039F	4F	# GREEK CAPITAL LETTER OMICRON	# Omicron
-03A0	50	# GREEK CAPITAL LETTER PI	# Pi
-0398	51	# GREEK CAPITAL LETTER THETA	# Theta
-03A1	52	# GREEK CAPITAL LETTER RHO	# Rho
-03A3	53	# GREEK CAPITAL LETTER SIGMA	# Sigma
-03A4	54	# GREEK CAPITAL LETTER TAU	# Tau
-03A5	55	# GREEK CAPITAL LETTER UPSILON	# Upsilon
-03C2	56	# GREEK SMALL LETTER FINAL SIGMA	# sigma1
-03A9	57	# GREEK CAPITAL LETTER OMEGA	# Omega
-2126	57	# OHM SIGN	# Omega
-039E	58	# GREEK CAPITAL LETTER XI	# Xi
-03A8	59	# GREEK CAPITAL LETTER PSI	# Psi
-0396	5A	# GREEK CAPITAL LETTER ZETA	# Zeta
-005B	5B	# LEFT SQUARE BRACKET	# bracketleft
-2234	5C	# THEREFORE	# therefore
-005D	5D	# RIGHT SQUARE BRACKET	# bracketright
-22A5	5E	# UP TACK	# perpendicular
-005F	5F	# LOW LINE	# underscore
-F8E5	60	# RADICAL EXTENDER	# radicalex (CUS)
-03B1	61	# GREEK SMALL LETTER ALPHA	# alpha
-03B2	62	# GREEK SMALL LETTER BETA	# beta
-03C7	63	# GREEK SMALL LETTER CHI	# chi
-03B4	64	# GREEK SMALL LETTER DELTA	# delta
-03B5	65	# GREEK SMALL LETTER EPSILON	# epsilon
-03C6	66	# GREEK SMALL LETTER PHI	# phi
-03B3	67	# GREEK SMALL LETTER GAMMA	# gamma
-03B7	68	# GREEK SMALL LETTER ETA	# eta
-03B9	69	# GREEK SMALL LETTER IOTA	# iota
-03D5	6A	# GREEK PHI SYMBOL	# phi1
-03BA	6B	# GREEK SMALL LETTER KAPPA	# kappa
-03BB	6C	# GREEK SMALL LETTER LAMDA	# lambda
-00B5	6D	# MICRO SIGN	# mu
-03BC	6D	# GREEK SMALL LETTER MU	# mu
-03BD	6E	# GREEK SMALL LETTER NU	# nu
-03BF	6F	# GREEK SMALL LETTER OMICRON	# omicron
-03C0	70	# GREEK SMALL LETTER PI	# pi
-03B8	71	# GREEK SMALL LETTER THETA	# theta
-03C1	72	# GREEK SMALL LETTER RHO	# rho
-03C3	73	# GREEK SMALL LETTER SIGMA	# sigma
-03C4	74	# GREEK SMALL LETTER TAU	# tau
-03C5	75	# GREEK SMALL LETTER UPSILON	# upsilon
-03D6	76	# GREEK PI SYMBOL	# omega1
-03C9	77	# GREEK SMALL LETTER OMEGA	# omega
-03BE	78	# GREEK SMALL LETTER XI	# xi
-03C8	79	# GREEK SMALL LETTER PSI	# psi
-03B6	7A	# GREEK SMALL LETTER ZETA	# zeta
-007B	7B	# LEFT CURLY BRACKET	# braceleft
-007C	7C	# VERTICAL LINE	# bar
-007D	7D	# RIGHT CURLY BRACKET	# braceright
-223C	7E	# TILDE OPERATOR	# similar
-20AC	A0	# EURO SIGN	# Euro
-03D2	A1	# GREEK UPSILON WITH HOOK SYMBOL	# Upsilon1
-2032	A2	# PRIME	# minute
-2264	A3	# LESS-THAN OR EQUAL TO	# lessequal
-2044	A4	# FRACTION SLASH	# fraction
-2215	A4	# DIVISION SLASH	# fraction
-221E	A5	# INFINITY	# infinity
-0192	A6	# LATIN SMALL LETTER F WITH HOOK	# florin
-2663	A7	# BLACK CLUB SUIT	# club
-2666	A8	# BLACK DIAMOND SUIT	# diamond
-2665	A9	# BLACK HEART SUIT	# heart
-2660	AA	# BLACK SPADE SUIT	# spade
-2194	AB	# LEFT RIGHT ARROW	# arrowboth
-2190	AC	# LEFTWARDS ARROW	# arrowleft
-2191	AD	# UPWARDS ARROW	# arrowup
-2192	AE	# RIGHTWARDS ARROW	# arrowright
-2193	AF	# DOWNWARDS ARROW	# arrowdown
-00B0	B0	# DEGREE SIGN	# degree
-00B1	B1	# PLUS-MINUS SIGN	# plusminus
-2033	B2	# DOUBLE PRIME	# second
-2265	B3	# GREATER-THAN OR EQUAL TO	# greaterequal
-00D7	B4	# MULTIPLICATION SIGN	# multiply
-221D	B5	# PROPORTIONAL TO	# proportional
-2202	B6	# PARTIAL DIFFERENTIAL	# partialdiff
-2022	B7	# BULLET	# bullet
-00F7	B8	# DIVISION SIGN	# divide
-2260	B9	# NOT EQUAL TO	# notequal
-2261	BA	# IDENTICAL TO	# equivalence
-2248	BB	# ALMOST EQUAL TO	# approxequal
-2026	BC	# HORIZONTAL ELLIPSIS	# ellipsis
-F8E6	BD	# VERTICAL ARROW EXTENDER	# arrowvertex (CUS)
-F8E7	BE	# HORIZONTAL ARROW EXTENDER	# arrowhorizex (CUS)
-21B5	BF	# DOWNWARDS ARROW WITH CORNER LEFTWARDS	# carriagereturn
-2135	C0	# ALEF SYMBOL	# aleph
-2111	C1	# BLACK-LETTER CAPITAL I	# Ifraktur
-211C	C2	# BLACK-LETTER CAPITAL R	# Rfraktur
-2118	C3	# SCRIPT CAPITAL P	# weierstrass
-2297	C4	# CIRCLED TIMES	# circlemultiply
-2295	C5	# CIRCLED PLUS	# circleplus
-2205	C6	# EMPTY SET	# emptyset
-2229	C7	# INTERSECTION	# intersection
-222A	C8	# UNION	# union
-2283	C9	# SUPERSET OF	# propersuperset
-2287	CA	# SUPERSET OF OR EQUAL TO	# reflexsuperset
-2284	CB	# NOT A SUBSET OF	# notsubset
-2282	CC	# SUBSET OF	# propersubset
-2286	CD	# SUBSET OF OR EQUAL TO	# reflexsubset
-2208	CE	# ELEMENT OF	# element
-2209	CF	# NOT AN ELEMENT OF	# notelement
-2220	D0	# ANGLE	# angle
-2207	D1	# NABLA	# gradient
-F6DA	D2	# REGISTERED SIGN SERIF	# registerserif (CUS)
-F6D9	D3	# COPYRIGHT SIGN SERIF	# copyrightserif (CUS)
-F6DB	D4	# TRADE MARK SIGN SERIF	# trademarkserif (CUS)
-220F	D5	# N-ARY PRODUCT	# product
-221A	D6	# SQUARE ROOT	# radical
-22C5	D7	# DOT OPERATOR	# dotmath
-00AC	D8	# NOT SIGN	# logicalnot
-2227	D9	# LOGICAL AND	# logicaland
-2228	DA	# LOGICAL OR	# logicalor
-21D4	DB	# LEFT RIGHT DOUBLE ARROW	# arrowdblboth
-21D0	DC	# LEFTWARDS DOUBLE ARROW	# arrowdblleft
-21D1	DD	# UPWARDS DOUBLE ARROW	# arrowdblup
-21D2	DE	# RIGHTWARDS DOUBLE ARROW	# arrowdblright
-21D3	DF	# DOWNWARDS DOUBLE ARROW	# arrowdbldown
-25CA	E0	# LOZENGE	# lozenge
-2329	E1	# LEFT-POINTING ANGLE BRACKET	# angleleft
-F8E8	E2	# REGISTERED SIGN SANS SERIF	# registersans (CUS)
-F8E9	E3	# COPYRIGHT SIGN SANS SERIF	# copyrightsans (CUS)
-F8EA	E4	# TRADE MARK SIGN SANS SERIF	# trademarksans (CUS)
-2211	E5	# N-ARY SUMMATION	# summation
-F8EB	E6	# LEFT PAREN TOP	# parenlefttp (CUS)
-F8EC	E7	# LEFT PAREN EXTENDER	# parenleftex (CUS)
-F8ED	E8	# LEFT PAREN BOTTOM	# parenleftbt (CUS)
-F8EE	E9	# LEFT SQUARE BRACKET TOP	# bracketlefttp (CUS)
-F8EF	EA	# LEFT SQUARE BRACKET EXTENDER	# bracketleftex (CUS)
-F8F0	EB	# LEFT SQUARE BRACKET BOTTOM	# bracketleftbt (CUS)
-F8F1	EC	# LEFT CURLY BRACKET TOP	# bracelefttp (CUS)
-F8F2	ED	# LEFT CURLY BRACKET MID	# braceleftmid (CUS)
-F8F3	EE	# LEFT CURLY BRACKET BOTTOM	# braceleftbt (CUS)
-F8F4	EF	# CURLY BRACKET EXTENDER	# braceex (CUS)
-232A	F1	# RIGHT-POINTING ANGLE BRACKET	# angleright
-222B	F2	# INTEGRAL	# integral
-2320	F3	# TOP HALF INTEGRAL	# integraltp
-F8F5	F4	# INTEGRAL EXTENDER	# integralex (CUS)
-2321	F5	# BOTTOM HALF INTEGRAL	# integralbt
-F8F6	F6	# RIGHT PAREN TOP	# parenrighttp (CUS)
-F8F7	F7	# RIGHT PAREN EXTENDER	# parenrightex (CUS)
-F8F8	F8	# RIGHT PAREN BOTTOM	# parenrightbt (CUS)
-F8F9	F9	# RIGHT SQUARE BRACKET TOP	# bracketrighttp (CUS)
-F8FA	FA	# RIGHT SQUARE BRACKET EXTENDER	# bracketrightex (CUS)
-F8FB	FB	# RIGHT SQUARE BRACKET BOTTOM	# bracketrightbt (CUS)
-F8FC	FC	# RIGHT CURLY BRACKET TOP	# bracerighttp (CUS)
-F8FD	FD	# RIGHT CURLY BRACKET MID	# bracerightmid (CUS)
-F8FE	FE	# RIGHT CURLY BRACKET BOTTOM	# bracerightbt (CUS)
diff --git a/linux/Dockerfile b/linux/Dockerfile
index 40d37d13d..8a43e59f7 100644
--- a/linux/Dockerfile
+++ b/linux/Dockerfile
@@ -1,18 +1,25 @@
 # USE ALPINE LINUX
-FROM alpine:edge
+FROM alpine
+RUN apk update
+# INSTALL BASIC DEV TOOLS, GHC, GMP & ZLIB
 RUN echo "https://s3-us-west-2.amazonaws.com/alpine-ghc/8.0" >> /etc/apk/repositories
 ADD https://raw.githubusercontent.com/mitchty/alpine-ghc/master/mitch.tishmack%40gmail.com-55881c97.rsa.pub \
     /etc/apk/keys/mitch.tishmack@gmail.com-55881c97.rsa.pub
 RUN apk update
-RUN apk add alpine-sdk git ca-certificates ghc cabal stack zlib-dev \
-    dpkg fakeroot sed gawk grep bash linux-headers
-RUN stack update
+RUN apk add alpine-sdk git ca-certificates ghc gmp-dev zlib-dev bash dpkg fakeroot
+# GRAB A RECENT BINARY OF STACK
+RUN curl -L https://www.stackage.org/stack/linux-x86_64-static | tar xz --wildcards --strip-components=1 -C /usr/local/bin '*/stack'
+# COMPRESS WITH UPX
+ADD https://github.com/lalyos/docker-upx/releases/download/v3.91/upx /usr/local/bin/upx
+RUN chmod 755 /usr/local/bin/upx
+RUN ulimit -n 4096
 RUN stack config set system-ghc --global true
+RUN stack --resolver lts-9 setup --install-cabal 2.0.1.1
 #RUN mkdir -p /etc/stack
 #RUN echo "build: { split-objs: true }" > /etc/stack/config.yaml
 RUN mkdir -p /usr/src/
 WORKDIR /usr/src/
-RUN git  clone https://github.com/jgm/pandoc
+RUN git clone https://github.com/jgm/pandoc
 WORKDIR /usr/src/pandoc
 RUN stack install --stack-yaml stack.lts9.yaml \
     --only-dependencies \
diff --git a/man/pandoc.1 b/man/pandoc.1
index ee33b09ba..ed9fdb009 100644
--- a/man/pandoc.1
+++ b/man/pandoc.1
@@ -1,5 +1,5 @@
 .\"t
-.TH PANDOC 1 "January 18, 2018" "pandoc 2.1.1"
+.TH PANDOC 1 "April 26, 2018" "pandoc 2.2"
 .SH NAME
 pandoc - general markup converter
 .SH SYNOPSIS
@@ -10,34 +10,21 @@ pandoc - general markup converter
 Pandoc is a Haskell library for converting from one markup format to
 another, and a command\-line tool that uses this library.
 .PP
-Pandoc 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, JATS,
-Muse, txt2tags, Vimwiki, EPUB, ODT, and Word docx.
-.PP
-Pandoc 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.
+Pandoc can convert between numerous markup and word processing formats,
+including, but not limited to, various flavors of Markdown, HTML, LaTeX
+and Word docx.
+For the full lists of input and output formats, see the
+\f[C]\-\-from\f[] and \f[C]\-\-to\f[] options below.
+Pandoc can also produce PDF output: see creating a PDF, below.
 .PP
 Pandoc\[aq]s enhanced version of Markdown includes syntax for tables,
-definition lists, metadata blocks, \f[C]Div\f[] blocks, footnotes and
-citations, embedded LaTeX (including math), Markdown inside HTML block
-elements, and much more.
-These enhancements, described further under Pandoc\[aq]s Markdown, can
-be disabled using the \f[C]markdown_strict\f[] format.
+definition lists, metadata blocks, footnotes, citations, math, and much
+more.
+See below under Pandoc\[aq]s Markdown.
 .PP
 Pandoc has a modular design: it consists of a set of readers, which
 parse text in a given format and produce a native representation of the
-document (like an \f[I]abstract syntax tree\f[] or AST), and a set of
+document (an \f[I]abstract syntax tree\f[] or AST), and a set of
 writers, which convert this native representation into a target format.
 Thus, adding an input or output format requires only adding a reader or
 writer.
@@ -175,7 +162,8 @@ When using an HTML/CSS\-to\-PDF\-engine, \f[C]\-\-css\f[] affects the
 output.
 If \f[C]wkhtmltopdf\f[] is used, then the variables
 \f[C]margin\-left\f[], \f[C]margin\-right\f[], \f[C]margin\-top\f[],
-\f[C]margin\-bottom\f[], and \f[C]papersize\f[] will affect the output.
+\f[C]margin\-bottom\f[], \f[C]footer\-html\f[], \f[C]header\-html\f[]
+and \f[C]papersize\f[] will affect the output.
 .PP
 To debug the PDF creation, it can be useful to look at the intermediate
 representation: instead of \f[C]\-o\ test.pdf\f[], use for example
@@ -228,69 +216,184 @@ pandoc\ \-f\ html\ \-t\ markdown\ \-\-request\-header\ User\-Agent:"Mozilla/5.0"
 .TP
 .B \f[C]\-f\f[] \f[I]FORMAT\f[], \f[C]\-r\f[] \f[I]FORMAT\f[], \f[C]\-\-from=\f[]\f[I]FORMAT\f[], \f[C]\-\-read=\f[]\f[I]FORMAT\f[]
 Specify input format.
-\f[I]FORMAT\f[] can be \f[C]native\f[] (native Haskell), \f[C]json\f[]
-(JSON version of native AST), \f[C]markdown\f[] (pandoc\[aq]s extended
-Markdown), \f[C]markdown_strict\f[] (original unextended Markdown),
-\f[C]markdown_phpextra\f[] (PHP Markdown Extra), \f[C]markdown_mmd\f[]
-(MultiMarkdown), \f[C]gfm\f[] (GitHub\-Flavored Markdown),
-\f[C]commonmark\f[] (CommonMark Markdown), \f[C]textile\f[] (Textile),
-\f[C]rst\f[] (reStructuredText), \f[C]html\f[] (HTML), \f[C]docbook\f[]
-(DocBook), \f[C]t2t\f[] (txt2tags), \f[C]docx\f[] (docx), \f[C]odt\f[]
-(ODT), \f[C]epub\f[] (EPUB), \f[C]opml\f[] (OPML), \f[C]org\f[] (Emacs
-Org mode), \f[C]mediawiki\f[] (MediaWiki markup), \f[C]twiki\f[] (TWiki
-markup), \f[C]tikiwiki\f[] (TikiWiki markup), \f[C]creole\f[] (Creole
-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[].) Extensions can be
-individually enabled or disabled by appending \f[C]+EXTENSION\f[] or
-\f[C]\-EXTENSION\f[] to the format name.
+\f[I]FORMAT\f[] can be:
+.RS
+.IP \[bu] 2
+\f[C]commonmark\f[] (CommonMark Markdown)
+.IP \[bu] 2
+\f[C]creole\f[] (Creole 1.0)
+.IP \[bu] 2
+\f[C]docbook\f[] (DocBook)
+.IP \[bu] 2
+\f[C]docx\f[] (Word docx)
+.IP \[bu] 2
+\f[C]epub\f[] (EPUB)
+.IP \[bu] 2
+\f[C]fb2\f[] (FictionBook2 e\-book)
+.IP \[bu] 2
+\f[C]gfm\f[] (GitHub\-Flavored Markdown), or \f[C]markdown_github\f[],
+which 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[].
+.IP \[bu] 2
+\f[C]haddock\f[] (Haddock markup)
+.IP \[bu] 2
+\f[C]html\f[] (HTML)
+.IP \[bu] 2
+\f[C]jats\f[] (JATS XML)
+.IP \[bu] 2
+\f[C]json\f[] (JSON version of native AST)
+.IP \[bu] 2
+\f[C]latex\f[] (LaTeX)
+.IP \[bu] 2
+\f[C]markdown\f[] (Pandoc\[aq]s Markdown)
+.IP \[bu] 2
+\f[C]markdown_mmd\f[] (MultiMarkdown)
+.IP \[bu] 2
+\f[C]markdown_phpextra\f[] (PHP Markdown Extra)
+.IP \[bu] 2
+\f[C]markdown_strict\f[] (original unextended Markdown)
+.IP \[bu] 2
+\f[C]mediawiki\f[] (MediaWiki markup)
+.IP \[bu] 2
+\f[C]muse\f[] (Muse)
+.IP \[bu] 2
+\f[C]native\f[] (native Haskell)
+.IP \[bu] 2
+\f[C]odt\f[] (ODT)
+.IP \[bu] 2
+\f[C]opml\f[] (OPML)
+.IP \[bu] 2
+\f[C]org\f[] (Emacs Org mode)
+.IP \[bu] 2
+\f[C]rst\f[] (reStructuredText)
+.IP \[bu] 2
+\f[C]t2t\f[] (txt2tags)
+.IP \[bu] 2
+\f[C]textile\f[] (Textile)
+.IP \[bu] 2
+\f[C]tikiwiki\f[] (TikiWiki markup)
+.IP \[bu] 2
+\f[C]twiki\f[] (TWiki markup)
+.IP \[bu] 2
+\f[C]vimwiki\f[] (Vimwiki)
+.PP
+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
 .RE
 .TP
 .B \f[C]\-t\f[] \f[I]FORMAT\f[], \f[C]\-w\f[] \f[I]FORMAT\f[], \f[C]\-\-to=\f[]\f[I]FORMAT\f[], \f[C]\-\-write=\f[]\f[I]FORMAT\f[]
 Specify output format.
-\f[I]FORMAT\f[] can be \f[C]native\f[] (native Haskell), \f[C]json\f[]
-(JSON version of native AST), \f[C]plain\f[] (plain text),
-\f[C]markdown\f[] (pandoc\[aq]s extended Markdown),
-\f[C]markdown_strict\f[] (original unextended Markdown),
-\f[C]markdown_phpextra\f[] (PHP Markdown Extra), \f[C]markdown_mmd\f[]
-(MultiMarkdown), \f[C]gfm\f[] (GitHub\-Flavored Markdown),
-\f[C]commonmark\f[] (CommonMark Markdown), \f[C]rst\f[]
-(reStructuredText), \f[C]html4\f[] (XHTML 1.0 Transitional),
-\f[C]html\f[] or \f[C]html5\f[] (HTML5/XHTML polyglot markup),
-\f[C]latex\f[] (LaTeX), \f[C]beamer\f[] (LaTeX beamer slide show),
-\f[C]context\f[] (ConTeXt), \f[C]man\f[] (groff man), \f[C]mediawiki\f[]
-(MediaWiki markup), \f[C]dokuwiki\f[] (DokuWiki markup),
-\f[C]zimwiki\f[] (ZimWiki markup), \f[C]textile\f[] (Textile),
-\f[C]org\f[] (Emacs Org mode), \f[C]texinfo\f[] (GNU Texinfo),
-\f[C]opml\f[] (OPML), \f[C]docbook\f[] or \f[C]docbook4\f[] (DocBook 4),
-\f[C]docbook5\f[] (DocBook 5), \f[C]jats\f[] (JATS XML),
-\f[C]opendocument\f[] (OpenDocument), \f[C]odt\f[] (OpenOffice text
-document), \f[C]docx\f[] (Word docx), \f[C]haddock\f[] (Haddock markup),
-\f[C]rtf\f[] (rich text format), \f[C]epub2\f[] (EPUB v2 book),
-\f[C]epub\f[] or \f[C]epub3\f[] (EPUB v3), \f[C]fb2\f[] (FictionBook2
-e\-book), \f[C]asciidoc\f[] (AsciiDoc), \f[C]icml\f[] (InDesign ICML),
-\f[C]tei\f[] (TEI Simple), \f[C]slidy\f[] (Slidy HTML and JavaScript
-slide show), \f[C]slideous\f[] (Slideous HTML and JavaScript slide
-show), \f[C]dzslides\f[] (DZSlides HTML5 + JavaScript slide show),
-\f[C]revealjs\f[] (reveal.js HTML5 + JavaScript slide show), \f[C]s5\f[]
-(S5 HTML and JavaScript slide show), \f[C]pptx\f[] (PowerPoint slide
-show) or the path of a custom lua writer (see Custom writers, below).
-(\f[C]markdown_github\f[] provides deprecated and less accurate support
-for Github\-Flavored Markdown; please use \f[C]gfm\f[] instead, unless
-you use extensions that do not work with \f[C]gfm\f[].) Note that
-\f[C]odt\f[], \f[C]docx\f[], and \f[C]epub\f[] output will not be
-directed to \f[I]stdout\f[] unless forced with \f[C]\-o\ \-\f[].
+\f[I]FORMAT\f[] can be:
+.RS
+.IP \[bu] 2
+\f[C]asciidoc\f[] (AsciiDoc)
+.IP \[bu] 2
+\f[C]beamer\f[] (LaTeX beamer slide show)
+.IP \[bu] 2
+\f[C]commonmark\f[] (CommonMark Markdown)
+.IP \[bu] 2
+\f[C]context\f[] (ConTeXt)
+.IP \[bu] 2
+\f[C]docbook\f[] or \f[C]docbook4\f[] (DocBook 4)
+.IP \[bu] 2
+\f[C]docbook5\f[] (DocBook 5)
+.IP \[bu] 2
+\f[C]docx\f[] (Word docx)
+.IP \[bu] 2
+\f[C]dokuwiki\f[] (DokuWiki markup)
+.IP \[bu] 2
+\f[C]epub\f[] or \f[C]epub3\f[] (EPUB v3 book)
+.IP \[bu] 2
+\f[C]epub2\f[] (EPUB v2)
+.IP \[bu] 2
+\f[C]fb2\f[] (FictionBook2 e\-book)
+.IP \[bu] 2
+\f[C]gfm\f[] (GitHub\-Flavored Markdown), or \f[C]markdown_github\f[],
+which provides deprecated and less accurate support for Github\-Flavored
+Markdown; please use \f[C]gfm\f[] instead, unless you use extensions
+that do not work with \f[C]gfm\f[].
+.IP \[bu] 2
+\f[C]haddock\f[] (Haddock markup)
+.IP \[bu] 2
+\f[C]html\f[] or \f[C]html5\f[] (HTML, i.e.
+HTML5/XHTML polyglot markup)
+.IP \[bu] 2
+\f[C]html4\f[] (XHTML 1.0 Transitional)
+.IP \[bu] 2
+\f[C]icml\f[] (InDesign ICML)
+.IP \[bu] 2
+\f[C]jats\f[] (JATS XML)
+.IP \[bu] 2
+\f[C]json\f[] (JSON version of native AST)
+.IP \[bu] 2
+\f[C]latex\f[] (LaTeX)
+.IP \[bu] 2
+\f[C]man\f[] (groff man)
+.IP \[bu] 2
+\f[C]markdown\f[] (Pandoc\[aq]s Markdown)
+.IP \[bu] 2
+\f[C]markdown_mmd\f[] (MultiMarkdown)
+.IP \[bu] 2
+\f[C]markdown_phpextra\f[] (PHP Markdown Extra)
+.IP \[bu] 2
+\f[C]markdown_strict\f[] (original unextended Markdown)
+.IP \[bu] 2
+\f[C]mediawiki\f[] (MediaWiki markup)
+.IP \[bu] 2
+\f[C]ms\f[] (groff ms)
+.IP \[bu] 2
+\f[C]muse\f[] (Muse),
+.IP \[bu] 2
+\f[C]native\f[] (native Haskell),
+.IP \[bu] 2
+\f[C]odt\f[] (OpenOffice text document)
+.IP \[bu] 2
+\f[C]opml\f[] (OPML)
+.IP \[bu] 2
+\f[C]opendocument\f[] (OpenDocument)
+.IP \[bu] 2
+\f[C]org\f[] (Emacs Org mode)
+.IP \[bu] 2
+\f[C]plain\f[] (plain text),
+.IP \[bu] 2
+\f[C]pptx\f[] (PowerPoint slide show)
+.IP \[bu] 2
+\f[C]rst\f[] (reStructuredText)
+.IP \[bu] 2
+\f[C]rtf\f[] (Rich Text Format)
+.IP \[bu] 2
+\f[C]texinfo\f[] (GNU Texinfo)
+.IP \[bu] 2
+\f[C]textile\f[] (Textile)
+.IP \[bu] 2
+\f[C]slideous\f[] (Slideous HTML and JavaScript slide show)
+.IP \[bu] 2
+\f[C]slidy\f[] (Slidy HTML and JavaScript slide show)
+.IP \[bu] 2
+\f[C]dzslides\f[] (DZSlides HTML5 + JavaScript slide show),
+.IP \[bu] 2
+\f[C]revealjs\f[] (reveal.js HTML5 + JavaScript slide show)
+.IP \[bu] 2
+\f[C]s5\f[] (S5 HTML and JavaScript slide show)
+.IP \[bu] 2
+\f[C]tei\f[] (TEI Simple)
+.IP \[bu] 2
+\f[C]zimwiki\f[] (ZimWiki markup)
+.IP \[bu] 2
+the path of a custom lua writer, see Custom writers below
+.PP
+Note that \f[C]odt\f[], \f[C]docx\f[], and \f[C]epub\f[] output will not
+be directed to \f[I]stdout\f[] unless forced with \f[C]\-o\ \-\f[].
+.PP
 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
 .RE
 .TP
 .B \f[C]\-o\f[] \f[I]FILE\f[], \f[C]\-\-output=\f[]\f[I]FILE\f[]
@@ -531,19 +634,29 @@ end
 return\ {{Str\ =\ expand_hello_world}}
 \f[]
 .fi
+.PP
+In order of preference, pandoc will look for lua filters in
+.IP "1." 3
+a specified full or relative path (executable or non\-executable)
+.IP "2." 3
+\f[C]$DATADIR/filters\f[] (executable or non\-executable) where
+\f[C]$DATADIR\f[] is the user data directory (see
+\f[C]\-\-data\-dir\f[], above).
 .RE
 .TP
 .B \f[C]\-M\f[] \f[I]KEY\f[][\f[C]=\f[]\f[I]VAL\f[]], \f[C]\-\-metadata=\f[]\f[I]KEY\f[][\f[C]:\f[]\f[I]VAL\f[]]
 Set the metadata field \f[I]KEY\f[] to the value \f[I]VAL\f[].
 A value specified on the command line overrides a value specified in the
-document.
+document using [YAML metadata
+blocks][Extension:\f[C]yaml_metadata_block\f[]].
 Values will be parsed as YAML boolean or string values.
 If no value is specified, the value will be treated as Boolean true.
 Like \f[C]\-\-variable\f[], \f[C]\-\-metadata\f[] causes template
 variables to be set.
 But unlike \f[C]\-\-variable\f[], \f[C]\-\-metadata\f[] affects the
 metadata of the underlying document (which is accessible from filters
-and may be printed in some output formats).
+and may be printed in some output formats) and metadata values will be
+escaped when inserted into the template.
 .RS
 .RE
 .TP
@@ -821,6 +934,7 @@ line, or when resources used in a document must be downloaded).
 Produce a standalone HTML file with no external dependencies, using
 \f[C]data:\f[] URIs to incorporate the contents of linked scripts,
 stylesheets, images, and videos.
+Implies \f[C]\-\-standalone\f[].
 The resulting file should be "self\-contained," in the sense that it
 needs no external files and no net access to be displayed properly by a
 browser.
@@ -850,8 +964,9 @@ Use \f[C]<q>\f[] tags for quotes in HTML.
 .TP
 .B \f[C]\-\-ascii\f[]
 Use only ASCII characters in output.
-Currently supported only for HTML and DocBook output (which uses
-numerical entities instead of UTF\-8 when this option is selected).
+Currently supported for XML and HTML formats (which use numerical
+entities instead of UTF\-8 when this option is selected) and for groff
+ms and man (which use hexadecimal escapes).
 .RS
 .RE
 .TP
@@ -1044,6 +1159,34 @@ default \f[C]reference.odt\f[]:
 Then open \f[C]custom\-reference.odt\f[] in LibreOffice, modify the
 styles as you wish, and save the file.
 .RE
+.TP
+.B PowerPoint
+Any template included with a recent install of Microsoft PowerPoint
+(either with \f[C]\&.pptx\f[] or \f[C]\&.potx\f[] extension) should
+work, as will most templates derived from these.
+.RS
+.PP
+The specific requirement is that the template should contain the
+following four layouts as its first four layouts:
+.IP "1." 3
+Title Slide
+.IP "2." 3
+Title and Content
+.IP "3." 3
+Section Header
+.IP "4." 3
+Two Content
+.PP
+All templates included with a recent version of MS PowerPoint will fit
+these criteria.
+(You can click on \f[C]Layout\f[] under the \f[C]Home\f[] menu to
+check.)
+.PP
+You can also modify the default \f[C]reference.pptx\f[]: first run
+\f[C]pandoc\ \-\-print\-default\-data\-file\ reference.pptx\ >\ custom\-reference.pptx\f[],
+and then modify \f[C]custom\-reference.pptx\f[] in MS PowerPoint (pandoc
+will use the first four layout slides, as mentioned above).
+.RE
 .RE
 .TP
 .B \f[C]\-\-epub\-cover\-image=\f[]\f[I]FILE\f[]
@@ -1270,60 +1413,6 @@ inserted.
 Note that this option does not imply \f[C]\-\-katex\f[].
 .RS
 .RE
-.TP
-.B \f[C]\-m\f[] [\f[I]URL\f[]], \f[C]\-\-latexmathml\f[][\f[C]=\f[]\f[I]URL\f[]]
-\f[I]Deprecated.\f[] Use the LaTeXMathML script to display embedded TeX
-math in HTML output.
-TeX math will be displayed between \f[C]$\f[] or \f[C]$$\f[] characters
-and put in \f[C]<span>\f[] tags with class \f[C]LaTeX\f[].
-The LaTeXMathML JavaScript will then change it to MathML.
-Note that currently only Firefox and Safari (and select e\-book readers)
-natively support MathML.
-To insert a link the \f[C]LaTeXMathML.js\f[] script, provide a
-\f[I]URL\f[].
-.RS
-.RE
-.TP
-.B \f[C]\-\-jsmath\f[][\f[C]=\f[]\f[I]URL\f[]]
-\f[I]Deprecated.\f[] Use jsMath (the predecessor of MathJax) to display
-embedded TeX math in HTML output.
-TeX math will be put inside \f[C]<span>\f[] tags (for inline math) or
-\f[C]<div>\f[] tags (for display math) with class \f[C]math\f[] and
-rendered by the jsMath script.
-The \f[I]URL\f[] should point to the script (e.g.
-\f[C]jsMath/easy/load.js\f[]); if provided, it will be linked to in the
-header of standalone HTML documents.
-If a \f[I]URL\f[] is not provided, no link to the jsMath load script
-will be inserted; it is then up to the author to provide such a link in
-the HTML template.
-.RS
-.RE
-.TP
-.B \f[C]\-\-gladtex\f[]
-\f[I]Deprecated.\f[] Enclose TeX math in \f[C]<eq>\f[] tags in HTML
-output.
-The resulting HTML can then be processed by gladTeX to produce images of
-the typeset formulas and an HTML file with links to these images.
-So, the procedure is:
-.RS
-.IP
-.nf
-\f[C]
-pandoc\ \-s\ \-\-gladtex\ input.md\ \-o\ myfile.htex
-gladtex\ \-d\ myfile\-images\ myfile.htex
-#\ produces\ myfile.html\ and\ images\ in\ myfile\-images
-\f[]
-.fi
-.RE
-.TP
-.B \f[C]\-\-mimetex\f[][\f[C]=\f[]\f[I]URL\f[]]
-\f[I]Deprecated.\f[] Render TeX math using the mimeTeX CGI script, which
-generates an image for each TeX formula.
-This should work in all browsers.
-If \f[I]URL\f[] is not specified, it is assumed that the script is at
-\f[C]/cgi\-bin/mimetex.cgi\f[].
-.RS
-.RE
 .SS Options for wrapper scripts
 .TP
 .B \f[C]\-\-dump\-args\f[]
@@ -1389,23 +1478,25 @@ template.
 For \f[C]pdf\f[] output, customize the \f[C]default.latex\f[] template
 (or the \f[C]default.context\f[] template, if you use
 \f[C]\-t\ context\f[], or the \f[C]default.ms\f[] template, if you use
-\f[C]\-t\ ms\f[], or the \f[C]default.html5\f[] template, if you use
-\f[C]\-t\ html5\f[]).
+\f[C]\-t\ ms\f[], or the \f[C]default.html\f[] template, if you use
+\f[C]\-t\ html\f[]).
 .IP \[bu] 2
 \f[C]docx\f[] has no template (however, you can use
 \f[C]\-\-reference\-doc\f[] to customize the output).
 .PP
 Templates contain \f[I]variables\f[], which allow for the inclusion of
 arbitrary information at any point in the file.
-Variables may be set within the document using YAML metadata blocks.
-They may also be set at the command line using the
-\f[C]\-V/\-\-variable\f[] option: variables set in this way override
-metadata fields with the same name.
+They may be set at the command line using the \f[C]\-V/\-\-variable\f[]
+option.
+If a variable is not set, pandoc will look for the key in the
+document\[aq]s metadata \[en] which can be set using either [YAML
+metadata blocks][Extension:\f[C]yaml_metadata_block\f[]] or with the
+\f[C]\-\-metadata\f[] option.
 .SS Variables set by pandoc
 .PP
 Some variables are set automatically by pandoc.
-These vary somewhat depending on the output format, but include metadata
-fields as well as the following:
+These vary somewhat depending on the output format, but include the
+following:
 .TP
 .B \f[C]sourcefile\f[], \f[C]outputfile\f[]
 source and destination filenames, as given on the command line.
@@ -1648,6 +1739,11 @@ option for document class, e.g.
 .RS
 .RE
 .TP
+.B \f[C]beameroption\f[]
+In beamer, add extra beamer option with \f[C]\\setbeameroption{}\f[]
+.RS
+.RE
+.TP
 .B \f[C]geometry\f[]
 option for \f[C]geometry\f[] package, e.g.
 \f[C]margin=1in\f[]; may be repeated for multiple options
@@ -1891,6 +1987,16 @@ include table of contents (can also be set using
 include list of figures, list of tables
 .RS
 .RE
+.TP
+.B \f[C]pdfa\f[]
+adds to the preamble the setup necessary to generate PDF/A\-1b:2005.
+To successfully generate PDF/A the required ICC color profiles have to
+be available and the content and all included files (such as images)
+have to be standard conforming.
+The ICC profiles can be obtained from ConTeXt ICC Profiles.
+See also ConTeXt PDFA for more details.
+.RS
+.RE
 .SS Variables for man pages
 .TP
 .B \f[C]section\f[]
@@ -2319,7 +2425,7 @@ 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.
 .PP
-Note that GHC expects the bird tracks in the first column, so indentend
+Note that GHC expects the bird tracks in the first column, so indented
 literate code blocks (e.g.
 inside an itemized environment) will not be picked up by the Haskell
 compiler.
@@ -2337,8 +2443,19 @@ This extension can be enabled/disabled for the following formats:
 .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[]
+\f[C]docx\f[], \f[C]odt\f[], \f[C]opendocument\f[], \f[C]html\f[]
+.RS
+.RE
+.SS Extension: \f[C]styles\f[]
+.PP
+Read all docx styles as divs (for paragraph styles) and spans (for
+character styles) regardless of whether pandoc understands the meaning
+of these styles.
+This can be used with docx custom styles.
+Disabled by default.
+.TP
+.B input formats
+\f[C]docx\f[]
 .RS
 .RE
 .SS Extension: \f[C]amuse\f[]
@@ -2741,7 +2858,7 @@ Here \f[C]mycode\f[] is an identifier, \f[C]haskell\f[] and
 with value \f[C]100\f[].
 Some output formats can use this information to do syntax highlighting.
 Currently, the only output formats that uses this information are HTML,
-LaTeX, Docx, and Ms.
+LaTeX, Docx, Ms, and PowerPoint.
 If highlighting is supported for your output format and language, then
 the code block above will appear highlighted, with numbered lines.
 (To see which languages are supported, type
@@ -3720,7 +3837,8 @@ For example:
 .nf
 \f[C]
 header\-includes:
-\-\ ```{=latex}
+\-\ |
+\ \ ```{=latex}
 \ \ \\let\\oldsection\\section
 \ \ \\renewcommand{\\section}[1]{\\clearpage\\oldsection{#1}}
 \ \ ```
@@ -4142,9 +4260,29 @@ This\ is\ `<a>html</a>`{=html}
 \f[]
 .fi
 .PP
+This can be useful to insert raw xml into \f[C]docx\f[] documents, e.g.
+a pagebreak:
+.IP
+.nf
+\f[C]
+```{=openxml}
+<w:p>
+\ \ <w:r>
+\ \ \ \ <w:br\ w:type="page"/>
+\ \ </w:r>
+</w:p>
+```
+\f[]
+.fi
+.PP
 The format name should match the target format name (see
 \f[C]\-t/\-\-to\f[], above, for a list, or use
 \f[C]pandoc\ \-\-list\-output\-formats\f[]).
+Use \f[C]openxml\f[] for \f[C]docx\f[] output, \f[C]opendocument\f[] for
+\f[C]odt\f[] output, \f[C]html5\f[] for \f[C]epub3\f[] output,
+\f[C]html4\f[] for \f[C]epub2\f[] output, and \f[C]latex\f[],
+\f[C]beamer\f[], \f[C]ms\f[], or \f[C]html5\f[] for \f[C]pdf\f[] output
+(depending on what you use for \f[C]\-\-pdf\-engine\f[]).
 .PP
 This extension presupposes that the relevant kind of inline code or
 fenced code block is enabled.
@@ -5204,9 +5342,42 @@ reveal.js.
 By default, these writers produce lists that display "all at once." If
 you want your lists to display incrementally (one item at a time), use
 the \f[C]\-i\f[] option.
-If you want a particular list to depart from the default (that is, to
+If you want a particular list to depart from the default, put it in a
+\f[C]div\f[] block with class \f[C]incremental\f[] or
+\f[C]nonincremental\f[].
+So, for example, using the \f[C]fenced\ div\f[] syntax, the following
+would be incremental regardless of the document default:
+.IP
+.nf
+\f[C]
+:::\ incremental
+
+\-\ Eat\ spaghetti
+\-\ Drink\ wine
+
+:::
+\f[]
+.fi
+.PP
+or
+.IP
+.nf
+\f[C]
+:::\ nonincremental
+
+\-\ Eat\ spaghetti
+\-\ Drink\ wine
+
+:::
+\f[]
+.fi
+.PP
+While using \f[C]incremental\f[] and \f[C]nonincremental\f[] divs are
+the recommended method of setting incremental lists on a per\-case
+basis, an older method is also supported: putting lists inside a
+blockquote will depart from the document default (that is, it will
 display incrementally without the \f[C]\-i\f[] option and all at once
-with the \f[C]\-i\f[] option), put it in a block quote:
+with the \f[C]\-i\f[] option):
 .IP
 .nf
 \f[C]
@@ -5215,7 +5386,7 @@ with the \f[C]\-i\f[] option), put it in a block quote:
 \f[]
 .fi
 .PP
-In this way incremental and nonincremental lists can be mixed in a
+Both methods allow incremental and nonincremental lists to be mixed in a
 single document.
 .SS Inserting pauses
 .PP
@@ -5286,7 +5457,7 @@ This is recommended especially for bibliographies:
 .fi
 .SS Speaker notes
 .PP
-reveal.js has good support for speaker notes.
+Speaker notes are supported in reveal.js and PowerPoint (pptx) output.
 You can add notes to your Markdown document thus:
 .IP
 .nf
@@ -5302,8 +5473,11 @@ This\ is\ my\ note.
 \f[]
 .fi
 .PP
-To show the notes window, press \f[C]s\f[] while viewing the
-presentation.
+To show the notes window in reveal.js, press \f[C]s\f[] while viewing
+the presentation.
+Speaker notes in PowerPoint will be available, as usual, in handouts and
+presenter view.
+.PP
 Notes are not yet supported for other slide formats, but the notes will
 not appear on the slides themselves.
 .SS Columns
@@ -5342,6 +5516,49 @@ All of the other frame attributes described in Section 8.1 of the Beamer
 User\[aq]s Guide may also be used: \f[C]allowdisplaybreaks\f[],
 \f[C]allowframebreaks\f[], \f[C]b\f[], \f[C]c\f[], \f[C]t\f[],
 \f[C]environment\f[], \f[C]label\f[], \f[C]plain\f[], \f[C]shrink\f[].
+.SS Background in reveal.js
+.PP
+Background images can be added to self\-contained reveal.js slideshows.
+.PP
+For the same image on every slide, use the reveal.js configuration
+option \f[C]parallaxBackgroundImage\f[] either in the YAML metadata
+block or as a command\-line variable.
+You can also set \f[C]parallaxBackgroundHorizontal\f[] and
+\f[C]parallaxBackgroundVertical\f[] the same way and must also set
+\f[C]parallaxBackgroundSize\f[] to have your values take effect.
+.PP
+To set an image for a particular slide, add
+\f[C]{data\-background\-image="/path/to/image"}\f[] to the first
+slide\-level header on the slide (which may even be empty).
+.PP
+In reveal.js\[aq]s overview mode, the parallaxBackgroundImage will show
+up only on the first slide.
+.PP
+Other background settings also work on individual slides, including
+\f[C]data\-background\-size\f[], \f[C]data\-background\-repeat\f[],
+\f[C]data\-background\-color\f[], \f[C]data\-transition\f[], and
+\f[C]data\-transition\-speed\f[].
+.PP
+See the reveal.js documentation for more details.
+.PP
+For example:
+.IP
+.nf
+\f[C]
+\-\-\-
+title:\ My\ Slideshow
+parallaxBackgroundImage:\ /path/to/my/background_image.png
+\-\-\-
+
+##\ Slide\ One
+
+Slide\ 1\ has\ background_image.png\ as\ its\ background.
+
+##\ {data\-background\-image="/path/to/special_image.jpg"}
+
+Slide\ 2\ has\ a\ special\ image\ for\ its\ background,\ even\ though\ the\ header\ has\ no\ content.
+\f[]
+.fi
 .SH CREATING EPUBS WITH PANDOC
 .SS EPUB Metadata
 .PP
@@ -5532,7 +5749,62 @@ To see a list of highlight styles, type
 \f[C]pandoc\ \-\-list\-highlight\-styles\f[].
 .PP
 To disable highlighting, use the \f[C]\-\-no\-highlight\f[] option.
-.SH CUSTOM STYLES IN DOCX OUTPUT
+.SH CUSTOM STYLES IN DOCX
+.SS Input
+.PP
+The docx reader, by default, only reads those styles that it can convert
+into pandoc elements, either by direct conversion or interpreting the
+derivation of the input document\[aq]s styles.
+.PP
+By enabling the \f[C]styles\f[] extension in the docx reader
+(\f[C]\-f\ docx+styles\f[]), you can produce output that maintains the
+styles of the input document, using the \f[C]custom\-style\f[] class.
+Paragraph styles are interpreted as divs, while character styles are
+interpreted as spans.
+.PP
+For example, using the \f[C]custom\-style\-reference.docx\f[] file in
+the test directory, we have the following different outputs:
+.PP
+Without the \f[C]+styles\f[] extension:
+.IP
+.nf
+\f[C]
+$\ pandoc\ test/docx/custom\-style\-reference.docx\ \-f\ docx\ \-t\ markdown
+This\ is\ some\ text.
+
+This\ is\ text\ with\ an\ *emphasized*\ text\ style.\ And\ this\ is\ text\ with\ a
+**strengthened**\ text\ style.
+
+>\ Here\ is\ a\ styled\ paragraph\ that\ inherits\ from\ Block\ Text.
+\f[]
+.fi
+.PP
+And with the extension:
+.IP
+.nf
+\f[C]
+$\ pandoc\ test/docx/custom\-style\-reference.docx\ \-f\ docx+styles\ \-t\ markdown
+
+:::\ {custom\-style="FirstParagraph"}
+This\ is\ some\ text.
+:::
+
+:::\ {custom\-style="BodyText"}
+This\ is\ text\ with\ an\ [emphasized]{custom\-style="Emphatic"}\ text\ style.
+And\ this\ is\ text\ with\ a\ [strengthened]{custom\-style="Strengthened"}
+text\ style.
+:::
+
+:::\ {custom\-style="MyBlockStyle"}
+>\ Here\ is\ a\ styled\ paragraph\ that\ inherits\ from\ Block\ Text.
+:::
+\f[]
+.fi
+.PP
+With these custom styles, you can use your input document as a
+reference\-doc while creating docx output (see below), and maintain the
+same styles in your input and output files.
+.SS Output
 .PP
 By default, pandoc\[aq]s docx output applies a predefined set of styles
 for blocks such as paragraphs and block quotes, and uses largely default
diff --git a/pandoc.cabal b/pandoc.cabal
index 9f00f91c5..7d69b4021 100644
--- a/pandoc.cabal
+++ b/pandoc.cabal
@@ -1,17 +1,17 @@
 name:            pandoc
-version:         2.1.1
+version:         2.2
 cabal-version:   >= 1.10
 build-type:      Custom
-license:         GPL
+license:         GPL-2
 license-file:    COPYING.md
 copyright:       (c) 2006-2018 John MacFarlane
 author:          John MacFarlane <jgm@berkeley.edu>
 maintainer:      John MacFarlane <jgm@berkeley.edu>
 bug-reports:     https://github.com/jgm/pandoc/issues
 stability:       alpha
-homepage:        http://pandoc.org
+homepage:        https://pandoc.org
 category:        Text
-tested-with:     GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2
+tested-with:     GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.1
 synopsis:        Conversion between markup formats
 description:     Pandoc is a Haskell library for converting from one markup
                  format to another, and a command-line tool that uses
@@ -19,11 +19,11 @@ description:     Pandoc is a Haskell library for converting from one markup
                  (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
-                 Markdown, reStructuredText, XHTML, HTML 5, LaTeX, ConTeXt,
-                 DocBook, JATS, OPML, TEI, OpenDocument, ODT, Word docx,
-                 RTF, MediaWiki, DokuWiki, ZimWiki, Textile, groff man,
-                 groff ms, plain text, Emacs Org-Mode, AsciiDoc,
+                 Vimwiki, Word Docx, ODT, EPUB, FictionBook2, and Textile,
+                 and it can write Markdown, reStructuredText, XHTML, HTML 5,
+                 LaTeX, ConTeXt, DocBook, JATS, OPML, TEI, OpenDocument,
+                 ODT, Word docx, RTF, MediaWiki, DokuWiki, ZimWiki, Textile,
+                 groff man, groff ms, plain text, Emacs Org-Mode, AsciiDoc,
                  Haddock markup, EPUB (v2 and v3), FictionBook2, InDesign
                  ICML, Muse, LaTeX beamer slides, PowerPoint, and several
                  kinds of HTML/JavaScript slide shows (S5, Slidy, Slideous,
@@ -102,7 +102,6 @@ data-files:
                  data/odt/META-INF/manifest.xml
                  -- source files for reference.pptx
                  data/pptx/_rels/.rels
-                 data/pptx/docProps/thumbnail.jpeg
                  data/pptx/docProps/app.xml
                  data/pptx/docProps/core.xml
                  data/pptx/ppt/slideLayouts/_rels/slideLayout1.xml.rels
@@ -149,8 +148,6 @@ data-files:
                  data/pptx/[Content_Types].xml
                   -- stylesheet for EPUB writer
                  data/epub.css
-                 -- data for LaTeXMathML writer
-                 data/LaTeXMathML.js
                  -- data for dzslides writer
                  data/dzslides/template.html
                  -- default abbreviations file
@@ -304,6 +301,8 @@ extra-source-files:
                  test/fb2/images-embedded.html
                  test/fb2/images-embedded.fb2
                  test/fb2/test-small.png
+                 test/fb2/reader/*.fb2
+                 test/fb2/reader/*.native
                  test/fb2/test.jpg
                  test/docx/*.docx
                  test/docx/golden/*.docx
@@ -335,18 +334,10 @@ flag trypandoc
   Description:   Build trypandoc cgi executable.
   Default:       False
 
-flag weigh-pandoc
-  Description:   Build weigh-pandoc to measure memory usage.
-  Default:       False
-
 flag network-uri
   Description:   Get Network.URI from the network-uri package
   Default:       True
 
-flag old-locale
-  Description:   Use old-locale and time < 1.5
-  Default:       False
-
 custom-setup
   setup-depends: base, Cabal
 
@@ -357,12 +348,13 @@ library
                  unordered-containers >= 0.2 && < 0.3,
                  parsec >= 3.1 && < 3.2,
                  mtl >= 2.2 && < 2.3,
-                 exceptions >= 0.8 && < 0.9,
+                 exceptions >= 0.8 && < 0.11,
                  filepath >= 1.1 && < 1.5,
                  process >= 1.2.3 && < 1.7,
                  directory >= 1 && < 1.4,
                  bytestring >= 0.9 && < 0.11,
                  text >= 0.11 && < 1.3,
+                 time >= 1.5 && < 1.10,
                  safe >= 0.3 && < 0.4,
                  zip-archive >= 0.2.3.4 && < 0.4,
                  HTTP >= 4000.0.5 && < 4000.4,
@@ -370,25 +362,25 @@ library
                  xml >= 1.3.12 && < 1.4,
                  split >= 0.2 && < 0.3,
                  random >= 1 && < 1.2,
-                 pandoc-types >= 1.17.3 && < 1.18,
-                 aeson >= 0.7 && < 1.3,
+                 pandoc-types >= 1.17.4.2 && < 1.18,
+                 aeson >= 0.7 && < 1.4,
                  aeson-pretty >= 0.8.5 && < 0.9,
-                 tagsoup >= 0.14.3 && < 0.15,
+                 tagsoup >= 0.14.6 && < 0.15,
                  base64-bytestring >= 0.1 && < 1.1,
                  zlib >= 0.5 && < 0.7,
-                 skylighting >= 0.5.1 && < 0.7,
+                 skylighting >= 0.5.1 && < 0.8,
                  data-default >= 0.4 && < 0.8,
-                 temporary >= 1.1 && < 1.3,
+                 temporary >= 1.1 && < 1.4,
                  blaze-html >= 0.9 && < 0.10,
                  blaze-markup >= 0.8 && < 0.9,
                  yaml >= 0.8.8.2 && < 0.9,
                  scientific >= 0.2 && < 0.4,
                  vector >= 0.10 && < 0.13,
-                 hslua >= 0.9.5 && < 0.10,
+                 hslua >= 0.9.5 && < 0.9.6,
                  hslua-module-text >= 0.1.2 && < 0.2,
                  binary >= 0.5 && < 0.10,
                  SHA >= 1.6 && < 1.7,
-                 haddock-library >= 1.1 && < 1.5,
+                 haddock-library >= 1.1 && < 1.6,
                  deepseq >= 1.3 && < 1.5,
                  JuicyPixels >= 3.1.6.1 && < 3.3,
                  Glob >= 0.7 && < 0.10,
@@ -396,17 +388,18 @@ library
                  doctemplates >= 0.2.1 && < 0.3,
                  http-client >= 0.4.30 && < 0.6,
                  http-client-tls >= 0.2.4 && < 0.4,
-                 http-types >= 0.8 && < 0.12,
+                 http-types >= 0.8 && < 0.13,
                  case-insensitive >= 1.2 && < 1.3
+  if impl(ghc < 8.0)
+    build-depends: semigroups == 0.18.*
+  if impl(ghc < 8.4)
+     hs-source-dirs: prelude
+     other-modules:  Prelude
+     build-depends:  base-compat >= 0.9
   if os(windows)
     cpp-options:      -D_WINDOWS
   else
     build-depends:  unix >= 2.4 && < 2.8
-  if flag(old-locale)
-     build-depends: old-locale >= 1 && < 1.1,
-                    time >= 1.2 && < 1.5
-  else
-     build-depends: time >= 1.5 && < 1.9
   if flag(network-uri)
      build-depends: network-uri >= 2.6 && < 2.7, network >= 2.6
   else
@@ -418,12 +411,8 @@ library
   if os(windows)
     cpp-options:      -D_WINDOWS
   ghc-options:   -Wall -fno-warn-unused-do-bind
-  ghc-prof-options: -fprof-auto-exported
-  default-language: Haskell98
-  other-extensions:   PatternGuards, OverloadedStrings,
-                      ScopedTypeVariables, GeneralizedNewtypeDeriving,
-                      RelaxedPolyRec, DeriveDataTypeable, TypeSynonymInstances,
-                      FlexibleInstances
+  default-language: Haskell2010
+  other-extensions: NoImplicitPrelude
   hs-source-dirs:  src
 
   exposed-modules: Text.Pandoc,
@@ -459,6 +448,7 @@ library
                    Text.Pandoc.Readers.EPUB,
                    Text.Pandoc.Readers.Muse,
                    Text.Pandoc.Readers.Man,
+                   Text.Pandoc.Readers.FB2,
                    Text.Pandoc.Writers,
                    Text.Pandoc.Writers.Native,
                    Text.Pandoc.Writers.Docbook,
@@ -555,22 +545,23 @@ library
                    Text.Pandoc.UUID,
                    Text.Pandoc.Translations,
                    Text.Pandoc.Slides,
-                   Text.Pandoc.Compat.Time,
                    Paths_pandoc
 
   buildable:       True
 
 executable pandoc
   build-depends: pandoc, base >= 4.7 && < 5
+  if impl(ghc < 8.0)
+    build-depends: semigroups == 0.18.*
+  if impl(ghc < 8.4)
+     hs-source-dirs: prelude
+     other-modules:  Prelude
+     build-depends:  base-compat >= 0.9
   ghc-options:   -rtsopts -with-rtsopts=-K16m -Wall -fno-warn-unused-do-bind -threaded
-  ghc-prof-options: -fprof-auto-exported -rtsopts -with-rtsopts=-K16m
   if flag(static)
     ld-options:     -static
-  default-language: Haskell98
-  other-extensions: PatternGuards, OverloadedStrings,
-                    ScopedTypeVariables, GeneralizedNewtypeDeriving,
-                    RelaxedPolyRec, DeriveDataTypeable, TypeSynonymInstances,
-                    FlexibleInstances
+  default-language: Haskell2010
+  other-extensions: NoImplicitPrelude
   hs-source-dirs:  .
   main-is:         pandoc.hs
   buildable:       True
@@ -580,27 +571,38 @@ executable trypandoc
   main-is:         trypandoc.hs
   hs-source-dirs:  trypandoc
   default-language: Haskell2010
+  other-extensions: NoImplicitPrelude
   if flag(trypandoc)
     build-depends: base, aeson, pandoc,
                    text, wai-extra, wai >= 0.3, http-types
     buildable:     True
   else
     buildable:     False
+  if impl(ghc < 8.0)
+    build-depends: semigroups == 0.18.*
+  if impl(ghc < 8.4)
+     hs-source-dirs: prelude
+     other-modules:  Prelude
+     build-depends:  base-compat >= 0.9
 
-executable weigh-pandoc
+benchmark weigh-pandoc
+  type:            exitcode-stdio-1.0
   main-is:         weigh-pandoc.hs
   hs-source-dirs:  benchmark
-  if flag(weigh-pandoc)
-     build-depends:   pandoc,
-                      base >= 4.2 && < 5,
-                      text,
-                      weigh >= 0.0 && < 0.1,
-                      mtl >= 2.2 && < 2.3
-     buildable:       True
-  else
-    buildable:     False
-  ghc-options:   -rtsopts -Wall -fno-warn-unused-do-bind
-  default-language: Haskell98
+  build-depends:   pandoc,
+                   base >= 4.2 && < 5,
+                   text,
+                   weigh >= 0.0 && < 0.1,
+                   mtl >= 2.2 && < 2.3
+  if impl(ghc < 8.0)
+    build-depends: semigroups == 0.18.*
+  if impl(ghc < 8.4)
+     hs-source-dirs: prelude
+     other-modules:  Prelude
+     build-depends:  base-compat >= 0.9
+  ghc-options:   -rtsopts -Wall -fno-warn-unused-do-bind -threaded
+  default-language: Haskell2010
+  other-extensions: NoImplicitPrelude
 
 test-suite test-pandoc
   type:           exitcode-stdio-1.0
@@ -608,20 +610,20 @@ test-suite test-pandoc
   hs-source-dirs: test
   build-depends:  base >= 4.2 && < 5,
                   pandoc,
-                  pandoc-types >= 1.17.3 && < 1.18,
+                  pandoc-types >= 1.17.4.2 && < 1.18,
                   bytestring >= 0.9 && < 0.11,
                   base64-bytestring >= 0.1 && < 1.1,
                   text >= 0.11 && < 1.3,
-                  time >= 1.5 && < 1.9,
+                  time >= 1.5 && < 1.10,
                   directory >= 1 && < 1.4,
                   filepath >= 1.1 && < 1.5,
-                  hslua >= 0.9 && < 0.10,
+                  hslua >= 0.9.5 && < 0.9.6,
                   process >= 1.2.3 && < 1.7,
-                  temporary >= 1.1 && < 1.3,
+                  temporary >= 1.1 && < 1.4,
                   Diff >= 0.2 && < 0.4,
                   tasty >= 0.11 && < 1.1,
                   tasty-hunit >= 0.9 && < 0.11,
-                  tasty-quickcheck >= 0.8 && < 0.10,
+                  tasty-quickcheck >= 0.8 && < 0.11,
                   tasty-golden >= 2.3 && < 2.4,
                   QuickCheck >= 2.4 && < 2.12,
                   containers >= 0.4.2.1 && < 0.6,
@@ -629,11 +631,12 @@ test-suite test-pandoc
                   zip-archive >= 0.2.3.4 && < 0.4,
                   xml >= 1.3.12 && < 1.4,
                   Glob >= 0.7 && < 0.10
-  if flag(old-locale)
-     build-depends: old-locale >= 1 && < 1.1,
-                    time >= 1.2 && < 1.5
-  else
-     build-depends: time >= 1.5 && < 1.9
+  if impl(ghc < 8.0)
+    build-depends: semigroups == 0.18.*
+  if impl(ghc < 8.4)
+     hs-source-dirs: prelude
+     other-modules:  Prelude
+     build-depends:  base-compat >= 0.9
   other-modules:  Tests.Old
                   Tests.Command
                   Tests.Helpers
@@ -652,6 +655,7 @@ test-suite test-pandoc
                   Tests.Readers.Org.Block.Table
                   Tests.Readers.Org.Directive
                   Tests.Readers.Org.Inline
+                  Tests.Readers.Org.Inline.Citation
                   Tests.Readers.Org.Inline.Note
                   Tests.Readers.Org.Inline.Smart
                   Tests.Readers.Org.Meta
@@ -664,6 +668,7 @@ test-suite test-pandoc
                   Tests.Readers.Muse
                   Tests.Readers.Creole
                   Tests.Readers.Man
+                  Tests.Readers.FB2
                   Tests.Writers.Native
                   Tests.Writers.ConTeXt
                   Tests.Writers.Docbook
@@ -682,7 +687,8 @@ test-suite test-pandoc
                   Tests.Writers.Powerpoint
                   Tests.Writers.OOXML
   ghc-options:  -rtsopts -Wall -fno-warn-unused-do-bind -threaded
-  default-language: Haskell98
+  default-language: Haskell2010
+  other-extensions: NoImplicitPrelude
 
 benchmark benchmark-pandoc
   type:            exitcode-stdio-1.0
@@ -692,6 +698,13 @@ benchmark benchmark-pandoc
                    time, bytestring, containers,
                    base >= 4.2 && < 5,
                    text >= 0.11 && < 1.3,
-                   criterion >= 1.0 && < 1.4
-  ghc-options:   -rtsopts -Wall -fno-warn-unused-do-bind
-  default-language: Haskell98
+                   criterion >= 1.0 && < 1.5
+  if impl(ghc < 8.0)
+    build-depends: semigroups == 0.18.*
+  if impl(ghc < 8.4)
+     hs-source-dirs: prelude
+     other-modules:  Prelude
+     build-depends:  base-compat >= 0.9
+  ghc-options:   -rtsopts -Wall -fno-warn-unused-do-bind -threaded
+  default-language: Haskell2010
+  other-extensions: NoImplicitPrelude
diff --git a/pandoc.hs b/pandoc.hs
index 780e41ce1..7e7749aa5 100644
--- a/pandoc.hs
+++ b/pandoc.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2006-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -29,6 +30,7 @@ Parses command-line options and calls the appropriate readers and
 writers.
 -}
 module Main where
+import Prelude
 import qualified Control.Exception as E
 import Text.Pandoc.App (convertWithOpts, defaultOpts, options, parseOptions)
 import Text.Pandoc.Error (handleError)
diff --git a/prelude/Prelude.hs b/prelude/Prelude.hs
new file mode 100644
index 000000000..5ea523433
--- /dev/null
+++ b/prelude/Prelude.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE PackageImports #-}
+{-# LANGUAGE CPP #-}
+
+-- The intent is that this Prelude provide the API of
+-- the base 4.11 Prelude in a way that is portable for
+-- all base versions.
+
+module Prelude
+(
+  module Prelude.Compat
+, Semigroup(..)
+)
+where
+
+import Prelude.Compat
+import Data.Semigroup (Semigroup(..))  -- includes (<>)
diff --git a/src/Text/Pandoc/App.hs b/src/Text/Pandoc/App.hs
index 26c754cd6..920462d48 100644
--- a/src/Text/Pandoc/App.hs
+++ b/src/Text/Pandoc/App.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE CPP                 #-}
 {-# LANGUAGE DeriveGeneric       #-}
 {-# LANGUAGE ScopedTypeVariables #-}
@@ -42,6 +43,7 @@ module Text.Pandoc.App (
           , options
           , applyFilters
           ) where
+import Prelude
 import qualified Control.Exception as E
 import Control.Monad
 import Control.Monad.Except (catchError, throwError)
@@ -50,11 +52,10 @@ import Data.Aeson (defaultOptions)
 import Data.Aeson.TH (deriveJSON)
 import qualified Data.ByteString as BS
 import qualified Data.ByteString.Lazy as B
-import Data.Char (toLower, toUpper)
+import Data.Char (toLower, toUpper, isAscii, ord)
 import Data.List (find, intercalate, isPrefixOf, isSuffixOf, sort)
 import qualified Data.Map as M
 import Data.Maybe (fromMaybe, isJust, isNothing)
-import Data.Monoid
 import qualified Data.Set as Set
 import Data.Text (Text)
 import qualified Data.Text as T
@@ -65,7 +66,12 @@ import Data.Yaml (decode)
 import qualified Data.Yaml as Yaml
 import GHC.Generics
 import Network.URI (URI (..), parseURI)
+#ifdef EMBED_DATA_FILES
+import Text.Pandoc.Data (dataFiles)
+#else
+import System.Directory (getDirectoryContents)
 import Paths_pandoc (getDataDir)
+#endif
 import Data.Aeson.Encode.Pretty (encodePretty', Config(..), keyOrder,
          defConfig, Indent(..), NumberFormat(..))
 import Skylighting (Style, Syntax (..), defaultSyntaxMap, parseTheme,
@@ -87,7 +93,7 @@ import Text.Pandoc.Highlighting (highlightingStyles)
 import Text.Pandoc.PDF (makePDF)
 import Text.Pandoc.SelfContained (makeDataURI, makeSelfContained)
 import Text.Pandoc.Shared (eastAsianLineBreakFilter, stripEmptyParagraphs,
-         headerShift, isURI, ordNub, safeRead, tabFilter)
+         headerShift, isURI, ordNub, safeRead, tabFilter, uriPathToPath)
 import qualified Text.Pandoc.UTF8 as UTF8
 import Text.Pandoc.Writers.Math (defaultKaTeXURL, defaultMathJaxURL)
 import Text.Pandoc.XML (toEntities)
@@ -217,17 +223,16 @@ convertWithOpts opts = do
        then pdfWriterAndProg (optWriter opts) (optPdfEngine opts)
        else return (nonPdfWriterName $ optWriter opts, Nothing)
 
-  let format = baseWriterName
+  let format = map toLower $ baseWriterName
                  $ takeFileName writerName  -- in case path to lua script
 
   -- disabling the custom writer for now
   (writer, writerExts) <-
             if ".lua" `isSuffixOf` format
-               -- note:  use non-lowercased version writerName
                then return (TextWriter
                        (\o d -> writeCustom writerName o d)
                                :: Writer PandocIO, mempty)
-               else case getWriter writerName of
+               else case getWriter (map toLower writerName) of
                          Left e  -> E.throwIO $ PandocAppError $
                            if format == "pdf"
                               then e ++
@@ -351,12 +356,6 @@ convertWithOpts opts = do
         maybe return (addStringAsVariable "epub-cover-image")
                      (optEpubCoverImage opts)
         >>=
-        (\vars -> case optHTMLMathMethod opts of
-                       LaTeXMathML Nothing -> do
-                          s <- UTF8.toString <$> readDataFile "LaTeXMathML.js"
-                          return $ ("mathml-script", s) : vars
-                       _ -> return vars)
-        >>=
         (\vars ->  if format == "dzslides"
                       then do
                           dztempl <- UTF8.toString <$> readDataFile
@@ -513,16 +512,19 @@ convertWithOpts opts = do
                 let htmlFormat = format `elem`
                       ["html","html4","html5","s5","slidy",
                        "slideous","dzslides","revealjs"]
-                    handleEntities = if (htmlFormat ||
-                                         format == "docbook4" ||
-                                         format == "docbook5" ||
-                                         format == "docbook") && optAscii opts
-                                     then toEntities
-                                     else id
+                    escape
+                      | optAscii opts
+                      , htmlFormat || format == "docbook4" ||
+                        format == "docbook5" || format == "docbook" ||
+                        format == "jats" || format == "opml" ||
+                        format == "icml" = toEntities
+                      | optAscii opts
+                      , format == "ms" || format == "man" = groffEscape
+                      | otherwise = id
                     addNl = if standalone
                                then id
                                else (<> T.singleton '\n')
-                output <- (addNl . handleEntities) <$> f writerOptions doc
+                output <- (addNl . escape) <$> f writerOptions doc
                 writerFn eol outputFile =<<
                   if optSelfContained opts && htmlFormat
                      -- TODO not maximally efficient; change type
@@ -530,6 +532,12 @@ convertWithOpts opts = do
                      then T.pack <$> makeSelfContained (T.unpack output)
                      else return output
 
+groffEscape :: Text -> Text
+groffEscape = T.concatMap toUchar
+  where toUchar c
+         | isAscii c = T.singleton c
+         | otherwise = T.pack $ printf "\\[u%04X]" (ord c)
+
 type Transform = Pandoc -> Pandoc
 
 isTextFormat :: String -> Bool
@@ -729,6 +737,7 @@ defaultReaderName fallback (x:xs) =
     ".odt"      -> "odt"
     ".pdf"      -> "pdf"  -- so we get an "unknown reader" error
     ".doc"      -> "doc"  -- so we get an "unknown reader" error
+    ".fb2"      -> "fb2"
     _           -> defaultReaderName fallback xs
 
 -- Determine default writer based on output file extension
@@ -786,7 +795,7 @@ readSource src = case parseURI src of
                                  readURI src
                              | uriScheme u == "file:" ->
                                  liftIO $ UTF8.toText <$>
-                                    BS.readFile (uriPath u)
+                                    BS.readFile (uriPathToPath $ uriPath u)
                       _       -> liftIO $ UTF8.toText <$>
                                     BS.readFile src
 
@@ -834,8 +843,7 @@ options =
 
     , Option "tw" ["to","write"]
                  (ReqArg
-                  (\arg opt -> return opt { optWriter =
-                                              Just (map toLower arg) })
+                  (\arg opt -> return opt { optWriter = Just arg })
                   "FORMAT")
                  ""
 
@@ -967,6 +975,9 @@ options =
                                 setUserDataDir Nothing
                                 getDefaultTemplate arg
                      case templ of
+                          Right "" -> do -- e.g. for docx, odt, json:
+                            E.throwIO $ PandocCouldNotFindDataFileError
+                               ("templates/default." ++ arg)
                           Right t -> UTF8.hPutStr stdout t
                           Left e  -> E.throwIO e
                      exitSuccess)
@@ -1392,40 +1403,6 @@ options =
                   "URL")
                   "" -- Use KaTeX for HTML Math
 
-    , Option "m" ["latexmathml", "asciimathml"]
-                 (OptArg
-                  (\arg opt -> do
-                      deprecatedOption "--latexmathml, --asciimathml, -m" ""
-                      return opt { optHTMLMathMethod = LaTeXMathML arg })
-                  "URL")
-                 "" -- "Use LaTeXMathML script in html output"
-
-    , Option "" ["mimetex"]
-                 (OptArg
-                  (\arg opt -> do
-                      deprecatedOption "--mimetex" ""
-                      let url' = case arg of
-                                      Just u  -> u ++ "?"
-                                      Nothing -> "/cgi-bin/mimetex.cgi?"
-                      return opt { optHTMLMathMethod = WebTeX url' })
-                  "URL")
-                 "" -- "Use mimetex for HTML math"
-
-    , Option "" ["jsmath"]
-                 (OptArg
-                  (\arg opt -> do
-                      deprecatedOption "--jsmath" ""
-                      return opt { optHTMLMathMethod = JsMath arg})
-                  "URL")
-                 "" -- "Use jsMath for HTML math"
-
-    , Option "" ["gladtex"]
-                 (NoArg
-                  (\opt -> do
-                      deprecatedOption "--gladtex" ""
-                      return opt { optHTMLMathMethod = GladTeX }))
-                 "" -- "Use gladtex for HTML math"
-
     , Option "" ["abbreviations"]
                 (ReqArg
                  (\arg opt -> return opt { optAbbreviations = Just arg })
@@ -1471,7 +1448,7 @@ options =
     , Option "" ["bash-completion"]
                  (NoArg
                   (\_ -> do
-                     ddir <- getDataDir
+                     datafiles <- getDataFileNames
                      tpl <- runIOorExplode $
                               UTF8.toString <$>
                                 readDefaultDataFile "bash_completion.tpl"
@@ -1483,7 +1460,7 @@ options =
                          (unwords readersNames)
                          (unwords writersNames)
                          (unwords $ map fst highlightingStyles)
-                         ddir
+                         (unwords datafiles)
                      exitSuccess ))
                  "" -- "Print bash completion script"
 
@@ -1557,6 +1534,16 @@ options =
 
     ]
 
+getDataFileNames :: IO [FilePath]
+getDataFileNames = do
+#ifdef EMBED_DATA_FILES
+  let allDataFiles = map fst dataFiles
+#else
+  allDataFiles <- filter (\x -> x /= "." && x /= "..") <$>
+                      (getDataDir >>= getDirectoryContents)
+#endif
+  return $ "reference.docx" : "reference.odt" : "reference.pptx" : allDataFiles
+
 -- Returns usage message
 usageMessage :: String -> [OptDescr (Opt -> IO Opt)] -> String
 usageMessage programName = usageInfo (programName ++ " [OPTIONS] [FILES]")
diff --git a/src/Text/Pandoc/Asciify.hs b/src/Text/Pandoc/Asciify.hs
index 11d3eddac..2de670270 100644
--- a/src/Text/Pandoc/Asciify.hs
+++ b/src/Text/Pandoc/Asciify.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2013-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -30,6 +31,7 @@ ascii equivalents (used in constructing HTML identifiers).
 -}
 module Text.Pandoc.Asciify (toAsciiChar)
 where
+import Prelude
 import Data.Char (isAscii)
 import qualified Data.Map as M
 
diff --git a/src/Text/Pandoc/BCP47.hs b/src/Text/Pandoc/BCP47.hs
index 2dd825142..7aadea52a 100644
--- a/src/Text/Pandoc/BCP47.hs
+++ b/src/Text/Pandoc/BCP47.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2017–2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -34,6 +35,7 @@ module Text.Pandoc.BCP47 (
                      , renderLang
                      )
 where
+import Prelude
 import Control.Monad (guard)
 import Data.Char (isAlphaNum, isAscii, isLetter, isLower, isUpper, toLower,
                   toUpper)
diff --git a/src/Text/Pandoc/CSS.hs b/src/Text/Pandoc/CSS.hs
index d44b5e1e2..2141b8430 100644
--- a/src/Text/Pandoc/CSS.hs
+++ b/src/Text/Pandoc/CSS.hs
@@ -1,9 +1,11 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 module Text.Pandoc.CSS ( foldOrElse
                        , pickStyleAttrProps
                        , pickStylesToKVs
                        )
 where
 
+import Prelude
 import Text.Pandoc.Shared (trim)
 import Text.Parsec
 import Text.Parsec.String
diff --git a/src/Text/Pandoc/CSV.hs b/src/Text/Pandoc/CSV.hs
index 3415ae88f..96bfd6d89 100644
--- a/src/Text/Pandoc/CSV.hs
+++ b/src/Text/Pandoc/CSV.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2017–2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -34,6 +35,7 @@ module Text.Pandoc.CSV (
   ParseError
 ) where
 
+import Prelude
 import Control.Monad (void)
 import Data.Text (Text)
 import qualified Data.Text as T
diff --git a/src/Text/Pandoc/Class.hs b/src/Text/Pandoc/Class.hs
index aa0379942..4ade2dc6d 100644
--- a/src/Text/Pandoc/Class.hs
+++ b/src/Text/Pandoc/Class.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE PatternGuards #-}
 {-# LANGUAGE DeriveFunctor #-}
@@ -96,6 +97,7 @@ module Text.Pandoc.Class ( PandocMonad(..)
                          , Translations
                          ) where
 
+import Prelude
 import Prelude hiding (readFile)
 import System.Random (StdGen, next, mkStdGen)
 import qualified System.Random as IO (newStdGen)
@@ -106,10 +108,11 @@ import Data.List (stripPrefix)
 import qualified Data.Unique as IO (newUnique)
 import qualified Text.Pandoc.UTF8 as UTF8
 import qualified System.Directory as Directory
-import Text.Pandoc.Compat.Time (UTCTime)
+import Data.Time (UTCTime)
 import Text.Pandoc.Logging
+import Text.Pandoc.Shared (uriPathToPath)
 import Text.Parsec (ParsecT, getPosition, sourceLine, sourceName)
-import qualified Text.Pandoc.Compat.Time as IO (getCurrentTime)
+import qualified Data.Time as IO (getCurrentTime)
 import Text.Pandoc.MIME (MimeType, getMimeType, extensionFromMimeType)
 import Text.Pandoc.Definition
 import Data.Digest.Pure.SHA (sha1, showDigest)
@@ -475,6 +478,14 @@ liftIOError f u = do
          Left e  -> throwError $ PandocIOError u e
          Right r -> return r
 
+-- | Show potential IO errors to the user continuing execution anyway
+logIOError :: IO () -> PandocIO ()
+logIOError f = do
+  res <- liftIO $ tryIOError f
+  case res of
+    Left e -> report $ IgnoredIOError (E.displayException e)
+    Right _ -> pure ()
+
 instance PandocMonad PandocIO where
   lookupEnv = liftIO . IO.lookupEnv
   getCurrentTime = liftIO IO.getCurrentTime
@@ -588,7 +599,7 @@ downloadOrRead s = do
             -- We don't want to treat C:/ as a scheme:
             Just u' | length (uriScheme u') > 2 -> openURL (show u')
             Just u' | uriScheme u' == "file:" ->
-                 readLocalFile $ dropWhile (=='/') (uriPath u')
+                 readLocalFile $ uriPathToPath (uriPath u')
             _ -> readLocalFile fp -- get from local file system
    where readLocalFile f = do
              resourcePath <- getResourcePath
@@ -853,14 +864,14 @@ writeMedia :: FilePath -> MediaBag -> FilePath -> PandocIO ()
 writeMedia dir mediabag subpath = do
   -- we join and split to convert a/b/c to a\b\c on Windows;
   -- in zip containers all paths use /
-  let fullpath = dir </> normalise subpath
+  let fullpath = dir </> unEscapeString (normalise subpath)
   let mbcontents = lookupMedia subpath mediabag
   case mbcontents of
        Nothing -> throwError $ PandocResourceNotFound subpath
        Just (_, bs) -> do
          report $ Extracting fullpath
          liftIOError (createDirectoryIfMissing True) (takeDirectory fullpath)
-         liftIOError (\p -> BL.writeFile p bs) fullpath
+         logIOError $ BL.writeFile fullpath bs
 
 adjustImagePath :: FilePath -> [FilePath] -> Inline -> Inline
 adjustImagePath dir paths (Image attr lab (src, tit))
@@ -923,7 +934,7 @@ data FileInfo = FileInfo { infoFileMTime :: UTCTime
                          }
 
 newtype FileTree = FileTree {unFileTree :: M.Map FilePath FileInfo}
-  deriving (Monoid)
+  deriving (Semigroup, Monoid)
 
 getFileInfo :: FilePath -> FileTree -> Maybe FileInfo
 getFileInfo fp tree =
diff --git a/src/Text/Pandoc/Compat/Time.hs b/src/Text/Pandoc/Compat/Time.hs
deleted file mode 100644
index b1cde82a4..000000000
--- a/src/Text/Pandoc/Compat/Time.hs
+++ /dev/null
@@ -1,30 +0,0 @@
-{-# LANGUAGE CPP #-}
-
-{-
-This compatibility module is needed because, in time 1.5, the
-`defaultTimeLocale` function was moved from System.Locale (in the
-old-locale library) into Data.Time.
-
-We support both behaviors because time 1.4 is a boot library for GHC
-7.8. time 1.5 is a boot library for GHC 7.10.
-
-When support is dropped for GHC 7.8, this module may be obsoleted.
--}
-
-#if MIN_VERSION_time(1,5,0)
-module Text.Pandoc.Compat.Time (
-  module Data.Time
-)
-where
-import Data.Time
-
-#else
-module Text.Pandoc.Compat.Time (
-  module Data.Time,
-  defaultTimeLocale
-)
-where
-import Data.Time
-import System.Locale ( defaultTimeLocale )
-
-#endif
diff --git a/src/Text/Pandoc/Data.hs b/src/Text/Pandoc/Data.hs
index af0e4504f..2cf0d3f81 100644
--- a/src/Text/Pandoc/Data.hs
+++ b/src/Text/Pandoc/Data.hs
@@ -1,7 +1,9 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE TemplateHaskell #-}
 
 module Text.Pandoc.Data (dataFiles) where
 
+import Prelude
 import qualified Data.ByteString as B
 import Data.FileEmbed
 import System.FilePath (splitDirectories)
diff --git a/src/Text/Pandoc/Emoji.hs b/src/Text/Pandoc/Emoji.hs
index 3766960ea..5cc965153 100644
--- a/src/Text/Pandoc/Emoji.hs
+++ b/src/Text/Pandoc/Emoji.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2015 John MacFarlane <jgm@berkeley.edu>
 
@@ -28,6 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Emoji symbol lookup from canonical string identifier.
 -}
 module Text.Pandoc.Emoji ( emojis ) where
+import Prelude
 import qualified Data.Map as M
 
 emojis :: M.Map String String
diff --git a/src/Text/Pandoc/Error.hs b/src/Text/Pandoc/Error.hs
index f78a31481..feb047f68 100644
--- a/src/Text/Pandoc/Error.hs
+++ b/src/Text/Pandoc/Error.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE DeriveGeneric      #-}
 {-
@@ -34,6 +35,7 @@ module Text.Pandoc.Error (
   PandocError(..),
   handleError) where
 
+import Prelude
 import Control.Exception (Exception)
 import Data.Typeable (Typeable)
 import GHC.Generics (Generic)
diff --git a/src/Text/Pandoc/Extensions.hs b/src/Text/Pandoc/Extensions.hs
index fe690713c..5ccb7dffb 100644
--- a/src/Text/Pandoc/Extensions.hs
+++ b/src/Text/Pandoc/Extensions.hs
@@ -1,3 +1,9 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE CPP                        #-}
+{-# LANGUAGE DeriveDataTypeable         #-}
+{-# LANGUAGE DeriveGeneric              #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE TemplateHaskell            #-}
 {-
 Copyright (C) 2012-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -15,10 +21,6 @@ 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 DeriveDataTypeable         #-}
-{-# LANGUAGE DeriveGeneric              #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE TemplateHaskell            #-}
 
 {- |
    Module      : Text.Pandoc.Extensions
@@ -47,6 +49,7 @@ module Text.Pandoc.Extensions ( Extension(..)
                               , githubMarkdownExtensions
                               , multimarkdownExtensions )
 where
+import Prelude
 import Data.Aeson (FromJSON (..), ToJSON (..), defaultOptions)
 import Data.Aeson.TH (deriveJSON)
 import Data.Bits (clearBit, setBit, testBit, (.|.))
@@ -59,9 +62,11 @@ import Text.Parsec
 newtype Extensions = Extensions Integer
   deriving (Show, Read, Eq, Ord, Data, Typeable, Generic, ToJSON, FromJSON)
 
+instance Semigroup Extensions where
+  (Extensions a) <> (Extensions b) = Extensions (a .|. b)
 instance Monoid Extensions where
   mempty = Extensions 0
-  mappend (Extensions a) (Extensions b) = Extensions (a .|. b)
+  mappend = (<>)
 
 extensionsFromList :: [Extension] -> Extensions
 extensionsFromList = foldr enableExtension emptyExtensions
@@ -317,6 +322,8 @@ getDefaultExtensions "muse"            = extensionsFromList
                                             Ext_auto_identifiers]
 getDefaultExtensions "plain"           = plainExtensions
 getDefaultExtensions "gfm"             = githubMarkdownExtensions
+getDefaultExtensions "commonmark"      = extensionsFromList
+                                          [Ext_raw_html]
 getDefaultExtensions "org"             = extensionsFromList
                                           [Ext_citations,
                                            Ext_auto_identifiers]
@@ -338,6 +345,10 @@ getDefaultExtensions "latex"           = extensionsFromList
                                           [Ext_smart,
                                            Ext_latex_macros,
                                            Ext_auto_identifiers]
+getDefaultExtensions "beamer"          = extensionsFromList
+                                          [Ext_smart,
+                                           Ext_latex_macros,
+                                           Ext_auto_identifiers]
 getDefaultExtensions "context"         = extensionsFromList
                                           [Ext_smart,
                                            Ext_auto_identifiers]
diff --git a/src/Text/Pandoc/Filter.hs b/src/Text/Pandoc/Filter.hs
index e2a3c3e16..5461648e1 100644
--- a/src/Text/Pandoc/Filter.hs
+++ b/src/Text/Pandoc/Filter.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>
 
@@ -33,6 +34,7 @@ module Text.Pandoc.Filter
   , applyFilters
   ) where
 
+import Prelude
 import Data.Aeson (defaultOptions)
 import Data.Aeson.TH (deriveJSON)
 import Data.Foldable (foldrM)
diff --git a/src/Text/Pandoc/Filter/JSON.hs b/src/Text/Pandoc/Filter/JSON.hs
index 5772c2c41..97b291603 100644
--- a/src/Text/Pandoc/Filter/JSON.hs
+++ b/src/Text/Pandoc/Filter/JSON.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2006-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -29,6 +30,7 @@ Programmatically modifications of pandoc documents via JSON filters.
 -}
 module Text.Pandoc.Filter.JSON (apply) where
 
+import Prelude
 import Control.Monad (unless, when)
 import Control.Monad.Trans (MonadIO (liftIO))
 import Data.Aeson (eitherDecode', encode)
diff --git a/src/Text/Pandoc/Filter/Lua.hs b/src/Text/Pandoc/Filter/Lua.hs
index 597a31cbc..d559fb912 100644
--- a/src/Text/Pandoc/Filter/Lua.hs
+++ b/src/Text/Pandoc/Filter/Lua.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2006-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -29,6 +30,7 @@ Apply Lua filters to modify a pandoc documents programmatically.
 -}
 module Text.Pandoc.Filter.Lua (apply) where
 
+import Prelude
 import Control.Exception (throw)
 import Text.Pandoc.Class (PandocIO)
 import Text.Pandoc.Definition (Pandoc)
diff --git a/src/Text/Pandoc/Filter/Path.hs b/src/Text/Pandoc/Filter/Path.hs
index 8074bcbb7..f244597aa 100644
--- a/src/Text/Pandoc/Filter/Path.hs
+++ b/src/Text/Pandoc/Filter/Path.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2006-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -31,6 +32,7 @@ module Text.Pandoc.Filter.Path
   ( expandFilterPath
   ) where
 
+import Prelude
 import Text.Pandoc.Class (PandocMonad, fileExists, getUserDataDir)
 import System.FilePath ((</>), isRelative)
 
diff --git a/src/Text/Pandoc/Highlighting.hs b/src/Text/Pandoc/Highlighting.hs
index 113727750..70bb70302 100644
--- a/src/Text/Pandoc/Highlighting.hs
+++ b/src/Text/Pandoc/Highlighting.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2008-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -49,6 +50,7 @@ module Text.Pandoc.Highlighting ( highlightingStyles
                                 , fromListingsLanguage
                                 , toListingsLanguage
                                 ) where
+import Prelude
 import Control.Monad
 import Data.Char (toLower)
 import qualified Data.Map as M
diff --git a/src/Text/Pandoc/ImageSize.hs b/src/Text/Pandoc/ImageSize.hs
index 4c76aac13..c5fe98a66 100644
--- a/src/Text/Pandoc/ImageSize.hs
+++ b/src/Text/Pandoc/ImageSize.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings, ScopedTypeVariables, CPP #-}
 {-# OPTIONS_GHC -fno-warn-type-defaults #-}
 {-
@@ -49,6 +50,7 @@ module Text.Pandoc.ImageSize ( ImageType(..)
                              , showInPixel
                              , showFl
                              ) where
+import Prelude
 import Data.ByteString (ByteString, unpack)
 import qualified Data.ByteString.Char8 as B
 import qualified Data.ByteString.Lazy as BL
@@ -126,7 +128,7 @@ imageType img = case B.take 4 img of
                        |  B.take 4 (B.drop 1 $ B.dropWhile (/=' ') img) == "EPSF"
                                         -> return Eps
                      "\x01\x00\x00\x00"
-                       | B.take 4 (B.drop 40 img) == " EMF" 
+                       | B.take 4 (B.drop 40 img) == " EMF"
                                         -> return Emf
                      _                  -> mzero
 
@@ -361,9 +363,9 @@ svgSize opts img = do
   , dpiX = dpi
   , dpiY = dpi
   }
-  
+
 emfSize :: ByteString -> Maybe ImageSize
-emfSize img = 
+emfSize img =
   let
     parseheader = runGetOrFail $ do
       skip 0x18             -- 0x00
@@ -388,11 +390,11 @@ emfSize img =
         , dpiX = fromIntegral dpiW
         , dpiY = fromIntegral dpiH
         }
-  in 
+  in
     case parseheader . BL.fromStrict $ img of
       Left _ -> Nothing
       Right (_, _, size) -> Just size
-  
+
 
 jpegSize :: ByteString -> Either String ImageSize
 jpegSize img =
diff --git a/src/Text/Pandoc/Logging.hs b/src/Text/Pandoc/Logging.hs
index b22c08467..4b025821c 100644
--- a/src/Text/Pandoc/Logging.hs
+++ b/src/Text/Pandoc/Logging.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE DeriveGeneric      #-}
 {-# LANGUAGE OverloadedStrings  #-}
@@ -39,6 +40,7 @@ module Text.Pandoc.Logging (
   , messageVerbosity
   ) where
 
+import Prelude
 import Control.Monad (mzero)
 import Data.Aeson
 import Data.Aeson.Encode.Pretty (Config (..), defConfig, encodePretty',
@@ -83,6 +85,7 @@ data LogMessage =
   | InlineNotRendered Inline
   | BlockNotRendered Block
   | DocxParserWarning String
+  | IgnoredIOError String
   | CouldNotFetchResource String String
   | CouldNotDetermineImageSize String String
   | CouldNotConvertImage String String
@@ -99,6 +102,7 @@ data LogMessage =
   | Deprecated String String
   | NoTranslation String
   | CouldNotLoadTranslations String String
+  | UnexpectedXmlElement String String
   deriving (Show, Eq, Data, Ord, Typeable, Generic)
 
 instance ToJSON LogMessage where
@@ -172,6 +176,8 @@ instance ToJSON LogMessage where
            ["contents" .= toJSON bl]
       DocxParserWarning s ->
            ["contents" .= Text.pack s]
+      IgnoredIOError s ->
+           ["contents" .= Text.pack s]
       CouldNotFetchResource fp s ->
            ["path" .= Text.pack fp,
             "message" .= Text.pack s]
@@ -209,6 +215,9 @@ instance ToJSON LogMessage where
       CouldNotLoadTranslations lang msg ->
            ["lang" .= Text.pack lang,
             "message" .= Text.pack msg]
+      UnexpectedXmlElement element parent ->
+           ["element" .= Text.pack element,
+            "parent" .= Text.pack parent]
 
 
 showPos :: SourcePos -> String
@@ -259,6 +268,8 @@ showLogMessage msg =
          "Not rendering " ++ show bl
        DocxParserWarning s ->
          "Docx parser warning: " ++ s
+       IgnoredIOError s ->
+         "IO Error (ignored): " ++ s
        CouldNotFetchResource fp s ->
          "Could not fetch resource '" ++ fp ++ "'" ++
            if null s then "" else ": " ++ s
@@ -303,6 +314,8 @@ showLogMessage msg =
        CouldNotLoadTranslations lang m ->
          "Could not load translations for " ++ lang ++
            if null m then "" else '\n' : m
+       UnexpectedXmlElement element parent ->
+         "Unexpected XML element " ++ element ++ " in " ++ parent
 
 messageVerbosity:: LogMessage -> Verbosity
 messageVerbosity msg =
@@ -324,6 +337,7 @@ messageVerbosity msg =
        InlineNotRendered{}          -> INFO
        BlockNotRendered{}           -> INFO
        DocxParserWarning{}          -> INFO
+       IgnoredIOError{}             -> WARNING
        CouldNotFetchResource{}      -> WARNING
        CouldNotDetermineImageSize{} -> WARNING
        CouldNotConvertImage{}       -> WARNING
@@ -340,3 +354,4 @@ messageVerbosity msg =
        Deprecated{}                 -> WARNING
        NoTranslation{}              -> WARNING
        CouldNotLoadTranslations{}   -> WARNING
+       UnexpectedXmlElement {}      -> WARNING
diff --git a/src/Text/Pandoc/Lua.hs b/src/Text/Pandoc/Lua.hs
index 790be47d5..cd7117074 100644
--- a/src/Text/Pandoc/Lua.hs
+++ b/src/Text/Pandoc/Lua.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright © 2017–2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
 
@@ -31,13 +32,14 @@ module Text.Pandoc.Lua
   , runPandocLua
   ) where
 
+import Prelude
 import Control.Monad ((>=>))
 import Foreign.Lua (FromLuaStack (peek), Lua, LuaException (..),
                     Status (OK), ToLuaStack (push))
 import Text.Pandoc.Class (PandocIO)
 import Text.Pandoc.Definition (Pandoc)
 import Text.Pandoc.Lua.Filter (LuaFilter, walkMWithLuaFilter)
-import Text.Pandoc.Lua.Init (runPandocLua)
+import Text.Pandoc.Lua.Init (runPandocLua, registerScriptPath)
 import Text.Pandoc.Lua.Util (popValue)
 import Text.Pandoc.Options (ReaderOptions)
 import qualified Foreign.Lua as Lua
@@ -55,11 +57,12 @@ runLuaFilter' :: ReaderOptions -> FilePath -> String
 runLuaFilter' ropts filterPath format pd = do
   registerFormat
   registerReaderOptions
+  registerScriptPath filterPath
   top <- Lua.gettop
   stat <- Lua.dofile filterPath
   if stat /= OK
     then do
-      luaErrMsg <- peek (-1) <* Lua.pop 1
+      luaErrMsg <- popValue
       Lua.throwLuaError luaErrMsg
     else do
       newtop <- Lua.gettop
diff --git a/src/Text/Pandoc/Lua/Filter.hs b/src/Text/Pandoc/Lua/Filter.hs
index cc2b9d47e..264066305 100644
--- a/src/Text/Pandoc/Lua/Filter.hs
+++ b/src/Text/Pandoc/Lua/Filter.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE FlexibleContexts #-}
 
 module Text.Pandoc.Lua.Filter ( LuaFilterFunction
@@ -10,6 +11,7 @@ module Text.Pandoc.Lua.Filter ( LuaFilterFunction
                               , blockElementNames
                               , inlineElementNames
                               ) where
+import Prelude
 import Control.Monad (mplus, unless, when, (>=>))
 import Control.Monad.Catch (finally)
 import Text.Pandoc.Definition
diff --git a/src/Text/Pandoc/Lua/Init.hs b/src/Text/Pandoc/Lua/Init.hs
index d1a26ebad..c8c7fdfbd 100644
--- a/src/Text/Pandoc/Lua/Init.hs
+++ b/src/Text/Pandoc/Lua/Init.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright © 2017-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
 
@@ -31,8 +32,10 @@ module Text.Pandoc.Lua.Init
   , runPandocLua
   , initLuaState
   , luaPackageParams
+  , registerScriptPath
   ) where
 
+import Prelude
 import Control.Monad.Trans (MonadIO (..))
 import Data.Data (Data, dataTypeConstrs, dataTypeOf, showConstr)
 import Data.IORef (newIORef, readIORef)
@@ -88,6 +91,11 @@ initLuaState luaPkgParams = do
   loadScriptFromDataDir (luaPkgDataDir luaPkgParams) "init.lua"
   putConstructorsInRegistry
 
+registerScriptPath :: FilePath -> Lua ()
+registerScriptPath fp = do
+  Lua.push fp
+  Lua.setglobal "PANDOC_SCRIPT_FILE"
+
 putConstructorsInRegistry :: Lua ()
 putConstructorsInRegistry = do
   Lua.getglobal "pandoc"
@@ -101,7 +109,7 @@ putConstructorsInRegistry = do
   Lua.pop 1
  where
   constrsToReg :: Data a => a -> Lua ()
-  constrsToReg = mapM_ putInReg . map showConstr . dataTypeConstrs . dataTypeOf
+  constrsToReg = mapM_ (putInReg . showConstr) . dataTypeConstrs . dataTypeOf
 
   putInReg :: String -> Lua ()
   putInReg name = do
diff --git a/src/Text/Pandoc/Lua/Module/MediaBag.hs b/src/Text/Pandoc/Lua/Module/MediaBag.hs
index 7d942a452..f48fe56c5 100644
--- a/src/Text/Pandoc/Lua/Module/MediaBag.hs
+++ b/src/Text/Pandoc/Lua/Module/MediaBag.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright © 2017-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
 
@@ -29,6 +30,7 @@ module Text.Pandoc.Lua.Module.MediaBag
   ( pushModule
   ) where
 
+import Prelude
 import Control.Monad (zipWithM_)
 import Data.IORef (IORef, modifyIORef', readIORef)
 import Data.Maybe (fromMaybe)
diff --git a/src/Text/Pandoc/Lua/Module/Pandoc.hs b/src/Text/Pandoc/Lua/Module/Pandoc.hs
index b9410a353..8cb630d7b 100644
--- a/src/Text/Pandoc/Lua/Module/Pandoc.hs
+++ b/src/Text/Pandoc/Lua/Module/Pandoc.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright © 2017-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
 
@@ -30,6 +31,7 @@ module Text.Pandoc.Lua.Module.Pandoc
   ( pushModule
   ) where
 
+import Prelude
 import Control.Monad (when)
 import Data.Default (Default (..))
 import Data.Maybe (fromMaybe)
diff --git a/src/Text/Pandoc/Lua/Module/Utils.hs b/src/Text/Pandoc/Lua/Module/Utils.hs
index f8eb96dc7..7fa4616be 100644
--- a/src/Text/Pandoc/Lua/Module/Utils.hs
+++ b/src/Text/Pandoc/Lua/Module/Utils.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright © 2017-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
 
@@ -29,6 +30,7 @@ module Text.Pandoc.Lua.Module.Utils
   ( pushModule
   ) where
 
+import Prelude
 import Control.Applicative ((<|>))
 import Data.Default (def)
 import Foreign.Lua (FromLuaStack, Lua, LuaInteger, NumResults)
diff --git a/src/Text/Pandoc/Lua/Packages.hs b/src/Text/Pandoc/Lua/Packages.hs
index 1e6ff22fe..59637826e 100644
--- a/src/Text/Pandoc/Lua/Packages.hs
+++ b/src/Text/Pandoc/Lua/Packages.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright © 2017-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
 
@@ -32,6 +33,7 @@ module Text.Pandoc.Lua.Packages
   , installPandocPackageSearcher
   ) where
 
+import Prelude
 import Control.Monad (forM_)
 import Data.ByteString.Char8 (unpack)
 import Data.IORef (IORef)
diff --git a/src/Text/Pandoc/Lua/StackInstances.hs b/src/Text/Pandoc/Lua/StackInstances.hs
index 7e0dc20c4..3298079c5 100644
--- a/src/Text/Pandoc/Lua/StackInstances.hs
+++ b/src/Text/Pandoc/Lua/StackInstances.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright © 2012-2018 John MacFarlane <jgm@berkeley.edu>
             2017-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
@@ -33,6 +34,7 @@ StackValue instances for pandoc types.
 -}
 module Text.Pandoc.Lua.StackInstances () where
 
+import Prelude
 import Control.Applicative ((<|>))
 import Control.Monad (when)
 import Control.Monad.Catch (finally)
diff --git a/src/Text/Pandoc/Lua/Util.hs b/src/Text/Pandoc/Lua/Util.hs
index b7149af39..ea9ec2554 100644
--- a/src/Text/Pandoc/Lua/Util.hs
+++ b/src/Text/Pandoc/Lua/Util.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright © 2012-2018 John MacFarlane <jgm@berkeley.edu>
             2017-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
@@ -46,6 +47,7 @@ module Text.Pandoc.Lua.Util
   , dostring'
   ) where
 
+import Prelude
 import Control.Monad (when)
 import Control.Monad.Catch (finally)
 import Data.ByteString.Char8 (unpack)
@@ -132,7 +134,7 @@ class PushViaCall a where
 instance PushViaCall (Lua ()) where
   pushViaCall' fn pushArgs num = do
     Lua.push fn
-    Lua.rawget (Lua.registryindex)
+    Lua.rawget Lua.registryindex
     pushArgs
     call num 1
 
diff --git a/src/Text/Pandoc/MIME.hs b/src/Text/Pandoc/MIME.hs
index 43abe9b2f..cb7debb2e 100644
--- a/src/Text/Pandoc/MIME.hs
+++ b/src/Text/Pandoc/MIME.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2011-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -29,6 +30,7 @@ Mime type lookup for ODT writer.
 -}
 module Text.Pandoc.MIME ( MimeType, getMimeType, getMimeTypeDef,
                           extensionFromMimeType )where
+import Prelude
 import Data.Char (toLower)
 import Data.List (isPrefixOf, isSuffixOf)
 import qualified Data.Map as M
@@ -172,7 +174,7 @@ mimeTypesList = -- List borrowed from happstack-server.
            ,("eml","message/rfc822")
            ,("ent","chemical/x-ncbi-asn1-ascii")
            ,("eot","application/vnd.ms-fontobject")
-           ,("eps","application/postscript")
+           ,("eps","application/eps")
            ,("etx","text/x-setext")
            ,("exe","application/x-msdos-program")
            ,("ez","application/andrew-inset")
diff --git a/src/Text/Pandoc/MediaBag.hs b/src/Text/Pandoc/MediaBag.hs
index 0d060fe1a..bb0d60aff 100644
--- a/src/Text/Pandoc/MediaBag.hs
+++ b/src/Text/Pandoc/MediaBag.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE CPP                        #-}
 {-# LANGUAGE DeriveDataTypeable         #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-
@@ -36,6 +38,7 @@ module Text.Pandoc.MediaBag (
                      insertMedia,
                      mediaDirectory,
                      ) where
+import Prelude
 import qualified Data.ByteString.Lazy as BL
 import Data.Data (Data)
 import qualified Data.Map as M
@@ -50,7 +53,7 @@ import Text.Pandoc.MIME (MimeType, getMimeTypeDef)
 -- can be used for an empty 'MediaBag', and '<>' can be used to append
 -- two 'MediaBag's.
 newtype MediaBag = MediaBag (M.Map [String] (MimeType, BL.ByteString))
-        deriving (Monoid, Data, Typeable)
+        deriving (Semigroup, Monoid, Data, Typeable)
 
 instance Show MediaBag where
   show bag = "MediaBag " ++ show (mediaDirectory bag)
diff --git a/src/Text/Pandoc/Options.hs b/src/Text/Pandoc/Options.hs
index bd4ab252b..4797a3094 100644
--- a/src/Text/Pandoc/Options.hs
+++ b/src/Text/Pandoc/Options.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE DeriveGeneric      #-}
 {-# LANGUAGE TemplateHaskell    #-}
@@ -46,6 +47,7 @@ module Text.Pandoc.Options ( module Text.Pandoc.Extensions
                            , def
                            , isEnabled
                            ) where
+import Prelude
 import Data.Aeson (defaultOptions)
 import Data.Aeson.TH (deriveJSON)
 import Data.Data (Data)
@@ -104,9 +106,6 @@ defaultAbbrevs = Set.fromList
 data EPUBVersion = EPUB2 | EPUB3 deriving (Eq, Show, Read, Data, Typeable, Generic)
 
 data HTMLMathMethod = PlainMath
-                    | LaTeXMathML (Maybe String)  -- url of LaTeXMathML.js
-                    | JsMath (Maybe String)       -- url of jsMath load script
-                    | GladTeX
                     | WebTeX String               -- url of TeX->image script.
                     | MathML
                     | MathJax String              -- url of MathJax.js
diff --git a/src/Text/Pandoc/PDF.hs b/src/Text/Pandoc/PDF.hs
index 5f41d6c55..b171d65b0 100644
--- a/src/Text/Pandoc/PDF.hs
+++ b/src/Text/Pandoc/PDF.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE CPP                 #-}
 {-# LANGUAGE OverloadedStrings   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
@@ -32,6 +33,7 @@ Conversion of LaTeX documents to PDF.
 -}
 module Text.Pandoc.PDF ( makePDF ) where
 
+import Prelude
 import qualified Codec.Picture as JP
 import qualified Control.Exception as E
 import Control.Monad (unless, when)
@@ -41,10 +43,8 @@ import Data.ByteString.Lazy (ByteString)
 import qualified Data.ByteString.Lazy as BL
 import qualified Data.ByteString.Lazy.Char8 as BC
 import Data.Maybe (fromMaybe)
-import Data.Monoid ((<>))
 import Data.Text (Text)
 import qualified Data.Text as T
-import qualified Data.Text.IO as TextIO
 import System.Directory
 import System.Environment
 import System.Exit (ExitCode (..))
@@ -61,7 +61,7 @@ import Text.Pandoc.Error (PandocError (PandocPDFProgramNotFoundError))
 import Text.Pandoc.MIME (getMimeType)
 import Text.Pandoc.Options (HTMLMathMethod (..), WriterOptions (..))
 import Text.Pandoc.Process (pipeProcess)
-import Text.Pandoc.Shared (inDirectory, stringify, withTempDir)
+import Text.Pandoc.Shared (inDirectory, stringify)
 import qualified Text.Pandoc.UTF8 as UTF8
 import Text.Pandoc.Walk (walkM)
 import Text.Pandoc.Writers.Shared (getField, metaToJSON)
@@ -127,9 +127,11 @@ makePDF "pdfroff" pdfargs writer opts doc = do
   verbosity <- getVerbosity
   liftIO $ ms2pdf verbosity args source
 makePDF program pdfargs writer opts doc = do
-  let withTemp = if takeBaseName program == "context"
-                    then withTempDirectory "."
-                    else withTempDir
+  -- With context and latex, we create a temp directory within
+  -- the working directory, since pdflatex sometimes tries to
+  -- use tools like epstopdf.pl, which are restricted if run
+  -- on files outside the working directory.
+  let withTemp = withTempDirectory "."
   commonState <- getCommonState
   verbosity <- getVerbosity
   liftIO $ withTemp "tex2pdf." $ \tmpdir -> do
@@ -170,6 +172,8 @@ convertImage tmpdir fname =
     Just "image/png" -> doNothing
     Just "image/jpeg" -> doNothing
     Just "application/pdf" -> doNothing
+    -- Note: eps is converted by pdflatex using epstopdf.pl
+    Just "application/eps" -> doNothing
     Just "image/svg+xml" -> E.catch (do
       (exit, _) <- pipeProcess Nothing "rsvg-convert"
                      ["-f","pdf","-a","-o",pdfOut,fname] BL.empty
@@ -274,7 +278,12 @@ runTeXProgram verbosity program args runNumber numRuns tmpDir source = do
     let file' = file
 #endif
     let programArgs = ["-halt-on-error", "-interaction", "nonstopmode",
-         "-output-directory", tmpDir'] ++ args ++ [file']
+         "-output-directory", tmpDir'] ++
+         -- see #4484, only compress images on last run:
+         if program == "xelatex" && runNumber < numRuns
+            then ["-output-driver", "xdvipdfmx -z0"]
+            else []
+         ++ args ++ [file']
     env' <- getEnvironment
     let sep = [searchPathSeparator]
     let texinputs = maybe (tmpDir' ++ sep) ((tmpDir' ++ sep) ++)
@@ -354,9 +363,14 @@ html2pdf  :: Verbosity    -- ^ Verbosity level
           -> Text         -- ^ HTML5 source
           -> IO (Either ByteString ByteString)
 html2pdf verbosity program args source = do
+  -- write HTML to temp file so we don't have to rewrite
+  -- all links in `a`, `img`, `style`, `script`, etc. tags,
+  -- and piping to weasyprint didn't work on Windows either.
+  file    <- withTempFile "." "html2pdf.html" $ \fp _ -> return fp
   pdfFile <- withTempFile "." "html2pdf.pdf" $ \fp _ -> return fp
+  BS.writeFile file $ UTF8.fromText source
   let pdfFileArgName = ["-o" | program == "prince"]
-  let programArgs = args ++ ["-"] ++ pdfFileArgName ++ [pdfFile]
+  let programArgs = args ++ [file] ++ pdfFileArgName ++ [pdfFile]
   env' <- getEnvironment
   when (verbosity >= INFO) $ do
     putStrLn "[makePDF] Command line:"
@@ -365,15 +379,16 @@ html2pdf verbosity program args source = do
     putStrLn "[makePDF] Environment:"
     mapM_ print env'
     putStr "\n"
-    putStrLn "[makePDF] Contents of intermediate HTML:"
-    TextIO.putStr source
+    putStrLn $ "[makePDF] Contents of " ++ file ++ ":"
+    BL.readFile file >>= BL.putStr
     putStr "\n"
   (exit, out) <- E.catch
-    (pipeProcess (Just env') program programArgs $ BL.fromStrict $ UTF8.fromText source)
+    (pipeProcess (Just env') program programArgs BL.empty)
     (\(e :: IOError) -> if isDoesNotExistError e
                            then E.throwIO $
                                   PandocPDFProgramNotFoundError program
                            else E.throwIO e)
+  removeFile file
   when (verbosity >= INFO) $ do
     BL.hPutStr stdout out
     putStr "\n"
diff --git a/src/Text/Pandoc/Parsing.hs b/src/Text/Pandoc/Parsing.hs
index 82abcb440..fa6baf1c7 100644
--- a/src/Text/Pandoc/Parsing.hs
+++ b/src/Text/Pandoc/Parsing.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE CPP                        #-}
 {-# LANGUAGE ExplicitForAll             #-}
 {-# LANGUAGE FlexibleContexts           #-}
 {-# LANGUAGE FlexibleInstances          #-}
@@ -133,7 +135,7 @@ module Text.Pandoc.Parsing ( takeWhileP,
                              extractIdClass,
                              insertIncludedFile,
                              insertIncludedFileF,
-                             -- * Re-exports from Text.Pandoc.Parsec
+                             -- * Re-exports from Text.Parsec
                              Stream,
                              runParser,
                              runParserT,
@@ -194,6 +196,7 @@ module Text.Pandoc.Parsing ( takeWhileP,
                              )
 where
 
+import Prelude
 import Control.Monad.Identity
 import Control.Monad.Reader
 import Data.Char (chr, isAlphaNum, isAscii, isAsciiUpper, isHexDigit,
@@ -202,7 +205,6 @@ import Data.Default
 import Data.List (intercalate, isSuffixOf, transpose)
 import qualified Data.Map as M
 import Data.Maybe (mapMaybe, fromMaybe)
-import Data.Monoid ((<>))
 import qualified Data.Set as Set
 import Data.Text (Text)
 import Text.HTML.TagSoup.Entity (lookupEntity)
@@ -250,10 +252,11 @@ returnF = return . return
 trimInlinesF :: Future s Inlines -> Future s Inlines
 trimInlinesF = liftM trimInlines
 
-instance Monoid a => Monoid (Future s a) where
+instance Semigroup a => Semigroup (Future s a) where
+  (<>) = liftM2 (<>)
+instance (Semigroup a, Monoid a) => Monoid (Future s a) where
   mempty = return mempty
-  mappend = liftM2 mappend
-  mconcat = liftM mconcat . sequence
+  mappend = (<>)
 
 -- | Parse characters while a predicate is true.
 takeWhileP :: Monad m
@@ -529,15 +532,15 @@ romanNumeral upperCase = do
           map char romanDigits
     thousands <- ((1000 *) . length) <$> many thousand
     ninehundreds <- option 0 $ try $ hundred >> thousand >> return 900
-    fivehundreds <- ((500 *) . length) <$> many fivehundred
+    fivehundreds <- option 0 $ 500 <$ fivehundred
     fourhundreds <- option 0 $ try $ hundred >> fivehundred >> return 400
     hundreds <- ((100 *) . length) <$> many hundred
     nineties <- option 0 $ try $ ten >> hundred >> return 90
-    fifties <- ((50 *) . length) <$> many fifty
+    fifties <- option 0 $ (50 <$ fifty)
     forties <- option 0 $ try $ ten >> fifty >> return 40
     tens <- ((10 *) . length) <$> many ten
     nines <- option 0 $ try $ one >> ten >> return 9
-    fives <- ((5 *) . length) <$> many five
+    fives <- option 0 $ (5 <$ five)
     fours <- option 0 $ try $ one >> five >> return 4
     ones <- length <$> many one
     let total = thousands + ninehundreds + fivehundreds + fourhundreds +
@@ -590,7 +593,7 @@ uri = try $ do
   -- http://en.wikipedia.org/wiki/State_of_emergency_(disambiguation)
   -- as a URL, while NOT picking up the closing paren in
   -- (http://wikipedia.org). So we include balanced parens in the URL.
-  let isWordChar c = isAlphaNum c || c `elem` "#$%*+/@\\_-&="
+  let isWordChar c = isAlphaNum c || c `elem` "#$%+/@\\_-&="
   let wordChar = satisfy isWordChar
   let percentEscaped = try $ char '%' >> skipMany1 (satisfy isHexDigit)
   let entity = () <$ characterReference
@@ -1437,7 +1440,7 @@ token pp pos match = tokenPrim pp (\_ t _ -> pos t) match
 
 infixr 5 <+?>
 (<+?>) :: (Monoid a) => ParserT s st m a -> ParserT s st m a -> ParserT s st m a
-a <+?> b = a >>= flip fmap (try b <|> return mempty) . (<>)
+a <+?> b = a >>= flip fmap (try b <|> return mempty) . mappend
 
 extractIdClass :: Attr -> Attr
 extractIdClass (ident, cls, kvs) = (ident', cls', kvs')
diff --git a/src/Text/Pandoc/Pretty.hs b/src/Text/Pandoc/Pretty.hs
index 25c2373a6..de3d54ee2 100644
--- a/src/Text/Pandoc/Pretty.hs
+++ b/src/Text/Pandoc/Pretty.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE CPP                        #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-
@@ -77,12 +78,12 @@ module Text.Pandoc.Pretty (
      )
 
 where
+import Prelude
 import Control.Monad
 import Control.Monad.State.Strict
 import Data.Char (isSpace)
 import Data.Foldable (toList)
 import Data.List (intersperse)
-import Data.Monoid ((<>))
 import Data.Sequence (Seq, ViewL (..), fromList, mapWithIndex, singleton, viewl,
                       (<|))
 import qualified Data.Sequence as Seq
@@ -112,7 +113,7 @@ data D = Text Int String
        deriving (Show, Eq)
 
 newtype Doc = Doc { unDoc :: Seq D }
-              deriving (Monoid, Show, Eq)
+              deriving (Semigroup, Monoid, Show, Eq)
 
 instance IsString Doc where
   fromString = text
diff --git a/src/Text/Pandoc/Process.hs b/src/Text/Pandoc/Process.hs
index 27807a8c8..868977c86 100644
--- a/src/Text/Pandoc/Process.hs
+++ b/src/Text/Pandoc/Process.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2013-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -29,6 +30,7 @@ ByteString variant of 'readProcessWithExitCode'.
 -}
 module Text.Pandoc.Process (pipeProcess)
 where
+import Prelude
 import Control.Concurrent (forkIO, newEmptyMVar, putMVar, takeMVar)
 import Control.Exception
 import Control.Monad (unless)
diff --git a/src/Text/Pandoc/Readers.hs b/src/Text/Pandoc/Readers.hs
index 77d6d9130..76492b0aa 100644
--- a/src/Text/Pandoc/Readers.hs
+++ b/src/Text/Pandoc/Readers.hs
@@ -1,6 +1,7 @@
-{-# LANGUAGE FlexibleInstances   #-}
-{-# LANGUAGE GADTs               #-}
+{-# LANGUAGE MonoLocalBinds      #-}
+{-# LANGUAGE NoImplicitPrelude   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+
 {-
 Copyright (C) 2006-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -64,11 +65,13 @@ module Text.Pandoc.Readers
   , readTxt2Tags
   , readEPUB
   , readMuse
+  , readFB2
   -- * Miscellaneous
   , getReader
   , getDefaultExtensions
   ) where
 
+import Prelude
 import Control.Monad.Except (throwError)
 import Data.Aeson
 import qualified Data.ByteString.Lazy as BL
@@ -84,6 +87,7 @@ import Text.Pandoc.Readers.Creole
 import Text.Pandoc.Readers.DocBook
 import Text.Pandoc.Readers.Docx
 import Text.Pandoc.Readers.EPUB
+import Text.Pandoc.Readers.FB2
 import Text.Pandoc.Readers.Haddock
 import Text.Pandoc.Readers.HTML (readHtml)
 import Text.Pandoc.Readers.JATS (readJATS)
@@ -143,6 +147,7 @@ readers = [ ("native"       , TextReader readNative)
            ,("epub"         , ByteStringReader readEPUB)
            ,("muse"         , TextReader readMuse)
            ,("man"          , TextReader readMan)
+           ,("fb2"          , TextReader readFB2)
            ]
 
 -- | Retrieve reader, extensions based on formatSpec (format+extensions).
diff --git a/src/Text/Pandoc/Readers/CommonMark.hs b/src/Text/Pandoc/Readers/CommonMark.hs
index 6fbc09c17..79a4abbc2 100644
--- a/src/Text/Pandoc/Readers/CommonMark.hs
+++ b/src/Text/Pandoc/Readers/CommonMark.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2015-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -32,6 +33,7 @@ CommonMark is a strongly specified variant of Markdown: http://commonmark.org.
 module Text.Pandoc.Readers.CommonMark (readCommonMark)
 where
 
+import Prelude
 import CMarkGFM
 import Control.Monad.State
 import Data.Char (isAlphaNum, isLetter, isSpace, toLower)
diff --git a/src/Text/Pandoc/Readers/Creole.hs b/src/Text/Pandoc/Readers/Creole.hs
index 505d1686d..4fd38c0fd 100644
--- a/src/Text/Pandoc/Readers/Creole.hs
+++ b/src/Text/Pandoc/Readers/Creole.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
   Copyright (C) 2017 Sascha Wilde <wilde@sha-bang.de>
 
@@ -35,10 +36,10 @@ Conversion of creole text to 'Pandoc' document.
 module Text.Pandoc.Readers.Creole ( readCreole
                                   ) where
 
+import Prelude
 import Control.Monad.Except (guard, liftM2, throwError)
 import qualified Data.Foldable as F
 import Data.Maybe (fromMaybe)
-import Data.Monoid
 import Data.Text (Text)
 import qualified Data.Text as T
 import qualified Text.Pandoc.Builder as B
@@ -67,7 +68,7 @@ type CRLParser = ParserT [Char] ParserState
 -- Utility functions
 --
 
-(<+>) :: (Monad m, Monoid a) => m a -> m a -> m a
+(<+>) :: (Monad m, Semigroup a) => m a -> m a -> m a
 (<+>) = liftM2 (<>)
 
 -- we have to redefine `enclosed' from Text.Pandoc.Parsing, because it
diff --git a/src/Text/Pandoc/Readers/DocBook.hs b/src/Text/Pandoc/Readers/DocBook.hs
index 728f77a05..3d48c7ee8 100644
--- a/src/Text/Pandoc/Readers/DocBook.hs
+++ b/src/Text/Pandoc/Readers/DocBook.hs
@@ -1,5 +1,35 @@
-{-# LANGUAGE ExplicitForAll #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-
+Copyright (C) 2006-2018 John MacFarlane <jgm@berkeley.edu>
+
+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.Readers.DocBook
+   Copyright   : Copyright (C) 2006-2018 John MacFarlane
+   License     : GNU GPL, version 2 or above
+
+   Maintainer  : John MacFarlane <jgm@berkeley.edu>
+   Stability   : alpha
+   Portability : portable
+
+Conversion of DocBook XML to 'Pandoc' document.
+-}
 module Text.Pandoc.Readers.DocBook ( readDocBook ) where
+import Prelude
 import Control.Monad.State.Strict
 import Data.Char (isSpace, toUpper)
 import Data.Default
@@ -235,7 +265,7 @@ List of all DocBook tags, with [x] indicating implemented,
 [ ] manvolnum - A reference volume number
 [x] markup - A string of formatting markup in text that is to be
     represented literally
-[ ] mathphrase - A mathematical phrase, an expression that can be represented
+[x] mathphrase - A mathematical phrase, an expression that can be represented
     with ordinary text and a small amount of markup
 [ ] medialabel - A name that identifies the physical medium on which some
     information resides
@@ -697,6 +727,8 @@ parseBlock (Elem e) =
         "bibliodiv" -> sect 1
         "biblioentry" -> parseMixed para (elContent e)
         "bibliomixed" -> parseMixed para (elContent e)
+        "equation"         -> para <$> equation e displayMath
+        "informalequation" -> para <$> equation e displayMath
         "glosssee" -> para . (\ils -> text "See " <> ils <> str ".")
                          <$> getInlines e
         "glossseealso" -> para . (\ils -> text "See also " <> ils <> str ".")
@@ -923,9 +955,9 @@ parseInline (CRef ref) =
   return $ maybe (text $ map toUpper ref) text $ lookupEntity ref
 parseInline (Elem e) =
   case qName (elName e) of
-        "equation" -> equation displayMath
-        "informalequation" -> equation displayMath
-        "inlineequation" -> equation math
+        "equation" -> equation e displayMath
+        "informalequation" -> equation e displayMath
+        "inlineequation" -> equation e math
         "subscript" -> subscript <$> innerInlines
         "superscript" -> superscript <$> innerInlines
         "inlinemediaobject" -> getMediaobject e
@@ -1004,13 +1036,6 @@ parseInline (Elem e) =
         _          -> innerInlines
    where innerInlines = (trimInlines . mconcat) <$>
                           mapM parseInline (elContent e)
-         equation constructor = return $ mconcat $
-           map (constructor . writeTeX)
-           $ rights
-           $ map (readMathML . showElement . everywhere (mkT removePrefix))
-           $ filterChildren (\x -> qName (elName x) == "math" &&
-                                   qPrefix (elName x) == Just "mml") e
-         removePrefix elname = elname { qPrefix = Nothing }
          codeWithLang = do
            let classes' = case attrValue "language" e of
                                "" -> []
@@ -1048,6 +1073,7 @@ parseInline (Elem e) =
              | not (null xrefLabel) = xrefLabel
              | otherwise            = case qName (elName el) of
                   "chapter"      -> descendantContent "title" el
+                  "section"      -> descendantContent "title" el
                   "sect1"        -> descendantContent "title" el
                   "sect2"        -> descendantContent "title" el
                   "sect3"        -> descendantContent "title" el
@@ -1060,3 +1086,45 @@ parseInline (Elem e) =
             xrefLabel = attrValue "xreflabel" el
             descendantContent name = maybe "???" strContent
                                    . filterElementName (\n -> qName n == name)
+
+-- | Extract a math equation from an element
+--
+-- asciidoc can generate Latex math in CDATA sections.
+--
+-- Note that if some MathML can't be parsed it is silently ignored!
+equation
+  :: Monad m
+  => Element
+  -- ^ The element from which to extract a mathematical equation
+  -> (String -> Inlines)
+  -- ^ A constructor for some Inlines, taking the TeX code as input
+  -> m Inlines
+equation e constructor =
+  return $ mconcat $ map constructor $ mathMLEquations ++ latexEquations
+  where
+    mathMLEquations :: [String]
+    mathMLEquations = map writeTeX $ rights $ readMath
+      (\x -> qName (elName x) == "math" && qPrefix (elName x) == Just "mml")
+      (readMathML . showElement)
+
+    latexEquations :: [String]
+    latexEquations = readMath (\x -> qName (elName x) == "mathphrase")
+                              (concat . fmap showVerbatimCData . elContent)
+
+    readMath :: (Element -> Bool) -> (Element -> b) -> [b]
+    readMath childPredicate fromElement =
+      ( map (fromElement . everywhere (mkT removePrefix))
+      $ filterChildren childPredicate e
+      )
+
+-- | Get the actual text stored in a verbatim CData block. 'showContent'
+-- returns the text still surrounded by the [[CDATA]] tags.
+--
+-- Returns 'showContent' if this is not a verbatim CData
+showVerbatimCData :: Content -> String
+showVerbatimCData (Text (CData CDataVerbatim d _)) = d
+showVerbatimCData c = showContent c
+
+-- | Set the prefix of a name to 'Nothing'
+removePrefix :: QName -> QName
+removePrefix elname = elname { qPrefix = Nothing }
diff --git a/src/Text/Pandoc/Readers/Docx.hs b/src/Text/Pandoc/Readers/Docx.hs
index 5f2ca0fff..ca9f8c8dd 100644
--- a/src/Text/Pandoc/Readers/Docx.hs
+++ b/src/Text/Pandoc/Readers/Docx.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE CPP               #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE PatternGuards     #-}
@@ -74,6 +75,7 @@ module Text.Pandoc.Readers.Docx
        ( readDocx
        ) where
 
+import Prelude
 import Codec.Archive.Zip
 import Control.Monad.Reader
 import Control.Monad.State.Strict
@@ -122,7 +124,6 @@ data DState = DState { docxAnchorMap :: M.Map String String
                      , docxImmedPrevAnchor :: Maybe String
                      , docxMediaBag  :: MediaBag
                      , docxDropCap   :: Inlines
-                     , docxWarnings  :: [String]
                      -- keep track of (numId, lvl) values for
                      -- restarting
                      , docxListState :: M.Map (String, String) Integer
@@ -135,18 +136,16 @@ instance Default DState where
                , docxImmedPrevAnchor = Nothing
                , docxMediaBag  = mempty
                , docxDropCap   = mempty
-               , docxWarnings  = []
                , docxListState = M.empty
                , docxPrevPara  = mempty
                }
 
 data DEnv = DEnv { docxOptions       :: ReaderOptions
                  , docxInHeaderBlock :: Bool
-                 , docxCustomStyleAlready :: Bool
                  }
 
 instance Default DEnv where
-  def = DEnv def False False
+  def = DEnv def False
 
 type DocxContext m = ReaderT DEnv (StateT DState m)
 
@@ -252,103 +251,88 @@ parPartToString _                          = ""
 blacklistedCharStyles :: [String]
 blacklistedCharStyles = ["Hyperlink"]
 
-resolveDependentRunStyle :: RunStyle -> RunStyle
+resolveDependentRunStyle :: PandocMonad m => RunStyle -> DocxContext m RunStyle
 resolveDependentRunStyle rPr
   | Just (s, _)  <- rStyle rPr, s `elem` blacklistedCharStyles =
-    rPr
-  | Just (_, cs) <- rStyle rPr =
-      let rPr' = resolveDependentRunStyle cs
-      in
-       RunStyle { isBold = case isBold rPr of
-                     Just bool -> Just bool
-                     Nothing   -> isBold rPr'
-                , isItalic = case isItalic rPr of
-                     Just bool -> Just bool
-                     Nothing   -> isItalic rPr'
-                , isSmallCaps = case isSmallCaps rPr of
-                     Just bool -> Just bool
-                     Nothing   -> isSmallCaps rPr'
-                , isStrike = case isStrike rPr of
-                     Just bool -> Just bool
-                     Nothing   -> isStrike rPr'
-                , rVertAlign = case rVertAlign rPr of
-                     Just valign -> Just valign
-                     Nothing     -> rVertAlign rPr'
-                , rUnderline = case rUnderline rPr of
-                     Just ulstyle -> Just ulstyle
-                     Nothing      -> rUnderline rPr'
-                , rStyle = rStyle rPr }
-  | otherwise = rPr
-
-extraRunStyleInfo :: PandocMonad m => RunStyle -> DocxContext m (Inlines -> Inlines)
-extraRunStyleInfo rPr
-  | Just (s, _) <- rStyle rPr = do
-      already <- asks docxCustomStyleAlready
+    return rPr
+  | Just (_, cs) <- rStyle rPr = do
       opts <- asks docxOptions
-      return $ if isEnabled Ext_styles opts && not already
-               then spanWith ("", [], [("custom-style", s)])
-               else id
-  | otherwise = return id
+      if isEnabled Ext_styles opts
+        then return rPr
+        else do rPr' <- resolveDependentRunStyle cs
+                return $
+                  RunStyle { isBold = case isBold rPr of
+                               Just bool -> Just bool
+                               Nothing   -> isBold rPr'
+                           , isItalic = case isItalic rPr of
+                               Just bool -> Just bool
+                               Nothing   -> isItalic rPr'
+                           , isSmallCaps = case isSmallCaps rPr of
+                               Just bool -> Just bool
+                               Nothing   -> isSmallCaps rPr'
+                           , isStrike = case isStrike rPr of
+                               Just bool -> Just bool
+                               Nothing   -> isStrike rPr'
+                           , rVertAlign = case rVertAlign rPr of
+                               Just valign -> Just valign
+                               Nothing     -> rVertAlign rPr'
+                           , rUnderline = case rUnderline rPr of
+                               Just ulstyle -> Just ulstyle
+                               Nothing      -> rUnderline rPr'
+                           , rStyle = rStyle rPr }
+  | otherwise = return rPr
 
 runStyleToTransform :: PandocMonad m => RunStyle -> DocxContext m (Inlines -> Inlines)
 runStyleToTransform rPr
   | Just (s, _) <- rStyle rPr
   , s `elem` spansToKeep = do
-      let rPr' = rPr{rStyle = Nothing}
-      transform <- runStyleToTransform rPr'
+      transform <- runStyleToTransform rPr{rStyle = Nothing}
       return $ spanWith ("", [s], []) . transform
+  | Just (s, _) <- rStyle rPr = do
+      opts <- asks docxOptions
+      let extraInfo = if isEnabled Ext_styles opts
+                      then spanWith ("", [], [("custom-style", s)])
+                      else id
+      transform <- runStyleToTransform rPr{rStyle = Nothing}
+      return $ extraInfo . transform
   | Just True <- isItalic rPr = do
-      extraInfo <- extraRunStyleInfo rPr
-      transform <- local (\e -> e{docxCustomStyleAlready = True}) $
-                   runStyleToTransform rPr {isItalic = Nothing}
-      return $ extraInfo . emph  . transform
+      transform <- runStyleToTransform rPr{isItalic = Nothing}
+      return $ emph  . transform
   | Just True <- isBold rPr = do
-      extraInfo <- extraRunStyleInfo rPr
-      transform <- local (\e -> e{docxCustomStyleAlready = True}) $
-                   runStyleToTransform rPr {isBold = Nothing}
-      return $ extraInfo . strong . transform
+      transform <- runStyleToTransform rPr{isBold = Nothing}
+      return $ strong . transform
   | Just True <- isSmallCaps rPr = do
-      extraInfo <- extraRunStyleInfo rPr
-      transform <- local (\e -> e{docxCustomStyleAlready = True}) $
-                   runStyleToTransform rPr {isSmallCaps = Nothing}
-      return $ extraInfo . smallcaps . transform
+      transform <- runStyleToTransform rPr{isSmallCaps = Nothing}
+      return $ smallcaps . transform
   | Just True <- isStrike rPr = do
-      extraInfo <- extraRunStyleInfo rPr
-      transform <- local (\e -> e{docxCustomStyleAlready = True}) $
-                   runStyleToTransform rPr {isStrike = Nothing}
-      return $ extraInfo . strikeout . transform
+      transform <- runStyleToTransform rPr{isStrike = Nothing}
+      return $ strikeout . transform
   | Just SupScrpt <- rVertAlign rPr = do
-      extraInfo <- extraRunStyleInfo rPr
-      transform <- local (\e -> e{docxCustomStyleAlready = True}) $
-                   runStyleToTransform rPr {rVertAlign = Nothing}
-      return $ extraInfo . superscript . transform
+      transform <- runStyleToTransform rPr{rVertAlign = Nothing}
+      return $ superscript . transform
   | Just SubScrpt <- rVertAlign rPr = do
-      extraInfo <- extraRunStyleInfo rPr
-      transform <- local (\e -> e{docxCustomStyleAlready = True}) $
-                   runStyleToTransform rPr {rVertAlign = Nothing}
-      return $ extraInfo . subscript . transform
+      transform <- runStyleToTransform rPr{rVertAlign = Nothing}
+      return $ subscript . transform
   | Just "single" <- rUnderline rPr = do
-      extraInfo <- extraRunStyleInfo rPr
-      transform <- local (\e -> e{docxCustomStyleAlready = True}) $
-                   runStyleToTransform rPr {rUnderline = Nothing}
-      return $ extraInfo . underlineSpan . transform
-  | otherwise = extraRunStyleInfo rPr
+      transform <- runStyleToTransform rPr{rUnderline = Nothing}
+      return $ underlineSpan . transform
+  | otherwise = return id
 
 runToInlines :: PandocMonad m => Run -> DocxContext m Inlines
 runToInlines (Run rs runElems)
   | Just (s, _) <- rStyle rs
-  , s `elem` codeStyles =
-    let rPr = resolveDependentRunStyle rs
-        codeString = code $ concatMap runElemToString runElems
-    in
-     return $ case rVertAlign rPr of
-     Just SupScrpt -> superscript codeString
-     Just SubScrpt -> subscript codeString
-     _             -> codeString
+  , s `elem` codeStyles = do
+      rPr <- resolveDependentRunStyle rs
+      let codeString = code $ concatMap runElemToString runElems
+      return $ case rVertAlign rPr of
+        Just SupScrpt -> superscript codeString
+        Just SubScrpt -> subscript codeString
+        _             -> codeString
   | otherwise = do
-    let ils = smushInlines (map runElemToInlines runElems)
-    transform <- runStyleToTransform $ resolveDependentRunStyle rs
-    return $ transform ils
+      rPr <- resolveDependentRunStyle rs
+      let ils = smushInlines (map runElemToInlines runElems)
+      transform <- runStyleToTransform rPr
+      return $ transform ils
 runToInlines (Footnote bps) = do
   blksList <- smushBlocks <$> mapM bodyPartToBlocks bps
   return $ note blksList
@@ -385,7 +369,7 @@ blocksToInlinesWarn cmtId blks = do
 parPartToInlines :: PandocMonad m => ParPart -> DocxContext m Inlines
 parPartToInlines parPart =
   case parPart of
-    (BookMark _ anchor) | notElem anchor dummyAnchors -> do
+    (BookMark _ anchor) | anchor `notElem` dummyAnchors -> do
       inHdrBool <- asks docxInHeaderBlock
       ils <- parPartToInlines' parPart
       immedPrevAnchor <- gets docxImmedPrevAnchor
@@ -478,8 +462,6 @@ parPartToInlines' (ExternalHyperLink target runs) = do
   return $ link target "" ils
 parPartToInlines' (PlainOMath exps) =
   return $ math $ writeTeX exps
-parPartToInlines' (SmartTag runs) =
-  smushInlines <$> mapM runToInlines runs
 parPartToInlines' (Field info runs) =
   case info of
     HyperlinkField url -> parPartToInlines' $ ExternalHyperLink url runs
@@ -706,6 +688,10 @@ bodyPartToBlocks (Tbl cap _ look parts@(r:rs)) = do
       rowLength :: Row -> Int
       rowLength (Row c) = length c
 
+  -- pad cells.  New Text.Pandoc.Builder will do that for us,
+  -- so this is for compatibility while we switch over.
+  let cells' = map (\row -> take width (row ++ repeat mempty)) cells
+
   hdrCells <- case hdr of
     Just r' -> rowToBlocksList r'
     Nothing -> return $ replicate width mempty
@@ -718,7 +704,7 @@ bodyPartToBlocks (Tbl cap _ look parts@(r:rs)) = do
   let alignments = replicate width AlignDefault
       widths = replicate width 0 :: [Double]
 
-  return $ table caption (zip alignments widths) hdrCells cells
+  return $ table caption (zip alignments widths) hdrCells cells'
 bodyPartToBlocks (OMathPara e) =
   return $ para $ displayMath (writeTeX e)
 
diff --git a/src/Text/Pandoc/Readers/Docx/Combine.hs b/src/Text/Pandoc/Readers/Docx/Combine.hs
index 003265e6e..108c4bbe5 100644
--- a/src/Text/Pandoc/Readers/Docx/Combine.hs
+++ b/src/Text/Pandoc/Readers/Docx/Combine.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE FlexibleInstances    #-}
 {-# LANGUAGE PatternGuards        #-}
 {-# LANGUAGE TypeSynonymInstances #-}
@@ -7,6 +8,7 @@ module Text.Pandoc.Readers.Docx.Combine ( smushInlines
                                         )
        where
 
+import Prelude
 import Data.List
 import Data.Sequence (ViewL (..), ViewR (..), viewl, viewr, (><), (|>))
 import qualified Data.Sequence as Seq (null)
@@ -133,6 +135,10 @@ combineBlocks bs cs
   | bs' :> BlockQuote bs'' <- viewr (unMany bs)
   , BlockQuote cs'' :< cs' <- viewl (unMany cs) =
       Many $ (bs' |> BlockQuote (bs'' <> cs'')) >< cs'
+  | bs' :> CodeBlock attr codeStr <- viewr (unMany bs)
+  , CodeBlock attr' codeStr' :< cs' <- viewl (unMany cs)
+  , attr == attr' =
+      Many $ (bs' |> CodeBlock attr (codeStr <> "\n" <> codeStr')) >< cs'
 combineBlocks bs cs = bs <> cs
 
 instance (Monoid a, Eq a) => Eq (Modifier a) where
diff --git a/src/Text/Pandoc/Readers/Docx/Fields.hs b/src/Text/Pandoc/Readers/Docx/Fields.hs
index 6eeb55d2f..c3f54560b 100644
--- a/src/Text/Pandoc/Readers/Docx/Fields.hs
+++ b/src/Text/Pandoc/Readers/Docx/Fields.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2014-2018 Jesse Rosenthal <jrosenthal@jhu.edu>
 
@@ -32,6 +33,7 @@ module Text.Pandoc.Readers.Docx.Fields ( FieldInfo(..)
                                        , parseFieldInfo
                                        ) where
 
+import Prelude
 import Text.Parsec
 import Text.Parsec.String (Parser)
 
diff --git a/src/Text/Pandoc/Readers/Docx/Lists.hs b/src/Text/Pandoc/Readers/Docx/Lists.hs
index c0f05094a..49ea71601 100644
--- a/src/Text/Pandoc/Readers/Docx/Lists.hs
+++ b/src/Text/Pandoc/Readers/Docx/Lists.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2014-2018 Jesse Rosenthal <jrosenthal@jhu.edu>
 
@@ -33,6 +34,7 @@ module Text.Pandoc.Readers.Docx.Lists ( blocksToBullets
                                       , listParagraphDivs
                                       ) where
 
+import Prelude
 import Data.List
 import Data.Maybe
 import Text.Pandoc.Generic (bottomUp)
diff --git a/src/Text/Pandoc/Readers/Docx/Parse.hs b/src/Text/Pandoc/Readers/Docx/Parse.hs
index c123a0018..4c4c06073 100644
--- a/src/Text/Pandoc/Readers/Docx/Parse.hs
+++ b/src/Text/Pandoc/Readers/Docx/Parse.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE PatternGuards     #-}
 {-# LANGUAGE ViewPatterns      #-}
@@ -58,6 +59,7 @@ module Text.Pandoc.Readers.Docx.Parse ( Docx(..)
                                       , archiveToDocx
                                       , archiveToDocxWithWarnings
                                       ) where
+import Prelude
 import Codec.Archive.Zip
 import Control.Applicative ((<|>))
 import Control.Monad.Except
@@ -132,21 +134,23 @@ mapD f xs =
   in
    concatMapM handler xs
 
-unwrapSDT :: NameSpaces -> Content -> [Content]
-unwrapSDT ns (Elem element)
+unwrap :: NameSpaces -> Content -> [Content]
+unwrap ns (Elem element)
   | isElem ns "w" "sdt" element
   , Just sdtContent <- findChildByName ns "w" "sdtContent" element
-  = map Elem $ elChildren sdtContent
-unwrapSDT _ content = [content]
+  = concatMap ((unwrap ns) . Elem) (elChildren sdtContent)
+  | isElem ns "w" "smartTag" element
+  = concatMap ((unwrap ns) . Elem) (elChildren element)
+unwrap _ content = [content]
 
-unwrapSDTchild :: NameSpaces -> Content -> Content
-unwrapSDTchild ns (Elem element) =
-  Elem $ element { elContent = concatMap (unwrapSDT ns) (elContent element) }
-unwrapSDTchild _ content = content
+unwrapChild :: NameSpaces -> Content -> Content
+unwrapChild ns (Elem element) =
+  Elem $ element { elContent = concatMap (unwrap ns) (elContent element) }
+unwrapChild _ content = content
 
 walkDocument' :: NameSpaces -> XMLC.Cursor -> XMLC.Cursor
 walkDocument' ns cur =
-  let modifiedCur = XMLC.modifyContent (unwrapSDTchild ns) cur
+  let modifiedCur = XMLC.modifyContent (unwrapChild ns) cur
   in
     case XMLC.nextDF modifiedCur of
       Just cur' -> walkDocument' ns cur'
@@ -275,7 +279,6 @@ data ParPart = PlainRun Run
              | Drawing FilePath String String B.ByteString Extent -- title, alt
              | Chart                                              -- placeholder for now
              | PlainOMath [Exp]
-             | SmartTag [Run]
              | Field FieldInfo [Run]
              | NullParPart      -- when we need to return nothing, but
                                 -- not because of an error.
@@ -825,10 +828,6 @@ elemToParPart ns element
   | Just change <- getTrackedChange ns element = do
       runs <- mapD (elemToRun ns) (elChildren element)
       return $ ChangedRuns change runs
-elemToParPart ns element
-  | isElem ns "w" "smartTag" element = do
-    runs <- mapD (elemToRun ns) (elChildren element)
-    return $ SmartTag runs
 elemToParPart ns element
   | isElem ns "w" "bookmarkStart" element
   , Just bmId <- findAttrByName ns "w" "id" element
diff --git a/src/Text/Pandoc/Readers/Docx/StyleMap.hs b/src/Text/Pandoc/Readers/Docx/StyleMap.hs
index b32a73770..6ccda3ccc 100644
--- a/src/Text/Pandoc/Readers/Docx/StyleMap.hs
+++ b/src/Text/Pandoc/Readers/Docx/StyleMap.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 module Text.Pandoc.Readers.Docx.StyleMap (  StyleMaps(..)
                                           , alterMap
                                           , getMap
@@ -7,6 +8,7 @@ module Text.Pandoc.Readers.Docx.StyleMap (  StyleMaps(..)
                                           , hasStyleName
                                           ) where
 
+import Prelude
 import Control.Monad.State.Strict
 import Data.Char (toLower)
 import qualified Data.Map as M
diff --git a/src/Text/Pandoc/Readers/Docx/Util.hs b/src/Text/Pandoc/Readers/Docx/Util.hs
index d9d65bc07..088950d26 100644
--- a/src/Text/Pandoc/Readers/Docx/Util.hs
+++ b/src/Text/Pandoc/Readers/Docx/Util.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 module Text.Pandoc.Readers.Docx.Util (
                                         NameSpaces
                                       , elemName
@@ -8,6 +9,7 @@ module Text.Pandoc.Readers.Docx.Util (
                                       , findAttrByName
                                       ) where
 
+import Prelude
 import Data.Maybe (mapMaybe)
 import Text.XML.Light
 
diff --git a/src/Text/Pandoc/Readers/EPUB.hs b/src/Text/Pandoc/Readers/EPUB.hs
index 3b13bbe13..c26447641 100644
--- a/src/Text/Pandoc/Readers/EPUB.hs
+++ b/src/Text/Pandoc/Readers/EPUB.hs
@@ -1,12 +1,41 @@
-{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE TupleSections     #-}
+{-# LANGUAGE ViewPatterns      #-}
+{-
+Copyright (C) 2014-2018 Matthew Pickering
 
-{-# LANGUAGE TupleSections    #-}
-{-# LANGUAGE ViewPatterns     #-}
+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.Readers.EPUB
+   Copyright   : Copyright (C) 2014-2018 Matthew Pickering
+   License     : GNU GPL, version 2 or above
+
+   Maintainer  : John MacFarlane <jgm@berkeley.edu>
+   Stability   : alpha
+   Portability : portable
+
+Conversion of EPUB to 'Pandoc' document.
+-}
 
 module Text.Pandoc.Readers.EPUB
   (readEPUB)
   where
 
+import Prelude
 import Codec.Archive.Zip (Archive (..), Entry, findEntryByPath, fromEntry,
                           toArchiveOrFail)
 import Control.DeepSeq (NFData, deepseq)
@@ -16,7 +45,6 @@ import qualified Data.ByteString.Lazy as BL (ByteString)
 import Data.List (isInfixOf, isPrefixOf)
 import qualified Data.Map as M (Map, elems, fromList, lookup)
 import Data.Maybe (fromMaybe, mapMaybe)
-import Data.Monoid ((<>))
 import qualified Data.Text.Lazy as TL
 import qualified Data.Text.Lazy.Encoding as TL
 import Network.URI (unEscapeString)
@@ -93,7 +121,7 @@ fetchImages mimes root arc (query iq -> links) =
     mapM_ (uncurry3 insertMedia) (mapMaybe getEntry links)
   where
     getEntry link =
-        let abslink = normalise (root </> link) in
+        let abslink = normalise (unEscapeString (root </> link)) in
         (link , lookup link mimes, ) . fromEntry
           <$> findEntryByPath abslink arc
 
@@ -264,7 +292,7 @@ findAttrE :: PandocMonad m => QName -> Element -> m String
 findAttrE q e = mkE "findAttr" $ findAttr q e
 
 findEntryByPathE :: PandocMonad m => FilePath -> Archive -> m Entry
-findEntryByPathE (normalise -> path) a =
+findEntryByPathE (normalise . unEscapeString -> path) a =
   mkE ("No entry on path: " ++ path) $ findEntryByPath path a
 
 parseXMLDocE :: PandocMonad m => String -> m Element
diff --git a/src/Text/Pandoc/Readers/FB2.hs b/src/Text/Pandoc/Readers/FB2.hs
new file mode 100644
index 000000000..577fc85b6
--- /dev/null
+++ b/src/Text/Pandoc/Readers/FB2.hs
@@ -0,0 +1,404 @@
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TupleSections #-}
+{-
+Copyright (C) 2018 Alexander Krotov <ilabdsf@gmail.com>
+
+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.Readers.FB2
+   Copyright   : Copyright (C) 2018 Alexander Krotov
+   License     : GNU GPL, version 2 or above
+
+   Maintainer  : Alexander Krotov <ilabdsf@gmail.com>
+   Stability   : alpha
+   Portability : portable
+
+Conversion of FB2 to 'Pandoc' document.
+-}
+
+{-
+
+TODO:
+ - Tables
+ - Named styles
+ - Parse ID attribute for all elements that have it
+
+-}
+
+module Text.Pandoc.Readers.FB2 ( readFB2 ) where
+import Prelude
+import Control.Monad.Except (throwError)
+import Control.Monad.State.Strict
+import Data.ByteString.Lazy.Char8 ( pack )
+import Data.ByteString.Base64.Lazy
+import Data.Char (isSpace, toUpper)
+import Data.Functor
+import Data.List (dropWhileEnd, intersperse)
+import Data.List.Split (splitOn)
+import Data.Text (Text)
+import Data.Default
+import Data.Maybe
+import Text.HTML.TagSoup.Entity (lookupEntity)
+import Text.Pandoc.Builder
+import Text.Pandoc.Class (PandocMonad, insertMedia, report)
+import Text.Pandoc.Error
+import Text.Pandoc.Logging
+import Text.Pandoc.Options
+import Text.Pandoc.Shared (crFilter)
+import Text.XML.Light
+
+type FB2 m = StateT FB2State m
+
+data FB2State = FB2State{ fb2SectionLevel :: Int
+                        , fb2Meta :: Meta
+                        , fb2Authors :: [String]
+                        } deriving Show
+
+instance Default FB2State where
+  def = FB2State{ fb2SectionLevel = 1
+                , fb2Meta = mempty
+                , fb2Authors = []
+                }
+
+instance HasMeta FB2State where
+  setMeta field v s = s {fb2Meta = setMeta field v (fb2Meta s)}
+  deleteMeta field s = s {fb2Meta = deleteMeta field (fb2Meta s)}
+
+readFB2 :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+readFB2 _ inp  = do
+  (bs, st) <- runStateT (mapM parseBlock $ parseXML (crFilter inp)) def
+  let authors = if null $ fb2Authors st
+                then id
+                else setMeta "author" (map text $ reverse $ fb2Authors st)
+  pure $ Pandoc (authors $ fb2Meta st) (toList . mconcat $ bs)
+
+-- * Utility functions
+
+trim :: String -> String
+trim = dropWhileEnd isSpace . dropWhile isSpace
+
+removeHash :: String -> String
+removeHash ('#':xs) = xs
+removeHash xs = xs
+
+convertEntity :: String -> String
+convertEntity e = fromMaybe (map toUpper e) (lookupEntity e)
+
+parseInline :: PandocMonad m => Content -> FB2 m Inlines
+parseInline (Elem e) =
+  case qName $ elName e of
+    "strong" -> strong <$> parseStyleType e
+    "emphasis" -> emph <$> parseStyleType e
+    "style" -> parseNamedStyle e
+    "a" -> parseLinkType e
+    "strikethrough" -> strikeout <$> parseStyleType e
+    "sub" -> subscript <$> parseStyleType e
+    "sup" -> superscript <$> parseStyleType e
+    "code" -> pure $ code $ strContent e
+    "image" -> parseInlineImageElement e
+    name -> throwError $ PandocParseError ("Couldn't parse FB2 file: unexpected element " ++ name ++ ".")
+parseInline (Text x) = pure $ text $ cdData x
+parseInline (CRef r) = pure $ str $ convertEntity r
+
+parseSubtitle :: PandocMonad m => Element -> FB2 m Blocks
+parseSubtitle e = headerWith ("", ["unnumbered"], []) <$> gets fb2SectionLevel <*> parsePType e
+
+-- * Root element parser
+
+parseBlock :: PandocMonad m => Content -> FB2 m Blocks
+parseBlock (Elem e) =
+  case qName $ elName e of
+    "?xml"  -> pure mempty
+    "FictionBook" -> mconcat <$> mapM parseFictionBookChild (elChildren e)
+    name -> report (UnexpectedXmlElement name "root") $> mempty
+parseBlock _ = pure mempty
+
+-- | Parse a child of @\<FictionBook>@ element.
+parseFictionBookChild :: PandocMonad m => Element -> FB2 m Blocks
+parseFictionBookChild e =
+  case qName $ elName e of
+    "stylesheet" -> pure mempty -- stylesheet is ignored
+    "description" -> mempty <$ mapM_ parseDescriptionChild (elChildren e)
+    "body" -> mconcat <$> mapM parseBodyChild (elChildren e)
+    "binary" -> mempty <$ parseBinaryElement e
+    name -> report (UnexpectedXmlElement name "FictionBook") $> mempty
+
+-- | Parse a child of @\<description>@ element.
+parseDescriptionChild :: PandocMonad m => Element -> FB2 m ()
+parseDescriptionChild e =
+  case qName $ elName e of
+    "title-info" -> mapM_ parseTitleInfoChild (elChildren e)
+    "src-title-info" -> pure () -- ignore
+    "document-info" -> pure ()
+    "publish-info" -> pure ()
+    "custom-info" -> pure ()
+    "output" -> pure ()
+    name -> throwError $ PandocParseError ("Couldn't parse FB2 file: unexpected element " ++ name ++ "in description.")
+
+-- | Parse a child of @\<body>@ element.
+parseBodyChild :: PandocMonad m => Element -> FB2 m Blocks
+parseBodyChild e =
+  case qName $ elName e of
+    "image" -> parseImageElement e
+    "title" -> header <$> gets fb2SectionLevel <*> parseTitleType (elContent e)
+    "epigraph" -> parseEpigraph e
+    "section" -> parseSection e
+    name -> throwError $ PandocParseError ("Couldn't parse FB2 file: unexpected element " ++ name ++ " in body.")
+
+-- | Parse a @\<binary>@ element.
+parseBinaryElement :: PandocMonad m => Element -> FB2 m ()
+parseBinaryElement e =
+  case (findAttr (QName "id" Nothing Nothing) e, findAttr (QName "content-type" Nothing Nothing) e) of
+    (Nothing, _) -> throwError $ PandocParseError "<binary> element must have an \"id\" attribute"
+    (Just _, Nothing) -> throwError $ PandocParseError "<binary> element must have a \"content-type\" attribute"
+    (Just filename, contentType) -> insertMedia filename contentType (decodeLenient (pack (strContent e)))
+
+-- * Type parsers
+
+-- | Parse @authorType@
+parseAuthor :: PandocMonad m => Element -> FB2 m String
+parseAuthor e = unwords <$> mapM parseAuthorChild (elChildren e)
+
+parseAuthorChild :: PandocMonad m => Element -> FB2 m String
+parseAuthorChild e =
+  case qName $ elName e of
+    "first-name" -> pure $ strContent e
+    "middle-name" -> pure $ strContent e
+    "last-name" -> pure $ strContent e
+    "nickname" -> pure $ strContent e
+    "home-page" -> pure $ strContent e
+    "email" -> pure $ strContent e
+    name -> throwError $ PandocParseError ("Couldn't parse FB2 file: unexpected element " ++ name ++ " in author.")
+
+-- | Parse @titleType@
+parseTitle :: PandocMonad m => Element -> FB2 m Blocks
+parseTitle e = header <$> gets fb2SectionLevel <*> parseTitleType (elContent e)
+
+parseTitleType :: PandocMonad m => [Content] -> FB2 m Inlines
+parseTitleType c = mconcat . intersperse linebreak . catMaybes <$> mapM parseTitleContent c
+
+parseTitleContent :: PandocMonad m => Content -> FB2 m (Maybe Inlines)
+parseTitleContent (Elem e) =
+  case qName $ elName e of
+    "p" -> Just <$> parsePType e
+    "empty-line" -> pure $ Just mempty
+    _ -> pure mempty
+parseTitleContent _ = pure Nothing
+
+-- | Parse @imageType@
+parseImageElement :: PandocMonad m => Element -> FB2 m Blocks
+parseImageElement e =
+  case href of
+    Just src -> pure $ para $ imageWith (imgId, [], []) (removeHash src) title alt
+    Nothing -> throwError $ PandocParseError "Couldn't parse FB2 file: image without href."
+  where alt = maybe mempty str $ findAttr (QName "alt" Nothing Nothing) e
+        title = fromMaybe "" $ findAttr (QName "title" Nothing Nothing) e
+        imgId = fromMaybe "" $ findAttr (QName "id" Nothing Nothing) e
+        href = findAttr (QName "href" (Just "http://www.w3.org/1999/xlink") Nothing) e
+
+-- | Parse @pType@
+parsePType :: PandocMonad m => Element -> FB2 m Inlines
+parsePType = parseStyleType -- TODO add support for optional "id" and "style" attributes
+
+-- | Parse @citeType@
+parseCite :: PandocMonad m => Element -> FB2 m Blocks
+parseCite e = blockQuote . mconcat <$> mapM parseCiteChild (elChildren e)
+
+-- | Parse @citeType@ child
+parseCiteChild :: PandocMonad m => Element -> FB2 m Blocks
+parseCiteChild e =
+  case qName $ elName e of
+    "p" -> para <$> parsePType e
+    "poem" -> parsePoem e
+    "empty-line" -> pure horizontalRule
+    "subtitle" -> parseSubtitle e
+    "table" -> parseTable e
+    "text-author" -> para <$> parsePType e
+    name -> report (UnexpectedXmlElement name "cite") $> mempty
+
+-- | Parse @poemType@
+parsePoem :: PandocMonad m => Element -> FB2 m Blocks
+parsePoem e = mconcat <$> mapM parsePoemChild (elChildren e)
+
+parsePoemChild :: PandocMonad m => Element -> FB2 m Blocks
+parsePoemChild e =
+  case qName $ elName e of
+    "title" -> parseTitle e
+    "subtitle" -> parseSubtitle e
+    "epigraph" -> parseEpigraph e
+    "stanza" -> parseStanza e
+    "text-author" -> para <$> parsePType e
+    "date" -> pure $ para $ text $ strContent e
+    name -> report (UnexpectedXmlElement name "poem") $> mempty
+
+parseStanza :: PandocMonad m => Element -> FB2 m Blocks
+parseStanza e = fromList . joinLineBlocks . toList . mconcat <$> mapM parseStanzaChild (elChildren e)
+
+joinLineBlocks :: [Block] -> [Block]
+joinLineBlocks (LineBlock xs:LineBlock ys:zs) = joinLineBlocks (LineBlock (xs ++ ys) : zs)
+joinLineBlocks (x:xs) = x:joinLineBlocks xs
+joinLineBlocks [] = []
+
+parseStanzaChild :: PandocMonad m => Element -> FB2 m Blocks
+parseStanzaChild e =
+  case qName $ elName e of
+    "title" -> parseTitle e
+    "subtitle" -> parseSubtitle e
+    "v" -> lineBlock . (:[]) <$> parsePType e
+    name -> report (UnexpectedXmlElement name "stanza") $> mempty
+
+-- | Parse @epigraphType@
+parseEpigraph :: PandocMonad m => Element -> FB2 m Blocks
+parseEpigraph e =
+  divWith (divId, ["epigraph"], []) . mconcat <$> mapM parseEpigraphChild (elChildren e)
+  where divId = fromMaybe "" $ findAttr (QName "id" Nothing Nothing) e
+
+parseEpigraphChild :: PandocMonad m => Element -> FB2 m Blocks
+parseEpigraphChild e =
+  case qName $ elName e of
+    "p" -> para <$> parsePType e
+    "poem" -> parsePoem e
+    "cite" -> parseCite e
+    "empty-line" -> pure horizontalRule
+    "text-author" -> para <$> parsePType e
+    name -> report (UnexpectedXmlElement name "epigraph") $> mempty
+
+-- | Parse @annotationType@
+parseAnnotation :: PandocMonad m => Element -> FB2 m Blocks
+parseAnnotation e = mconcat <$> mapM parseAnnotationChild (elChildren e)
+
+parseAnnotationChild :: PandocMonad m => Element -> FB2 m Blocks
+parseAnnotationChild e =
+  case qName $ elName e of
+    "p" -> para <$> parsePType e
+    "poem" -> parsePoem e
+    "cite" -> parseCite e
+    "subtitle" -> parseSubtitle e
+    "table" -> parseTable e
+    "empty-line" -> pure horizontalRule
+    name -> report (UnexpectedXmlElement name "annotation") $> mempty
+
+-- | Parse @sectionType@
+parseSection :: PandocMonad m => Element -> FB2 m Blocks
+parseSection e = do
+  n <- gets fb2SectionLevel
+  modify $ \st -> st{ fb2SectionLevel = n + 1 }
+  let sectionId = fromMaybe "" $ findAttr (QName "id" Nothing Nothing) e
+  bs <- divWith (sectionId, ["section"], []) . mconcat <$> mapM parseSectionChild (elChildren e)
+  modify $ \st -> st{ fb2SectionLevel = n }
+  pure bs
+
+parseSectionChild :: PandocMonad m => Element -> FB2 m Blocks
+parseSectionChild e =
+  case qName $ elName e of
+    "title" -> parseBodyChild e
+    "epigraph" -> parseEpigraph e
+    "image" -> parseImageElement e
+    "annotation" -> parseAnnotation e
+    "poem" -> parsePoem e
+    "cite" -> parseCite e
+    "empty-line" -> pure horizontalRule
+    "table" -> parseTable e
+    "subtitle" -> parseSubtitle e
+    "p" -> para <$> parsePType e
+    "section" -> parseSection e
+    name -> report (UnexpectedXmlElement name "section") $> mempty
+
+-- | parse @styleType@
+parseStyleType :: PandocMonad m => Element -> FB2 m Inlines
+parseStyleType e = mconcat <$> mapM parseInline (elContent e)
+
+-- | Parse @namedStyleType@
+parseNamedStyle :: PandocMonad m => Element -> FB2 m Inlines
+parseNamedStyle e = do
+  content <- mconcat <$> mapM parseNamedStyleChild (elContent e)
+  let lang = maybeToList $ ("lang",) <$> findAttr (QName "lang" Nothing (Just "xml")) e
+  case findAttr (QName "name" Nothing Nothing) e of
+    Just name -> pure $ spanWith ("", [name], lang) content
+    Nothing -> throwError $ PandocParseError "Couldn't parse FB2 file: link without required name."
+
+parseNamedStyleChild :: PandocMonad m => Content -> FB2 m Inlines
+parseNamedStyleChild (Elem e) =
+  case qName (elName e) of
+    "strong" -> strong <$> parseStyleType e
+    "emphasis" -> emph <$> parseStyleType e
+    "style" -> parseNamedStyle e
+    "a" -> parseLinkType e
+    "strikethrough" -> strikeout <$> parseStyleType e
+    "sub" -> subscript <$> parseStyleType e
+    "sup" -> superscript <$> parseStyleType e
+    "code" -> pure $ code $ strContent e
+    "image" -> parseInlineImageElement e
+    name -> throwError $ PandocParseError ("Couldn't parse FB2 file: unexpected element " ++ name ++ ".")
+parseNamedStyleChild x = parseInline x
+
+-- | Parse @linkType@
+parseLinkType :: PandocMonad m => Element -> FB2 m Inlines
+parseLinkType e = do
+  content <- mconcat <$> mapM parseStyleLinkType (elContent e)
+  case findAttr (QName "href" (Just "http://www.w3.org/1999/xlink") Nothing) e of
+    Just href -> pure $ link href "" content
+    Nothing -> throwError $ PandocParseError "Couldn't parse FB2 file: link without required href."
+
+-- | Parse @styleLinkType@
+parseStyleLinkType :: PandocMonad m => Content -> FB2 m Inlines
+parseStyleLinkType x@(Elem e) =
+  case qName (elName e) of
+    "a" -> throwError $ PandocParseError "Couldn't parse FB2 file: links cannot be nested."
+    _ -> parseInline x
+parseStyleLinkType x = parseInline x
+
+-- | Parse @tableType@
+parseTable :: PandocMonad m => Element -> FB2 m Blocks
+parseTable _ = pure mempty -- TODO: tables are not supported yet
+
+-- | Parse @title-infoType@
+parseTitleInfoChild :: PandocMonad m => Element -> FB2 m ()
+parseTitleInfoChild e =
+  case qName (elName e) of
+    "genre" -> pure ()
+    "author" -> parseAuthor e >>= \author -> modify (\st -> st {fb2Authors = author:fb2Authors st})
+    "book-title" -> modify (setMeta "title" (text $ strContent e))
+    "annotation" -> parseAnnotation e >>= modify . setMeta "abstract"
+    "keywords" -> modify (setMeta "keywords" (map (MetaString . trim) $ splitOn "," $ strContent e))
+    "date" -> modify (setMeta "date" (text $ strContent e))
+    "coverpage" -> parseCoverPage e
+    "lang" -> pure ()
+    "src-lang" -> pure ()
+    "translator" -> pure ()
+    "sequence" -> pure ()
+    name -> throwError $ PandocParseError ("Couldn't parse FB2 file: unexpected element " ++ name ++ " in title-info.")
+
+parseCoverPage :: PandocMonad m => Element -> FB2 m ()
+parseCoverPage e =
+  case findChild (QName "image" (Just "http://www.gribuser.ru/xml/fictionbook/2.0") Nothing) e of
+    Just img -> case href of
+                  Just src -> modify (setMeta "cover-image" (MetaString $ removeHash src))
+                  Nothing -> pure ()
+                where href = findAttr (QName "href" (Just "http://www.w3.org/1999/xlink") Nothing) img
+    Nothing -> pure ()
+
+-- | Parse @inlineImageType@ element
+parseInlineImageElement :: PandocMonad m
+                        => Element
+                        -> FB2 m Inlines
+parseInlineImageElement e =
+  case href of
+    Just src -> pure $ imageWith ("", [], []) (removeHash src) "" alt
+    Nothing -> throwError $ PandocParseError "Couldn't parse FB2 file: inline image without href."
+  where alt = maybe mempty str $ findAttr (QName "alt" Nothing Nothing) e
+        href = findAttr (QName "href" (Just "http://www.w3.org/1999/xlink") Nothing) e
diff --git a/src/Text/Pandoc/Readers/HTML.hs b/src/Text/Pandoc/Readers/HTML.hs
index 0e79f9ec3..32a1ba5a6 100644
--- a/src/Text/Pandoc/Readers/HTML.hs
+++ b/src/Text/Pandoc/Readers/HTML.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE FlexibleContexts      #-}
 {-# LANGUAGE FlexibleInstances     #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
@@ -42,6 +43,7 @@ module Text.Pandoc.Readers.HTML ( readHtml
                                 , isCommentTag
                                 ) where
 
+import Prelude
 import Control.Applicative ((<|>))
 import Control.Arrow (first)
 import Control.Monad (guard, mplus, msum, mzero, unless, void)
@@ -54,7 +56,7 @@ import Data.List (isPrefixOf)
 import Data.List.Split (wordsBy, splitWhen)
 import qualified Data.Map as M
 import Data.Maybe (fromMaybe, isJust, isNothing)
-import Data.Monoid (First (..), (<>))
+import Data.Monoid (First (..))
 import qualified Data.Set as Set
 import Data.Text (Text)
 import qualified Data.Text as T
@@ -508,14 +510,16 @@ pTable = try $ do
                              [Plain _] -> True
                              _         -> False
   let isSimple = all isSinglePlain $ concat (head':rows''')
-  let cols = length $ if null head' then head rows''' else head'
+  let cols = if null head'
+                then maximum (map length rows''')
+                else length head'
   -- add empty cells to short rows
   let addEmpties r = case cols - length r of
                            n | n > 0 -> r <> replicate n mempty
                              | otherwise -> r
   let rows = map addEmpties rows'''
   let aligns = case rows'' of
-                    (cs:_) -> map fst cs
+                    (cs:_) -> take cols $ map fst cs ++ repeat AlignDefault
                     _      -> replicate cols AlignDefault
   let widths = if null widths'
                   then if isSimple
diff --git a/src/Text/Pandoc/Readers/Haddock.hs b/src/Text/Pandoc/Readers/Haddock.hs
index e98c79ed8..967037e4e 100644
--- a/src/Text/Pandoc/Readers/Haddock.hs
+++ b/src/Text/Pandoc/Readers/Haddock.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE CPP #-}
 {- |
    Module      : Text.Pandoc.Readers.Haddock
@@ -14,13 +15,13 @@ module Text.Pandoc.Readers.Haddock
     ( readHaddock
     ) where
 
+import Prelude
 import Control.Monad.Except (throwError)
 import Data.List (intersperse, stripPrefix)
 import Data.Maybe (fromMaybe)
-import Data.Monoid ((<>))
 import Data.Text (Text, unpack)
 import Documentation.Haddock.Parser
-import Documentation.Haddock.Types
+import Documentation.Haddock.Types as H
 import Text.Pandoc.Builder (Blocks, Inlines)
 import qualified Text.Pandoc.Builder as B
 import Text.Pandoc.Class (PandocMonad)
@@ -86,6 +87,20 @@ docHToBlocks d' =
     DocProperty s -> B.codeBlockWith ("",["property","haskell"],[]) (trim s)
     DocExamples es -> mconcat $ map (\e ->
        makeExample ">>>" (exampleExpression e) (exampleResult e)) es
+#if MIN_VERSION_haddock_library(1,5,0)
+    DocTable H.Table{ tableHeaderRows = headerRows
+                    , tableBodyRows = bodyRows
+                    }
+      -> let toCells = map (docHToBlocks . tableCellContents) . tableRowCells
+             (header, body) =
+               if null headerRows
+                  then ([], map toCells bodyRows)
+                  else (toCells (head headerRows),
+                        map toCells (tail headerRows ++ bodyRows))
+             colspecs = replicate (maximum (map length body))
+                             (AlignDefault, 0.0)
+         in  B.table mempty colspecs header body
+#endif
 
   where inlineFallback = B.plain $ docHToInlines False d'
         consolidatePlains = B.fromList . consolidatePlains' . B.toList
@@ -134,6 +149,9 @@ docHToInlines isCode d' =
     DocAName s -> B.spanWith (s,["anchor"],[]) mempty
     DocProperty _ -> mempty
     DocExamples _ -> mempty
+#if MIN_VERSION_haddock_library(1,5,0)
+    DocTable _ -> mempty
+#endif
 
 -- | Create an 'Example', stripping superfluous characters as appropriate
 makeExample :: String -> String -> [String] -> Blocks
diff --git a/src/Text/Pandoc/Readers/JATS.hs b/src/Text/Pandoc/Readers/JATS.hs
index 8158a4511..59af76d23 100644
--- a/src/Text/Pandoc/Readers/JATS.hs
+++ b/src/Text/Pandoc/Readers/JATS.hs
@@ -1,5 +1,37 @@
-{-# LANGUAGE ExplicitForAll, TupleSections #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE TupleSections #-}
+{-
+Copyright (C) 2017-2018 Hamish Mackenzie
+
+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.Readers.JATS
+   Copyright   : Copyright (C) 2017-2018 Hamish Mackenzie
+   License     : GNU GPL, version 2 or above
+
+   Maintainer  : John MacFarlane <jgm@berkeley.edu>
+   Stability   : alpha
+   Portability : portable
+
+Conversion of JATS XML to 'Pandoc' document.
+-}
+
 module Text.Pandoc.Readers.JATS ( readJATS ) where
+import Prelude
 import Control.Monad.State.Strict
 import Data.Char (isDigit, isSpace, toUpper)
 import Data.Default
diff --git a/src/Text/Pandoc/Readers/LaTeX.hs b/src/Text/Pandoc/Readers/LaTeX.hs
index cb70b6403..39dffde76 100644
--- a/src/Text/Pandoc/Readers/LaTeX.hs
+++ b/src/Text/Pandoc/Readers/LaTeX.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE FlexibleInstances     #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE OverloadedStrings     #-}
@@ -42,11 +43,12 @@ module Text.Pandoc.Readers.LaTeX ( readLaTeX,
                                    untokenize
                                  ) where
 
+import Prelude
 import Control.Applicative (many, optional, (<|>))
 import Control.Monad
 import Control.Monad.Except (throwError)
 import Control.Monad.Trans (lift)
-import Data.Char (chr, isAlphaNum, isDigit, isLetter, ord, toLower)
+import Data.Char (chr, isAlphaNum, isDigit, isLetter, ord, toLower, toUpper)
 import Data.Default
 import Data.List (intercalate, isPrefixOf)
 import qualified Data.Map as M
@@ -60,7 +62,7 @@ import Text.Pandoc.BCP47 (Lang (..), renderLang)
 import Text.Pandoc.Builder
 import Text.Pandoc.Class (PandocMonad, PandocPure, getResourcePath, lookupEnv,
                           readFileFromDirs, report, setResourcePath,
-                          setTranslations, translateTerm)
+                          setTranslations, translateTerm, trace)
 import Text.Pandoc.Error (PandocError (PandocMacroLoop, PandocParseError, PandocParsecError))
 import Text.Pandoc.Highlighting (fromListingsLanguage, languagesByExtension)
 import Text.Pandoc.ImageSize (numUnit, showFl)
@@ -74,6 +76,7 @@ import Text.Pandoc.Shared
 import qualified Text.Pandoc.Translations as Translations
 import Text.Pandoc.Walk
 import Text.Parsec.Pos
+import qualified Text.Pandoc.Builder as B
 
 -- for debugging:
 -- import Text.Pandoc.Extensions (getDefaultExtensions)
@@ -161,6 +164,7 @@ data LaTeXState = LaTeXState{ sOptions       :: ReaderOptions
                             , sInTableCell   :: Bool
                             , sLastHeaderNum :: HeaderNum
                             , sLabels        :: M.Map String [Inline]
+                            , sHasChapters   :: Bool
                             , sToggles       :: M.Map String Bool
                             }
      deriving Show
@@ -180,6 +184,7 @@ defaultLaTeXState = LaTeXState{ sOptions       = def
                               , sInTableCell   = False
                               , sLastHeaderNum = HeaderNum []
                               , sLabels        = M.empty
+                              , sHasChapters   = False
                               , sToggles       = M.empty
                               }
 
@@ -237,21 +242,30 @@ withVerbatimMode parser = do
   return result
 
 rawLaTeXParser :: (PandocMonad m, HasMacros s, HasReaderOptions s)
-               => LP m a -> ParserT String s m (a, String)
-rawLaTeXParser parser = do
+               => LP m a -> LP m a -> ParserT String s m (a, String)
+rawLaTeXParser parser valParser = do
   inp <- getInput
   let toks = tokenize "source" $ T.pack inp
   pstate <- getState
-  let lstate = def{ sOptions = extractReaderOptions pstate
-                  , sMacros = extractMacros pstate }
-  let rawparser = (,) <$> withRaw parser <*> getState
-  res <- lift $ runParserT rawparser lstate "chunk" toks
-  case res of
+  let lstate = def{ sOptions = extractReaderOptions pstate }
+  let lstate' = lstate { sMacros = extractMacros pstate }
+  let rawparser = (,) <$> withRaw valParser <*> getState
+  res' <- lift $ runParserT (snd <$> withRaw parser) lstate "chunk" toks
+  case res' of
        Left _    -> mzero
-       Right ((val, raw), st) -> do
-         updateState (updateMacros (sMacros st <>))
-         rawstring <- takeP (T.length (untokenize raw))
-         return (val, rawstring)
+       Right toks' -> do
+         res <- lift $ runParserT (do doMacros 0
+                                      -- retokenize, applying macros
+                                      ts <- many (satisfyTok (const True))
+                                      setInput ts
+                                      rawparser)
+                        lstate' "chunk" toks'
+         case res of
+              Left _    -> mzero
+              Right ((val, raw), st) -> do
+                updateState (updateMacros (sMacros st <>))
+                _ <- takeP (T.length (untokenize toks'))
+                return (val, T.unpack (untokenize raw))
 
 applyMacros :: (PandocMonad m, HasMacros s, HasReaderOptions s)
             => String -> ParserT String s m String
@@ -272,19 +286,18 @@ rawLaTeXBlock = do
   lookAhead (try (char '\\' >> letter))
   -- we don't want to apply newly defined latex macros to their own
   -- definitions:
-  snd <$> rawLaTeXParser macroDef
-  <|> ((snd <$> rawLaTeXParser (environment <|> blockCommand)) >>= applyMacros)
+  snd <$> rawLaTeXParser (environment <|> macroDef <|> blockCommand) blocks
 
 rawLaTeXInline :: (PandocMonad m, HasMacros s, HasReaderOptions s)
                => ParserT String s m String
 rawLaTeXInline = do
   lookAhead (try (char '\\' >> letter))
-  rawLaTeXParser (inlineEnvironment <|> inlineCommand') >>= applyMacros . snd
+  snd <$> rawLaTeXParser (inlineEnvironment <|> inlineCommand') inlines
 
 inlineCommand :: PandocMonad m => ParserT String ParserState m Inlines
 inlineCommand = do
   lookAhead (try (char '\\' >> letter))
-  fst <$> rawLaTeXParser (inlineEnvironment <|> inlineCommand')
+  fst <$> rawLaTeXParser (inlineEnvironment <|> inlineCommand') inlines
 
 tokenize :: SourceName -> Text -> [Tok]
 tokenize sourcename = totoks (initialPos sourcename)
@@ -665,7 +678,7 @@ dosiunitx = do
   skipopts
   value <- tok
   valueprefix <- option "" $ bracketed tok
-  unit <- tok
+  unit <- inlineCommand' <|> tok
   let emptyOr160 "" = ""
       emptyOr160 _  = "\160"
   return . mconcat $ [valueprefix,
@@ -674,6 +687,12 @@ dosiunitx = do
                       emptyOr160 unit,
                       unit]
 
+-- siunitx's \square command
+dosquare :: PandocMonad m => LP m Inlines
+dosquare = do
+  unit <- inlineCommand' <|> tok
+  return . mconcat $ [unit, "\178"]
+
 lit :: String -> LP m Inlines
 lit = pure . str
 
@@ -1034,13 +1053,28 @@ dollarsMath :: PandocMonad m => LP m Inlines
 dollarsMath = do
   symbol '$'
   display <- option False (True <$ symbol '$')
-  contents <- trim . toksToString <$>
-               many (notFollowedBy (symbol '$') >> anyTok)
-  if display
-     then
-       mathDisplay contents <$ try (symbol '$' >> symbol '$')
-   <|> (guard (null contents) >> return (mathInline ""))
-     else mathInline contents <$ symbol '$'
+  (do contents <- try $ T.unpack <$> pDollarsMath 0
+      if display
+         then (mathDisplay contents <$ symbol '$')
+         else return $ mathInline contents)
+   <|> (guard display >> return (mathInline ""))
+
+-- Int is number of embedded groupings
+pDollarsMath :: PandocMonad m => Int -> LP m Text
+pDollarsMath n = do
+  Tok _ toktype t <- anyTok
+  case toktype of
+       Symbol | t == "$"
+              , n == 0 -> return mempty
+              | t == "\\" -> do
+                  Tok _ _ t' <- anyTok
+                  return (t <> t')
+              | t == "{" -> (t <>) <$> pDollarsMath (n+1)
+              | t == "}" ->
+                if n > 0
+                then (t <>) <$> pDollarsMath (n-1)
+                else mzero
+       _ -> (t <>) <$> pDollarsMath n
 
 -- citations
 
@@ -1161,7 +1195,7 @@ singleChar = try $ do
      else return $ Tok pos toktype t
 
 opt :: PandocMonad m => LP m Inlines
-opt = bracketed inline
+opt = bracketed inline <|> (str . T.unpack <$> rawopt)
 
 rawopt :: PandocMonad m => LP m Text
 rawopt = do
@@ -1304,6 +1338,12 @@ inlineCommands = M.union inlineLanguageCommands $ M.fromList
   , ("slshape", extractSpaces emph <$> inlines)
   , ("scshape", extractSpaces smallcaps <$> inlines)
   , ("bfseries", extractSpaces strong <$> inlines)
+  , ("MakeUppercase", makeUppercase <$> tok)
+  , ("MakeTextUppercase", makeUppercase <$> tok) -- textcase
+  , ("uppercase", makeUppercase <$> tok)
+  , ("MakeLowercase", makeLowercase <$> tok)
+  , ("MakeTextLowercase", makeLowercase <$> tok)
+  , ("lowercase", makeLowercase <$> tok)
   , ("/", pure mempty) -- italic correction
   , ("aa", lit "å")
   , ("AA", lit "Å")
@@ -1467,6 +1507,13 @@ inlineCommands = M.union inlineLanguageCommands $ M.fromList
   , ("acsp", doAcronymPlural "abbrv")
   -- siuntix
   , ("SI", dosiunitx)
+  -- units of siuntix
+  , ("celsius", lit "°C")
+  , ("degreeCelsius", lit "°C")
+  , ("gram", lit "g")
+  , ("meter", lit "m")
+  , ("milli", lit "m")
+  , ("square", dosquare)
   -- hyphenat
   , ("bshyp", lit "\\\173")
   , ("fshyp", lit "/\173")
@@ -1497,6 +1544,16 @@ inlineCommands = M.union inlineLanguageCommands $ M.fromList
   , ("foreignlanguage", foreignlanguage)
   ]
 
+makeUppercase :: Inlines -> Inlines
+makeUppercase = fromList . walk (alterStr (map toUpper)) . toList
+
+makeLowercase :: Inlines -> Inlines
+makeLowercase = fromList . walk (alterStr (map toLower)) . toList
+
+alterStr :: (String -> String) -> Inline -> Inline
+alterStr f (Str xs) = Str (f xs)
+alterStr _ x = x
+
 foreignlanguage :: PandocMonad m => LP m Inlines
 foreignlanguage = do
   babelLang <- T.unpack . untokenize <$> braced
@@ -1669,6 +1726,9 @@ treatAsBlock = Set.fromList
    , "clearpage"
    , "pagebreak"
    , "titleformat"
+   , "listoffigures"
+   , "listoftables"
+   , "write"
    ]
 
 isInlineCommand :: Text -> Bool
@@ -1968,9 +2028,13 @@ section starred (ident, classes, kvs) lvl = do
           try (spaces >> controlSeq "label"
                >> spaces >> toksToString <$> braced)
   let classes' = if starred then "unnumbered" : classes else classes
+  when (lvl == 0) $
+    updateState $ \st -> st{ sHasChapters = True }
   unless starred $ do
     hn <- sLastHeaderNum <$> getState
-    let num = incrementHeaderNum lvl hn
+    hasChapters <- sHasChapters <$> getState
+    let lvl' = lvl + if hasChapters then 1 else 0
+    let num = incrementHeaderNum lvl' hn
     updateState $ \st -> st{ sLastHeaderNum = num }
     updateState $ \st -> st{ sLabels = M.insert lab
                             [Str (renderHeaderNum num)]
@@ -2095,6 +2159,7 @@ environments :: PandocMonad m => M.Map Text (LP m Blocks)
 environments = M.fromList
    [ ("document", env "document" blocks)
    , ("abstract", mempty <$ (env "abstract" blocks >>= addMeta "abstract"))
+   , ("sloppypar", env "sloppypar" $ blocks)
    , ("letter", env "letter" letterContents)
    , ("minipage", env "minipage" $
           skipopts *> spaces *> optional braced *> spaces *> blocks)
@@ -2126,19 +2191,6 @@ environments = M.fromList
                        codeBlockWith attr <$> verbEnv "lstlisting")
    , ("minted", minted)
    , ("obeylines", obeylines)
-   , ("displaymath", mathEnvWith para Nothing "displaymath")
-   , ("equation", mathEnvWith para Nothing "equation")
-   , ("equation*", mathEnvWith para Nothing "equation*")
-   , ("gather", mathEnvWith para (Just "gathered") "gather")
-   , ("gather*", mathEnvWith para (Just "gathered") "gather*")
-   , ("multline", mathEnvWith para (Just "gathered") "multline")
-   , ("multline*", mathEnvWith para (Just "gathered") "multline*")
-   , ("eqnarray", mathEnvWith para (Just "aligned") "eqnarray")
-   , ("eqnarray*", mathEnvWith para (Just "aligned") "eqnarray*")
-   , ("align", mathEnvWith para (Just "aligned") "align")
-   , ("align*", mathEnvWith para (Just "aligned") "align*")
-   , ("alignat", mathEnvWith para (Just "aligned") "alignat")
-   , ("alignat*", mathEnvWith para (Just "aligned") "alignat*")
    , ("tikzpicture", rawVerbEnv "tikzpicture")
    -- etoolbox
    , ("ifstrequal", ifstrequal)
@@ -2149,11 +2201,14 @@ environments = M.fromList
    ]
 
 environment :: PandocMonad m => LP m Blocks
-environment = do
+environment = try $ do
   controlSeq "begin"
   name <- untokenize <$> braced
-  M.findWithDefault mzero name environments
-    <|> rawEnv name
+  M.findWithDefault mzero name environments <|>
+    if M.member name (inlineEnvironments
+                       :: M.Map Text (LP PandocPure Inlines))
+       then mzero
+       else rawEnv name
 
 env :: PandocMonad m => Text -> LP m a -> LP m a
 env name p = p <* end_ name
@@ -2532,13 +2587,16 @@ addTableCaption = walkM go
 
 
 block :: PandocMonad m => LP m Blocks
-block = (mempty <$ spaces1)
+block = do
+  res <- (mempty <$ spaces1)
     <|> environment
     <|> include
     <|> macroDef
     <|> blockCommand
     <|> paragraph
     <|> grouped block
+  trace (take 60 $ show $ B.toList res)
+  return res
 
 blocks :: PandocMonad m => LP m Blocks
 blocks = mconcat <$> many block
diff --git a/src/Text/Pandoc/Readers/LaTeX/Types.hs b/src/Text/Pandoc/Readers/LaTeX/Types.hs
index c9cbaa9b9..fa832114b 100644
--- a/src/Text/Pandoc/Readers/LaTeX/Types.hs
+++ b/src/Text/Pandoc/Readers/LaTeX/Types.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2017-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -34,6 +35,7 @@ module Text.Pandoc.Readers.LaTeX.Types ( Tok(..)
                                        , SourcePos
                                        )
 where
+import Prelude
 import Data.Text (Text)
 import Text.Parsec.Pos (SourcePos)
 
diff --git a/src/Text/Pandoc/Readers/Markdown.hs b/src/Text/Pandoc/Readers/Markdown.hs
index 14cf73de4..156b2b622 100644
--- a/src/Text/Pandoc/Readers/Markdown.hs
+++ b/src/Text/Pandoc/Readers/Markdown.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE RelaxedPolyRec      #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
@@ -32,6 +33,7 @@ Conversion of markdown-formatted plain text to 'Pandoc' document.
 -}
 module Text.Pandoc.Readers.Markdown ( readMarkdown ) where
 
+import Prelude
 import Control.Monad
 import Control.Monad.Except (throwError)
 import Data.Char (isAlphaNum, isPunctuation, isSpace, toLower)
@@ -39,7 +41,6 @@ import qualified Data.HashMap.Strict as H
 import Data.List (intercalate, sortBy, transpose, elemIndex)
 import qualified Data.Map as M
 import Data.Maybe
-import Data.Monoid ((<>))
 import Data.Ord (comparing)
 import Data.Scientific (base10Exponent, coefficient)
 import qualified Data.Set as Set
@@ -162,7 +163,7 @@ inlinesInBalancedBrackets =
         stripBracket xs = if last xs == ']' then init xs else xs
         go :: PandocMonad m => Int -> MarkdownParser m ()
         go 0 = return ()
-        go openBrackets = 
+        go openBrackets =
           (() <$ (escapedChar <|>
                 code <|>
                 rawHtmlInline <|>
@@ -673,6 +674,8 @@ keyValAttr = try $ do
   char '='
   val <- enclosed (char '"') (char '"') litChar
      <|> enclosed (char '\'') (char '\'') litChar
+     <|> ("" <$ try (string "\"\""))
+     <|> ("" <$ try (string "''"))
      <|> many (escapedChar' <|> noneOf " \t\n\r}")
   return $ \(id',cs,kvs) ->
     case key of
@@ -909,6 +912,17 @@ listContinuation continuationIndent = try $ do
   blanks <- many blankline
   return $ concat (x:xs) ++ blanks
 
+-- Variant of blanklines that doesn't require blank lines
+-- before a fence or eof.
+blanklines' :: PandocMonad m => MarkdownParser m [Char]
+blanklines' = blanklines <|> try checkDivCloser
+  where checkDivCloser = do
+          guardEnabled Ext_fenced_divs
+          divLevel <- stateFencedDivLevel <$> getState
+          guard (divLevel >= 1)
+          lookAhead divFenceEnd
+          return ""
+
 notFollowedByDivCloser :: PandocMonad m => MarkdownParser m ()
 notFollowedByDivCloser =
   guardDisabled Ext_fenced_divs <|>
@@ -1250,7 +1264,7 @@ alignType strLst len =
 
 -- Parse a table footer - dashed lines followed by blank line.
 tableFooter :: PandocMonad m => MarkdownParser m String
-tableFooter = try $ skipNonindentSpaces >> many1 (dashedLine '-') >> blanklines
+tableFooter = try $ skipNonindentSpaces >> many1 (dashedLine '-') >> blanklines'
 
 -- Parse a table separator - dashed line.
 tableSep :: PandocMonad m => MarkdownParser m Char
@@ -1261,7 +1275,7 @@ rawTableLine :: PandocMonad m
              => [Int]
              -> MarkdownParser m [String]
 rawTableLine indices = do
-  notFollowedBy' (blanklines <|> tableFooter)
+  notFollowedBy' (blanklines' <|> tableFooter)
   line <- many1Till anyChar newline
   return $ map trim $ tail $
            splitStringByIndices (init indices) line
@@ -1299,7 +1313,7 @@ simpleTable headless = do
   (aligns, _widths, heads', lines') <-
        tableWith (simpleTableHeader headless) tableLine
               (return ())
-              (if headless then tableFooter else tableFooter <|> blanklines)
+              (if headless then tableFooter else tableFooter <|> blanklines')
   -- Simple tables get 0s for relative column widths (i.e., use default)
   return (aligns, replicate (length aligns) 0, heads', lines')
 
@@ -1327,11 +1341,16 @@ multilineTableHeader headless = try $ do
   newline
   let (lengths, lines') = unzip dashes
   let indices  = scanl (+) (length initSp) lines'
+  -- compensate for the fact that intercolumn spaces are
+  -- not included in the last index:
+  let indices' = case reverse indices of
+                      []     -> []
+                      (x:xs) -> reverse (x+1:xs)
   rawHeadsList <- if headless
                      then fmap (map (:[]) . tail .
-                              splitStringByIndices (init indices)) $ lookAhead anyLine
+                              splitStringByIndices (init indices')) $ lookAhead anyLine
                      else return $ transpose $ map
-                           (tail . splitStringByIndices (init indices))
+                           (tail . splitStringByIndices (init indices'))
                            rawContent
   let aligns   = zipWith alignType rawHeadsList lengths
   let rawHeads = if headless
@@ -1339,7 +1358,7 @@ multilineTableHeader headless = try $ do
                     else map (unlines . map trim) rawHeadsList
   heads <- fmap sequence $
             mapM ((parseFromString' (mconcat <$> many plain)).trim) rawHeads
-  return (heads, aligns, indices)
+  return (heads, aligns, indices')
 
 -- Parse a grid table:  starts with row of '-' on top, then header
 -- (which may be grid), then the rows,
@@ -2145,7 +2164,6 @@ singleQuoted = try $ do
 doubleQuoted :: PandocMonad m => MarkdownParser m (F Inlines)
 doubleQuoted = try $ do
   doubleQuoteStart
-  contents <- mconcat <$> many (try $ notFollowedBy doubleQuoteEnd >> inline)
-  withQuoteContext InDoubleQuote (doubleQuoteEnd >> return
-       (fmap B.doubleQuoted . trimInlinesF $ contents))
-   <|> return (return (B.str "\8220") <> contents)
+  withQuoteContext InDoubleQuote $
+    fmap B.doubleQuoted . trimInlinesF . mconcat <$>
+      many1Till inline doubleQuoteEnd
diff --git a/src/Text/Pandoc/Readers/MediaWiki.hs b/src/Text/Pandoc/Readers/MediaWiki.hs
index c19ef2f46..764b57f18 100644
--- a/src/Text/Pandoc/Readers/MediaWiki.hs
+++ b/src/Text/Pandoc/Readers/MediaWiki.hs
@@ -1,6 +1,5 @@
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE RelaxedPolyRec       #-}
-{-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE RelaxedPolyRec #-}
 -- RelaxedPolyRec needed for inlinesBetween on GHC < 7
 {-
   Copyright (C) 2012-2018 John MacFarlane <jgm@berkeley.edu>
@@ -38,6 +37,7 @@ _ parse templates?
 -}
 module Text.Pandoc.Readers.MediaWiki ( readMediaWiki ) where
 
+import Prelude
 import Control.Monad
 import Control.Monad.Except (throwError)
 import Data.Char (isDigit, isSpace)
@@ -45,7 +45,6 @@ import qualified Data.Foldable as F
 import Data.List (intercalate, intersperse, isPrefixOf)
 import qualified Data.Map as M
 import Data.Maybe (fromMaybe, maybeToList)
-import Data.Monoid ((<>))
 import Data.Sequence (ViewL (..), viewl, (<|))
 import qualified Data.Set as Set
 import Data.Text (Text, unpack)
@@ -231,7 +230,8 @@ para = do
 table :: PandocMonad m => MWParser m Blocks
 table = do
   tableStart
-  styles <- option [] parseAttrs
+  styles <- option [] $
+               parseAttrs <* skipMany spaceChar <* optional (char '|')
   skipMany spaceChar
   optional blanklines
   let tableWidth = case lookup "width" styles of
@@ -282,17 +282,29 @@ rowsep = try $ guardColumnOne *> skipSpaces *> sym "|-" <*
 
 cellsep :: PandocMonad m => MWParser m ()
 cellsep = try $ do
+  col <- sourceColumn <$> getPosition
   skipSpaces
-  (char '|' *> notFollowedBy (oneOf "-}+") *> optional (char '|'))
-    <|> (char '!' *> optional (char '!'))
+  let pipeSep = do
+        char '|'
+        notFollowedBy (oneOf "-}+")
+        if col == 1
+           then optional (char '|')
+           else void (char '|')
+  let exclSep = do
+        char '!'
+        if col == 1
+           then optional (char '!')
+           else void (char '!')
+  pipeSep <|> exclSep
 
 tableCaption :: PandocMonad m => MWParser m Inlines
 tableCaption = try $ do
   guardColumnOne
   skipSpaces
   sym "|+"
-  optional (try $ parseAttr *> skipSpaces *> char '|' *> skipSpaces)
-  (trimInlines . mconcat) <$> many (notFollowedBy (cellsep <|> rowsep) *> inline)
+  optional (try $ parseAttr *> skipSpaces *> char '|' *> blanklines)
+  (trimInlines . mconcat) <$>
+    many (notFollowedBy (cellsep <|> rowsep) *> inline)
 
 tableRow :: PandocMonad m => MWParser m [((Alignment, Double), Blocks)]
 tableRow = try $ skipMany htmlComment *> many tableCell
diff --git a/src/Text/Pandoc/Readers/Muse.hs b/src/Text/Pandoc/Readers/Muse.hs
index 1fb37aa16..fe6b3698c 100644
--- a/src/Text/Pandoc/Readers/Muse.hs
+++ b/src/Text/Pandoc/Readers/Muse.hs
@@ -1,4 +1,6 @@
-{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TupleSections #-}
 {-
   Copyright (C) 2017-2018 Alexander Krotov <ilabdsf@gmail.com>
 
@@ -34,13 +36,14 @@ TODO:
 - Org tables
 - table.el tables
 - Images with attributes (floating and width)
-- Citations and <biblio>
-- <play> environment
+- <cite> tag
 -}
 module Text.Pandoc.Readers.Muse (readMuse) where
 
+import Prelude
 import Control.Monad
 import Control.Monad.Except (throwError)
+import Data.Bifunctor
 import Data.Char (isLetter)
 import Data.Default
 import Data.List (stripPrefix, intercalate)
@@ -81,24 +84,21 @@ data MuseState = MuseState { museMeta :: F Meta -- ^ Document metadata
                            , museLastStrPos :: Maybe SourcePos -- ^ Position after last str parsed
                            , museLogMessages :: [LogMessage]
                            , museNotes :: M.Map String (SourcePos, F Blocks)
-                           , museInLink :: Bool
-                           , museInPara :: Bool
+                           , museInLink :: Bool -- ^ True when parsing a link description to avoid nested links
+                           , museInPara :: Bool -- ^ True when looking for a paragraph terminator
                            }
 
 instance Default MuseState where
-  def = defaultMuseState
-
-defaultMuseState :: MuseState
-defaultMuseState = MuseState { museMeta = return nullMeta
-                             , museOptions = def
-                             , museHeaders = M.empty
-                             , museIdentifierList = Set.empty
-                             , museLastStrPos = Nothing
-                             , museLogMessages = []
-                             , museNotes = M.empty
-                             , museInLink = False
-                             , museInPara = False
-                             }
+  def = MuseState { museMeta = return nullMeta
+                  , museOptions = def
+                  , museHeaders = M.empty
+                  , museIdentifierList = Set.empty
+                  , museLastStrPos = Nothing
+                  , museLogMessages = []
+                  , museNotes = M.empty
+                  , museInLink = False
+                  , museInPara = False
+                  }
 
 type MuseParser = ParserT String MuseState
 
@@ -121,10 +121,7 @@ instance HasLogMessages MuseState where
   addLogMessage m s = s{ museLogMessages = m : museLogMessages s }
   getLogMessages = reverse . museLogMessages
 
---
--- main parser
---
-
+-- | Parse Muse document
 parseMuse :: PandocMonad m => MuseParser m Pandoc
 parseMuse = do
   many directive
@@ -136,44 +133,7 @@ parseMuse = do
   reportLogMessages
   return doc
 
---
--- utility functions
---
-
-eol :: Stream s m Char => ParserT s st m ()
-eol = void newline <|> eof
-
-htmlElement :: PandocMonad m => String -> MuseParser m (Attr, String)
-htmlElement tag = try $ do
-  (TagOpen _ attr, _) <- htmlTag (~== TagOpen tag [])
-  content <- manyTill anyChar endtag
-  return (htmlAttrToPandoc attr, content)
-  where
-    endtag = void $ htmlTag (~== TagClose tag)
-
-htmlBlock :: PandocMonad m => String -> MuseParser m (Attr, String)
-htmlBlock tag = try $ do
-  res <- htmlElement tag
-  manyTill spaceChar eol
-  return res
-
-htmlAttrToPandoc :: [Attribute String] -> Attr
-htmlAttrToPandoc attrs = (ident, classes, keyvals)
-  where
-    ident   = fromMaybe "" $ lookup "id" attrs
-    classes = maybe [] words $ lookup "class" attrs
-    keyvals = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"]
-
-parseHtmlContent :: PandocMonad m
-                 => String -> MuseParser m (Attr, F Blocks)
-parseHtmlContent tag = do
-  (TagOpen _ attr, _) <- htmlTag (~== TagOpen tag [])
-  manyTill spaceChar eol
-  content <- parseBlocksTill (manyTill spaceChar endtag)
-  manyTill spaceChar eol -- closing tag must be followed by optional whitespace and newline
-  return (htmlAttrToPandoc attr, content)
-  where
-    endtag = void $ htmlTag (~== TagClose tag)
+-- * Utility functions
 
 commonPrefix :: String -> String -> String
 commonPrefix _ [] = []
@@ -182,6 +142,22 @@ commonPrefix (x:xs) (y:ys)
   | x == y    = x : commonPrefix xs ys
   | otherwise = []
 
+-- | Trim up to one newline from the beginning of the string.
+lchop :: String -> String
+lchop s = case s of
+                    '\n':ss -> ss
+                    _       -> s
+
+-- | Trim up to one newline from the end of the string.
+rchop :: String -> String
+rchop = reverse . lchop . reverse
+
+dropSpacePrefix :: [String] -> [String]
+dropSpacePrefix lns =
+  map (drop maxIndent) lns
+  where flns = filter (not . all (== ' ')) lns
+        maxIndent = if null flns then maximum (map length lns) else length $ takeWhile (== ' ') $ foldl1 commonPrefix flns
+
 atStart :: PandocMonad m => MuseParser m a -> MuseParser m a
 atStart p = do
   pos <- getPosition
@@ -189,24 +165,67 @@ atStart p = do
   guard $ museLastStrPos st /= Just pos
   p
 
+-- * Parsers
+
+-- | Parse end-of-line, which can be either a newline or end-of-file.
+eol :: Stream s m Char => ParserT s st m ()
+eol = void newline <|> eof
+
 someUntil :: (Stream s m t)
           => ParserT s u m a
           -> ParserT s u m b
           -> ParserT s u m ([a], b)
-someUntil p end = do
-  first <- p
-  (rest, e) <- manyUntil p end
-  return (first:rest, e)
+someUntil p end = first <$> ((:) <$> p) <*> manyUntil p end
 
---
--- directive parsers
---
+-- ** HTML parsers
+
+-- | Parse HTML tag, returning its attributes and literal contents.
+htmlElement :: PandocMonad m
+            => String -- ^ Tag name
+            -> MuseParser m (Attr, String)
+htmlElement tag = try $ do
+  (TagOpen _ attr, _) <- htmlTag (~== TagOpen tag [])
+  content <- manyTill anyChar endtag
+  return (htmlAttrToPandoc attr, content)
+  where
+    endtag = void $ htmlTag (~== TagClose tag)
+
+htmlBlock :: PandocMonad m
+          => String -- ^ Tag name
+          -> MuseParser m (Attr, String)
+htmlBlock tag = try $ do
+  many spaceChar
+  res <- htmlElement tag
+  manyTill spaceChar eol
+  return res
+
+-- | Convert HTML attributes to Pandoc 'Attr'
+htmlAttrToPandoc :: [Attribute String] -> Attr
+htmlAttrToPandoc attrs = (ident, classes, keyvals)
+  where
+    ident   = fromMaybe "" $ lookup "id" attrs
+    classes = maybe [] words $ lookup "class" attrs
+    keyvals = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"]
+
+parseHtmlContent :: PandocMonad m
+                 => String -- ^ Tag name
+                 -> MuseParser m (Attr, F Blocks)
+parseHtmlContent tag = try $ do
+  many spaceChar
+  pos <- getPosition
+  (TagOpen _ attr, _) <- htmlTag (~== TagOpen tag [])
+  manyTill spaceChar eol
+  content <- parseBlocksTill $ try $ count (sourceColumn pos - 1) spaceChar >> endtag
+  manyTill spaceChar eol -- closing tag must be followed by optional whitespace and newline
+  return (htmlAttrToPandoc attr, content)
+  where
+    endtag = void $ htmlTag (~== TagClose tag)
+
+-- ** Directive parsers
 
 -- While not documented, Emacs Muse allows "-" in directive name
 parseDirectiveKey :: PandocMonad m => MuseParser m String
-parseDirectiveKey = do
-  char '#'
-  many (letter <|> char '-')
+parseDirectiveKey = char '#' *> many (letter <|> char '-')
 
 parseEmacsDirective :: PandocMonad m => MuseParser m (String, F Inlines)
 parseEmacsDirective = do
@@ -233,55 +252,42 @@ directive = do
   where translateKey "cover" = "cover-image"
         translateKey x = x
 
---
--- block parsers
---
+-- ** Block parsers
 
 parseBlocks :: PandocMonad m
             => MuseParser m (F Blocks)
 parseBlocks =
-  try parseEnd <|>
-  try blockStart <|>
-  try listStart <|>
-  try paraStart
+  try (parseEnd <|>
+       blockStart <|>
+       listStart <|>
+       paraStart)
   where
     parseEnd = mempty <$ eof
-    blockStart = do first <- header <|> blockElements <|> emacsNoteBlock
-                    rest <- parseBlocks
-                    return $ first B.<> rest
+    blockStart = ((B.<>) <$> (emacsHeading <|> blockElements <|> emacsNoteBlock)
+                         <*> parseBlocks) <|> (uncurry (B.<>) <$> amuseHeadingUntil parseBlocks)
     listStart = do
       updateState (\st -> st { museInPara = False })
-      (first, rest) <- anyListUntil parseBlocks <|> amuseNoteBlockUntil parseBlocks
-      return $ first B.<> rest
+      uncurry (B.<>) <$> (anyListUntil parseBlocks <|> amuseNoteBlockUntil parseBlocks)
     paraStart = do
       indent <- length <$> many spaceChar
-      (first, rest) <- paraUntil parseBlocks
-      let first' = if indent >= 2 && indent < 6 then B.blockQuote <$> first else first
-      return $ first' B.<> rest
+      uncurry (B.<>) . first (p indent) <$> paraUntil parseBlocks
+      where p indent = if indent >= 2 && indent < 6 then fmap B.blockQuote else id
 
 parseBlocksTill :: PandocMonad m
                 => MuseParser m a
                 -> MuseParser m (F Blocks)
 parseBlocksTill end =
-  try parseEnd <|>
-  try blockStart <|>
-  try listStart <|>
-  try paraStart
+  try (parseEnd <|>
+       blockStart <|>
+       listStart <|>
+       paraStart)
   where
     parseEnd = mempty <$ end
-    blockStart = do first <- blockElements
-                    rest <- continuation
-                    return $ first B.<> rest
+    blockStart = (B.<>) <$> blockElements <*> continuation
     listStart = do
       updateState (\st -> st { museInPara = False })
-      (first, e) <- anyListUntil ((Left <$> end) <|> (Right <$> continuation))
-      case e of
-        Left _ -> return first
-        Right rest -> return $ first B.<> rest
-    paraStart = do (first, e) <- paraUntil ((Left <$> end) <|> (Right <$> continuation))
-                   case e of
-                     Left _ -> return first
-                     Right rest -> return $ first B.<> rest
+      uncurry (B.<>) <$> anyListUntil (parseEnd <|> continuation)
+    paraStart = uncurry (B.<>) <$> paraUntil (parseEnd <|> continuation)
     continuation = parseBlocksTill end
 
 listItemContentsUntil :: PandocMonad m
@@ -294,24 +300,17 @@ listItemContentsUntil col pre end =
   try listStart <|>
   try paraStart
   where
-    parsePre = do e <- pre
-                  return (mempty, e)
-    parseEnd = do e <- end
-                  return (mempty, e)
+    parsePre = (mempty,) <$> pre
+    parseEnd = (mempty,) <$> end
     paraStart = do
-      (first, e) <- paraUntil ((Left <$> pre) <|> (Right <$> continuation) <|> (Left <$> end))
-      case e of
-        Left ee -> return (first, ee)
-        Right (rest, ee) -> return (first B.<> rest, ee)
-    blockStart = do first <- blockElements
-                    (rest, e) <- parsePre <|> continuation <|> parseEnd
-                    return (first B.<> rest, e)
+      (f, (r, e)) <- paraUntil (parsePre <|> continuation <|> parseEnd)
+      return (f B.<> r, e)
+    blockStart = first <$> ((B.<>) <$> blockElements)
+                       <*> (parsePre <|> continuation <|> parseEnd)
     listStart = do
       updateState (\st -> st { museInPara = False })
-      (first, e) <- anyListUntil ((Left <$> pre) <|> (Right <$> continuation) <|> (Left <$> end))
-      case e of
-        Left ee -> return (first, ee)
-        Right (rest, ee) -> return (first B.<> rest, ee)
+      (f, (r, e)) <- anyListUntil (parsePre <|> continuation <|> parseEnd)
+      return (f B.<> r, e)
     continuation = try $ do blank <- optionMaybe blankline
                             skipMany blankline
                             indentWith col
@@ -338,19 +337,24 @@ blockElements = do
          , rightTag
          , quoteTag
          , divTag
+         , biblioTag
+         , playTag
          , verseTag
          , lineBlock
          , table
          , commentTag
          ]
 
+-- | Parse a line comment, starting with @;@ in the first column.
 comment :: PandocMonad m => MuseParser m (F Blocks)
 comment = try $ do
+  getPosition >>= \pos -> guard (sourceColumn pos == 1)
   char ';'
   optional (spaceChar >> many (noneOf "\n"))
   eol
   return mempty
 
+-- | Parse a horizontal rule, consisting of 4 or more @\'-\'@ characters.
 separator :: PandocMonad m => MuseParser m (F Blocks)
 separator = try $ do
   string "----"
@@ -359,17 +363,37 @@ separator = try $ do
   eol
   return $ return B.horizontalRule
 
-header :: PandocMonad m => MuseParser m (F Blocks)
-header = try $ do
+-- | Parse a single-line heading.
+emacsHeading :: PandocMonad m => MuseParser m (F Blocks)
+emacsHeading = try $ do
+  guardDisabled Ext_amuse
+  anchorId <- option "" $ try (parseAnchor <* manyTill spaceChar eol)
   getPosition >>= \pos -> guard (sourceColumn pos == 1)
   level <- fmap length $ many1 $ char '*'
   guard $ level <= 5
   spaceChar
   content <- trimInlinesF . mconcat <$> manyTill inline eol
-  anchorId <- option "" parseAnchor
   attr <- registerHeader (anchorId, [], []) (runF content def)
   return $ B.headerWith attr level <$> content
 
+-- | Parse a multi-line heading.
+-- It is a Text::Amuse extension, Emacs Muse does not allow heading to span multiple lines.
+amuseHeadingUntil :: PandocMonad m
+                  => MuseParser m a -- ^ Terminator parser
+                  -> MuseParser m (F Blocks, a)
+amuseHeadingUntil end = try $ do
+  guardEnabled Ext_amuse
+  anchorId <- option "" $ try (parseAnchor <* manyTill spaceChar eol)
+  getPosition >>= \pos -> guard (sourceColumn pos == 1)
+  level <- fmap length $ many1 $ char '*'
+  guard $ level <= 5
+  spaceChar
+  (content, e) <- paraContentsUntil end
+  attr <- registerHeader (anchorId, [], []) (runF content def)
+  return (B.headerWith attr level <$> content, e)
+
+-- | Parse an example between @{{{@ and @}}}@.
+-- It is an Amusewiki extension influenced by Creole wiki, as described in @Text::Amuse@ documentation.
 example :: PandocMonad m => MuseParser m (F Blocks)
 example = try $ do
   string "{{{"
@@ -377,57 +401,63 @@ example = try $ do
   contents <- manyTill anyChar $ try (optional blankline >> string "}}}")
   return $ return $ B.codeBlock contents
 
--- Trim up to one newline from the beginning and the end,
--- in case opening and/or closing tags are on separate lines.
-chop :: String -> String
-chop = lchop . rchop
-
-lchop :: String -> String
-lchop s = case s of
-                    '\n':ss -> ss
-                    _       -> s
-
-rchop :: String -> String
-rchop = reverse . lchop . reverse
-
-dropSpacePrefix :: [String] -> [String]
-dropSpacePrefix lns =
-  map (drop maxIndent) lns
-  where flns = filter (not . all (== ' ')) lns
-        maxIndent = if null flns then maximum (map length lns) else length $ takeWhile (== ' ') $ foldl1 commonPrefix flns
-
+-- | Parse an @\<example>@ tag.
 exampleTag :: PandocMonad m => MuseParser m (F Blocks)
 exampleTag = try $ do
-  many spaceChar
   (attr, contents) <- htmlBlock "example"
   return $ return $ B.codeBlockWith attr $ rchop $ intercalate "\n" $ dropSpacePrefix $ splitOn "\n" $ lchop contents
 
+-- | Parse a @\<literal>@ tag as a raw block.
+-- For 'RawInline' @\<literal>@ parser, see 'inlineLiteralTag'.
 literalTag :: PandocMonad m => MuseParser m (F Blocks)
-literalTag = do
-  guardDisabled Ext_amuse -- Text::Amuse does not support <literal>
-  (return . rawBlock) <$> htmlBlock "literal"
+literalTag = try $ do
+  many spaceChar
+  (TagOpen _ attr, _) <- htmlTag (~== TagOpen "literal" [])
+  manyTill spaceChar eol
+  content <- manyTill anyChar endtag
+  manyTill spaceChar eol
+  return $ return $ rawBlock (htmlAttrToPandoc attr, content)
   where
+    endtag = void $ htmlTag (~== TagClose "literal")
     -- FIXME: Emacs Muse inserts <literal> without style into all output formats, but we assume HTML
     format (_, _, kvs)        = fromMaybe "html" $ lookup "style" kvs
-    rawBlock (attrs, content) = B.rawBlock (format attrs) $ chop content
+    rawBlock (attrs, content) = B.rawBlock (format attrs) $ rchop $ intercalate "\n" $ dropSpacePrefix $ splitOn "\n" $ lchop content
 
--- <center> tag is ignored
+-- | Parse @\<center>@ tag.
+-- Currently it is ignored as Pandoc cannot represent centered blocks.
 centerTag :: PandocMonad m => MuseParser m (F Blocks)
 centerTag = snd <$> parseHtmlContent "center"
 
--- <right> tag is ignored
+-- | Parse @\<right>@ tag.
+-- Currently it is ignored as Pandoc cannot represent centered blocks.
 rightTag :: PandocMonad m => MuseParser m (F Blocks)
 rightTag = snd <$> parseHtmlContent "right"
 
+-- | Parse @\<quote>@ tag.
 quoteTag :: PandocMonad m => MuseParser m (F Blocks)
 quoteTag = fmap B.blockQuote . snd <$> parseHtmlContent "quote"
 
--- <div> tag is supported by Emacs Muse, but not Amusewiki 2.025
+-- | Parse @\<div>@ tag.
+-- @\<div>@ tag is supported by Emacs Muse, but not Amusewiki 2.025.
 divTag :: PandocMonad m => MuseParser m (F Blocks)
 divTag = do
   (attrs, content) <- parseHtmlContent "div"
   return $ B.divWith attrs <$> content
 
+-- | Parse @\<biblio>@ tag, the result is the same as @\<div class="biblio">@.
+-- @\<biblio>@ tag is supported only in Text::Amuse mode.
+biblioTag :: PandocMonad m => MuseParser m (F Blocks)
+biblioTag = do
+  guardEnabled Ext_amuse
+  fmap (B.divWith ("", ["biblio"], [])) . snd <$> parseHtmlContent "biblio"
+
+-- | Parse @\<play>@ tag, the result is the same as @\<div class="play">@.
+-- @\<play>@ tag is supported only in Text::Amuse mode.
+playTag :: PandocMonad m => MuseParser m (F Blocks)
+playTag = do
+  guardEnabled Ext_amuse
+  fmap (B.divWith ("", ["play"], [])) . snd <$> parseHtmlContent "play"
+
 verseLine :: PandocMonad m => MuseParser m (F Inlines)
 verseLine = do
   indent <- (B.str <$> many1 (char ' ' >> pure '\160')) <|> pure mempty
@@ -439,32 +469,39 @@ verseLines = do
   lns <- many verseLine
   return $ B.lineBlock <$> sequence lns
 
+-- | Parse @\<verse>@ tag.
 verseTag :: PandocMonad m => MuseParser m (F Blocks)
 verseTag = do
   (_, content) <- htmlBlock "verse"
   parseFromString verseLines (intercalate "\n" $ dropSpacePrefix $ splitOn "\n" $ lchop content)
 
+-- | Parse @\<comment>@ tag.
 commentTag :: PandocMonad m => MuseParser m (F Blocks)
 commentTag = htmlBlock "comment" >> return mempty
 
--- Indented paragraph is either center, right or quote
+-- | Parse paragraph contents.
+paraContentsUntil :: PandocMonad m
+                  => MuseParser m a -- ^ Terminator parser
+                  -> MuseParser m (F Inlines, a)
+paraContentsUntil end = do
+  updateState (\st -> st { museInPara = True })
+  (l, e) <- someUntil inline $ try (manyTill spaceChar eol >> end)
+  updateState (\st -> st { museInPara = False })
+  return (trimInlinesF $ mconcat l, e)
+
+-- | Parse a paragraph.
 paraUntil :: PandocMonad m
-          => MuseParser m a
+          => MuseParser m a -- ^ Terminator parser
           -> MuseParser m (F Blocks, a)
 paraUntil end = do
   state <- getState
   guard $ not $ museInPara state
-  setState $ state{ museInPara = True }
-  (l, e) <- someUntil inline $ try (manyTill spaceChar eol >> end)
-  updateState (\st -> st { museInPara = False })
-  return (fmap B.para $ trimInlinesF $ mconcat l, e)
+  first (fmap B.para) <$> paraContentsUntil end
 
 noteMarker :: PandocMonad m => MuseParser m String
 noteMarker = try $ do
   char '['
-  first <- oneOf "123456789"
-  rest <- manyTill digit (char ']')
-  return $ first:rest
+  (:) <$> oneOf "123456789" <*> manyTill digit (char ']')
 
 -- Amusewiki version of note
 -- Parsing is similar to list item, except that note marker is used instead of list marker
@@ -473,14 +510,13 @@ amuseNoteBlockUntil :: PandocMonad m
                     -> MuseParser m (F Blocks, a)
 amuseNoteBlockUntil end = try $ do
   guardEnabled Ext_amuse
-  pos <- getPosition
   ref <- noteMarker <* spaceChar
+  pos <- getPosition
   updateState (\st -> st { museInPara = False })
-  (content, e) <- listItemContentsUntil (sourceColumn pos) (fail "x") end
+  (content, e) <- listItemContentsUntil (sourceColumn pos - 1) (fail "x") end
   oldnotes <- museNotes <$> getState
-  case M.lookup ref oldnotes of
-    Just _  -> logMessage $ DuplicateNoteReference ref pos
-    Nothing -> return ()
+  when (M.member ref oldnotes)
+    (logMessage $ DuplicateNoteReference ref pos)
   updateState $ \s -> s{ museNotes = M.insert ref (pos, content) oldnotes }
   return (mempty, e)
 
@@ -493,9 +529,8 @@ emacsNoteBlock = try $ do
   ref <- noteMarker <* skipSpaces
   content <- mconcat <$> blocksTillNote
   oldnotes <- museNotes <$> getState
-  case M.lookup ref oldnotes of
-    Just _  -> logMessage $ DuplicateNoteReference ref pos
-    Nothing -> return ()
+  when (M.member ref oldnotes)
+    (logMessage $ DuplicateNoteReference ref pos)
   updateState $ \s -> s{ museNotes = M.insert ref (pos, content) oldnotes }
   return mempty
   where
@@ -509,9 +544,10 @@ emacsNoteBlock = try $ do
 lineVerseLine :: PandocMonad m => MuseParser m (F Inlines)
 lineVerseLine = try $ do
   string "> "
-  indent <- B.str <$> many (char ' ' >> pure '\160')
+  indent <- many (char ' ' >> pure '\160')
+  let indentEl = if null indent then mempty else B.str indent
   rest <- manyTill (choice inlineList) eol
-  return $ trimInlinesF $ mconcat (pure indent : rest)
+  return $ trimInlinesF $ mconcat (pure indentEl : rest)
 
 blanklineVerseLine :: PandocMonad m => MuseParser m (F Inlines)
 blanklineVerseLine = try $ do
@@ -519,29 +555,28 @@ blanklineVerseLine = try $ do
   blankline
   pure mempty
 
+-- | Parse a line block indicated by @\'>\'@ characters.
 lineBlock :: PandocMonad m => MuseParser m (F Blocks)
 lineBlock = try $ do
+  many spaceChar
   col <- sourceColumn <$> getPosition
   lns <- (blanklineVerseLine <|> lineVerseLine) `sepBy1'` try (indentWith (col - 1))
   return $ B.lineBlock <$> sequence lns
 
---
--- lists
---
+-- *** List parsers
 
 bulletListItemsUntil :: PandocMonad m
-                     => Int
-                     -> MuseParser m a
+                     => Int -- ^ Indentation
+                     -> MuseParser m a -- ^ Terminator parser
                      -> MuseParser m ([F Blocks], a)
 bulletListItemsUntil indent end = try $ do
   char '-'
   void spaceChar <|> lookAhead eol
   updateState (\st -> st { museInPara = False })
-  (x, e) <- listItemContentsUntil (indent + 2) (Right <$> try (optional blankline >> indentWith indent >> bulletListItemsUntil indent end)) (Left <$> end)
-  case e of
-    Left ee -> return ([x], ee)
-    Right (xs, ee) -> return (x:xs, ee)
+  (x, (xs, e)) <- listItemContentsUntil (indent + 2) (try (optional blankline >> indentWith indent >> bulletListItemsUntil indent end)) (([],) <$> end)
+  return (x:xs, e)
 
+-- | Parse a bullet list.
 bulletListUntil :: PandocMonad m
                 => MuseParser m a
                 -> MuseParser m (F Blocks, a)
@@ -563,16 +598,15 @@ anyMuseOrderedListMarker = do
 museOrderedListMarker :: PandocMonad m
                       => ListNumberStyle
                       -> MuseParser m Int
-museOrderedListMarker style = do
-  (_, start) <- case style of
-                  Decimal    -> decimal
-                  UpperRoman -> upperRoman
-                  LowerRoman -> lowerRoman
-                  UpperAlpha -> upperAlpha
-                  LowerAlpha -> lowerAlpha
-                  _          -> fail "Unhandled case"
-  char '.'
-  return start
+museOrderedListMarker style =
+  snd <$> p <* char '.'
+  where p = case style of
+              Decimal    -> decimal
+              UpperRoman -> upperRoman
+              LowerRoman -> lowerRoman
+              UpperAlpha -> upperAlpha
+              LowerAlpha -> lowerAlpha
+              _          -> fail "Unhandled case"
 
 orderedListItemsUntil :: PandocMonad m
                       => Int
@@ -586,11 +620,10 @@ orderedListItemsUntil indent style end =
       pos <- getPosition
       void spaceChar <|> lookAhead eol
       updateState (\st -> st { museInPara = False })
-      (x, e) <- listItemContentsUntil (sourceColumn pos) (Right <$> try (optionMaybe blankline >> indentWith indent >> museOrderedListMarker style >> continuation)) (Left <$> end)
-      case e of
-        Left ee -> return ([x], ee)
-        Right (xs, ee) -> return (x:xs, ee)
+      (x, (xs, e)) <- listItemContentsUntil (sourceColumn pos) (try (optional blankline >> indentWith indent >> museOrderedListMarker style >> continuation)) (([],) <$> end)
+      return (x:xs, e)
 
+-- | Parse an ordered list.
 orderedListUntil :: PandocMonad m
                  => MuseParser m a
                  -> MuseParser m (F Blocks, a)
@@ -611,10 +644,8 @@ descriptionsUntil :: PandocMonad m
 descriptionsUntil indent end = do
   void spaceChar <|> lookAhead eol
   updateState (\st -> st { museInPara = False })
-  (x, e) <- listItemContentsUntil indent (Right <$> try (optional blankline >> indentWith indent >> manyTill spaceChar (string "::") >> descriptionsUntil indent end)) (Left <$> end)
-  case e of
-    Right (xs, ee) -> return (x:xs, ee)
-    Left ee -> return ([x], ee)
+  (x, (xs, e)) <- listItemContentsUntil indent (try (optional blankline >> indentWith indent >> manyTill spaceChar (string "::") >> descriptionsUntil indent end)) (([],) <$> end)
+  return (x:xs, e)
 
 definitionListItemsUntil :: PandocMonad m
                          => Int
@@ -625,37 +656,31 @@ definitionListItemsUntil indent end =
   where
     continuation = try $ do
       pos <- getPosition
-      term <- trimInlinesF . mconcat <$> manyTill (choice inlineList) (string "::")
-      (x, e) <- descriptionsUntil (sourceColumn pos) ((Right <$> try (optional blankline >> indentWith indent >> continuation)) <|> (Left <$> end))
-      let xx = do
-            term' <- term
-            x' <- sequence x
-            return (term', x')
-      case e of
-        Left ee -> return ([xx], ee)
-        Right (xs, ee) -> return (xx:xs, ee)
+      term <- trimInlinesF . mconcat <$> manyTill (choice inlineList) (try $ string "::")
+      (x, (xs, e)) <- descriptionsUntil (sourceColumn pos) (try (optional blankline >> indentWith indent >> continuation) <|> (([],) <$> end))
+      let xx = (,) <$> term <*> sequence x
+      return (xx:xs, e)
 
+-- | Parse a definition list.
 definitionListUntil :: PandocMonad m
-                    => MuseParser m a
+                    => MuseParser m a -- ^ Terminator parser
                     -> MuseParser m (F Blocks, a)
 definitionListUntil end = try $ do
   many spaceChar
   pos <- getPosition
   let indent = sourceColumn pos - 1
   guardDisabled Ext_amuse <|> guard (indent /= 0) -- Initial space is required by Amusewiki, but not Emacs Muse
-  (items, e) <- definitionListItemsUntil indent end
-  return (B.definitionList <$> sequence items, e)
+  first (fmap B.definitionList . sequence) <$> definitionListItemsUntil indent end
 
 anyListUntil :: PandocMonad m
-             => MuseParser m a
+             => MuseParser m a -- ^ Terminator parser
              -> MuseParser m (F Blocks, a)
 anyListUntil end =
   bulletListUntil end <|> orderedListUntil end <|> definitionListUntil end
 
---
--- tables
---
+-- *** Table parsers
 
+-- | Internal Muse table representation.
 data MuseTable = MuseTable
   { museTableCaption :: Inlines
   , museTableHeaders :: [[Blocks]]
@@ -663,10 +688,10 @@ data MuseTable = MuseTable
   , museTableFooters :: [[Blocks]]
   }
 
-data MuseTableElement = MuseHeaderRow (F [Blocks])
-                      | MuseBodyRow   (F [Blocks])
-                      | MuseFooterRow (F [Blocks])
-                      | MuseCaption (F Inlines)
+data MuseTableElement = MuseHeaderRow [Blocks]
+                      | MuseBodyRow [Blocks]
+                      | MuseFooterRow [Blocks]
+                      | MuseCaption Inlines
 
 museToPandocTable :: MuseTable -> Blocks
 museToPandocTable (MuseTable caption headers body footers) =
@@ -676,73 +701,66 @@ museToPandocTable (MuseTable caption headers body footers) =
         headRow = if null headers then [] else head headers
         rows = (if null headers then [] else tail headers) ++ body ++ footers
 
-museAppendElement :: MuseTable
-                  -> MuseTableElement
-                  -> F MuseTable
-museAppendElement tbl element =
+museAppendElement :: MuseTableElement
+                  -> MuseTable
+                  -> MuseTable
+museAppendElement element tbl =
   case element of
-    MuseHeaderRow row -> do
-      row' <- row
-      return tbl{ museTableHeaders = museTableHeaders tbl ++ [row'] }
-    MuseBodyRow row -> do
-      row' <- row
-      return tbl{ museTableRows = museTableRows tbl ++ [row'] }
-    MuseFooterRow row-> do
-      row' <- row
-      return tbl{ museTableFooters = museTableFooters tbl ++ [row'] }
-    MuseCaption inlines -> do
-      inlines' <- inlines
-      return tbl{ museTableCaption = inlines' }
+    MuseHeaderRow row -> tbl{ museTableHeaders = row : museTableHeaders tbl }
+    MuseBodyRow row -> tbl{ museTableRows = row : museTableRows tbl }
+    MuseFooterRow row -> tbl{ museTableFooters = row : museTableFooters tbl }
+    MuseCaption inlines -> tbl{ museTableCaption = inlines }
 
 tableCell :: PandocMonad m => MuseParser m (F Blocks)
 tableCell = try $ fmap B.plain . trimInlinesF . mconcat <$> manyTill inline (lookAhead cellEnd)
   where cellEnd = try $ void (many1 spaceChar >> char '|') <|> eol
 
-tableElements :: PandocMonad m => MuseParser m [MuseTableElement]
-tableElements = tableParseElement `sepEndBy1` eol
+tableElements :: PandocMonad m => MuseParser m (F [MuseTableElement])
+tableElements = sequence <$> (tableParseElement `sepEndBy1` eol)
 
-elementsToTable :: [MuseTableElement] -> F MuseTable
-elementsToTable = foldM museAppendElement emptyTable
+elementsToTable :: [MuseTableElement] -> MuseTable
+elementsToTable = foldr museAppendElement emptyTable
   where emptyTable = MuseTable mempty mempty mempty mempty
 
+-- | Parse a table.
 table :: PandocMonad m => MuseParser m (F Blocks)
-table = try $ do
-  rows <- tableElements
-  let tbl = elementsToTable rows
-  let pandocTbl = museToPandocTable <$> tbl :: F Blocks
-  return pandocTbl
+table = try $ fmap (museToPandocTable . elementsToTable) <$> tableElements
 
-tableParseElement :: PandocMonad m => MuseParser m MuseTableElement
+tableParseElement :: PandocMonad m => MuseParser m (F MuseTableElement)
 tableParseElement = tableParseHeader
                 <|> tableParseBody
                 <|> tableParseFooter
                 <|> tableParseCaption
 
-tableParseRow :: PandocMonad m => Int -> MuseParser m (F [Blocks])
+tableParseRow :: PandocMonad m
+              => Int -- ^ Number of separator characters
+              -> MuseParser m (F [Blocks])
 tableParseRow n = try $ do
   fields <- tableCell `sepBy2` fieldSep
   return $ sequence fields
     where p `sepBy2` sep = (:) <$> p <*> many1 (sep >> p)
           fieldSep = many1 spaceChar >> count n (char '|') >> (void (many1 spaceChar) <|> void (lookAhead newline))
 
-tableParseHeader :: PandocMonad m => MuseParser m MuseTableElement
-tableParseHeader = MuseHeaderRow <$> tableParseRow 2
+-- | Parse a table header row.
+tableParseHeader :: PandocMonad m => MuseParser m (F MuseTableElement)
+tableParseHeader = fmap MuseHeaderRow <$> tableParseRow 2
 
-tableParseBody :: PandocMonad m => MuseParser m MuseTableElement
-tableParseBody = MuseBodyRow <$> tableParseRow 1
+-- | Parse a table body row.
+tableParseBody :: PandocMonad m => MuseParser m (F MuseTableElement)
+tableParseBody = fmap MuseBodyRow <$> tableParseRow 1
 
-tableParseFooter :: PandocMonad m => MuseParser m MuseTableElement
-tableParseFooter = MuseFooterRow <$> tableParseRow 3
+-- | Parse a table footer row.
+tableParseFooter :: PandocMonad m => MuseParser m (F MuseTableElement)
+tableParseFooter = fmap MuseFooterRow <$> tableParseRow 3
 
-tableParseCaption :: PandocMonad m => MuseParser m MuseTableElement
+-- | Parse table caption.
+tableParseCaption :: PandocMonad m => MuseParser m (F MuseTableElement)
 tableParseCaption = try $ do
   many spaceChar
   string "|+"
-  MuseCaption <$> (trimInlinesF . mconcat <$> many1Till inline (string "+|"))
+  fmap MuseCaption <$> (trimInlinesF . mconcat <$> many1Till inline (string "+|"))
 
---
--- inline parsers
---
+-- ** Inline parsers
 
 inlineList :: PandocMonad m => [MuseParser m (F Inlines)]
 inlineList = [ whitespace
@@ -758,10 +776,12 @@ inlineList = [ whitespace
              , subscriptTag
              , strikeoutTag
              , verbatimTag
+             , classTag
              , nbsp
              , link
              , code
              , codeTag
+             , mathTag
              , inlineLiteralTag
              , str
              , symbol
@@ -770,28 +790,30 @@ inlineList = [ whitespace
 inline :: PandocMonad m => MuseParser m (F Inlines)
 inline = endline <|> choice inlineList <?> "inline"
 
+-- | Parse a soft break.
 endline :: PandocMonad m => MuseParser m (F Inlines)
 endline = try $ do
   newline
   notFollowedBy blankline
-  returnF B.softbreak
+  return $ return B.softbreak
 
 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
-  return $ first:rest
+  (:) <$> letter <*> many (letter <|> digit <|> char '-')
 
 anchor :: PandocMonad m => MuseParser m (F Inlines)
 anchor = try $ do
   anchorId <- parseAnchor
+  skipMany spaceChar <|> void newline
   return $ return $ B.spanWith (anchorId, [], []) mempty
 
+-- | Parse a footnote reference.
 footnote :: PandocMonad m => MuseParser m (F Inlines)
 footnote = try $ do
+  inLink <- museInLink <$> getState
+  guard $ not inLink
   ref <- noteMarker
   return $ do
     notes <- asksF museNotes
@@ -799,7 +821,7 @@ footnote = try $ do
       Nothing -> return $ B.str $ "[" ++ ref ++ "]"
       Just (_pos, contents) -> do
         st <- askF
-        let contents' = runF contents st { museNotes = M.empty }
+        let contents' = runF contents st { museNotes = M.delete ref (museNotes st) }
         return $ B.note contents'
 
 whitespace :: PandocMonad m => MuseParser m (F Inlines)
@@ -807,6 +829,7 @@ whitespace = try $ do
   skipMany1 spaceChar
   return $ return B.space
 
+-- | Parse @\<br>@ tag.
 br :: PandocMonad m => MuseParser m (F Inlines)
 br = try $ do
   string "<br>"
@@ -822,49 +845,68 @@ enclosedInlines :: (PandocMonad m, Show a, Show b)
 enclosedInlines start end = try $
   trimInlinesF . mconcat <$> (enclosed (atStart start) end inline <* notFollowedBy (satisfy isLetter))
 
+-- | Parse an inline tag, such as @\<em>@ and @\<strong>@.
 inlineTag :: PandocMonad m
-          => (Inlines -> Inlines)
-          -> String
+          => String -- ^ Tag name
           -> MuseParser m (F Inlines)
-inlineTag f tag = try $ do
+inlineTag tag = try $ do
   htmlTag (~== TagOpen tag [])
-  res <- manyTill inline (void $ htmlTag (~== TagClose tag))
-  return $ f <$> mconcat res
-
-strongTag :: PandocMonad m => MuseParser m (F Inlines)
-strongTag = inlineTag B.strong "strong"
+  mconcat <$> manyTill inline (void $ htmlTag (~== TagClose tag))
 
+-- | Parse strong inline markup, indicated by @**@.
 strong :: PandocMonad m => MuseParser m (F Inlines)
 strong = fmap B.strong <$> emphasisBetween (string "**")
 
+-- | Parse emphasis inline markup, indicated by @*@.
 emph :: PandocMonad m => MuseParser m (F Inlines)
 emph = fmap B.emph <$> emphasisBetween (char '*')
 
+-- | Parse underline inline markup, indicated by @_@.
+-- Supported only in Emacs Muse mode, not Text::Amuse.
 underlined :: PandocMonad m => MuseParser m (F Inlines)
 underlined = do
   guardDisabled Ext_amuse -- Supported only by Emacs Muse
   fmap underlineSpan <$> emphasisBetween (char '_')
 
+-- | Parse @\<strong>@ tag.
+strongTag :: PandocMonad m => MuseParser m (F Inlines)
+strongTag = fmap B.strong <$> inlineTag "strong"
+
+-- | Parse @\<em>@ tag.
 emphTag :: PandocMonad m => MuseParser m (F Inlines)
-emphTag = inlineTag B.emph "em"
+emphTag = fmap B.emph <$> inlineTag "em"
 
+-- | Parse @\<sup>@ tag.
 superscriptTag :: PandocMonad m => MuseParser m (F Inlines)
-superscriptTag = inlineTag B.superscript "sup"
+superscriptTag = fmap B.superscript <$> inlineTag "sup"
 
+-- | Parse @\<sub>@ tag.
 subscriptTag :: PandocMonad m => MuseParser m (F Inlines)
-subscriptTag = inlineTag B.subscript "sub"
+subscriptTag = fmap B.subscript <$> inlineTag "sub"
 
+-- | Parse @\<del>@ tag.
 strikeoutTag :: PandocMonad m => MuseParser m (F Inlines)
-strikeoutTag = inlineTag B.strikeout "del"
+strikeoutTag = fmap B.strikeout <$> inlineTag "del"
 
+-- | Parse @\<verbatim>@ tag.
 verbatimTag :: PandocMonad m => MuseParser m (F Inlines)
 verbatimTag = return . B.text . snd <$> htmlElement "verbatim"
 
+-- | Parse @\<class>@ tag.
+classTag :: PandocMonad m => MuseParser m (F Inlines)
+classTag = do
+  (TagOpen _ attrs, _) <- htmlTag (~== TagOpen "class" [])
+  res <- manyTill inline (void $ htmlTag (~== TagClose "class"))
+  let classes = maybe [] words $ lookup "name" attrs
+  return $ B.spanWith ("", classes, []) <$> mconcat res
+
+-- | Parse "~~" as nonbreaking space.
 nbsp :: PandocMonad m => MuseParser m (F Inlines)
 nbsp = try $ do
   string "~~"
   return $ return $ B.str "\160"
 
+-- | Parse code markup, indicated by @\'=\'@ characters.
 code :: PandocMonad m => MuseParser m (F Inlines)
 code = try $ do
   atStart $ char '='
@@ -875,14 +917,18 @@ code = try $ do
   notFollowedBy $ satisfy isLetter
   return $ return $ B.code contents
 
+-- | Parse @\<code>@ tag.
 codeTag :: PandocMonad m => MuseParser m (F Inlines)
-codeTag = do
-  (attrs, content) <- htmlElement "code"
-  return $ return $ B.codeWith attrs content
+codeTag = return . uncurry B.codeWith <$> htmlElement "code"
 
+-- | Parse @\<math>@ tag.
+-- @\<math>@ tag is an Emacs Muse extension enabled by @(require 'muse-latex2png)@
+mathTag :: PandocMonad m => MuseParser m (F Inlines)
+mathTag = return . B.math . snd <$> htmlElement "math"
+
+-- | Parse inline @\<literal>@ tag as a raw inline.
 inlineLiteralTag :: PandocMonad m => MuseParser m (F Inlines)
-inlineLiteralTag = do
-  guardDisabled Ext_amuse -- Text::Amuse does not support <literal>
+inlineLiteralTag =
   (return . rawInline) <$> htmlElement "literal"
   where
     -- FIXME: Emacs Muse inserts <literal> without style into all output formats, but we assume HTML
@@ -890,39 +936,35 @@ inlineLiteralTag = do
     rawInline (attrs, content) = B.rawInline (format attrs) content
 
 str :: PandocMonad m => MuseParser m (F Inlines)
-str = do
-  result <- many1 alphaNum
-  updateLastStrPos
-  return $ return $ B.str result
+str = return . B.str <$> many1 alphaNum <* updateLastStrPos
 
 symbol :: PandocMonad m => MuseParser m (F Inlines)
 symbol = return . B.str <$> count 1 nonspaceChar
 
+-- | Parse a link or image.
 link :: PandocMonad m => MuseParser m (F Inlines)
 link = try $ do
   st <- getState
   guard $ not $ museInLink st
   setState $ st{ museInLink = True }
-  (url, title, content) <- linkText
+  (url, content) <- linkText
   updateState (\state -> state { museInLink = False })
   return $ case stripPrefix "URL:" url of
              Nothing -> if isImageUrl url
-                          then B.image url title <$> fromMaybe (return mempty) content
-                          else B.link url title <$> fromMaybe (return $ B.str url) content
-             Just url' -> B.link url' title <$> fromMaybe (return $ B.str url') content
+                          then B.image url "" <$> fromMaybe (return mempty) content
+                          else B.link url "" <$> fromMaybe (return $ B.str url) content
+             Just url' -> B.link url' "" <$> fromMaybe (return $ B.str url') content
     where -- Taken from muse-image-regexp defined in Emacs Muse file lisp/muse-regexps.el
           imageExtensions = [".eps", ".gif", ".jpg", ".jpeg", ".pbm", ".png", ".tiff", ".xbm", ".xpm"]
           isImageUrl = (`elem` imageExtensions) . takeExtension
 
 linkContent :: PandocMonad m => MuseParser m (F Inlines)
-linkContent = do
-  char '['
-  trimInlinesF . mconcat <$> many1Till inline (string "]")
+linkContent = char '[' >> trimInlinesF . mconcat <$> manyTill inline (string "]")
 
-linkText :: PandocMonad m => MuseParser m (String, String, Maybe (F Inlines))
+linkText :: PandocMonad m => MuseParser m (String, Maybe (F Inlines))
 linkText = do
   string "[["
-  url <- many1Till anyChar $ char ']'
+  url <- manyTill anyChar $ char ']'
   content <- optionMaybe linkContent
   char ']'
-  return (url, "", content)
+  return (url, content)
diff --git a/src/Text/Pandoc/Readers/Native.hs b/src/Text/Pandoc/Readers/Native.hs
index 88f6bfe8f..ef200aa19 100644
--- a/src/Text/Pandoc/Readers/Native.hs
+++ b/src/Text/Pandoc/Readers/Native.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2011-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -30,6 +31,7 @@ Conversion of a string representation of a pandoc type (@Pandoc@,
 -}
 module Text.Pandoc.Readers.Native ( readNative ) where
 
+import Prelude
 import Text.Pandoc.Definition
 import Text.Pandoc.Options (ReaderOptions)
 import Text.Pandoc.Shared (safeRead)
diff --git a/src/Text/Pandoc/Readers/OPML.hs b/src/Text/Pandoc/Readers/OPML.hs
index 82266748f..1a489ab94 100644
--- a/src/Text/Pandoc/Readers/OPML.hs
+++ b/src/Text/Pandoc/Readers/OPML.hs
@@ -1,5 +1,36 @@
-{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-
+Copyright (C) 2013-2018 John MacFarlane <jgm@berkeley.edu>
+
+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.Readers.OPML
+   Copyright   : Copyright (C) 2013-2018 John MacFarlane
+   License     : GNU GPL, version 2 or above
+
+   Maintainer  : John MacFarlane <jgm@berkeley.edu>
+   Stability   : alpha
+   Portability : portable
+
+Conversion of OPML to 'Pandoc' document.
+-}
+
 module Text.Pandoc.Readers.OPML ( readOPML ) where
+import Prelude
 import Control.Monad.State.Strict
 import Data.Char (toUpper)
 import Data.Default
diff --git a/src/Text/Pandoc/Readers/Odt.hs b/src/Text/Pandoc/Readers/Odt.hs
index 875c18a85..30016e444 100644
--- a/src/Text/Pandoc/Readers/Odt.hs
+++ b/src/Text/Pandoc/Readers/Odt.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE PatternGuards #-}
 
 {-
@@ -32,6 +33,7 @@ Entry point to the odt reader.
 
 module Text.Pandoc.Readers.Odt ( readOdt ) where
 
+import Prelude
 import Codec.Archive.Zip
 import qualified Text.XML.Light as XML
 
diff --git a/src/Text/Pandoc/Readers/Odt/Arrows/State.hs b/src/Text/Pandoc/Readers/Odt/Arrows/State.hs
index 73bed545e..971442613 100644
--- a/src/Text/Pandoc/Readers/Odt/Arrows/State.hs
+++ b/src/Text/Pandoc/Readers/Odt/Arrows/State.hs
@@ -1,4 +1,4 @@
-
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE TupleSections     #-}
 {-
@@ -38,15 +38,13 @@ faster and easier to implement this way.
 
 module Text.Pandoc.Readers.Odt.Arrows.State where
 
+import Prelude
 import Prelude hiding (foldl, foldr)
 
 import Control.Arrow
 import qualified Control.Category as Cat
 import Control.Monad
 
-import Data.Foldable
-import Data.Monoid
-
 import Text.Pandoc.Readers.Odt.Arrows.Utils
 import Text.Pandoc.Readers.Odt.Generic.Fallible
 
@@ -131,7 +129,7 @@ withSubStateF' unlift a = ArrowState go
 -- and one with any function.
 foldS :: (Foldable f, Monoid m) => ArrowState s x m -> ArrowState s (f x) m
 foldS a = ArrowState $ \(s,f) -> foldr a' (s,mempty) f
-  where a' x (s',m) = second (m <>)  $ runArrowState a (s',x)
+  where a' x (s',m) = second (mappend m)  $ runArrowState a (s',x)
 
 -- | Fold a state arrow through something 'Foldable'. Collect the results in a
 -- 'MonadPlus'.
diff --git a/src/Text/Pandoc/Readers/Odt/Arrows/Utils.hs b/src/Text/Pandoc/Readers/Odt/Arrows/Utils.hs
index ef8b2d18a..d3db3a9e2 100644
--- a/src/Text/Pandoc/Readers/Odt/Arrows/Utils.hs
+++ b/src/Text/Pandoc/Readers/Odt/Arrows/Utils.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2015 Martin Linnemann <theCodingMarlin@googlemail.com>
 
@@ -39,6 +40,7 @@ with an equivalent return value.
 -- We export everything
 module Text.Pandoc.Readers.Odt.Arrows.Utils where
 
+import Prelude
 import Control.Arrow
 import Control.Monad (join)
 
@@ -61,13 +63,13 @@ and6 :: (Arrow a)
      => a b c0->a b c1->a b c2->a b c3->a b c4->a b c5
      -> a b (c0,c1,c2,c3,c4,c5      )
 
-and3 a b c           = (and2 a b          ) &&& c
+and3 a b c           = and2 a b &&& c
                        >>^ \((z,y          ) , x) -> (z,y,x          )
-and4 a b c d         = (and3 a b c        ) &&& d
+and4 a b c d         = and3 a b c &&& d
                        >>^ \((z,y,x        ) , w) -> (z,y,x,w        )
-and5 a b c d e       = (and4 a b c d      ) &&& e
+and5 a b c d e       = and4 a b c d &&& e
                        >>^ \((z,y,x,w      ) , v) -> (z,y,x,w,v      )
-and6 a b c d e f     = (and5 a b c d e    ) &&& f
+and6 a b c d e f     = and5 a b c d e &&& f
                        >>^ \((z,y,x,w,v    ) , u) -> (z,y,x,w,v,u    )
 
 liftA2 :: (Arrow a) => (x -> y -> z) -> a b x -> a b y -> a b z
diff --git a/src/Text/Pandoc/Readers/Odt/Base.hs b/src/Text/Pandoc/Readers/Odt/Base.hs
index 51c2da788..5e731aefe 100644
--- a/src/Text/Pandoc/Readers/Odt/Base.hs
+++ b/src/Text/Pandoc/Readers/Odt/Base.hs
@@ -1,5 +1,3 @@
-
-
 {-
 Copyright (C) 2015 Martin Linnemann <theCodingMarlin@googlemail.com>
 
diff --git a/src/Text/Pandoc/Readers/Odt/ContentReader.hs b/src/Text/Pandoc/Readers/Odt/ContentReader.hs
index 380f16c66..78881914d 100644
--- a/src/Text/Pandoc/Readers/Odt/ContentReader.hs
+++ b/src/Text/Pandoc/Readers/Odt/ContentReader.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE Arrows          #-}
 {-# LANGUAGE PatternGuards   #-}
 {-# LANGUAGE RecordWildCards #-}
@@ -39,6 +40,7 @@ module Text.Pandoc.Readers.Odt.ContentReader
 , read_body
 ) where
 
+import Prelude
 import Control.Applicative hiding (liftA, liftA2, liftA3)
 import Control.Arrow
 
@@ -520,7 +522,7 @@ matchingElement :: (Monoid e)
 matchingElement ns name reader = (ns, name, asResultAccumulator reader)
   where
    asResultAccumulator :: (ArrowChoice a, Monoid m) => a m m -> a m (Fallible m)
-   asResultAccumulator a = liftAsSuccess $ keepingTheValue a >>% (<>)
+   asResultAccumulator a = liftAsSuccess $ keepingTheValue a >>% mappend
 
 --
 matchChildContent'   :: (Monoid result)
@@ -554,7 +556,7 @@ read_plain_text =  fst ^&&& read_plain_text' >>% recover
     read_plain_text' =      (     second ( arr extractText )
                               >>^ spreadChoice >>?! second text
                             )
-                       >>?% (<>)
+                       >>?% mappend
     --
     extractText     :: XML.Content -> Fallible String
     extractText (XML.Text cData) = succeedWith (XML.cdData cData)
@@ -565,7 +567,7 @@ read_text_seq  = matchingElement NsText "sequence"
                  $ matchChildContent [] read_plain_text
 
 
--- specifically. I honor that, although the current implementation of '(<>)'
+-- specifically. I honor that, although the current implementation of 'mappend'
 -- for 'Inlines' in "Text.Pandoc.Builder" will collapse them again.
 -- The rational is to be prepared for future modifications.
 read_spaces      :: InlineMatcher
diff --git a/src/Text/Pandoc/Readers/Odt/Generic/Fallible.hs b/src/Text/Pandoc/Readers/Odt/Generic/Fallible.hs
index f8ea5c605..1fb5b5477 100644
--- a/src/Text/Pandoc/Readers/Odt/Generic/Fallible.hs
+++ b/src/Text/Pandoc/Readers/Odt/Generic/Fallible.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 
 
 {-
@@ -38,8 +39,7 @@ compatible instances of "ArrowChoice".
 
 -- We export everything
 module Text.Pandoc.Readers.Odt.Generic.Fallible where
-
-import Data.Monoid ((<>))
+import Prelude
 
 -- | Default for now. Will probably become a class at some point.
 type Failure = ()
@@ -90,7 +90,7 @@ collapseEither (Right (Right x)) = Right x
 -- (possibly combined) non-error. If both values represent an error, an error
 -- is returned.
 chooseMax :: (Monoid a, Monoid b) => Either a b -> Either a b -> Either a b
-chooseMax = chooseMaxWith (<>)
+chooseMax = chooseMaxWith mappend
 
 -- | If either of the values represents a non-error, the result is a
 -- (possibly combined) non-error. If both values represent an error, an error
@@ -100,7 +100,7 @@ chooseMaxWith :: (Monoid a) => (b -> b -> b)
                             -> Either a b
                             -> Either a b
 chooseMaxWith (><) (Right a) (Right b) = Right $ a >< b
-chooseMaxWith  _   (Left  a) (Left  b) = Left  $ a <> b
+chooseMaxWith  _   (Left  a) (Left  b) = Left  $ a `mappend` b
 chooseMaxWith  _   (Right a)     _     = Right a
 chooseMaxWith  _       _     (Right b) = Right b
 
diff --git a/src/Text/Pandoc/Readers/Odt/Generic/Namespaces.hs b/src/Text/Pandoc/Readers/Odt/Generic/Namespaces.hs
index 82ae3e20e..6d96897aa 100644
--- a/src/Text/Pandoc/Readers/Odt/Generic/Namespaces.hs
+++ b/src/Text/Pandoc/Readers/Odt/Generic/Namespaces.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2015 Martin Linnemann <theCodingMarlin@googlemail.com>
 
@@ -31,6 +32,7 @@ typesafe Haskell namespace identifiers and unsafe "real world" namespaces.
 
 module Text.Pandoc.Readers.Odt.Generic.Namespaces where
 
+import Prelude
 import qualified Data.Map as M
 
 --
diff --git a/src/Text/Pandoc/Readers/Odt/Generic/SetMap.hs b/src/Text/Pandoc/Readers/Odt/Generic/SetMap.hs
index afd7d616c..b0543b6d1 100644
--- a/src/Text/Pandoc/Readers/Odt/Generic/SetMap.hs
+++ b/src/Text/Pandoc/Readers/Odt/Generic/SetMap.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2015 Martin Linnemann <theCodingMarlin@googlemail.com>
 
@@ -30,6 +31,7 @@ A map of values to sets of values.
 
 module Text.Pandoc.Readers.Odt.Generic.SetMap where
 
+import Prelude
 import qualified Data.Map as M
 import qualified Data.Set as S
 
diff --git a/src/Text/Pandoc/Readers/Odt/Generic/Utils.hs b/src/Text/Pandoc/Readers/Odt/Generic/Utils.hs
index 556517259..616d9290b 100644
--- a/src/Text/Pandoc/Readers/Odt/Generic/Utils.hs
+++ b/src/Text/Pandoc/Readers/Odt/Generic/Utils.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 
 
 {-# LANGUAGE TypeOperators #-}
@@ -51,6 +52,7 @@ module Text.Pandoc.Readers.Odt.Generic.Utils
 , composition
 ) where
 
+import Prelude
 import Control.Category (Category, (<<<), (>>>))
 import qualified Control.Category as Cat (id)
 import Control.Monad (msum)
diff --git a/src/Text/Pandoc/Readers/Odt/Generic/XMLConverter.hs b/src/Text/Pandoc/Readers/Odt/Generic/XMLConverter.hs
index 428048427..81392e16b 100644
--- a/src/Text/Pandoc/Readers/Odt/Generic/XMLConverter.hs
+++ b/src/Text/Pandoc/Readers/Odt/Generic/XMLConverter.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE Arrows          #-}
 {-# LANGUAGE TupleSections   #-}
 {-# LANGUAGE GADTs           #-}
@@ -67,6 +68,7 @@ module Text.Pandoc.Readers.Odt.Generic.XMLConverter
 , matchContent
 ) where
 
+import Prelude
 import           Control.Applicative  hiding ( liftA, liftA2 )
 import           Control.Monad               ( MonadPlus )
 import           Control.Arrow
diff --git a/src/Text/Pandoc/Readers/Odt/Namespaces.hs b/src/Text/Pandoc/Readers/Odt/Namespaces.hs
index 92e12931d..28865182f 100644
--- a/src/Text/Pandoc/Readers/Odt/Namespaces.hs
+++ b/src/Text/Pandoc/Readers/Odt/Namespaces.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2015 Martin Linnemann <theCodingMarlin@googlemail.com>
 
@@ -31,6 +32,7 @@ Namespaces used in odt files.
 module Text.Pandoc.Readers.Odt.Namespaces ( Namespace (..)
                                           ) where
 
+import Prelude
 import Data.List (isPrefixOf)
 import qualified Data.Map as M (empty, insert)
 import Data.Maybe (fromMaybe, listToMaybe)
diff --git a/src/Text/Pandoc/Readers/Odt/StyleReader.hs b/src/Text/Pandoc/Readers/Odt/StyleReader.hs
index 58be8e4a3..e0444559b 100644
--- a/src/Text/Pandoc/Readers/Odt/StyleReader.hs
+++ b/src/Text/Pandoc/Readers/Odt/StyleReader.hs
@@ -1,5 +1,6 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE CPP             #-}
 {-# LANGUAGE Arrows          #-}
-
 {-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE TupleSections   #-}
 
@@ -57,6 +58,7 @@ module Text.Pandoc.Readers.Odt.StyleReader
 , readStylesAt
 ) where
 
+import Prelude
 import Control.Applicative hiding (liftA, liftA2, liftA3)
 import Control.Arrow
 
@@ -80,7 +82,6 @@ import Text.Pandoc.Readers.Odt.Generic.XMLConverter
 import Text.Pandoc.Readers.Odt.Base
 import Text.Pandoc.Readers.Odt.Namespaces
 
-
 readStylesAt :: XML.Element -> Fallible Styles
 readStylesAt e = runConverter' readAllStyles mempty e
 
@@ -183,13 +184,14 @@ data Styles           = Styles
   deriving ( Show )
 
 -- Styles from a monoid under union
-instance Monoid Styles where
-  mempty  = Styles M.empty M.empty M.empty
-  mappend  (Styles sBn1 dSm1 lsBn1)
-           (Styles sBn2 dSm2 lsBn2)
+instance Semigroup Styles where
+  (Styles sBn1 dSm1 lsBn1) <> (Styles sBn2 dSm2 lsBn2)
           = Styles (M.union sBn1  sBn2)
                    (M.union dSm1  dSm2)
                    (M.union lsBn1 lsBn2)
+instance Monoid Styles where
+  mempty  = Styles M.empty M.empty M.empty
+  mappend = (<>)
 
 -- Not all families from the specifications are implemented, only those we need.
 -- But there are none that are not mentioned here.
diff --git a/src/Text/Pandoc/Readers/Org.hs b/src/Text/Pandoc/Readers/Org.hs
index 292830bd2..75b99e079 100644
--- a/src/Text/Pandoc/Readers/Org.hs
+++ b/src/Text/Pandoc/Readers/Org.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2014-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
 
@@ -27,6 +28,7 @@ Conversion of org-mode formatted plain text to 'Pandoc' document.
 -}
 module Text.Pandoc.Readers.Org ( readOrg ) where
 
+import Prelude
 import Text.Pandoc.Readers.Org.Blocks (blockList, meta)
 import Text.Pandoc.Readers.Org.ParserState (optionsToParserState)
 import Text.Pandoc.Readers.Org.Parsing (OrgParser, readWithM)
diff --git a/src/Text/Pandoc/Readers/Org/BlockStarts.hs b/src/Text/Pandoc/Readers/Org/BlockStarts.hs
index 424102cb0..5dbce01bd 100644
--- a/src/Text/Pandoc/Readers/Org/BlockStarts.hs
+++ b/src/Text/Pandoc/Readers/Org/BlockStarts.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2014-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
 
@@ -40,6 +41,7 @@ module Text.Pandoc.Readers.Org.BlockStarts
   , endOfBlock
   ) where
 
+import Prelude
 import Control.Monad (void)
 import Text.Pandoc.Readers.Org.Parsing
 
diff --git a/src/Text/Pandoc/Readers/Org/Blocks.hs b/src/Text/Pandoc/Readers/Org/Blocks.hs
index fa016283c..888cd9307 100644
--- a/src/Text/Pandoc/Readers/Org/Blocks.hs
+++ b/src/Text/Pandoc/Readers/Org/Blocks.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2014-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
 
@@ -31,6 +32,7 @@ module Text.Pandoc.Readers.Org.Blocks
   , meta
   ) where
 
+import Prelude
 import Text.Pandoc.Readers.Org.BlockStarts
 import Text.Pandoc.Readers.Org.DocumentTree (documentTree, headlineToBlocks)
 import Text.Pandoc.Readers.Org.Inlines
@@ -51,7 +53,6 @@ import Data.Char (isSpace, toLower, toUpper)
 import Data.Default (Default)
 import Data.List (foldl', isPrefixOf)
 import Data.Maybe (fromMaybe, isJust, isNothing)
-import Data.Monoid ((<>))
 
 import qualified Text.Pandoc.Builder as B
 import qualified Text.Pandoc.Walk as Walk
diff --git a/src/Text/Pandoc/Readers/Org/DocumentTree.hs b/src/Text/Pandoc/Readers/Org/DocumentTree.hs
index f77778ec9..c9465581a 100644
--- a/src/Text/Pandoc/Readers/Org/DocumentTree.hs
+++ b/src/Text/Pandoc/Readers/Org/DocumentTree.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2014-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
 
@@ -32,11 +33,11 @@ module Text.Pandoc.Readers.Org.DocumentTree
   , headlineToBlocks
   ) where
 
+import Prelude
 import Control.Arrow ((***))
 import Control.Monad (guard, void)
 import Data.Char (toLower, toUpper)
 import Data.List (intersperse)
-import Data.Monoid ((<>))
 import Text.Pandoc.Builder (Blocks, Inlines)
 import Text.Pandoc.Class (PandocMonad)
 import Text.Pandoc.Definition
diff --git a/src/Text/Pandoc/Readers/Org/ExportSettings.hs b/src/Text/Pandoc/Readers/Org/ExportSettings.hs
index 6a70c50b9..d02eb37c5 100644
--- a/src/Text/Pandoc/Readers/Org/ExportSettings.hs
+++ b/src/Text/Pandoc/Readers/Org/ExportSettings.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2016-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
 
@@ -29,6 +30,7 @@ module Text.Pandoc.Readers.Org.ExportSettings
   ( exportSettings
   ) where
 
+import Prelude
 import Text.Pandoc.Readers.Org.ParserState
 import Text.Pandoc.Readers.Org.Parsing
 
diff --git a/src/Text/Pandoc/Readers/Org/Inlines.hs b/src/Text/Pandoc/Readers/Org/Inlines.hs
index 3a12f38d0..7d1568b80 100644
--- a/src/Text/Pandoc/Readers/Org/Inlines.hs
+++ b/src/Text/Pandoc/Readers/Org/Inlines.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-
 Copyright (C) 2014-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
@@ -33,6 +34,7 @@ module Text.Pandoc.Readers.Org.Inlines
   , linkTarget
   ) where
 
+import Prelude
 import Text.Pandoc.Readers.Org.BlockStarts (endOfBlock, noteMarker)
 import Text.Pandoc.Readers.Org.ParserState
 import Text.Pandoc.Readers.Org.Parsing
@@ -55,9 +57,6 @@ import Data.Char (isAlphaNum, isSpace)
 import Data.List (intersperse)
 import qualified Data.Map as M
 import Data.Maybe (fromMaybe)
-import Data.Monoid ((<>))
-import Data.Traversable (sequence)
-import Prelude hiding (sequence)
 
 --
 -- Functions acting on the parser state
diff --git a/src/Text/Pandoc/Readers/Org/Meta.hs b/src/Text/Pandoc/Readers/Org/Meta.hs
index 6ad403fd8..965e33d94 100644
--- a/src/Text/Pandoc/Readers/Org/Meta.hs
+++ b/src/Text/Pandoc/Readers/Org/Meta.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE TupleSections    #-}
 {-
@@ -33,6 +34,7 @@ module Text.Pandoc.Readers.Org.Meta
   , metaLine
   ) where
 
+import Prelude
 import Text.Pandoc.Readers.Org.BlockStarts
 import Text.Pandoc.Readers.Org.ExportSettings (exportSettings)
 import Text.Pandoc.Readers.Org.Inlines
@@ -48,6 +50,7 @@ import Text.Pandoc.Shared (safeRead)
 import Control.Monad (mzero, void, when)
 import Data.Char (toLower)
 import Data.List (intersperse)
+import Data.Maybe (fromMaybe)
 import qualified Data.Map as M
 import Network.HTTP (urlEncode)
 
@@ -189,16 +192,12 @@ parseFormat = try $ replacePlain <|> replaceUrl <|> justAppend
 
 setEmphasisPreChar :: Maybe [Char] -> OrgParserState -> OrgParserState
 setEmphasisPreChar csMb st =
-  let preChars = case csMb of
-                   Nothing -> orgStateEmphasisPreChars defaultOrgParserState
-                   Just cs -> cs
+  let preChars = fromMaybe (orgStateEmphasisPostChars defaultOrgParserState) csMb
   in st { orgStateEmphasisPreChars = preChars }
 
 setEmphasisPostChar :: Maybe [Char] -> OrgParserState -> OrgParserState
 setEmphasisPostChar csMb st =
-  let postChars = case csMb of
-                   Nothing -> orgStateEmphasisPostChars defaultOrgParserState
-                   Just cs -> cs
+  let postChars = fromMaybe (orgStateEmphasisPostChars defaultOrgParserState) csMb
   in st { orgStateEmphasisPostChars = postChars }
 
 emphChars :: Monad m => OrgParser m (Maybe [Char])
diff --git a/src/Text/Pandoc/Readers/Org/ParserState.hs b/src/Text/Pandoc/Readers/Org/ParserState.hs
index 6316766fa..4cb5bb626 100644
--- a/src/Text/Pandoc/Readers/Org/ParserState.hs
+++ b/src/Text/Pandoc/Readers/Org/ParserState.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE FlexibleInstances     #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-
@@ -54,6 +55,7 @@ module Text.Pandoc.Readers.Org.ParserState
   , optionsToParserState
   ) where
 
+import Prelude
 import Control.Monad.Reader (ReaderT, asks, local)
 
 import Data.Default (Default (..))
diff --git a/src/Text/Pandoc/Readers/Org/Parsing.hs b/src/Text/Pandoc/Readers/Org/Parsing.hs
index 36420478b..e014de65e 100644
--- a/src/Text/Pandoc/Readers/Org/Parsing.hs
+++ b/src/Text/Pandoc/Readers/Org/Parsing.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2014-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
 
@@ -112,6 +113,7 @@ module Text.Pandoc.Readers.Org.Parsing
   , getPosition
   ) where
 
+import Prelude
 import Text.Pandoc.Readers.Org.ParserState
 
 import Text.Pandoc.Parsing hiding (F, anyLine, blanklines, newline,
diff --git a/src/Text/Pandoc/Readers/Org/Shared.hs b/src/Text/Pandoc/Readers/Org/Shared.hs
index cba72cc07..07dbeca2a 100644
--- a/src/Text/Pandoc/Readers/Org/Shared.hs
+++ b/src/Text/Pandoc/Readers/Org/Shared.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-
 Copyright (C) 2014-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
@@ -33,6 +34,7 @@ module Text.Pandoc.Readers.Org.Shared
   , translateLang
   ) where
 
+import Prelude
 import Data.Char (isAlphaNum)
 import Data.List (isPrefixOf, isSuffixOf)
 
diff --git a/src/Text/Pandoc/Readers/RST.hs b/src/Text/Pandoc/Readers/RST.hs
index e88d997f0..71a38cf82 100644
--- a/src/Text/Pandoc/Readers/RST.hs
+++ b/src/Text/Pandoc/Readers/RST.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE FlexibleContexts    #-}
 {-# LANGUAGE OverloadedStrings   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
@@ -31,6 +32,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Conversion from reStructuredText to 'Pandoc' document.
 -}
 module Text.Pandoc.Readers.RST ( readRST ) where
+import Prelude
 import Control.Arrow (second)
 import Control.Monad (forM_, guard, liftM, mplus, mzero, when)
 import Control.Monad.Except (throwError)
@@ -40,7 +42,6 @@ import Data.List (deleteFirstsBy, elemIndex, intercalate, isInfixOf, isSuffixOf,
                   nub, sort, transpose, union)
 import qualified Data.Map as M
 import Data.Maybe (fromMaybe, isJust)
-import Data.Monoid ((<>))
 import Data.Sequence (ViewR (..), viewr)
 import Data.Text (Text)
 import qualified Data.Text as T
@@ -80,7 +81,7 @@ type RSTParser m = ParserT [Char] ParserState m
 ---
 
 bulletListMarkers :: [Char]
-bulletListMarkers = "*+-"
+bulletListMarkers = "*+-•‣⁃"
 
 underlineChars :: [Char]
 underlineChars = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
@@ -650,11 +651,15 @@ directive' = do
   skipMany spaceChar
   top <- many $ satisfy (/='\n')
              <|> try (char '\n' <*
-                      notFollowedBy' (rawFieldListItem 3) <*
-                      count 3 (char ' ') <*
+                      notFollowedBy' (rawFieldListItem 1) <*
+                      many1 (char ' ') <*
                       notFollowedBy blankline)
   newline
-  fields <- many $ rawFieldListItem 3
+  fields <- do
+    fieldIndent <- length <$> lookAhead (many (char ' '))
+    if fieldIndent == 0
+       then return []
+       else many $ rawFieldListItem fieldIndent
   body <- option "" $ try $ blanklines >> indentedBlock
   optional blanklines
   let body' = body ++ "\n\n"
@@ -1085,10 +1090,15 @@ targetURI :: Monad m => ParserT [Char] st m [Char]
 targetURI = do
   skipSpaces
   optional newline
-  contents <- many1 (try (many spaceChar >> newline >>
-                          many1 spaceChar >> noneOf " \t\n") <|> noneOf "\n")
+  contents <- trim <$>
+     many1 (satisfy (/='\n')
+     <|> try (newline >> many1 spaceChar >> noneOf " \t\n"))
   blanklines
-  return $ escapeURI $ trim contents
+  case reverse contents of
+       -- strip backticks
+       '_':'`':xs -> return (dropWhile (=='`') (reverse xs) ++ "_")
+       '_':_      -> return contents
+       _          -> return (escapeURI contents)
 
 substKey :: PandocMonad m => RSTParser m ()
 substKey = try $ do
diff --git a/src/Text/Pandoc/Readers/TWiki.hs b/src/Text/Pandoc/Readers/TWiki.hs
index 75e3f89eb..1f230ae7e 100644
--- a/src/Text/Pandoc/Readers/TWiki.hs
+++ b/src/Text/Pandoc/Readers/TWiki.hs
@@ -1,7 +1,7 @@
-{-# LANGUAGE FlexibleContexts     #-}
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE RelaxedPolyRec       #-}
-{-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE FlexibleContexts  #-}
+{-# LANGUAGE RelaxedPolyRec    #-}
+
 -- RelaxedPolyRec needed for inlinesBetween on GHC < 7
 {-
   Copyright (C) 2014 Alexander Sulfrian <alexander.sulfrian@fu-berlin.de>
@@ -35,6 +35,7 @@ Conversion of twiki text to 'Pandoc' document.
 module Text.Pandoc.Readers.TWiki ( readTWiki
                                  ) where
 
+import Prelude
 import Control.Monad
 import Control.Monad.Except (throwError)
 import Data.Char (isAlphaNum)
diff --git a/src/Text/Pandoc/Readers/Textile.hs b/src/Text/Pandoc/Readers/Textile.hs
index 30bb6a715..bc3bcaf26 100644
--- a/src/Text/Pandoc/Readers/Textile.hs
+++ b/src/Text/Pandoc/Readers/Textile.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2010-2012 Paul Rivier <paul*rivier#demotera*com> | tr '*#' '.@'
               2010-2018 John MacFarlane
@@ -52,11 +53,11 @@ TODO : refactor common patterns across readers :
 
 
 module Text.Pandoc.Readers.Textile ( readTextile) where
+import Prelude
 import Control.Monad (guard, liftM)
 import Control.Monad.Except (throwError)
 import Data.Char (digitToInt, isUpper)
 import Data.List (intercalate, intersperse, transpose)
-import Data.Monoid ((<>))
 import Data.Text (Text)
 import qualified Data.Text as T
 import Text.HTML.TagSoup (Tag (..), fromAttrib)
@@ -394,7 +395,7 @@ table = try $ do
                              (toprow:rest) | any (fst . fst) toprow ->
                                 (toprow, rest)
                              _ -> (mempty, rawrows)
-  let nbOfCols = max (length headers) (length $ head rows)
+  let nbOfCols = maximum $ map length (headers:rows)
   let aligns = map minimum $ transpose $ map (map (snd . fst)) (headers:rows)
   return $ B.table caption
     (zip aligns (replicate nbOfCols 0.0))
diff --git a/src/Text/Pandoc/Readers/TikiWiki.hs b/src/Text/Pandoc/Readers/TikiWiki.hs
index a92f7bed2..5c7507248 100644
--- a/src/Text/Pandoc/Readers/TikiWiki.hs
+++ b/src/Text/Pandoc/Readers/TikiWiki.hs
@@ -1,13 +1,12 @@
-{-# LANGUAGE FlexibleContexts     #-}
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE OverloadedStrings    #-}
-{-# LANGUAGE RelaxedPolyRec       #-}
-{-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE FlexibleContexts  #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RelaxedPolyRec    #-}
 
 {- |
    Module      : Text.Pandoc.Readers.TikiWiki
    Copyright   : Copyright (C) 2017 Robin Lee Powell
-   License     : GPLv2
+   License     : GNU GPL, version 2 or above
 
    Maintainer  : Robin Lee Powell <robinleepowell@gmail.com>
    Stability   : alpha
@@ -19,6 +18,7 @@ Conversion of TikiWiki text to 'Pandoc' document.
 module Text.Pandoc.Readers.TikiWiki ( readTikiWiki
                                     ) where
 
+import Prelude
 import Control.Monad
 import Control.Monad.Except (throwError)
 import qualified Data.Foldable as F
diff --git a/src/Text/Pandoc/Readers/Txt2Tags.hs b/src/Text/Pandoc/Readers/Txt2Tags.hs
index f4dda7a11..bed49fd46 100644
--- a/src/Text/Pandoc/Readers/Txt2Tags.hs
+++ b/src/Text/Pandoc/Readers/Txt2Tags.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2014 Matthew Pickering <matthewtpickering@gmail.com>
 
@@ -31,6 +32,7 @@ module Text.Pandoc.Readers.Txt2Tags ( readTxt2Tags
                                     )
                                     where
 
+import Prelude
 import Control.Monad (guard, void, when)
 import Control.Monad.Except (catchError, throwError)
 import Control.Monad.Reader (Reader, asks, runReader)
@@ -38,7 +40,6 @@ import Data.Char (toLower)
 import Data.Default
 import Data.List (intercalate, transpose)
 import Data.Maybe (fromMaybe)
-import Data.Monoid ((<>))
 import Data.Text (Text)
 import qualified Data.Text as T
 import Data.Time.Format (formatTime)
@@ -46,7 +47,7 @@ import Text.Pandoc.Builder (Blocks, Inlines, trimInlines)
 import qualified Text.Pandoc.Builder as B
 import Text.Pandoc.Class (PandocMonad)
 import qualified Text.Pandoc.Class as P
-import Text.Pandoc.Compat.Time (defaultTimeLocale)
+import Data.Time (defaultTimeLocale)
 import Text.Pandoc.Definition
 import Text.Pandoc.Options
 import Text.Pandoc.Parsing hiding (space, spaces, uri)
@@ -444,7 +445,7 @@ inlineMarkup p f c special = try $ do
       let end' = case drop 2 end of
                           "" -> mempty
                           xs -> special xs
-      return $ f (start' <> body' <> end')
+      return $ f (start' `mappend` body' `mappend` end')
     Nothing -> do -- Either bad or case such as *****
       guard (l >= 5)
       let body' = replicate (l - 4) c
diff --git a/src/Text/Pandoc/Readers/Vimwiki.hs b/src/Text/Pandoc/Readers/Vimwiki.hs
index d717a1ba8..824a912c3 100644
--- a/src/Text/Pandoc/Readers/Vimwiki.hs
+++ b/src/Text/Pandoc/Readers/Vimwiki.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE CPP #-}
 {-
   Copyright (C) 2017-2018 Yuchen Pei <me@ypei.me>
 
@@ -63,12 +65,12 @@ Conversion of vimwiki text to 'Pandoc' document.
 
 module Text.Pandoc.Readers.Vimwiki ( readVimwiki
                                  ) where
+import Prelude
 import Control.Monad (guard)
 import Control.Monad.Except (throwError)
 import Data.Default
 import Data.List (isInfixOf, isPrefixOf)
 import Data.Maybe
-import Data.Monoid ((<>))
 import Data.Text (Text, unpack)
 import Text.Pandoc.Builder (Blocks, Inlines, fromList, toList, trimInlines)
 import qualified Text.Pandoc.Builder as B (blockQuote, bulletList, code,
diff --git a/src/Text/Pandoc/SelfContained.hs b/src/Text/Pandoc/SelfContained.hs
index a1c5c919e..2aab015c2 100644
--- a/src/Text/Pandoc/SelfContained.hs
+++ b/src/Text/Pandoc/SelfContained.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-
 Copyright (C) 2011-2018 John MacFarlane <jgm@berkeley.edu>
@@ -31,6 +32,7 @@ offline, by incorporating linked images, CSS, and scripts into
 the HTML using data URIs.
 -}
 module Text.Pandoc.SelfContained ( makeDataURI, makeSelfContained ) where
+import Prelude
 import Codec.Compression.GZip as Gzip
 import Control.Applicative ((<|>))
 import Control.Monad.Except (throwError)
@@ -41,7 +43,6 @@ import qualified Data.ByteString.Char8 as B
 import qualified Data.ByteString.Lazy as L
 import Data.Char (isAlphaNum, isAscii, toLower)
 import Data.List (isPrefixOf)
-import Data.Monoid ((<>))
 import Network.URI (escapeURIString)
 import System.FilePath (takeDirectory, takeExtension, (</>))
 import Text.HTML.TagSoup
diff --git a/src/Text/Pandoc/Shared.hs b/src/Text/Pandoc/Shared.hs
index 52e1447db..26b01bc90 100644
--- a/src/Text/Pandoc/Shared.hs
+++ b/src/Text/Pandoc/Shared.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE CPP                   #-}
 {-# LANGUAGE DeriveDataTypeable    #-}
 {-# LANGUAGE FlexibleContexts      #-}
@@ -83,6 +84,7 @@ module Text.Pandoc.Shared (
                      -- * File handling
                      inDirectory,
                      collapseFilePath,
+                     uriPathToPath,
                      filteredFilesFromArchive,
                      -- * URI handling
                      schemes,
@@ -100,6 +102,7 @@ module Text.Pandoc.Shared (
                      pandocVersion
                     ) where
 
+import Prelude
 import Codec.Archive.Zip
 import qualified Control.Exception as E
 import Control.Monad (MonadPlus (..), msum, unless)
@@ -111,7 +114,6 @@ import Data.Data (Data, Typeable)
 import Data.List (find, intercalate, intersperse, stripPrefix)
 import qualified Data.Map as M
 import Data.Maybe (mapMaybe)
-import Data.Monoid ((<>))
 import Data.Sequence (ViewL (..), ViewR (..), viewl, viewr)
 import qualified Data.Set as Set
 import qualified Data.Text as T
@@ -126,7 +128,7 @@ import Text.HTML.TagSoup (RenderOptions (..), Tag (..), renderOptions,
                           renderTagsOptions)
 import Text.Pandoc.Builder (Blocks, Inlines, ToMetaValue (..))
 import qualified Text.Pandoc.Builder as B
-import Text.Pandoc.Compat.Time
+import Data.Time
 import Text.Pandoc.Definition
 import Text.Pandoc.Generic (bottomUp)
 import Text.Pandoc.Pretty (charWidth)
@@ -286,12 +288,7 @@ normalizeDate s = fmap (formatTime defaultTimeLocale "%F")
   where rejectBadYear day = case toGregorian day of
           (y, _, _) | y >= 1601 && y <= 9999 -> Just day
           _         -> Nothing
-        parsetimeWith =
-#if MIN_VERSION_time(1,5,0)
-             parseTimeM True defaultTimeLocale
-#else
-             parseTime defaultTimeLocale
-#endif
+        parsetimeWith = parseTimeM True defaultTimeLocale
         formats = ["%x","%m/%d/%Y", "%D","%F", "%d %b %Y",
                     "%e %B %Y", "%b. %e, %Y", "%B %e, %Y",
                     "%Y%m%d", "%Y%m", "%Y"]
@@ -447,7 +444,7 @@ instance Walkable Inline Element where
     elts' <- walkM f elts
     return $ Sec lev nums attr ils' elts'
   query f (Blk x)              = query f x
-  query f (Sec _ _ _ ils elts) = query f ils <> query f elts
+  query f (Sec _ _ _ ils elts) = query f ils `mappend` query f elts
 
 instance Walkable Block Element where
   walk f (Blk x) = Blk (walk f x)
@@ -458,7 +455,7 @@ instance Walkable Block Element where
     elts' <- walkM f elts
     return $ Sec lev nums attr ils' elts'
   query f (Blk x)              = query f x
-  query f (Sec _ _ _ ils elts) = query f ils <> query f elts
+  query f (Sec _ _ _ ils elts) = query f ils `mappend` query f elts
 
 
 -- | Convert Pandoc inline list to plain text identifier.  HTML
@@ -639,6 +636,19 @@ collapseFilePath = Posix.joinPath . reverse . foldl go [] . splitDirectories
     isSingleton _   = Nothing
     checkPathSeperator = fmap isPathSeparator . isSingleton
 
+-- Convert the path part of a file: URI to a regular path.
+-- On windows, @/c:/foo@ should be @c:/foo@.
+-- On linux, @/foo@ should be @/foo@.
+uriPathToPath :: String -> FilePath
+uriPathToPath path =
+#ifdef _WINDOWS
+  case path of
+    '/':ps -> ps
+    ps     -> ps
+#else
+  path
+#endif
+
 --
 -- File selection from the archive
 --
diff --git a/src/Text/Pandoc/Slides.hs b/src/Text/Pandoc/Slides.hs
index 9d63555c2..2f7d83527 100644
--- a/src/Text/Pandoc/Slides.hs
+++ b/src/Text/Pandoc/Slides.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2012-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -29,6 +30,7 @@ Utility functions for splitting documents into slides for slide
 show formats (dzslides, revealjs, s5, slidy, slideous, beamer).
 -}
 module Text.Pandoc.Slides ( getSlideLevel, prepSlides ) where
+import Prelude
 import Text.Pandoc.Definition
 
 -- | Find level of header that starts slides (defined as the least header
diff --git a/src/Text/Pandoc/Templates.hs b/src/Text/Pandoc/Templates.hs
index 4be0d081c..80e2b1fa4 100644
--- a/src/Text/Pandoc/Templates.hs
+++ b/src/Text/Pandoc/Templates.hs
@@ -1,7 +1,4 @@
-{-# LANGUAGE FlexibleInstances    #-}
-
-{-# LANGUAGE OverloadedStrings    #-}
-{-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE OverloadedStrings #-}
 {-
 Copyright (C) 2009-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -38,6 +35,7 @@ module Text.Pandoc.Templates ( module Text.DocTemplates
                              , getDefaultTemplate
                              ) where
 
+import Prelude
 import Control.Monad.Except (throwError)
 import Data.Aeson (ToJSON (..))
 import qualified Data.Text as T
diff --git a/src/Text/Pandoc/Translations.hs b/src/Text/Pandoc/Translations.hs
index 949618178..4a216af92 100644
--- a/src/Text/Pandoc/Translations.hs
+++ b/src/Text/Pandoc/Translations.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE CPP                        #-}
 {-# LANGUAGE DeriveGeneric              #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-
@@ -45,6 +47,7 @@ module Text.Pandoc.Translations (
                          , readTranslations
                          )
 where
+import Prelude
 import Data.Aeson.Types (typeMismatch)
 import qualified Data.HashMap.Strict as HM
 import qualified Data.Map as M
@@ -80,7 +83,7 @@ data Term =
   deriving (Show, Eq, Ord, Generic, Enum, Read)
 
 newtype Translations = Translations (M.Map Term String)
-        deriving (Show, Generic, Monoid)
+        deriving (Show, Generic, Semigroup, Monoid)
 
 instance FromJSON Term where
   parseJSON (String t) = case safeRead (T.unpack t) of
diff --git a/src/Text/Pandoc/UTF8.hs b/src/Text/Pandoc/UTF8.hs
index 3f759958f..2bfda1ee8 100644
--- a/src/Text/Pandoc/UTF8.hs
+++ b/src/Text/Pandoc/UTF8.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-
 Copyright (C) 2010-2018 John MacFarlane <jgm@berkeley.edu>
diff --git a/src/Text/Pandoc/UUID.hs b/src/Text/Pandoc/UUID.hs
index 4d99324db..c1bae7038 100644
--- a/src/Text/Pandoc/UUID.hs
+++ b/src/Text/Pandoc/UUID.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2010-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -31,6 +32,7 @@ in RFC4122. See http://tools.ietf.org/html/rfc4122
 
 module Text.Pandoc.UUID ( UUID(..), getRandomUUID, getUUID ) where
 
+import Prelude
 import Data.Bits (clearBit, setBit)
 import Data.Word
 import System.Random (RandomGen, getStdGen, randoms)
diff --git a/src/Text/Pandoc/Writers.hs b/src/Text/Pandoc/Writers.hs
index 596a8680e..5d4a9122a 100644
--- a/src/Text/Pandoc/Writers.hs
+++ b/src/Text/Pandoc/Writers.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2006-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -82,6 +83,7 @@ module Text.Pandoc.Writers
     , getWriter
     ) where
 
+import Prelude
 import Data.Aeson
 import qualified Data.ByteString.Lazy as BL
 import Data.List (intercalate)
diff --git a/src/Text/Pandoc/Writers/AsciiDoc.hs b/src/Text/Pandoc/Writers/AsciiDoc.hs
index f91fa8fa0..036185282 100644
--- a/src/Text/Pandoc/Writers/AsciiDoc.hs
+++ b/src/Text/Pandoc/Writers/AsciiDoc.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-
 Copyright (C) 2006-2018 John MacFarlane <jgm@berkeley.edu>
@@ -37,6 +38,7 @@ that it has omitted the construct.
 AsciiDoc:  <http://www.methods.co.nz/asciidoc/>
 -}
 module Text.Pandoc.Writers.AsciiDoc (writeAsciiDoc) where
+import Prelude
 import Control.Monad.State.Strict
 import Data.Aeson (Result (..), Value (String), fromJSON, toJSON)
 import Data.Char (isPunctuation, isSpace)
diff --git a/src/Text/Pandoc/Writers/CommonMark.hs b/src/Text/Pandoc/Writers/CommonMark.hs
index 7a6eb2948..98c1101fa 100644
--- a/src/Text/Pandoc/Writers/CommonMark.hs
+++ b/src/Text/Pandoc/Writers/CommonMark.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-
 Copyright (C) 2015-2018 John MacFarlane <jgm@berkeley.edu>
@@ -32,11 +33,12 @@ CommonMark:  <http://commonmark.org>
 -}
 module Text.Pandoc.Writers.CommonMark (writeCommonMark) where
 
+import Prelude
 import CMarkGFM
 import Control.Monad.State.Strict (State, get, modify, runState)
 import Data.Foldable (foldrM)
 import Data.List (transpose)
-import Data.Monoid (Any (..), (<>))
+import Data.Monoid (Any (..))
 import Data.Text (Text)
 import qualified Data.Text as T
 import Network.HTTP (urlEncode)
@@ -114,7 +116,7 @@ blockToNodes _ (CodeBlock (_,classes,_) xs) ns = return
 blockToNodes opts (RawBlock fmt xs) ns
   | fmt == Format "html" && isEnabled Ext_raw_html opts
               = return (node (HTML_BLOCK (T.pack xs)) [] : ns)
-  | fmt == Format "latex" || fmt == Format "tex" && isEnabled Ext_raw_tex opts
+  | (fmt == Format "latex" || fmt == Format "tex") && isEnabled Ext_raw_tex opts
               = return (node (CUSTOM_BLOCK (T.pack xs) T.empty) [] : ns)
   | otherwise = return ns
 blockToNodes opts (BlockQuote bs) ns = do
diff --git a/src/Text/Pandoc/Writers/ConTeXt.hs b/src/Text/Pandoc/Writers/ConTeXt.hs
index f94c12d89..10e996bdb 100644
--- a/src/Text/Pandoc/Writers/ConTeXt.hs
+++ b/src/Text/Pandoc/Writers/ConTeXt.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-
@@ -30,6 +31,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Conversion of 'Pandoc' format into ConTeXt.
 -}
 module Text.Pandoc.Writers.ConTeXt ( writeConTeXt ) where
+import Prelude
 import Control.Monad.State.Strict
 import Data.Char (ord, isDigit)
 import Data.List (intercalate, intersperse)
diff --git a/src/Text/Pandoc/Writers/Custom.hs b/src/Text/Pandoc/Writers/Custom.hs
index 37b44b646..53b321c7c 100644
--- a/src/Text/Pandoc/Writers/Custom.hs
+++ b/src/Text/Pandoc/Writers/Custom.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE DeriveDataTypeable   #-}
 {-# LANGUAGE FlexibleInstances    #-}
 {- Copyright (C) 2012-2018 John MacFarlane <jgm@berkeley.edu>
@@ -30,6 +31,7 @@ Conversion of 'Pandoc' documents to custom markup using
 a lua writer.
 -}
 module Text.Pandoc.Writers.Custom ( writeCustom ) where
+import Prelude
 import Control.Arrow ((***))
 import Control.Exception
 import Control.Monad (when)
@@ -44,7 +46,7 @@ import Foreign.Lua.Api
 import Text.Pandoc.Class (PandocIO)
 import Text.Pandoc.Definition
 import Text.Pandoc.Error
-import Text.Pandoc.Lua.Init (runPandocLua)
+import Text.Pandoc.Lua.Init (runPandocLua, registerScriptPath)
 import Text.Pandoc.Lua.StackInstances ()
 import Text.Pandoc.Lua.Util (addValue, dostring')
 import Text.Pandoc.Options
@@ -106,6 +108,7 @@ writeCustom :: FilePath -> WriterOptions -> Pandoc -> PandocIO Text
 writeCustom luaFile opts doc@(Pandoc meta _) = do
   luaScript <- liftIO $ UTF8.readFile luaFile
   res <- runPandocLua $ do
+    registerScriptPath luaFile
     stat <- dostring' luaScript
     -- check for error in lua script (later we'll change the return type
     -- to handle this more gracefully):
diff --git a/src/Text/Pandoc/Writers/Docbook.hs b/src/Text/Pandoc/Writers/Docbook.hs
index 3034fade5..f6e814095 100644
--- a/src/Text/Pandoc/Writers/Docbook.hs
+++ b/src/Text/Pandoc/Writers/Docbook.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE PatternGuards     #-}
 {-
@@ -30,6 +31,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Conversion of 'Pandoc' documents to Docbook XML.
 -}
 module Text.Pandoc.Writers.Docbook ( writeDocbook4, writeDocbook5 ) where
+import Prelude
 import Control.Monad.Reader
 import Data.Char (toLower)
 import Data.Generics (everywhere, mkT)
diff --git a/src/Text/Pandoc/Writers/Docx.hs b/src/Text/Pandoc/Writers/Docx.hs
index 5ad6bf82b..1666c0562 100644
--- a/src/Text/Pandoc/Writers/Docx.hs
+++ b/src/Text/Pandoc/Writers/Docx.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE PatternGuards       #-}
 {-# LANGUAGE RankNTypes          #-}
 {-# LANGUAGE ScopedTypeVariables #-}
@@ -32,6 +33,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Conversion of 'Pandoc' documents to docx.
 -}
 module Text.Pandoc.Writers.Docx ( writeDocx ) where
+import Prelude
 import Codec.Archive.Zip
 import Control.Applicative ((<|>))
 import Control.Monad.Except (catchError)
@@ -51,7 +53,7 @@ import System.Random (randomR, StdGen, mkStdGen)
 import Text.Pandoc.BCP47 (getLang, renderLang)
 import Text.Pandoc.Class (PandocMonad, report, toLang)
 import qualified Text.Pandoc.Class as P
-import Text.Pandoc.Compat.Time
+import Data.Time
 import Text.Pandoc.Definition
 import Text.Pandoc.Generic
 import Text.Pandoc.Highlighting (highlight)
@@ -123,7 +125,7 @@ data WriterState = WriterState{
        , stComments       :: [([(String,String)], [Inline])]
        , stSectionIds     :: Set.Set String
        , stExternalLinks  :: M.Map String String
-       , stImages         :: M.Map FilePath (String, String, Maybe MimeType, Element, B.ByteString)
+       , stImages         :: M.Map FilePath (String, String, Maybe MimeType, B.ByteString)
        , stLists          :: [ListMarker]
        , stInsId          :: Int
        , stDelId          :: Int
@@ -294,7 +296,7 @@ writeDocx opts doc@(Pandoc meta _) = do
   let imgs = M.elems $ stImages st
 
   -- create entries for images in word/media/...
-  let toImageEntry (_,path,_,_,img) = toEntry ("word/" ++ path) epochtime $ toLazy img
+  let toImageEntry (_,path,_,img) = toEntry ("word/" ++ path) epochtime $ toLazy img
   let imageEntries = map toImageEntry imgs
 
   let stdAttributes =
@@ -326,7 +328,7 @@ writeDocx opts doc@(Pandoc meta _) = do
   -- [Content_Types].xml
   let mkOverrideNode (part', contentType') = mknode "Override"
                [("PartName",part'),("ContentType",contentType')] ()
-  let mkImageOverride (_, imgpath, mbMimeType, _, _) =
+  let mkImageOverride (_, imgpath, mbMimeType, _) =
           mkOverrideNode ("/word/" ++ imgpath,
                           fromMaybe "application/octet-stream" mbMimeType)
   let mkMediaOverride imgpath =
@@ -407,7 +409,7 @@ writeDocx opts doc@(Pandoc meta _) = do
   let renumHeaders = renumIds (\q -> qName q == "Id") idMap headers
   let renumFooters = renumIds (\q -> qName q == "Id") idMap footers
   let baserels = baserels' ++ renumHeaders ++ renumFooters
-  let toImgRel (ident,path,_,_,_) =  mknode "Relationship" [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"),("Id",ident),("Target",path)] ()
+  let toImgRel (ident,path,_,_) =  mknode "Relationship" [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"),("Id",ident),("Target",path)] ()
   let imgrels = map toImgRel imgs
   let toLinkRel (src,ident) =  mknode "Relationship" [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"),("Id",ident),("Target",src),("TargetMode","External") ] ()
   let linkrels = map toLinkRel $ M.toList $ stExternalLinks st
@@ -708,12 +710,12 @@ mkLvl marker lvl =
           styleFor UpperRoman _   = "upperRoman"
           styleFor LowerRoman _   = "lowerRoman"
           styleFor Decimal _      = "decimal"
-          styleFor DefaultStyle 1 = "decimal"
-          styleFor DefaultStyle 2 = "lowerLetter"
-          styleFor DefaultStyle 3 = "lowerRoman"
-          styleFor DefaultStyle 4 = "decimal"
-          styleFor DefaultStyle 5 = "lowerLetter"
-          styleFor DefaultStyle 0 = "lowerRoman"
+          styleFor DefaultStyle 0 = "decimal"
+          styleFor DefaultStyle 1 = "lowerLetter"
+          styleFor DefaultStyle 2 = "lowerRoman"
+          styleFor DefaultStyle 3 = "decimal"
+          styleFor DefaultStyle 4 = "lowerLetter"
+          styleFor DefaultStyle 5 = "lowerRoman"
           styleFor DefaultStyle x = styleFor DefaultStyle (x `mod` 6)
           styleFor _ _            = "decimal"
           patternFor OneParen s  = s ++ ")"
@@ -1109,6 +1111,9 @@ inlineToOpenXML' _ (Str str) =
   formattedString str
 inlineToOpenXML' opts Space = inlineToOpenXML opts (Str " ")
 inlineToOpenXML' opts SoftBreak = inlineToOpenXML opts (Str " ")
+inlineToOpenXML' opts (Span (_,["underline"],_) ils) = do
+  withTextProp (mknode "w:u" [("w:val","single")] ()) $
+    inlinesToOpenXML opts ils
 inlineToOpenXML' _ (Span (ident,["comment-start"],kvs) ils) = do
   -- prefer the "id" in kvs, since that is the one produced by the docx
   -- reader.
@@ -1275,87 +1280,103 @@ inlineToOpenXML' opts (Link _ txt (src,_)) = do
               return i
   return [ mknode "w:hyperlink" [("r:id",id')] contents ]
 inlineToOpenXML' opts (Image attr alt (src, title)) = do
-  -- first, check to see if we've already done this image
   pageWidth <- asks envPrintWidth
   imgs <- gets stImages
-  case M.lookup src imgs of
-    Just (_,_,_,elt,_) -> return [elt]
-    Nothing ->
-      catchError
-      (do (img, mt) <- P.fetchItem src
-          ident <- ("rId"++) `fmap` getUniqueId
-          let (xpt,ypt) = desiredSizeInPoints opts attr
-                 (either (const def) id (imageSize opts img))
-          -- 12700 emu = 1 pt
-          let (xemu,yemu) = fitToPage (xpt * 12700, ypt * 12700)
-                                  (pageWidth * 12700)
-          let cNvPicPr = mknode "pic:cNvPicPr" [] $
-                           mknode "a:picLocks" [("noChangeArrowheads","1")
-                                               ,("noChangeAspect","1")] ()
-          let nvPicPr  = mknode "pic:nvPicPr" []
-                          [ mknode "pic:cNvPr"
-                              [("descr",src),("id","0"),("name","Picture")] ()
-                          , cNvPicPr ]
-          let blipFill = mknode "pic:blipFill" []
-                           [ mknode "a:blip" [("r:embed",ident)] ()
-                           , mknode "a:stretch" [] $
-                             mknode "a:fillRect" [] () ]
-          let xfrm =    mknode "a:xfrm" []
-                          [ mknode "a:off" [("x","0"),("y","0")] ()
-                          , mknode "a:ext" [("cx",show xemu)
-                                           ,("cy",show yemu)] () ]
-          let prstGeom = mknode "a:prstGeom" [("prst","rect")] $
-                           mknode "a:avLst" [] ()
-          let ln =      mknode "a:ln" [("w","9525")]
-                          [ mknode "a:noFill" [] ()
-                          , mknode "a:headEnd" [] ()
-                          , mknode "a:tailEnd" [] () ]
-          let spPr =    mknode "pic:spPr" [("bwMode","auto")]
-                          [xfrm, prstGeom, mknode "a:noFill" [] (), ln]
-          let graphic = mknode "a:graphic" [] $
-                          mknode "a:graphicData"
-                            [("uri","http://schemas.openxmlformats.org/drawingml/2006/picture")]
-                            [ mknode "pic:pic" []
-                              [ nvPicPr
-                              , blipFill
-                              , spPr ] ]
-          let imgElt = mknode "w:r" [] $
-               mknode "w:drawing" [] $
-                 mknode "wp:inline" []
-                  [ mknode "wp:extent" [("cx",show xemu),("cy",show yemu)] ()
-                  , mknode "wp:effectExtent"
-                       [("b","0"),("l","0"),("r","0"),("t","0")] ()
-                  , mknode "wp:docPr" [("descr",stringify alt)
-                                      ,("title", title)
-                                      ,("id","1")
-                                      ,("name","Picture")] ()
-                  , graphic ]
-          let imgext = case mt >>= extensionFromMimeType of
-                            Just x    -> '.':x
-                            Nothing   -> case imageType img of
-                                              Just Png  -> ".png"
-                                              Just Jpeg -> ".jpeg"
-                                              Just Gif  -> ".gif"
-                                              Just Pdf  -> ".pdf"
-                                              Just Eps  -> ".eps"
-                                              Just Svg  -> ".svg"
-                                              Just Emf  -> ".emf"
-                                              Nothing   -> ""
-          if null imgext
-             then -- without an extension there is no rule for content type
-               inlinesToOpenXML opts alt -- return alt to avoid corrupted docx
-             else do
-               let imgpath = "media/" ++ ident ++ imgext
-               let mbMimeType = mt <|> getMimeType imgpath
-               -- insert mime type to use in constructing [Content_Types].xml
-               modify $ \st -> st{ stImages =
-                   M.insert src (ident, imgpath, mbMimeType, imgElt, img)
-                           $ stImages st }
-               return [imgElt])
-      (\e -> do
-         report $ CouldNotFetchResource src (show e)
-         -- emit alt text
-         inlinesToOpenXML opts alt)
+  let
+    stImage = M.lookup src imgs
+    generateImgElt (ident, _, _, img) =
+      let
+        (xpt,ypt) = desiredSizeInPoints opts attr
+               (either (const def) id (imageSize opts img))
+        -- 12700 emu = 1 pt
+        (xemu,yemu) = fitToPage (xpt * 12700, ypt * 12700)
+                                (pageWidth * 12700)
+        cNvPicPr = mknode "pic:cNvPicPr" [] $
+                         mknode "a:picLocks" [("noChangeArrowheads","1")
+                                             ,("noChangeAspect","1")] ()
+        nvPicPr  = mknode "pic:nvPicPr" []
+                        [ mknode "pic:cNvPr"
+                            [("descr",src),("id","0"),("name","Picture")] ()
+                        , cNvPicPr ]
+        blipFill = mknode "pic:blipFill" []
+          [ mknode "a:blip" [("r:embed",ident)] ()
+          , mknode "a:stretch" [] $
+              mknode "a:fillRect" [] ()
+          ]
+        xfrm =    mknode "a:xfrm" []
+                        [ mknode "a:off" [("x","0"),("y","0")] ()
+                        , mknode "a:ext" [("cx",show xemu)
+                                         ,("cy",show yemu)] () ]
+        prstGeom = mknode "a:prstGeom" [("prst","rect")] $
+                         mknode "a:avLst" [] ()
+        ln =      mknode "a:ln" [("w","9525")]
+                        [ mknode "a:noFill" [] ()
+                        , mknode "a:headEnd" [] ()
+                        , mknode "a:tailEnd" [] () ]
+        spPr =    mknode "pic:spPr" [("bwMode","auto")]
+                        [xfrm, prstGeom, mknode "a:noFill" [] (), ln]
+        graphic = mknode "a:graphic" [] $
+          mknode "a:graphicData"
+            [("uri","http://schemas.openxmlformats.org/drawingml/2006/picture")]
+            [ mknode "pic:pic" []
+              [ nvPicPr
+              , blipFill
+              , spPr
+              ]
+            ]
+        imgElt = mknode "w:r" [] $
+          mknode "w:drawing" [] $
+            mknode "wp:inline" []
+              [ mknode "wp:extent" [("cx",show xemu),("cy",show yemu)] ()
+              , mknode "wp:effectExtent"
+                [("b","0"),("l","0"),("r","0"),("t","0")] ()
+              , mknode "wp:docPr"
+                [ ("descr", stringify alt)
+                , ("title", title)
+                , ("id","1")
+                , ("name","Picture")
+                ] ()
+              , graphic
+              ]
+      in
+        imgElt
+
+  case stImage of
+    Just imgData -> return [generateImgElt imgData]
+    Nothing -> ( do --try
+      (img, mt) <- P.fetchItem src
+      ident <- ("rId"++) `fmap` getUniqueId
+
+      let
+        imgext = case mt >>= extensionFromMimeType of
+          Just x    -> '.':x
+          Nothing   -> case imageType img of
+            Just Png  -> ".png"
+            Just Jpeg -> ".jpeg"
+            Just Gif  -> ".gif"
+            Just Pdf  -> ".pdf"
+            Just Eps  -> ".eps"
+            Just Svg  -> ".svg"
+            Just Emf  -> ".emf"
+            Nothing   -> ""
+        imgpath = "media/" ++ ident ++ imgext
+        mbMimeType = mt <|> getMimeType imgpath
+
+        imgData = (ident, imgpath, mbMimeType, img)
+
+      if null imgext
+         then -- without an extension there is no rule for content type
+           inlinesToOpenXML opts alt -- return alt to avoid corrupted docx
+         else do
+           -- insert mime type to use in constructing [Content_Types].xml
+           modify $ \st -> st { stImages = M.insert src imgData $ stImages st }
+           return [generateImgElt imgData]
+      )
+      `catchError` ( \e -> do
+        report $ CouldNotFetchResource src (show e)
+        -- emit alt text
+        inlinesToOpenXML opts alt
+      )
 
 br :: Element
 br = breakElement "textWrapping"
@@ -1370,12 +1391,12 @@ breakElement kind = mknode "w:r" [] [mknode "w:br" [("w:type",kind)] () ]
 defaultFootnotes :: [Element]
 defaultFootnotes = [ mknode "w:footnote"
                      [("w:type", "separator"), ("w:id", "-1")]
-                     [ mknode "w:p" [] $
+                     [ mknode "w:p" []
                        [mknode "w:r" [] $
                         [ mknode "w:separator" [] ()]]]
                    , mknode "w:footnote"
                      [("w:type", "continuationSeparator"), ("w:id", "0")]
-                     [ mknode "w:p" [] $
+                     [ mknode "w:p" []
                        [ mknode "w:r" [] $
                          [ mknode "w:continuationSeparator" [] ()]]]]
 
diff --git a/src/Text/Pandoc/Writers/DokuWiki.hs b/src/Text/Pandoc/Writers/DokuWiki.hs
index dda21d23d..189bf138e 100644
--- a/src/Text/Pandoc/Writers/DokuWiki.hs
+++ b/src/Text/Pandoc/Writers/DokuWiki.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2008-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -39,6 +40,7 @@ DokuWiki:  <https://www.dokuwiki.org/dokuwiki>
 -}
 
 module Text.Pandoc.Writers.DokuWiki ( writeDokuWiki ) where
+import Prelude
 import Control.Monad (zipWithM)
 import Control.Monad.Reader (ReaderT, ask, local, runReaderT)
 import Control.Monad.State.Strict (StateT, evalStateT)
@@ -366,12 +368,16 @@ isSimpleBlockQuote bs  = all isPlainOrPara bs
 vcat :: [String] -> String
 vcat = intercalate "\n"
 
-backSlashLineBreaks :: String -> String
-backSlashLineBreaks cs = reverse $ g $ reverse $ concatMap f cs
-  where f '\n' = "\\\\ "
-        f c    = [c]
-        g (' ' : '\\':'\\': xs) = xs
-        g s                     = s
+-- | For each string in the input list, convert all newlines to
+-- dokuwiki escaped newlines. Then concat the list using double linebreaks.
+backSlashLineBreaks :: [String] -> String
+backSlashLineBreaks ls = vcatBackSlash $ map escape ls
+  where
+    vcatBackSlash = intercalate "\\\\ \\\\ " -- simulate paragraphs.
+    escape ['\n'] = "" -- remove trailing newlines
+    escape ('\n':cs) = "\\\\ " ++ escape cs
+    escape (c:cs)    = c : escape cs
+    escape []        = []
 
 -- Auxiliary functions for tables:
 
@@ -400,7 +406,7 @@ blockListToDokuWiki opts blocks = do
   backSlash <- stBackSlashLB <$> ask
   let blocks' = consolidateRawBlocks blocks
   if backSlash
-    then (backSlashLineBreaks . vcat) <$> mapM (blockToDokuWiki opts) blocks'
+    then backSlashLineBreaks <$> mapM (blockToDokuWiki opts) blocks'
     else vcat <$> mapM (blockToDokuWiki opts) blocks'
 
 consolidateRawBlocks :: [Block] -> [Block]
@@ -479,7 +485,11 @@ inlineToDokuWiki _ il@(RawInline f str)
   | f == Format "html"     = return $ "<html>" ++ str ++ "</html>"
   | otherwise              = "" <$ report (InlineNotRendered il)
 
-inlineToDokuWiki _ LineBreak = return "\\\\\n"
+inlineToDokuWiki _ LineBreak = do
+  backSlash <- stBackSlashLB <$> ask
+  return $ if backSlash
+           then "\n"
+           else "\\\\\n"
 
 inlineToDokuWiki opts SoftBreak =
   case writerWrapText opts of
diff --git a/src/Text/Pandoc/Writers/EPUB.hs b/src/Text/Pandoc/Writers/EPUB.hs
index 7b4853a24..f1ff8b482 100644
--- a/src/Text/Pandoc/Writers/EPUB.hs
+++ b/src/Text/Pandoc/Writers/EPUB.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE CPP                 #-}
 {-# LANGUAGE FlexibleContexts    #-}
 {-# LANGUAGE PatternGuards       #-}
@@ -32,6 +33,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Conversion of 'Pandoc' documents to EPUB.
 -}
 module Text.Pandoc.Writers.EPUB ( writeEPUB2, writeEPUB3 ) where
+import Prelude
 import Codec.Archive.Zip (Entry, addEntryToArchive, eRelativePath, emptyArchive,
                           fromArchive, fromEntry, toEntry)
 import Control.Monad (mplus, unless, when, zipWithM)
@@ -53,7 +55,7 @@ import Text.HTML.TagSoup (Tag (TagOpen), fromAttrib, parseTags)
 import Text.Pandoc.Builder (fromList, setMeta)
 import Text.Pandoc.Class (PandocMonad, report)
 import qualified Text.Pandoc.Class as P
-import Text.Pandoc.Compat.Time
+import Data.Time
 import Text.Pandoc.Definition
 import Text.Pandoc.Error
 import Text.Pandoc.Logging
@@ -401,6 +403,12 @@ pandocToEPUB version opts doc@(Pandoc meta _) = do
                       writeHtmlStringForEPUB version o
   metadata <- getEPUBMetadata opts meta
 
+  let plainTitle = case docTitle' meta of
+                        [] -> case epubTitle metadata of
+                                   []    -> "UNTITLED"
+                                   (x:_) -> titleText x
+                        x  -> stringify x
+
   -- stylesheet
   stylesheets <- case epubStylesheets metadata of
                       [] -> (\x -> [B.fromChunks [x]]) <$>
@@ -438,6 +446,7 @@ pandocToEPUB version opts doc@(Pandoc meta _) = do
                        cpContent <- lift $ writeHtml
                             opts'{ writerVariables =
                                     ("coverpage","true"):
+                                    ("pagetitle",plainTitle):
                                      cssvars True ++ vars }
                             (Pandoc meta [RawBlock (Format "html") $ "<div id=\"cover-image\">\n<img src=\"../media/" ++ coverImage ++ "\" alt=\"cover image\" />\n</div>"])
                        imgContent <- lift $ P.readFileLazy img
@@ -450,6 +459,7 @@ pandocToEPUB version opts doc@(Pandoc meta _) = do
   -- title page
   tpContent <- lift $ writeHtml opts'{
                                   writerVariables = ("titlepage","true"):
+                                  ("pagetitle",plainTitle):
                                   cssvars True ++ vars }
                                (Pandoc meta [])
   tpEntry <- mkEntry "text/title_page.xhtml" tpContent
@@ -458,7 +468,7 @@ pandocToEPUB version opts doc@(Pandoc meta _) = do
   -- mediaRef <- P.newIORef []
   Pandoc _ blocks <- walkM (transformInline opts') doc >>=
                      walkM transformBlock
-  picEntries <- (mapMaybe (snd . snd)) <$> gets stMediaPaths
+  picEntries <- mapMaybe (snd . snd) <$> gets stMediaPaths
   -- handle fonts
   let matchingGlob f = do
         xs <- lift $ P.glob f
@@ -602,11 +612,6 @@ pandocToEPUB version opts doc@(Pandoc meta _) = do
                                      $ eRelativePath ent),
                             ("media-type", fromMaybe "" $
                                   getMimeType $ eRelativePath ent)] $ ()
-  let plainTitle = case docTitle' meta of
-                        [] -> case epubTitle metadata of
-                                   []    -> "UNTITLED"
-                                   (x:_) -> titleText x
-                        x  -> stringify x
 
   let tocTitle = fromMaybe plainTitle $
                    metaValueToString <$> lookupMeta "toc-title" meta
@@ -747,14 +752,18 @@ pandocToEPUB version opts doc@(Pandoc meta _) = do
           where titElements = parseXML titRendered
                 titRendered = case P.runPure
                                (writeHtmlStringForEPUB version
-                                 opts{ writerTemplate = Nothing }
+                                 opts{ writerTemplate = Nothing
+                                     , writerVariables =
+                                       ("pagetitle",plainTitle):
+                                       writerVariables opts}
                                  (Pandoc nullMeta
-                                   [Plain $ walk delink tit])) of
+                                   [Plain $ walk clean tit])) of
                                 Left _  -> TS.pack $ stringify tit
                                 Right x -> x
-                -- can't have a element inside a...
-                delink (Link _ ils _) = Span ("", [], []) ils
-                delink x              = x
+                -- can't have <a> elements inside generated links...
+                clean (Link _ ils _) = Span ("", [], []) ils
+                clean (Note _)       = Str ""
+                clean x              = x
 
   let navtag = if epub3 then "nav" else "div"
   tocBlocks <- lift $ evalStateT (mapM (navPointNode navXhtmlFormatter) secs) 1
@@ -872,7 +881,7 @@ metadataElement version md currentTime =
         dcTag' n s = [dcTag n s]
         toIdentifierNode id' (Identifier txt scheme)
           | version == EPUB2 = [dcNode "identifier" !
-              ([("id",id')] ++ maybe [] (\x -> [("opf:scheme", x)]) scheme) $
+              (("id",id') : maybe [] (\x -> [("opf:scheme", x)]) scheme) $
               txt]
           | otherwise = [dcNode "identifier" ! [("id",id')] $ txt] ++
               maybe [] (\x -> [unode "meta" !
diff --git a/src/Text/Pandoc/Writers/FB2.hs b/src/Text/Pandoc/Writers/FB2.hs
index e322c7d98..a46011a8f 100644
--- a/src/Text/Pandoc/Writers/FB2.hs
+++ b/src/Text/Pandoc/Writers/FB2.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE PatternGuards #-}
 
 {-
@@ -37,6 +38,7 @@ FictionBook is an XML-based e-book format. For more information see:
 -}
 module Text.Pandoc.Writers.FB2 (writeFB2)  where
 
+import Prelude
 import Control.Monad (zipWithM)
 import Control.Monad.Except (catchError)
 import Control.Monad.State.Strict (StateT, evalStateT, get, lift, liftM, modify)
@@ -44,7 +46,7 @@ import Data.ByteString.Base64 (encode)
 import qualified Data.ByteString.Char8 as B8
 import Data.Char (isAscii, isControl, isSpace, toLower)
 import Data.Either (lefts, rights)
-import Data.List (intercalate, intersperse, isPrefixOf, stripPrefix)
+import Data.List (intercalate, isPrefixOf, stripPrefix)
 import Data.Text (Text, pack)
 import Network.HTTP (urlEncode)
 import Text.XML.Light
@@ -116,6 +118,9 @@ description meta' = do
   bt <- booktitle meta'
   let as = authors meta'
   dd <- docdate meta'
+  annotation <- case lookupMeta "abstract" meta' of
+                  Just (MetaBlocks bs) -> (list . el "annotation") <$> cMapM blockToXml bs
+                  _ -> pure mempty
   let lang = case lookupMeta "lang" meta' of
                Just (MetaInlines [Str s]) -> [el "lang" $ iso639 s]
                Just (MetaString s)        -> [el "lang" $ iso639 s]
@@ -130,7 +135,7 @@ description meta' = do
                     Just (MetaString s) -> coverimage s
                     _       -> return []
   return $ el "description"
-    [ el "title-info" (genre : (bt ++ as ++ dd ++ lang))
+    [ el "title-info" (genre : (bt ++ annotation ++ as ++ dd ++ lang))
     , el "document-info" (el "program-used" "pandoc" : coverpage)
     ]
 
@@ -178,7 +183,7 @@ renderSection :: PandocMonad m => Int -> ([Inline], [Block]) -> FBM m Content
 renderSection level (ttl, body) = do
     title <- if null ttl
             then return []
-            else return . list . el "title" . formatTitle $ ttl
+            else list . el "title" <$> formatTitle ttl
     content <- if hasSubsections body
                then renderSections (level + 1) body
                else cMapM blockToXml body
@@ -187,11 +192,9 @@ renderSection level (ttl, body) = do
     hasSubsections = any isHeaderBlock
 
 -- | Only <p> and <empty-line> are allowed within <title> in FB2.
-formatTitle :: [Inline] -> [Content]
+formatTitle :: PandocMonad m => [Inline] -> FBM m [Content]
 formatTitle inlines =
-  let lns = split isLineBreak inlines
-      lns' = map (el "p" . cMap plain) lns
-  in  intersperse (el "empty-line" ()) lns'
+  cMapM (blockToXml . Para) $ split (== LineBreak) inlines
 
 split :: (a -> Bool) -> [a] -> [[a]]
 split _ [] = []
@@ -311,9 +314,6 @@ isMimeType s =
 footnoteID :: Int -> String
 footnoteID i = "n" ++ show i
 
-linkID :: Int -> String
-linkID i = "l" ++ show i
-
 -- | Convert a block-level Pandoc's element to FictionBook XML representation.
 blockToXml :: PandocMonad m => Block -> FBM m [Content]
 blockToXml (Plain ss) = cMapM toXml ss  -- FIXME: can lead to malformed FB2
@@ -365,10 +365,7 @@ blockToXml h@Header{} = do
   -- should not occur after hierarchicalize, except inside lists/blockquotes
   report $ BlockNotRendered h
   return []
-blockToXml HorizontalRule = return
-                            [ el "empty-line" ()
-                            , el "p" (txt (replicate 10 '—'))
-                            , el "empty-line" () ]
+blockToXml HorizontalRule = return [ el "empty-line" () ]
 blockToXml (Table caption aligns _ headers rows) = do
     hd <- mkrow "th" headers aligns
     bd <- mapM (\r -> mkrow "td" r aligns) rows
@@ -398,7 +395,7 @@ plainToPara [] = []
 plainToPara (Plain inlines : rest) =
     Para inlines : plainToPara rest
 plainToPara (Para inlines : rest) =
-    Para inlines : Plain [LineBreak] : plainToPara rest
+    Para inlines : HorizontalRule : plainToPara rest -- HorizontalRule will be converted to <empty-line />
 plainToPara (p:rest) = p : plainToPara rest
 
 -- Simulate increased indentation level. Will not really work
@@ -449,29 +446,15 @@ toXml (Quoted DoubleQuote ss) = do
 toXml (Cite _ ss) = cMapM toXml ss  -- FIXME: support citation styles
 toXml (Code _ s) = return [el "code" s]
 toXml Space = return [txt " "]
-toXml SoftBreak = return [txt " "]
-toXml LineBreak = return [el "empty-line" ()]
+toXml SoftBreak = return [txt "\n"]
+toXml LineBreak = return [txt "\n"]
 toXml (Math _ formula) = insertMath InlineImage formula
 toXml il@(RawInline _ _) = do
   report $ InlineNotRendered il
   return []  -- raw TeX and raw HTML are suppressed
-toXml (Link _ text (url,ttl)) = do
-  fns <- footnotes `liftM` get
-  let n = 1 + length fns
-  let ln_id = linkID n
-  let ln_ref = list . el "sup" . txt $ "[" ++ show n ++ "]"
+toXml (Link _ text (url,_)) = do
   ln_text <- cMapM toXml text
-  let ln_desc =
-          let ttl' = dropWhile isSpace ttl
-          in if null ttl'
-             then list . el "p" $ el "code" url
-             else list . el "p" $ [ txt (ttl' ++ ": "), el "code" url ]
-  modify (\s -> s { footnotes = (n, ln_id, ln_desc) : fns })
-  return $ ln_text ++
-         [ el "a"
-                  ( [ attr ("l","href") ('#':ln_id)
-                    , uattr "type" "note" ]
-                  , ln_ref) ]
+  return [ el "a" ( [ attr ("l","href") url ], ln_text) ]
 toXml img@Image{} = insertImage InlineImage img
 toXml (Note bs) = do
   fns <- footnotes `liftM` get
diff --git a/src/Text/Pandoc/Writers/HTML.hs b/src/Text/Pandoc/Writers/HTML.hs
index 1647df7ea..646168c72 100644
--- a/src/Text/Pandoc/Writers/HTML.hs
+++ b/src/Text/Pandoc/Writers/HTML.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE CPP                 #-}
 {-# LANGUAGE OverloadedStrings   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
@@ -45,11 +46,11 @@ module Text.Pandoc.Writers.HTML (
   writeRevealJs,
   tagWithAttributes
   ) where
+import Prelude
 import Control.Monad.State.Strict
 import Data.Char (ord, toLower)
 import Data.List (intercalate, intersperse, isPrefixOf, partition)
 import Data.Maybe (catMaybes, fromMaybe, isJust, isNothing)
-import Data.Monoid ((<>))
 import qualified Data.Set as Set
 import Data.String (fromString)
 import Data.Text (Text)
@@ -259,10 +260,6 @@ pandocToHtml opts (Pandoc meta blocks) = do
   notes <- footnoteSection opts (reverse (stNotes st))
   let thebody = blocks' >> notes
   let  math = case writerHTMLMathMethod opts of
-                      LaTeXMathML (Just url) ->
-                         H.script ! A.src (toValue url)
-                                  ! A.type_ "text/javascript"
-                                  $ mempty
                       MathJax url
                         | slideVariant /= RevealJsSlides ->
                         -- mathjax is handled via a special plugin in revealjs
@@ -273,21 +270,15 @@ pandocToHtml opts (Pandoc meta blocks) = do
                                             preEscapedString
                                             "MathJax.Hub.Queue([\"Typeset\",MathJax.Hub]);"
                                          _ -> mempty
-                      JsMath (Just url) ->
-                         H.script ! A.src (toValue url)
-                                  ! A.type_ "text/javascript"
-                                  $ mempty
-                      KaTeX url ->
-                         (H.script !
-                           A.src (toValue $ url ++ "katex.min.js") $ mempty) <>
-                         (H.script !
-                           A.src (toValue $ url ++ "contrib/auto-render.min.js")
-                             $ mempty) <>
-                         (
-                                  H.script
-                            "document.addEventListener(\"DOMContentLoaded\", function() {\n  renderMathInElement(document.body);\n});") <>
-                         (H.link ! A.rel "stylesheet" !
-                           A.href (toValue $ url ++ "katex.min.css"))
+                      KaTeX url -> do
+                         H.script !
+                           A.src (toValue $ url ++ "katex.min.js") $ mempty
+                         H.script !
+                           A.src (toValue $ url ++ "contrib/auto-render.min.js") $ mempty
+                         H.script
+                            "document.addEventListener(\"DOMContentLoaded\", function() {\n  renderMathInElement(document.body);\n});"
+                         H.link ! A.rel "stylesheet" !
+                           A.href (toValue $ url ++ "katex.min.css")
 
                       _ -> case lookup "mathml-script" (writerVariables opts) of
                                  Just s | not (stHtml5 st) ->
@@ -363,7 +354,8 @@ defList :: PandocMonad m
 defList opts items = toList H.dl opts (items ++ [nl opts])
 
 -- | Construct table of contents from list of elements.
-tableOfContents :: PandocMonad m => WriterOptions -> [Element] -> StateT WriterState m (Maybe Html)
+tableOfContents :: PandocMonad m => WriterOptions -> [Element]
+                -> StateT WriterState m (Maybe Html)
 tableOfContents _ [] = return Nothing
 tableOfContents opts sects = do
   contents  <- mapM (elementToListItem opts) sects
@@ -378,7 +370,8 @@ showSecNum = intercalate "." . map show
 
 -- | Converts an Element to a list item for a table of contents,
 -- retrieving the appropriate identifier from state.
-elementToListItem :: PandocMonad m => WriterOptions -> Element -> StateT WriterState m (Maybe Html)
+elementToListItem :: PandocMonad m => WriterOptions -> Element
+                  -> StateT WriterState m (Maybe Html)
 -- Don't include the empty headers created in slide shows
 -- shows when an hrule is used to separate slides without a new title:
 elementToListItem _ (Sec _ _ _ [Str "\0"] _) = return Nothing
@@ -390,7 +383,8 @@ elementToListItem opts (Sec lev num (id',classes,_) headerText subsecs)
                    then (H.span ! A.class_ "toc-section-number"
                         $ toHtml $ showSecNum num') >> preEscapedString " "
                    else mempty
-  txt <- liftM (sectnum >>) $ inlineListToHtml opts $ walk deNote headerText
+  txt <- liftM (sectnum >>) $
+         inlineListToHtml opts $ walk (deLink . deNote) headerText
   subHeads <- mapM (elementToListItem opts) subsecs >>= return . catMaybes
   subList <- if null subHeads
                 then return mempty
@@ -406,8 +400,13 @@ elementToListItem opts (Sec lev num (id',classes,_) headerText subsecs)
                        $ toHtml txt) >> subList
 elementToListItem _ _ = return Nothing
 
+deLink :: Inline -> Inline
+deLink (Link _ ils _) = Span nullAttr ils
+deLink x              = x
+
 -- | Convert an Element to Html.
-elementToHtml :: PandocMonad m => Int -> WriterOptions -> Element -> StateT WriterState m Html
+elementToHtml :: PandocMonad m => Int -> WriterOptions -> Element
+              -> StateT WriterState m Html
 elementToHtml _slideLevel opts (Blk block) = blockToHtml opts block
 elementToHtml slideLevel opts (Sec level num (id',classes,keyvals) title' elements) = do
   slideVariant <- gets stSlideVariant
@@ -479,7 +478,12 @@ footnoteSection opts notes = do
   html5 <- gets stHtml5
   slideVariant <- gets stSlideVariant
   let hrtag = if html5 then H5.hr else H.hr
+  epubVersion <- gets stEPUBVersion
   let container x
+        | html5
+        , epubVersion == Just EPUB3
+                = H5.section ! A.class_ "footnotes"
+                             ! customAttribute "epub:type" "footnotes" $ x
         | html5 = H5.section ! A.class_ "footnotes" $ x
         | slideVariant /= NoSlides = H.div ! A.class_ "footnotes slide" $ x
         | otherwise = H.div ! A.class_ "footnotes" $ x
@@ -962,8 +966,9 @@ inlineToHtml opts inline = do
                                      WrapNone     -> preEscapedString " "
                                      WrapAuto     -> preEscapedString " "
                                      WrapPreserve -> preEscapedString "\n"
-    LineBreak      -> return $ (if html5 then H5.br else H.br)
-                                 <> strToHtml "\n"
+    LineBreak      -> return $ do
+                        if html5 then H5.br else H.br
+                        strToHtml "\n"
     (Span (id',classes,kvs) ils)
                      -> inlineListToHtml opts ils >>=
                            addAttrs opts attr' . H.span
@@ -1019,19 +1024,6 @@ inlineToHtml opts inline = do
       let mathClass = toValue $ ("math " :: String) ++
                       if t == InlineMath then "inline" else "display"
       case writerHTMLMathMethod opts of
-           LaTeXMathML _ ->
-              -- putting LaTeXMathML in container with class "LaTeX" prevents
-              -- non-math elements on the page from being treated as math by
-              -- the javascript
-              return $ H.span ! A.class_ "LaTeX" $
-                     case t of
-                       InlineMath  -> toHtml ("$" ++ str ++ "$")
-                       DisplayMath -> toHtml ("$$" ++ str ++ "$$")
-           JsMath _ -> do
-              let m = preEscapedString str
-              return $ case t of
-                       InlineMath  -> H.span ! A.class_ mathClass $ m
-                       DisplayMath -> H.div ! A.class_ mathClass $ m
            WebTeX url -> do
               let imtag = if html5 then H5.img else H.img
               let m = imtag ! A.style "vertical-align:middle"
@@ -1042,10 +1034,6 @@ inlineToHtml opts inline = do
               return $ case t of
                         InlineMath  -> m
                         DisplayMath -> brtag >> m >> brtag
-           GladTeX ->
-              return $ case t of
-                         InlineMath -> preEscapedString $ "<EQ ENV=\"math\">" ++ str ++ "</EQ>"
-                         DisplayMath -> preEscapedString $ "<EQ ENV=\"displaymath\">" ++ str ++ "</EQ>"
            MathML -> do
               let conf = useShortEmptyTags (const False)
                            defaultConfigPP
diff --git a/src/Text/Pandoc/Writers/Haddock.hs b/src/Text/Pandoc/Writers/Haddock.hs
index 688c1f390..75b8c78dc 100644
--- a/src/Text/Pandoc/Writers/Haddock.hs
+++ b/src/Text/Pandoc/Writers/Haddock.hs
@@ -1,6 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TupleSections       #-}
+
 {-
 Copyright (C) 2014-2015, 2017-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -33,9 +34,9 @@ Conversion of 'Pandoc' documents to haddock markup.
 Haddock:  <http://www.haskell.org/haddock/doc/html/>
 -}
 module Text.Pandoc.Writers.Haddock (writeHaddock) where
+import Prelude
 import Control.Monad.State.Strict
 import Data.Default
-import Data.List (intersperse, transpose)
 import Data.Text (Text)
 import Text.Pandoc.Class (PandocMonad, report)
 import Text.Pandoc.Definition
@@ -136,29 +137,15 @@ blockToHaddock _ (CodeBlock (_,_,_) str) =
 -- Nothing in haddock corresponds to block quotes:
 blockToHaddock opts (BlockQuote blocks) =
   blockListToHaddock opts blocks
--- Haddock doesn't have tables.  Use haddock tables in code.
 blockToHaddock opts (Table caption aligns widths headers rows) = do
   caption' <- inlineListToHaddock opts caption
   let caption'' = if null caption
                      then empty
                      else blankline <> caption' <> blankline
-  rawHeaders <- mapM (blockListToHaddock opts) headers
-  rawRows <- mapM (mapM (blockListToHaddock opts)) rows
-  let isSimple = all (==0) widths
-  let isPlainBlock (Plain _) = True
-      isPlainBlock _         = False
-  let hasBlocks = not (all isPlainBlock $ concat . concat $ headers:rows)
-  (nst,tbl) <- case True of
-                _ | isSimple -> (nest 2,) <$>
-                         pandocTable opts (all null headers) aligns widths
-                             rawHeaders rawRows
-                  | not hasBlocks -> (nest 2,) <$>
-                         pandocTable opts (all null headers) aligns widths
-                             rawHeaders rawRows
-                  | otherwise -> (id,) <$>
-                         gridTable opts blockListToHaddock
-                          (all null headers) aligns widths headers rows
-  return $ prefixed "> " (nst $ tbl $$ blankline $$ caption'') $$ blankline
+  tbl <- gridTable opts blockListToHaddock
+              (all null headers) (map (const AlignDefault) aligns)
+                widths headers rows
+  return $ prefixed "> " (tbl $$ blankline $$ caption'') $$ blankline
 blockToHaddock opts (BulletList items) = do
   contents <- mapM (bulletListItemToHaddock opts) items
   return $ cat contents <> blankline
@@ -174,46 +161,6 @@ blockToHaddock opts (DefinitionList items) = do
   contents <- mapM (definitionListItemToHaddock opts) items
   return $ cat contents <> blankline
 
-pandocTable :: PandocMonad m
-            => WriterOptions -> Bool -> [Alignment] -> [Double]
-            -> [Doc] -> [[Doc]] -> StateT WriterState m Doc
-pandocTable opts headless aligns widths rawHeaders rawRows =  do
-  let isSimple = all (==0) widths
-  let alignHeader alignment = case alignment of
-                                AlignLeft    -> lblock
-                                AlignCenter  -> cblock
-                                AlignRight   -> rblock
-                                AlignDefault -> lblock
-  let numChars = maximum . map offset
-  let widthsInChars = if isSimple
-                         then map ((+2) . numChars)
-                              $ transpose (rawHeaders : rawRows)
-                         else map
-                              (floor . (fromIntegral (writerColumns opts) *))
-                              widths
-  let makeRow = hcat . intersperse (lblock 1 (text " ")) .
-                   zipWith3 alignHeader aligns widthsInChars
-  let rows' = map makeRow rawRows
-  let head' = makeRow rawHeaders
-  let maxRowHeight = maximum $ map height (head':rows')
-  let underline = cat $ intersperse (text " ") $
-                  map (\width -> text (replicate width '-')) widthsInChars
-  let border
-        | maxRowHeight > 1 = text (replicate (sum widthsInChars +
-                 length widthsInChars - 1) '-')
-        | headless = underline
-        | otherwise = empty
-  let head'' = if headless
-                  then empty
-                  else border <> cr <> head'
-  let body = if maxRowHeight > 1
-                then vsep rows'
-                else vcat rows'
-  let bottom = if headless
-                  then underline
-                  else border
-  return $ head'' $$ underline $$ body $$ bottom
-
 -- | Convert bullet list item (list of blocks) to haddock
 bulletListItemToHaddock :: PandocMonad m
                         => WriterOptions -> [Block] -> StateT WriterState m Doc
diff --git a/src/Text/Pandoc/Writers/ICML.hs b/src/Text/Pandoc/Writers/ICML.hs
index a5d851e40..266d58007 100644
--- a/src/Text/Pandoc/Writers/ICML.hs
+++ b/src/Text/Pandoc/Writers/ICML.hs
@@ -1,5 +1,6 @@
-{-# LANGUAGE FlexibleContexts    #-}
-{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
 {- |
@@ -16,6 +17,7 @@ InCopy is the companion word-processor to Adobe InDesign and ICML documents can
 into InDesign with File -> Place.
 -}
 module Text.Pandoc.Writers.ICML (writeICML) where
+import Prelude
 import Control.Monad.Except (catchError)
 import Control.Monad.State.Strict
 import Data.List (intersperse, isInfixOf, isPrefixOf, stripPrefix)
diff --git a/src/Text/Pandoc/Writers/JATS.hs b/src/Text/Pandoc/Writers/JATS.hs
index 639961acd..fb3236bd9 100644
--- a/src/Text/Pandoc/Writers/JATS.hs
+++ b/src/Text/Pandoc/Writers/JATS.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 {-
@@ -28,9 +29,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
 Conversion of 'Pandoc' documents to JATS XML.
 Reference:
-https://jats.nlm.nih.gov/publishing/tag-library/1.1d3/element/mml-math.html
+https://jats.nlm.nih.gov/publishing/tag-library
 -}
 module Text.Pandoc.Writers.JATS ( writeJATS ) where
+import Prelude
 import Control.Monad.Reader
 import Data.Char (toLower)
 import Data.Generics (everywhere, mkT)
@@ -139,7 +141,7 @@ deflistItemToJATS opts term defs = do
   term' <- inlinesToJATS opts term
   def' <- blocksToJATS opts $ concatMap (map plainToPara) defs
   return $ inTagsIndented "def-item" $
-      inTagsIndented "term" term' $$
+      inTagsSimple "term" term' $$
       inTagsIndented "def" def'
 
 -- | Convert a list of lists of blocks to a list of JATS list items.
@@ -156,7 +158,7 @@ listItemToJATS :: PandocMonad m
 listItemToJATS opts mbmarker item = do
   contents <- blocksToJATS opts item
   return $ inTagsIndented "list-item" $
-           maybe empty (\lbl -> inTagsIndented "label" (text lbl)) mbmarker
+           maybe empty (\lbl -> inTagsSimple "label" (text lbl)) mbmarker
            $$ contents
 
 imageMimeType :: String -> [(String, String)] -> (String, String)
@@ -250,7 +252,7 @@ blockToJATS _ (Para [Image (ident,_,kvs) _ (src, tit)]) = do
                         "xlink:type"]]
   return $ selfClosingTag "graphic" attr
 blockToJATS opts (Para lst) =
-  inTagsIndented "p" <$> inlinesToJATS opts lst
+  inTagsSimple "p" <$> inlinesToJATS opts lst
 blockToJATS opts (LineBlock lns) =
   blockToJATS opts $ linesToPara lns
 blockToJATS opts (BlockQuote blocks) =
@@ -326,10 +328,10 @@ tableItemToJATS :: PandocMonad m
                    -> [Block]
                    -> JATS m Doc
 tableItemToJATS opts isHeader [Plain item] =
-  inTags True (if isHeader then "th" else "td") [] <$>
+  inTags False (if isHeader then "th" else "td") [] <$>
     inlinesToJATS opts item
 tableItemToJATS opts isHeader item =
-  (inTags True (if isHeader then "th" else "td") [] . vcat) <$>
+  (inTags False (if isHeader then "th" else "td") [] . vcat) <$>
     mapM (blockToJATS opts) item
 
 -- | Convert a list of inline elements to JATS.
diff --git a/src/Text/Pandoc/Writers/LaTeX.hs b/src/Text/Pandoc/Writers/LaTeX.hs
index f61c878e5..2904bec06 100644
--- a/src/Text/Pandoc/Writers/LaTeX.hs
+++ b/src/Text/Pandoc/Writers/LaTeX.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings   #-}
 {-# LANGUAGE PatternGuards       #-}
 {-# LANGUAGE ScopedTypeVariables #-}
@@ -34,6 +35,7 @@ module Text.Pandoc.Writers.LaTeX (
     writeLaTeX
   , writeBeamer
   ) where
+import Prelude
 import Control.Applicative ((<|>))
 import Control.Monad.State.Strict
 import Data.Aeson (FromJSON, object, (.=))
@@ -411,15 +413,15 @@ elementToBeamer slideLevel  (Sec lvl _num (ident,classes,kvs) tit elts)
       slideTitle <-
             if tit == [Str "\0"] -- marker for hrule
                then return []
-               else
-                 if null ident
-                    then return $ latex "{" : tit ++ [latex "}"]
-                    else do
-                      ref <- toLabel ident
-                      return $ latex ("{%\n\\protect\\hypertarget{" ++
-                                ref ++ "}{%\n") : tit ++ [latex "}}"]
+               else return $ latex "{" : tit ++ [latex "}"]
+      ref <- toLabel ident
+      let slideAnchor = if null ident
+                           then []
+                           else [latex ("\n\\protect\\hypertarget{" ++
+                                  ref ++ "}{}")]
       let slideStart = Para $
-              RawInline "latex" ("\\begin{frame}" ++ options) : slideTitle
+              RawInline "latex" ("\\begin{frame}" ++ options) :
+                 slideTitle ++ slideAnchor
       let slideEnd = RawBlock "latex" "\\end{frame}"
       -- now carve up slide into blocks if there are sections inside
       bs <- concat `fmap` mapM (elementToBeamer slideLevel) elts
@@ -676,6 +678,7 @@ blockToLaTeX (OrderedList (start, numstyle, numdelim) lst) = do
   let enum = text $ "enum" ++ map toLower (toRomanNumeral oldlevel)
   let stylecommand
         | numstyle == DefaultStyle && numdelim == DefaultDelim = empty
+        | beamer && numstyle == Decimal && numdelim == Period = empty
         | beamer = brackets (todelim exemplar)
         | otherwise = "\\def" <> "\\label" <> enum <>
           braces (todelim $ tostyle enum)
@@ -1033,7 +1036,7 @@ inlineToLaTeX (Code (_,classes,_) str) = do
                                Nothing -> ""
         inNote <- gets stInNote
         when inNote $ modify $ \s -> s{ stVerbInNote = True }
-        let chr = case "!\"&'()*,-./:;?@_" \\ str of
+        let chr = case "!\"'()*,-./:;?@" \\ str of
                        (c:_) -> c
                        []    -> '!'
         let str' = escapeStringUsing (backslashEscapes "\\{}%~_&") str
diff --git a/src/Text/Pandoc/Writers/Man.hs b/src/Text/Pandoc/Writers/Man.hs
index 1be955fe3..912231a88 100644
--- a/src/Text/Pandoc/Writers/Man.hs
+++ b/src/Text/Pandoc/Writers/Man.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-
 Copyright (C) 2007-2018 John MacFarlane <jgm@berkeley.edu>
@@ -30,6 +31,7 @@ Conversion of 'Pandoc' documents to groff man page format.
 
 -}
 module Text.Pandoc.Writers.Man ( writeMan) where
+import Prelude
 import Control.Monad.State.Strict
 import Data.List (intercalate, intersperse, sort, stripPrefix)
 import qualified Data.Map as Map
diff --git a/src/Text/Pandoc/Writers/Markdown.hs b/src/Text/Pandoc/Writers/Markdown.hs
index cdd8f3b66..075858e5e 100644
--- a/src/Text/Pandoc/Writers/Markdown.hs
+++ b/src/Text/Pandoc/Writers/Markdown.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE MultiWayIf          #-}
 {-# LANGUAGE OverloadedStrings   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
@@ -34,6 +35,7 @@ Conversion of 'Pandoc' documents to markdown-formatted plain text.
 Markdown:  <http://daringfireball.net/projects/markdown/>
 -}
 module Text.Pandoc.Writers.Markdown (writeMarkdown, writePlain) where
+import Prelude
 import Control.Monad.Reader
 import Control.Monad.State.Strict
 import Data.Char (chr, isPunctuation, isSpace, ord, isAlphaNum)
@@ -730,7 +732,10 @@ pandocTable opts multiline headless aligns widths rawHeaders rawRows = do
                   then empty
                   else border <> cr <> head'
   let body = if multiline
-                then vsep rows'
+                then vsep rows' $$
+                     if length rows' < 2
+                        then blankline -- #4578
+                        else empty
                 else vcat rows'
   let bottom = if headless
                   then underline
diff --git a/src/Text/Pandoc/Writers/Math.hs b/src/Text/Pandoc/Writers/Math.hs
index 477f5a0b1..99d17d594 100644
--- a/src/Text/Pandoc/Writers/Math.hs
+++ b/src/Text/Pandoc/Writers/Math.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 module Text.Pandoc.Writers.Math
   ( texMathToInlines
   , convertMath
@@ -6,6 +7,7 @@ module Text.Pandoc.Writers.Math
   )
 where
 
+import Prelude
 import Text.Pandoc.Class
 import Text.Pandoc.Definition
 import Text.Pandoc.Logging
diff --git a/src/Text/Pandoc/Writers/MediaWiki.hs b/src/Text/Pandoc/Writers/MediaWiki.hs
index 2470d9200..df50028a0 100644
--- a/src/Text/Pandoc/Writers/MediaWiki.hs
+++ b/src/Text/Pandoc/Writers/MediaWiki.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2008-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -30,6 +31,7 @@ Conversion of 'Pandoc' documents to MediaWiki markup.
 MediaWiki:  <http://www.mediawiki.org/wiki/MediaWiki>
 -}
 module Text.Pandoc.Writers.MediaWiki ( writeMediaWiki ) where
+import Prelude
 import Control.Monad.Reader
 import Control.Monad.State.Strict
 import Data.List (intercalate)
diff --git a/src/Text/Pandoc/Writers/Ms.hs b/src/Text/Pandoc/Writers/Ms.hs
index 83d80cd4a..16a66c85b 100644
--- a/src/Text/Pandoc/Writers/Ms.hs
+++ b/src/Text/Pandoc/Writers/Ms.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2007-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -36,9 +37,10 @@ TODO:
 -}
 
 module Text.Pandoc.Writers.Ms ( writeMs ) where
+import Prelude
 import Control.Monad.State.Strict
-import Data.Char (isLower, isUpper, toUpper)
-import Data.List (intercalate, intersperse, sort)
+import Data.Char (isLower, isUpper, toUpper, ord)
+import Data.List (intercalate, intersperse)
 import qualified Data.Map as Map
 import Data.Maybe (catMaybes, fromMaybe)
 import Data.Text (Text)
@@ -46,6 +48,7 @@ import qualified Data.Text as T
 import Network.URI (escapeURIString, isAllowedInURI)
 import Skylighting
 import System.FilePath (takeExtension)
+import Text.Pandoc.Asciify (toAsciiChar)
 import Text.Pandoc.Class (PandocMonad, report)
 import Text.Pandoc.Definition
 import Text.Pandoc.Highlighting
@@ -65,6 +68,7 @@ data WriterState = WriterState { stHasInlineMath :: Bool
                                , stNotes         :: [Note]
                                , stSmallCaps     :: Bool
                                , stHighlighting  :: Bool
+                               , stInHeader      :: Bool
                                , stFontFeatures  :: Map.Map Char Bool
                                }
 
@@ -74,6 +78,7 @@ defaultWriterState = WriterState{ stHasInlineMath = False
                                 , stNotes         = []
                                 , stSmallCaps     = False
                                 , stHighlighting  = False
+                                , stInHeader      = False
                                 , stFontFeatures  = Map.fromList [
                                                        ('I',False)
                                                      , ('B',False)
@@ -132,14 +137,12 @@ msEscapes = Map.fromList
               [ ('\160', "\\~")
               , ('\'', "\\[aq]")
               , ('`', "\\`")
-              , ('\8217', "'")
               , ('"', "\\[dq]")
               , ('\x2014', "\\[em]")
               , ('\x2013', "\\[en]")
               , ('\x2026', "\\&...")
               , ('~', "\\[ti]")
               , ('^', "\\[ha]")
-              , ('-', "\\-")
               , ('@', "\\@")
               , ('\\', "\\\\")
               ]
@@ -216,11 +219,16 @@ blockToMs :: PandocMonad m
           -> Block         -- ^ Block element
           -> MS m Doc
 blockToMs _ Null = return empty
-blockToMs opts (Div _ bs) = do
+blockToMs opts (Div (ident,_,_) bs) = do
+  let anchor = if null ident
+                  then empty
+                  else nowrap $
+                         text ".pdfhref M "
+                         <> doubleQuotes (text (toAscii ident))
   setFirstPara
   res <- blockListToMs opts bs
   setFirstPara
-  return res
+  return $ anchor $$ res
 blockToMs opts (Plain inlines) =
   liftM vcat $ mapM (inlineListToMs' opts) $ splitSentences inlines
 blockToMs opts (Para [Image attr alt (src,_tit)])
@@ -258,7 +266,9 @@ blockToMs _ HorizontalRule = do
   return $ text ".HLINE"
 blockToMs opts (Header level (ident,classes,_) inlines) = do
   setFirstPara
+  modify $ \st -> st{ stInHeader = True }
   contents <- inlineListToMs' opts $ map breakToSpace inlines
+  modify $ \st -> st{ stInHeader = False }
   let (heading, secnum) = if writerNumberSections opts &&
                               "unnumbered" `notElem` classes
                              then (".NH", "\\*[SN]")
@@ -266,7 +276,8 @@ blockToMs opts (Header level (ident,classes,_) inlines) = do
   let anchor = if null ident
                   then empty
                   else nowrap $
-                         text ".pdfhref M " <> doubleQuotes (text ident)
+                         text ".pdfhref M "
+                         <> doubleQuotes (text (toAscii ident))
   let bookmark = text ".pdfhref O " <> text (show level ++ " ") <>
                       doubleQuotes (text $ secnum ++
                                       (if null secnum
@@ -274,7 +285,7 @@ blockToMs opts (Header level (ident,classes,_) inlines) = do
                                           else "  ") ++
                                       escapeString (stringify inlines))
   let backlink = nowrap (text ".pdfhref L -D " <>
-       doubleQuotes (text ident) <> space <> text "\\") <> cr <>
+       doubleQuotes (text (toAscii ident)) <> space <> text "\\") <> cr <>
        text " -- "
   let tocEntry = if writerTableOfContents opts &&
                      level <= writerTOCDepth opts
@@ -513,7 +524,7 @@ inlineToMs opts (Link _ txt ('#':ident, _)) = do
   -- internal link
   contents <- inlineListToMs' opts $ map breakToSpace txt
   return $ text "\\c" <> cr <> nowrap (text ".pdfhref L -D " <>
-       doubleQuotes (text ident) <> text " -A " <>
+       doubleQuotes (text (toAscii ident)) <> text " -A " <>
        doubleQuotes (text "\\c") <> space <> text "\\") <> cr <>
        text " -- " <> doubleQuotes (nowrap contents) <> cr <> text "\\&"
 inlineToMs opts (Link _ txt (src, _)) = do
@@ -552,8 +563,15 @@ handleNote opts bs = do
 fontChange :: PandocMonad m => MS m Doc
 fontChange = do
   features <- gets stFontFeatures
-  let filling = sort [c | (c,True) <- Map.toList features]
-  return $ text $ "\\f[" ++ filling ++ "]"
+  inHeader <- gets stInHeader
+  let filling = ['C' | fromMaybe False $ Map.lookup 'C' features] ++
+                ['B' | inHeader ||
+                       fromMaybe False (Map.lookup 'B' features)] ++
+                ['I' | fromMaybe False $ Map.lookup 'I' features]
+  return $
+    if null filling
+       then text "\\f[R]"
+       else text $ "\\f[" ++ filling ++ "]"
 
 withFontFeature :: PandocMonad m => Char -> MS m Doc -> MS m Doc
 withFontFeature c action = do
@@ -637,3 +655,11 @@ highlightCode opts attr str =
          Right h -> do
            modify (\st -> st{ stHighlighting = True })
            return h
+
+-- This is used for PDF anchors.
+toAscii :: String -> String
+toAscii = concatMap
+  (\c -> case toAsciiChar c of
+              Nothing -> '_':'u':show (ord c) ++ "_"
+              Just '/' -> '_':'u':show (ord c) ++ "_" -- see #4515
+              Just c' -> [c'])
diff --git a/src/Text/Pandoc/Writers/Muse.hs b/src/Text/Pandoc/Writers/Muse.hs
index 7f53e202d..3681fcc0d 100644
--- a/src/Text/Pandoc/Writers/Muse.hs
+++ b/src/Text/Pandoc/Writers/Muse.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-
 Copyright (C) 2017-2018 Alexander Krotov <ilabdsf@gmail.com>
@@ -42,7 +43,11 @@ However, @\<literal style="html">@ tag is used for HTML raw blocks
 even though it is supported only in Emacs Muse.
 -}
 module Text.Pandoc.Writers.Muse (writeMuse) where
+import Prelude
+import Control.Monad.Reader
 import Control.Monad.State.Strict
+import Data.Char (isSpace, isDigit, isAsciiUpper, isAsciiLower)
+import Data.Default
 import Data.Text (Text)
 import Data.List (intersperse, transpose, isInfixOf)
 import System.FilePath (takeExtension)
@@ -58,34 +63,54 @@ import Text.Pandoc.Writers.Shared
 import qualified Data.Set as Set
 
 type Notes = [[Block]]
+
+type Muse m = ReaderT WriterEnv (StateT WriterState m)
+
+data WriterEnv =
+  WriterEnv { envOptions :: WriterOptions
+            , envTopLevel :: Bool
+            , envInsideBlock :: Bool
+            , envInlineStart :: Bool
+            , envInsideLinkDescription :: Bool -- ^ Escape ] if True
+            , envAfterSpace :: Bool
+            , envOneLine :: Bool -- ^ True if newlines are not allowed
+            }
+
 data WriterState =
   WriterState { stNotes       :: Notes
-              , stOptions     :: WriterOptions
-              , stTopLevel    :: Bool
-              , stInsideBlock :: Bool
               , stIds         :: Set.Set String
               }
 
+instance Default WriterState
+  where def = WriterState { stNotes = []
+                          , stIds = Set.empty
+                          }
+
+evalMuse :: PandocMonad m => Muse m a -> WriterEnv -> WriterState -> m a
+evalMuse document env = evalStateT $ runReaderT document env
+
 -- | Convert Pandoc to Muse.
 writeMuse :: PandocMonad m
           => WriterOptions
           -> Pandoc
           -> m Text
 writeMuse opts document =
-  let st = WriterState { stNotes = []
-                       , stOptions = opts
-                       , stTopLevel = True
-                       , stInsideBlock = False
-                       , stIds = Set.empty
-                       }
-  in evalStateT (pandocToMuse document) st
+  evalMuse (pandocToMuse document) env def
+  where env = WriterEnv { envOptions = opts
+                        , envTopLevel = True
+                        , envInsideBlock = False
+                        , envInlineStart = True
+                        , envInsideLinkDescription = False
+                        , envAfterSpace = False
+                        , envOneLine = False
+                        }
 
 -- | Return Muse representation of document.
 pandocToMuse :: PandocMonad m
              => Pandoc
-             -> StateT WriterState m Text
+             -> Muse m Text
 pandocToMuse (Pandoc meta blocks) = do
-  opts <- gets stOptions
+  opts <- asks envOptions
   let colwidth = if writerWrapText opts == WrapAuto
                     then Just $ writerColumns opts
                     else Nothing
@@ -96,7 +121,7 @@ pandocToMuse (Pandoc meta blocks) = do
                (fmap render' . inlineListToMuse)
                meta
   body <- blockListToMuse blocks
-  notes <- liftM (reverse . stNotes) get >>= notesToMuse
+  notes <- fmap (reverse . stNotes) get >>= notesToMuse
   let main = render colwidth $ body $+$ notes
   let context = defField "body" main metadata
   case writerTemplate opts of
@@ -108,7 +133,7 @@ pandocToMuse (Pandoc meta blocks) = do
 catWithBlankLines :: PandocMonad m
                   => [Block]       -- ^ List of block elements
                   -> Int           -- ^ Number of blank lines
-                  -> StateT WriterState m Doc
+                  -> Muse m Doc
 catWithBlankLines (b : bs) n = do
   b' <- blockToMuse b
   bs' <- flatBlockListToMuse bs
@@ -116,10 +141,10 @@ catWithBlankLines (b : bs) n = do
 catWithBlankLines _ _ = error "Expected at least one block"
 
 -- | Convert list of Pandoc block elements to Muse
--- | without setting stTopLevel.
+-- | without setting envTopLevel.
 flatBlockListToMuse :: PandocMonad m
                 => [Block]       -- ^ List of block elements
-                -> StateT WriterState m Doc
+                -> Muse m Doc
 flatBlockListToMuse bs@(BulletList _ : BulletList _ : _) = catWithBlankLines bs 2
 flatBlockListToMuse bs@(OrderedList (_, style1, _) _ : OrderedList (_, style2, _) _ : _) =
   catWithBlankLines bs (if style1' == style2' then 2 else 0)
@@ -135,36 +160,23 @@ flatBlockListToMuse [] = return mempty
 -- | Convert list of Pandoc block elements to Muse.
 blockListToMuse :: PandocMonad m
                 => [Block]       -- ^ List of block elements
-                -> StateT WriterState m Doc
-blockListToMuse blocks = do
-  oldState <- get
-  modify $ \s -> s { stTopLevel = not $ stInsideBlock s
-                   , stInsideBlock = True
-                   }
-  result <- flatBlockListToMuse blocks
-  modify $ \s -> s { stTopLevel = stTopLevel oldState
-                   , stInsideBlock = stInsideBlock oldState
-                   }
-  return result
+                -> Muse m Doc
+blockListToMuse =
+  local (\env -> env { envTopLevel = not (envInsideBlock env)
+                     , envInsideBlock = True
+                     }) . flatBlockListToMuse
 
 -- | Convert Pandoc block element to Muse.
 blockToMuse :: PandocMonad m
             => Block         -- ^ Block element
-            -> StateT WriterState m Doc
-blockToMuse (Plain inlines) = inlineListToMuse inlines
+            -> Muse m Doc
+blockToMuse (Plain inlines) = inlineListToMuse' inlines
 blockToMuse (Para inlines) = do
-  contents <- inlineListToMuse inlines
+  contents <- inlineListToMuse' inlines
   return $ contents <> blankline
 blockToMuse (LineBlock lns) = do
-  let splitStanza [] = []
-      splitStanza xs = case break (== mempty) xs of
-        (l, [])  -> [l]
-        (l, _:r) -> l : splitStanza r
-  let joinWithLinefeeds  = nowrap . mconcat . intersperse cr
-  let joinWithBlankLines = mconcat . intersperse blankline
-  let prettyfyStanza ls  = joinWithLinefeeds <$> mapM inlineListToMuse ls
-  contents <- joinWithBlankLines <$> mapM prettyfyStanza (splitStanza lns)
-  return $ blankline $$ "<verse>" $$ contents $$ "</verse>" <> blankline
+  lns' <- local (\env -> env { envOneLine = True }) $ mapM inlineListToMuse lns
+  return $ nowrap $ vcat (map (text "> " <>) lns') <> blankline
 blockToMuse (CodeBlock (_,_,_) str) =
   return $ "<example>" $$ text str $$ "</example>" $$ blankline
 blockToMuse (RawBlock (Format format) str) =
@@ -180,50 +192,48 @@ blockToMuse (BlockQuote blocks) = do
 blockToMuse (OrderedList (start, style, _) items) = do
   let markers = take (length items) $ orderedListMarkers
                                       (start, style, Period)
-  let maxMarkerLength = maximum $ map length markers
-  let markers' = map (\m -> let s = maxMarkerLength - length m
-                            in  m ++ replicate s ' ') markers
-  contents <- zipWithM orderedListItemToMuse markers' items
+  contents <- zipWithM orderedListItemToMuse markers items
   -- ensure that sublists have preceding blank line
-  topLevel <- gets stTopLevel
+  topLevel <- asks envTopLevel
   return $ cr $$ (if topLevel then nest 1 else id) (vcat contents) $$ blankline
   where orderedListItemToMuse :: PandocMonad m
                               => String   -- ^ marker for list item
                               -> [Block]  -- ^ list item (list of blocks)
-                              -> StateT WriterState m Doc
+                              -> Muse m Doc
         orderedListItemToMuse marker item = do
-        contents <- blockListToMuse item
-        return $ hang (length marker + 1) (text marker <> space) contents
+          contents <- blockListToMuse item
+          return $ hang (length marker + 1) (text marker <> space) contents
 blockToMuse (BulletList items) = do
   contents <- mapM bulletListItemToMuse items
   -- ensure that sublists have preceding blank line
-  topLevel <- gets stTopLevel
+  topLevel <- asks envTopLevel
   return $ cr $$ (if topLevel then nest 1 else id) (vcat contents) $$ blankline
   where bulletListItemToMuse :: PandocMonad m
                              => [Block]
-                             -> StateT WriterState m Doc
+                             -> Muse m Doc
         bulletListItemToMuse item = do
           contents <- blockListToMuse item
           return $ hang 2 "- " contents
 blockToMuse (DefinitionList items) = do
   contents <- mapM definitionListItemToMuse items
-  return $ cr $$ nest 1 (vcat contents) $$ blankline
+  -- ensure that sublists have preceding blank line
+  topLevel <- asks envTopLevel
+  return $ cr $$ (if topLevel then nest 1 else id) (vcat contents) $$ blankline
   where definitionListItemToMuse :: PandocMonad m
                                  => ([Inline], [[Block]])
-                                 -> StateT WriterState m Doc
+                                 -> Muse m Doc
         definitionListItemToMuse (label, defs) = do
-          label' <- inlineListToMuse label
-          contents <- liftM vcat $ mapM descriptionToMuse defs
+          label' <- local (\env -> env { envOneLine = True, envAfterSpace = True }) $ inlineListToMuse' label
+          contents <- vcat <$> mapM descriptionToMuse defs
           let ind = offset label'
           return $ hang ind label' contents
         descriptionToMuse :: PandocMonad m
                           => [Block]
-                          -> StateT WriterState m Doc
+                          -> Muse m Doc
         descriptionToMuse desc = hang 4 " :: " <$> blockListToMuse desc
 blockToMuse (Header level (ident,_,_) inlines) = do
-  opts <- gets stOptions
-  contents <- inlineListToMuse inlines
-
+  opts <- asks envOptions
+  contents <- local (\env -> env { envOneLine = True }) $ inlineListToMuse' inlines
   ids <- gets stIds
   let autoId = uniqueIdent inlines ids
   modify $ \st -> st{ stIds = Set.insert autoId ids }
@@ -232,8 +242,7 @@ blockToMuse (Header level (ident,_,_) inlines) = do
                  then empty
                  else "#" <> text ident <> cr
   let header' = text $ replicate level '*'
-  return $ blankline <> nowrap (header' <> space <> contents)
-                 $$ attr' <> blankline
+  return $ blankline <> attr' $$ nowrap (header' <> space <> contents) <> 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
@@ -266,18 +275,18 @@ blockToMuse Null = return empty
 -- | Return Muse representation of notes.
 notesToMuse :: PandocMonad m
             => Notes
-            -> StateT WriterState m Doc
-notesToMuse notes = liftM vsep (zipWithM noteToMuse [1 ..] notes)
+            -> Muse m Doc
+notesToMuse notes = vsep <$> zipWithM noteToMuse [1 ..] notes
 
 -- | Return Muse representation of a note.
 noteToMuse :: PandocMonad m
            => Int
            -> [Block]
-           -> StateT WriterState m Doc
-noteToMuse num note = do
-  contents <- blockListToMuse note
-  let marker = "[" ++ show num ++ "] "
-  return $ hang (length marker) (text marker) contents
+           -> Muse m Doc
+noteToMuse num note =
+  hang (length marker) (text marker) <$> blockListToMuse note
+  where
+    marker = "[" ++ show num ++ "] "
 
 -- | Escape special characters for Muse.
 escapeString :: String -> String
@@ -286,17 +295,74 @@ escapeString s =
   substitute "</verbatim>" "<</verbatim><verbatim>/verbatim>" s ++
   "</verbatim>"
 
+startsWithMarker :: (Char -> Bool) -> String -> Bool
+startsWithMarker f (' ':xs) = startsWithMarker f xs
+startsWithMarker f (x:xs) =
+  f x && (startsWithMarker f xs || startsWithDot xs)
+  where
+    startsWithDot ['.'] = True
+    startsWithDot ('.':c:_) = isSpace c
+    startsWithDot _ = False
+startsWithMarker _ [] = False
+
 -- | Escape special characters for Muse if needed.
-conditionalEscapeString :: String -> String
-conditionalEscapeString s =
-  if any (`elem` ("#*<=>[]|" :: String)) s ||
+containsFootnotes :: String -> Bool
+containsFootnotes = p
+  where p ('[':xs) = q xs || p xs
+        p (_:xs) = p xs
+        p "" = False
+        q (x:xs)
+          | x `elem` ("123456789"::String) = r xs || p xs
+          | otherwise = p xs
+        q [] = False
+        r ('0':xs) = r xs || p xs
+        r xs = s xs || q xs || p xs
+        s (']':_) = True
+        s (_:xs) = p xs
+        s [] = False
+
+conditionalEscapeString :: Bool -> String -> String
+conditionalEscapeString isInsideLinkDescription s =
+  if any (`elem` ("#*<=|" :: String)) s ||
      "::" `isInfixOf` s ||
-     "----" `isInfixOf` s ||
-     "~~" `isInfixOf` s
+     "~~" `isInfixOf` s ||
+     "[[" `isInfixOf` s ||
+     ("]" `isInfixOf` s && isInsideLinkDescription) ||
+     containsFootnotes s
     then escapeString s
     else s
 
+-- Expand Math and Cite before normalizing inline list
+preprocessInlineList :: PandocMonad m
+                     => [Inline]
+                     -> m [Inline]
+preprocessInlineList (Math t str:xs) = (++) <$> texMathToInlines t str <*> preprocessInlineList xs
+-- Amusewiki does not support <cite> tag,
+-- and Emacs Muse citation support is limited
+-- (https://www.gnu.org/software/emacs-muse/manual/html_node/Citations.html#Citation)
+-- so just fallback to expanding inlines.
+preprocessInlineList (Cite _  lst:xs) = (lst ++) <$> preprocessInlineList xs
+preprocessInlineList (x:xs) = (x:) <$> preprocessInlineList xs
+preprocessInlineList [] = return []
+
+replaceSmallCaps :: Inline -> Inline
+replaceSmallCaps (SmallCaps lst) = Emph lst
+replaceSmallCaps x = x
+
+removeKeyValues :: Inline -> Inline
+removeKeyValues (Code (i, cls, _) xs) = Code (i, cls, []) xs
+-- Do not remove attributes from Link
+-- Do not remove attributes, such as "width", from Image
+removeKeyValues (Span (i, cls, _) xs) = Span (i, cls, []) xs
+removeKeyValues x = x
+
 normalizeInlineList :: [Inline] -> [Inline]
+normalizeInlineList (Str "" : xs)
+  = normalizeInlineList xs
+normalizeInlineList (x : Str "" : xs)
+  = normalizeInlineList (x:xs)
+normalizeInlineList (Str x1 : Str x2 : xs)
+  = normalizeInlineList $ Str (x1 ++ x2) : xs
 normalizeInlineList (Emph x1 : Emph x2 : ils)
   = normalizeInlineList $ Emph (x1 ++ x2) : ils
 normalizeInlineList (Strong x1 : Strong x2 : ils)
@@ -313,8 +379,7 @@ normalizeInlineList (Code _ x1 : Code _ x2 : ils)
   = normalizeInlineList $ Code nullAttr (x1 ++ x2) : ils
 normalizeInlineList (RawInline f1 x1 : RawInline f2 x2 : ils) | f1 == f2
   = normalizeInlineList $ RawInline f1 (x1 ++ x2) : ils
-normalizeInlineList (Span a1 x1 : Span a2 x2 : ils) | a1 == a2
-  = normalizeInlineList $ Span a1 (x1 ++ x2) : ils
+-- Do not join Span's during normalization
 normalizeInlineList (x:xs) = x : normalizeInlineList xs
 normalizeInlineList [] = []
 
@@ -324,17 +389,77 @@ 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
+urlEscapeBrackets :: String -> String
+urlEscapeBrackets (']':xs) = '%':'5':'D':urlEscapeBrackets xs
+urlEscapeBrackets (x:xs) = x:urlEscapeBrackets xs
+urlEscapeBrackets [] = []
+
+isHorizontalRule :: String -> Bool
+isHorizontalRule s = length s >= 4 && all (== '-') s
+
+startsWithSpace :: String -> Bool
+startsWithSpace (x:_) = isSpace x
+startsWithSpace [] = False
+
+fixOrEscape :: Bool -> Inline -> Bool
+fixOrEscape sp (Str "-") = sp
+fixOrEscape sp (Str ";") = not sp
+fixOrEscape _ (Str ">") = True
+fixOrEscape sp (Str s) = (sp && (startsWithMarker isDigit s ||
+                                startsWithMarker isAsciiLower s ||
+                                startsWithMarker isAsciiUpper s))
+                         || isHorizontalRule s || startsWithSpace s
+fixOrEscape _ Space = True
+fixOrEscape _ SoftBreak = True
+fixOrEscape _ _ = False
+
+-- | Convert list of Pandoc inline elements to Muse
+renderInlineList :: PandocMonad m
                  => [Inline]
-                 -> StateT WriterState m Doc
-inlineListToMuse lst = hcat <$> mapM inlineToMuse (fixNotes $ normalizeInlineList lst)
+                 -> Muse m Doc
+renderInlineList [] = do
+  start <- asks envInlineStart
+  pure $ if start then "<verbatim></verbatim>" else ""
+renderInlineList (x:xs) = do
+  start <- asks envInlineStart
+  afterSpace <- asks envAfterSpace
+  topLevel <- asks envTopLevel
+  r <- inlineToMuse x
+  opts <- asks envOptions
+  let isNewline = (x == SoftBreak && writerWrapText opts == WrapPreserve) || x == LineBreak
+  lst' <- local (\env -> env { envInlineStart = isNewline
+                             , envAfterSpace = x == Space || (not topLevel && isNewline)
+                             }) $ renderInlineList xs
+  if start && fixOrEscape afterSpace x
+    then pure (text "<verbatim></verbatim>" <> r <> lst')
+    else pure (r <> lst')
+
+-- | Normalize and convert list of Pandoc inline elements to Muse.
+inlineListToMuse'' :: PandocMonad m
+                   => Bool
+                   -> [Inline]
+                   -> Muse m Doc
+inlineListToMuse'' start lst = do
+  lst' <- (normalizeInlineList . fixNotes) <$> preprocessInlineList (map (removeKeyValues . replaceSmallCaps) lst)
+  topLevel <- asks envTopLevel
+  afterSpace <- asks envAfterSpace
+  local (\env -> env { envInlineStart = start
+                     , envAfterSpace = afterSpace || (start && not topLevel)
+                     }) $ renderInlineList lst'
+
+inlineListToMuse' :: PandocMonad m => [Inline] -> Muse m Doc
+inlineListToMuse' = inlineListToMuse'' True
+
+inlineListToMuse :: PandocMonad m => [Inline] -> Muse m Doc
+inlineListToMuse = inlineListToMuse'' False
 
 -- | Convert Pandoc inline element to Muse.
 inlineToMuse :: PandocMonad m
              => Inline
-             -> StateT WriterState m Doc
-inlineToMuse (Str str) = return $ text $ conditionalEscapeString str
+             -> Muse m Doc
+inlineToMuse (Str str) = do
+  insideLink <- asks envInsideLinkDescription
+  return $ text $ conditionalEscapeString insideLink str
 inlineToMuse (Emph lst) = do
   contents <- inlineListToMuse lst
   return $ "<em>" <> contents <> "</em>"
@@ -350,60 +475,73 @@ inlineToMuse (Superscript lst) = do
 inlineToMuse (Subscript lst) = do
   contents <- inlineListToMuse lst
   return $ "<sub>" <> contents <> "</sub>"
-inlineToMuse (SmallCaps lst) = inlineListToMuse lst
+inlineToMuse SmallCaps {} =
+  fail "SmallCaps should be expanded before normalization"
 inlineToMuse (Quoted SingleQuote lst) = do
   contents <- inlineListToMuse lst
   return $ "‘" <> contents <> "’"
 inlineToMuse (Quoted DoubleQuote lst) = do
   contents <- inlineListToMuse lst
   return $ "“" <> contents <> "”"
--- Amusewiki does not support <cite> tag,
--- and Emacs Muse citation support is limited
--- (https://www.gnu.org/software/emacs-muse/manual/html_node/Citations.html#Citation)
--- so just fallback to expanding inlines.
-inlineToMuse (Cite _  lst) = inlineListToMuse lst
+inlineToMuse Cite {} =
+  fail "Citations should be expanded before normalization"
 inlineToMuse (Code _ str) = return $
   "<code>" <> text (substitute "</code>" "<</code><code>/code>" str) <> "</code>"
-inlineToMuse (Math t str) =
-  lift (texMathToInlines t str) >>= inlineListToMuse
+inlineToMuse Math{} =
+  fail "Math should be expanded before normalization"
 inlineToMuse (RawInline (Format f) str) =
   return $ "<literal style=\"" <> text f <> "\">" <> text str <> "</literal>"
-inlineToMuse LineBreak = return $ "<br>" <> cr
+inlineToMuse LineBreak = do
+  oneline <- asks envOneLine
+  return $ if oneline then "<br>" else "<br>" <> cr
 inlineToMuse Space = return space
 inlineToMuse SoftBreak = do
-  wrapText <- gets $ writerWrapText . stOptions
-  return $ if wrapText == WrapPreserve then cr else space
+  oneline <- asks envOneLine
+  wrapText <- asks $ writerWrapText . envOptions
+  return $ if not oneline && wrapText == WrapPreserve then cr else space
 inlineToMuse (Link _ txt (src, _)) =
   case txt of
         [Str x] | escapeURI x == src ->
              return $ "[[" <> text (escapeLink x) <> "]]"
-        _ -> do contents <- inlineListToMuse txt
+        _ -> do contents <- local (\env -> env { envInsideLinkDescription = True }) $ inlineListToMuse txt
                 return $ "[[" <> text (escapeLink src) <> "][" <> contents <> "]]"
-  where escapeLink lnk = if isImageUrl lnk then "URL:" ++ lnk else lnk
+  where escapeLink lnk = if isImageUrl lnk then "URL:" ++ urlEscapeBrackets lnk else urlEscapeBrackets lnk
         -- Taken from muse-image-regexp defined in Emacs Muse file lisp/muse-regexps.el
         imageExtensions = [".eps", ".gif", ".jpg", ".jpeg", ".pbm", ".png", ".tiff", ".xbm", ".xpm"]
         isImageUrl = (`elem` imageExtensions) . takeExtension
 inlineToMuse (Image attr alt (source,'f':'i':'g':':':title)) =
   inlineToMuse (Image attr alt (source,title))
-inlineToMuse (Image attr inlines (source, title)) = do
-  opts <- gets stOptions
-  alt <- inlineListToMuse inlines
+inlineToMuse (Image attr@(_, classes, _) inlines (source, title)) = do
+  opts <- asks envOptions
+  alt <- local (\env -> env { envInsideLinkDescription = True }) $ inlineListToMuse inlines
   let title' = if null title
                   then if null inlines
                           then ""
                           else "[" <> alt <> "]"
-                  else "[" <> text title <> "]"
+                  else "[" <> text (conditionalEscapeString True title) <> "]"
   let width = case dimension Width attr of
                 Just (Percent x) | isEnabled Ext_amuse opts -> " " ++ show (round x :: Integer)
                 _ -> ""
-  return $ "[[" <> text (source ++ width) <> "]" <> title' <> "]"
+  let leftalign = if "align-left" `elem` classes
+                  then " l"
+                  else ""
+  let rightalign = if "align-right" `elem` classes
+                   then " r"
+                   else ""
+  return $ "[[" <> text (urlEscapeBrackets source ++ width ++ leftalign ++ rightalign) <> "]" <> title' <> "]"
 inlineToMuse (Note contents) = do
   -- add to notes in state
   notes <- gets stNotes
   modify $ \st -> st { stNotes = contents:notes }
   let ref = show $ length notes + 1
   return $ "[" <> text ref <> "]"
-inlineToMuse (Span (_,name:_,_) inlines) = do
+inlineToMuse (Span (anchor,names,_) inlines) = do
   contents <- inlineListToMuse inlines
-  return $ "<class name=\"" <> text name <> "\">" <> contents <> "</class>"
-inlineToMuse (Span _ lst) = inlineListToMuse lst
+  let anchorDoc = if null anchor
+                     then mempty
+                     else text ('#':anchor) <> space
+  return $ anchorDoc <> (if null inlines && not (null anchor)
+                         then mempty
+                         else (if null names
+                               then "<class>"
+                               else "<class name=\"" <> text (head names) <> "\">") <> contents <> "</class>")
diff --git a/src/Text/Pandoc/Writers/Native.hs b/src/Text/Pandoc/Writers/Native.hs
index f852bad96..730e3800a 100644
--- a/src/Text/Pandoc/Writers/Native.hs
+++ b/src/Text/Pandoc/Writers/Native.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-
 Copyright (C) 2006-2018 John MacFarlane <jgm@berkeley.edu>
@@ -30,6 +31,7 @@ Conversion of a 'Pandoc' document to a string representation.
 -}
 module Text.Pandoc.Writers.Native ( writeNative )
 where
+import Prelude
 import Data.List (intersperse)
 import Data.Text (Text)
 import Text.Pandoc.Class (PandocMonad)
diff --git a/src/Text/Pandoc/Writers/ODT.hs b/src/Text/Pandoc/Writers/ODT.hs
index 63a3f915a..7aecb3da5 100644
--- a/src/Text/Pandoc/Writers/ODT.hs
+++ b/src/Text/Pandoc/Writers/ODT.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-
 Copyright (C) 2008-2018 John MacFarlane <jgm@berkeley.edu>
@@ -29,6 +30,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Conversion of 'Pandoc' documents to ODT.
 -}
 module Text.Pandoc.Writers.ODT ( writeODT ) where
+import Prelude
 import Codec.Archive.Zip
 import Control.Monad.Except (catchError)
 import Control.Monad.State.Strict
diff --git a/src/Text/Pandoc/Writers/OOXML.hs b/src/Text/Pandoc/Writers/OOXML.hs
index 30d8d72dd..9e1c81964 100644
--- a/src/Text/Pandoc/Writers/OOXML.hs
+++ b/src/Text/Pandoc/Writers/OOXML.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2012-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -39,13 +40,13 @@ module Text.Pandoc.Writers.OOXML ( mknode
                                  , fitToPage
                                  ) where
 
+import Prelude
 import Codec.Archive.Zip
 import Control.Monad.Reader
 import qualified Data.ByteString as B
 import qualified Data.ByteString.Lazy as BL
 import qualified Data.ByteString.Lazy.Char8 as BL8
 import Data.Maybe (mapMaybe)
-import Data.Monoid ((<>))
 import Text.Pandoc.Class (PandocMonad)
 import qualified Text.Pandoc.UTF8 as UTF8
 import Text.XML.Light as XML
diff --git a/src/Text/Pandoc/Writers/OPML.hs b/src/Text/Pandoc/Writers/OPML.hs
index 29e1bc80c..6c48046a2 100644
--- a/src/Text/Pandoc/Writers/OPML.hs
+++ b/src/Text/Pandoc/Writers/OPML.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE CPP #-}
 {-
 Copyright (C) 2013-2018 John MacFarlane <jgm@berkeley.edu>
@@ -29,12 +30,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Conversion of 'Pandoc' documents to OPML XML.
 -}
 module Text.Pandoc.Writers.OPML ( writeOPML) where
+import Prelude
 import Control.Monad.Except (throwError)
 import Data.Text (Text, unpack)
 import qualified Data.Text as T
 import qualified Text.Pandoc.Builder as B
 import Text.Pandoc.Class (PandocMonad)
-import Text.Pandoc.Compat.Time
+import Data.Time
 import Text.Pandoc.Definition
 import Text.Pandoc.Error
 import Text.Pandoc.Options
@@ -75,12 +77,7 @@ showDateTimeRFC822 = formatTime defaultTimeLocale "%a, %d %b %Y %X %Z"
 
 convertDate :: [Inline] -> String
 convertDate ils = maybe "" showDateTimeRFC822 $
-#if MIN_VERSION_time(1,5,0)
-  parseTimeM True
-#else
-  parseTime
-#endif
-  defaultTimeLocale "%F" =<< normalizeDate (stringify ils)
+  parseTimeM True defaultTimeLocale "%F" =<< normalizeDate (stringify ils)
 
 -- | Convert an Element to OPML.
 elementToOPML :: PandocMonad m => WriterOptions -> Element -> m Doc
diff --git a/src/Text/Pandoc/Writers/OpenDocument.hs b/src/Text/Pandoc/Writers/OpenDocument.hs
index 17edc0cbd..514327e9a 100644
--- a/src/Text/Pandoc/Writers/OpenDocument.hs
+++ b/src/Text/Pandoc/Writers/OpenDocument.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE FlexibleContexts  #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE PatternGuards     #-}
@@ -32,6 +33,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Conversion of 'Pandoc' documents to OpenDocument XML.
 -}
 module Text.Pandoc.Writers.OpenDocument ( writeOpenDocument ) where
+import Prelude
 import Control.Arrow ((***), (>>>))
 import Control.Monad.State.Strict hiding (when)
 import Data.Char (chr)
diff --git a/src/Text/Pandoc/Writers/Org.hs b/src/Text/Pandoc/Writers/Org.hs
index 72def8e48..a71775e13 100644
--- a/src/Text/Pandoc/Writers/Org.hs
+++ b/src/Text/Pandoc/Writers/Org.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-
 Copyright (C) 2010-2015 Puneeth Chaganti <punchagan@gmail.com>
@@ -35,6 +36,7 @@ Conversion of 'Pandoc' documents to Emacs Org-Mode.
 Org-Mode:  <http://orgmode.org>
 -}
 module Text.Pandoc.Writers.Org (writeOrg) where
+import Prelude
 import Control.Monad.State.Strict
 import Data.Char (isAlphaNum, toLower)
 import Data.List (intersect, intersperse, isPrefixOf, partition, transpose)
@@ -166,8 +168,8 @@ blockToOrg (LineBlock lns) = do
         (l, _:r) -> l : splitStanza r
   let joinWithLinefeeds  = nowrap . mconcat . intersperse cr
   let joinWithBlankLines = mconcat . intersperse blankline
-  let prettyfyStanza ls  = joinWithLinefeeds <$> mapM inlineListToOrg ls
-  contents <- joinWithBlankLines <$> mapM prettyfyStanza (splitStanza lns)
+  let prettifyStanza ls  = joinWithLinefeeds <$> mapM inlineListToOrg ls
+  contents <- joinWithBlankLines <$> mapM prettifyStanza (splitStanza lns)
   return $ blankline $$ "#+BEGIN_VERSE" $$
            nest 2 contents $$ "#+END_VERSE" <> blankline
 blockToOrg (RawBlock "html" str) =
diff --git a/src/Text/Pandoc/Writers/Powerpoint.hs b/src/Text/Pandoc/Writers/Powerpoint.hs
index 645a4cb86..665fd3f57 100644
--- a/src/Text/Pandoc/Writers/Powerpoint.hs
+++ b/src/Text/Pandoc/Writers/Powerpoint.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 
 
 {-
@@ -41,6 +42,7 @@ This is a wrapper around two modules:
 
 module Text.Pandoc.Writers.Powerpoint (writePowerpoint) where
 
+import Prelude
 import Codec.Archive.Zip
 import Text.Pandoc.Definition
 import Text.Pandoc.Walk
diff --git a/src/Text/Pandoc/Writers/Powerpoint/Output.hs b/src/Text/Pandoc/Writers/Powerpoint/Output.hs
index b5138b514..865ef1efc 100644
--- a/src/Text/Pandoc/Writers/Powerpoint/Output.hs
+++ b/src/Text/Pandoc/Writers/Powerpoint/Output.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE PatternGuards #-}
 
 {-
@@ -34,6 +35,7 @@ Text.Pandoc.Writers.Powerpoint.Presentation) to a zip archive.
 module Text.Pandoc.Writers.Powerpoint.Output ( presentationToArchive
                                              ) where
 
+import Prelude
 import Control.Monad.Except (throwError, catchError)
 import Control.Monad.Reader
 import Control.Monad.State
@@ -41,7 +43,7 @@ import Codec.Archive.Zip
 import Data.Char (toUpper)
 import Data.List (intercalate, stripPrefix, nub, union, isPrefixOf, intersperse)
 import Data.Default
-import Text.Pandoc.Compat.Time (formatTime, defaultTimeLocale)
+import Data.Time (formatTime, defaultTimeLocale)
 import Data.Time.Clock (UTCTime)
 import Data.Time.Clock.POSIX (utcTimeToPOSIXSeconds, posixSecondsToUTCTime)
 import System.FilePath.Posix (splitDirectories, splitExtension, takeExtension)
@@ -56,7 +58,7 @@ import Text.Pandoc.MIME
 import qualified Data.ByteString.Lazy as BL
 import Text.Pandoc.Writers.OOXML
 import qualified Data.Map as M
-import Data.Maybe (mapMaybe, listToMaybe, fromMaybe, isJust, maybeToList, catMaybes)
+import Data.Maybe (mapMaybe, listToMaybe, fromMaybe, maybeToList, catMaybes)
 import Text.Pandoc.ImageSize
 import Control.Applicative ((<|>))
 import System.FilePath.Glob
@@ -281,8 +283,9 @@ makeSlideIdMap (Presentation _ slides) =
 makeSpeakerNotesMap :: Presentation -> M.Map Int Int
 makeSpeakerNotesMap (Presentation _ slides) =
   M.fromList $ (mapMaybe f $ slides `zip` [1..]) `zip` [1..]
-  where f (Slide _ _ Nothing, _) = Nothing
-        f (Slide _ _ (Just _), n)  = Just n
+  where f (Slide _ _ notes, n) = if notes == mempty
+                                 then Nothing
+                                 else Just n
 
 presentationToArchive :: PandocMonad m => WriterOptions -> Presentation -> m Archive
 presentationToArchive opts pres = do
@@ -322,13 +325,11 @@ presentationToArchive opts pres = do
 -- Check to see if the presentation has speaker notes. This will
 -- influence whether we import the notesMaster template.
 presHasSpeakerNotes :: Presentation -> Bool
-presHasSpeakerNotes (Presentation _ slides) = any isJust $ map slideSpeakerNotes slides
+presHasSpeakerNotes (Presentation _ slides) = not $ all (mempty ==) $ map slideSpeakerNotes slides
 
 curSlideHasSpeakerNotes :: PandocMonad m => P m Bool
-curSlideHasSpeakerNotes = do
-  sldId <- asks envCurSlideId
-  notesIdMap <- asks envSpeakerNotesIdMap
-  return $ isJust $ M.lookup sldId notesIdMap
+curSlideHasSpeakerNotes =
+  M.member <$> asks envCurSlideId <*> asks envSpeakerNotesIdMap
 
 --------------------------------------------------
 
@@ -339,17 +340,9 @@ getLayout layout = do
         (TitleSlide _)          -> "ppt/slideLayouts/slideLayout3.xml"
         (ContentSlide _ _)      -> "ppt/slideLayouts/slideLayout2.xml"
         (TwoColumnSlide _ _ _)    -> "ppt/slideLayouts/slideLayout4.xml"
+  refArchive <- asks envRefArchive
   distArchive <- asks envDistArchive
-  root <- case findEntryByPath layoutpath distArchive of
-        Just e -> case parseXMLDoc $ UTF8.toStringLazy $ fromEntry e of
-                    Just element -> return $ element
-                    Nothing      -> throwError $
-                                    PandocSomeError $
-                                    layoutpath ++ " corrupt in reference file"
-        Nothing -> throwError $
-                   PandocSomeError $
-                   layoutpath ++ " missing in reference file"
-  return root
+  parseXml refArchive distArchive layoutpath
 
 shapeHasId :: NameSpaces -> String -> Element -> Bool
 shapeHasId ns ident element
@@ -930,6 +923,13 @@ graphicFrameToElements layout tbls caption = do
             return [graphicFrameElts, capElt]
     else return [graphicFrameElts]
 
+getDefaultTableStyle :: PandocMonad m => P m (Maybe String)
+getDefaultTableStyle = do
+  refArchive <- asks envRefArchive
+  distArchive <- asks envDistArchive
+  tblStyleLst <- parseXml refArchive distArchive "ppt/tableStyles.xml"
+  return $ findAttr (QName "def" Nothing Nothing) tblStyleLst
+
 graphicToElement :: PandocMonad m => Integer -> Graphic -> P m Element
 graphicToElement tableWidth (Tbl tblPr hdrCells rows) = do
   let colWidths = if null hdrCells
@@ -967,12 +967,19 @@ graphicToElement tableWidth (Tbl tblPr hdrCells rows) = do
   let mkgridcol w = mknode "a:gridCol"
                        [("w", show ((12700 * w) :: Integer))] ()
   let hasHeader = not (all null hdrCells)
+
+  mbDefTblStyle <- getDefaultTableStyle
+  let tblPrElt = mknode "a:tblPr"
+                 [ ("firstRow", if tblPrFirstRow tblPr then "1" else "0")
+                 , ("bandRow", if tblPrBandRow tblPr then "1" else "0")
+                 ] (case mbDefTblStyle of
+                      Nothing -> []
+                      Just sty -> [mknode "a:tableStyleId" [] sty])
+
   return $ mknode "a:graphic" [] $
     [mknode "a:graphicData" [("uri", "http://schemas.openxmlformats.org/drawingml/2006/table")] $
      [mknode "a:tbl" [] $
-      [ mknode "a:tblPr" [ ("firstRow", if tblPrFirstRow tblPr then "1" else "0")
-                         , ("bandRow", if tblPrBandRow tblPr then "1" else "0")
-                         ] ()
+      [ tblPrElt
       , mknode "a:tblGrid" [] (if all (==0) colWidths
                                then []
                                else map mkgridcol colWidths)
@@ -994,6 +1001,14 @@ getShapeByPlaceHolderType ns spTreeElem phType
       filterChild findPhType spTreeElem
   | otherwise = Nothing
 
+-- Like the above, but it tries a number of different placeholder types
+getShapeByPlaceHolderTypes :: NameSpaces -> Element -> [String] -> Maybe Element
+getShapeByPlaceHolderTypes _ _ [] = Nothing
+getShapeByPlaceHolderTypes ns spTreeElem (s:ss) =
+  case getShapeByPlaceHolderType ns spTreeElem s of
+    Just element -> Just element
+    Nothing -> getShapeByPlaceHolderTypes ns spTreeElem ss
+
 getShapeByPlaceHolderIndex :: NameSpaces -> Element -> String -> Maybe Element
 getShapeByPlaceHolderIndex ns spTreeElem phIdx
   | isElem ns "p" "spTree" spTreeElem =
@@ -1008,12 +1023,12 @@ getShapeByPlaceHolderIndex ns spTreeElem phIdx
   | otherwise = Nothing
 
 
-nonBodyTextToElement :: PandocMonad m => Element -> String -> [ParaElem] -> P m Element
-nonBodyTextToElement layout phType paraElements
+nonBodyTextToElement :: PandocMonad m => Element -> [String] -> [ParaElem] -> P m Element
+nonBodyTextToElement layout phTypes paraElements
   | ns <- elemToNameSpaces layout
   , Just cSld <- findChild (elemName ns "p" "cSld") layout
   , Just spTree <- findChild (elemName ns "p" "spTree") cSld
-  , Just sp <- getShapeByPlaceHolderType ns spTree phType = do
+  , Just sp <- getShapeByPlaceHolderTypes ns spTree phTypes = do
       let hdrPara = Paragraph def paraElements
       element <- paragraphToElement hdrPara
       let txBody = mknode "p:txBody" [] $
@@ -1028,7 +1043,7 @@ contentToElement layout hdrShape shapes
   | ns <- elemToNameSpaces layout
   , Just cSld <- findChild (elemName ns "p" "cSld") layout
   , Just spTree <- findChild (elemName ns "p" "spTree") cSld = do
-      element <- nonBodyTextToElement layout "title" hdrShape
+      element <- nonBodyTextToElement layout ["title"] hdrShape
       let hdrShapeElements = if null hdrShape
                              then []
                              else [element]
@@ -1046,7 +1061,7 @@ twoColumnToElement layout hdrShape shapesL shapesR
   | ns <- elemToNameSpaces layout
   , Just cSld <- findChild (elemName ns "p" "cSld") layout
   , Just spTree <- findChild (elemName ns "p" "spTree") cSld = do
-      element <- nonBodyTextToElement layout "title" hdrShape
+      element <- nonBodyTextToElement layout ["title"] hdrShape
       let hdrShapeElements = if null hdrShape
                              then []
                              else [element]
@@ -1070,7 +1085,7 @@ titleToElement layout titleElems
   | ns <- elemToNameSpaces layout
   , Just cSld <- findChild (elemName ns "p" "cSld") layout
   , Just spTree <- findChild (elemName ns "p" "spTree") cSld = do
-      element <- nonBodyTextToElement layout "title" titleElems
+      element <- nonBodyTextToElement layout ["title", "ctrTitle"] titleElems
       let titleShapeElements = if null titleElems
                                then []
                                else [element]
@@ -1084,15 +1099,15 @@ metadataToElement layout titleElems subtitleElems authorsElems dateElems
   , Just spTree <- findChild (elemName ns "p" "spTree") cSld = do
       titleShapeElements <- if null titleElems
                             then return []
-                            else sequence [nonBodyTextToElement layout "ctrTitle" titleElems]
+                            else sequence [nonBodyTextToElement layout ["ctrTitle"] titleElems]
       let combinedAuthorElems = intercalate [Break] authorsElems
           subtitleAndAuthorElems = intercalate [Break, Break] [subtitleElems, combinedAuthorElems]
       subtitleShapeElements <- if null subtitleAndAuthorElems
                                then return []
-                               else sequence [nonBodyTextToElement layout "subTitle" subtitleAndAuthorElems]
+                               else sequence [nonBodyTextToElement layout ["subTitle"] subtitleAndAuthorElems]
       dateShapeElements <- if null dateElems
                            then return []
-                           else sequence [nonBodyTextToElement layout "dt" dateElems]
+                           else sequence [nonBodyTextToElement layout ["dt"] dateElems]
       return $ replaceNamedChildren ns "p" "sp"
         (titleShapeElements ++ subtitleShapeElements ++ dateShapeElements)
         spTree
@@ -1144,18 +1159,9 @@ slideToElement (Slide _ l@(MetadataSlide titleElems subtitleElems authorElems da
 
 getNotesMaster :: PandocMonad m => P m Element
 getNotesMaster = do
-  let notesMasterPath = "ppt/notesMasters/notesMaster1.xml"
+  refArchive <- asks envRefArchive
   distArchive <- asks envDistArchive
-  root <- case findEntryByPath notesMasterPath distArchive of
-        Just e -> case parseXMLDoc $ UTF8.toStringLazy $ fromEntry e of
-                    Just element -> return $ element
-                    Nothing      -> throwError $
-                                    PandocSomeError $
-                                    notesMasterPath ++ " corrupt in reference file"
-        Nothing -> throwError $
-                   PandocSomeError $
-                   notesMasterPath ++ " missing in reference file"
-  return root
+  parseXml refArchive distArchive "ppt/notesMasters/notesMaster1.xml"
 
 getSlideNumberFieldId :: PandocMonad m => Element -> P m String
 getSlideNumberFieldId notesMaster
@@ -1256,42 +1262,40 @@ speakerNotesSlideNumber pgNum fieldId =
   ]
 
 slideToSpeakerNotesElement :: PandocMonad m => Slide -> P m (Maybe Element)
-slideToSpeakerNotesElement slide
-  | Slide _ _ mbNotes <- slide
-  , Just (SpeakerNotes paras) <- mbNotes = do
-      master <- getNotesMaster
-      fieldId  <- getSlideNumberFieldId master
-      num <- slideNum slide
-      let imgShape = speakerNotesSlideImage
-          sldNumShape = speakerNotesSlideNumber num fieldId
-      bodyShape <- speakerNotesBody paras
-      return $ Just $
-        mknode "p:notes"
-        [ ("xmlns:a", "http://schemas.openxmlformats.org/drawingml/2006/main")
-        , ("xmlns:r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships")
-        , ("xmlns:p", "http://schemas.openxmlformats.org/presentationml/2006/main")
-        ] [ mknode "p:cSld" []
-            [ mknode "p:spTree" []
-              [ mknode "p:nvGrpSpPr" []
-                [ mknode "p:cNvPr" [("id", "1"), ("name", "")] ()
-                , mknode "p:cNvGrpSpPr" [] ()
-                , mknode "p:nvPr" [] ()
-                ]
-            , mknode "p:grpSpPr" []
-              [ mknode "a:xfrm" []
-                [ mknode "a:off" [("x", "0"), ("y", "0")] ()
-                , mknode "a:ext" [("cx", "0"), ("cy", "0")] ()
-                , mknode "a:chOff" [("x", "0"), ("y", "0")] ()
-                , mknode "a:chExt" [("cx", "0"), ("cy", "0")] ()
-                ]
+slideToSpeakerNotesElement (Slide _ _ (SpeakerNotes [])) = return Nothing
+slideToSpeakerNotesElement slide@(Slide _ _ (SpeakerNotes paras)) = do
+  master <- getNotesMaster
+  fieldId  <- getSlideNumberFieldId master
+  num <- slideNum slide
+  let imgShape = speakerNotesSlideImage
+      sldNumShape = speakerNotesSlideNumber num fieldId
+  bodyShape <- speakerNotesBody paras
+  return $ Just $
+    mknode "p:notes"
+    [ ("xmlns:a", "http://schemas.openxmlformats.org/drawingml/2006/main")
+    , ("xmlns:r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships")
+    , ("xmlns:p", "http://schemas.openxmlformats.org/presentationml/2006/main")
+    ] [ mknode "p:cSld" []
+        [ mknode "p:spTree" []
+          [ mknode "p:nvGrpSpPr" []
+            [ mknode "p:cNvPr" [("id", "1"), ("name", "")] ()
+            , mknode "p:cNvGrpSpPr" [] ()
+            , mknode "p:nvPr" [] ()
+            ]
+          , mknode "p:grpSpPr" []
+            [ mknode "a:xfrm" []
+              [ mknode "a:off" [("x", "0"), ("y", "0")] ()
+              , mknode "a:ext" [("cx", "0"), ("cy", "0")] ()
+              , mknode "a:chOff" [("x", "0"), ("y", "0")] ()
+              , mknode "a:chExt" [("cx", "0"), ("cy", "0")] ()
               ]
-            , imgShape
-            , bodyShape
-            , sldNumShape
-            ]
             ]
+          , imgShape
+          , bodyShape
+          , sldNumShape
           ]
-slideToSpeakerNotesElement _ = return Nothing
+        ]
+      ]
 
 -----------------------------------------------------------------------
 
@@ -1466,23 +1470,22 @@ slideToSpeakerNotesEntry slide = do
       _ -> return Nothing
 
 slideToSpeakerNotesRelElement :: PandocMonad m => Slide -> P m (Maybe Element)
-slideToSpeakerNotesRelElement slide
-  | Slide _ _ mbNotes <- slide
-  , Just _ <- mbNotes = do
-      idNum <- slideNum slide
-      return $ Just $
-        mknode "Relationships"
-        [("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships")]
-        [ mknode "Relationship" [ ("Id", "rId2")
-                                , ("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide")
-                                , ("Target", "../slides/slide" ++ show idNum ++ ".xml")
-                                ] ()
-        , mknode "Relationship" [ ("Id", "rId1")
-                                , ("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesMaster")
-                                , ("Target", "../notesMasters/notesMaster1.xml")
-                                ] ()
-        ]
-slideToSpeakerNotesRelElement _ = return Nothing
+slideToSpeakerNotesRelElement (Slide _ _ (SpeakerNotes [])) = return Nothing
+slideToSpeakerNotesRelElement slide@(Slide _ _ _) = do
+  idNum <- slideNum slide
+  return $ Just $
+    mknode "Relationships"
+    [("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships")]
+    [ mknode "Relationship" [ ("Id", "rId2")
+                            , ("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide")
+                            , ("Target", "../slides/slide" ++ show idNum ++ ".xml")
+                            ] ()
+    , mknode "Relationship" [ ("Id", "rId1")
+                            , ("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesMaster")
+                            , ("Target", "../notesMasters/notesMaster1.xml")
+                            ] ()
+    ]
+
 
 slideToSpeakerNotesRelEntry :: PandocMonad m => Slide -> P m (Maybe Entry)
 slideToSpeakerNotesRelEntry slide = do
diff --git a/src/Text/Pandoc/Writers/Powerpoint/Presentation.hs b/src/Text/Pandoc/Writers/Powerpoint/Presentation.hs
index ac7c86945..e14476b16 100644
--- a/src/Text/Pandoc/Writers/Powerpoint/Presentation.hs
+++ b/src/Text/Pandoc/Writers/Powerpoint/Presentation.hs
@@ -1,4 +1,6 @@
-{-# LANGUAGE PatternGuards #-}
+{-# LANGUAGE NoImplicitPrelude          #-}
+{-# LANGUAGE PatternGuards              #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
 
 {-
 Copyright (C) 2017-2018 Jesse Rosenthal <jrosenthal@jhu.edu>
@@ -57,6 +59,7 @@ module Text.Pandoc.Writers.Powerpoint.Presentation ( documentToPresentation
                                                    ) where
 
 
+import Prelude
 import Control.Monad.Reader
 import Control.Monad.State
 import Data.List (intercalate)
@@ -67,7 +70,7 @@ import Text.Pandoc.Slides (getSlideLevel)
 import Text.Pandoc.Options
 import Text.Pandoc.Logging
 import Text.Pandoc.Walk
-import Text.Pandoc.Compat.Time (UTCTime)
+import Data.Time (UTCTime)
 import qualified Text.Pandoc.Shared as Shared -- so we don't overlap "Element"
 import Text.Pandoc.Writers.Shared (metaValueToInlines)
 import qualified Data.Map as M
@@ -110,7 +113,7 @@ data WriterState = WriterState { stNoteIds :: M.Map Int [Block]
                                , stAnchorMap :: M.Map String SlideId
                                , stSlideIdSet :: S.Set SlideId
                                , stLog :: [LogMessage]
-                               , stSpeakerNotesMap :: M.Map SlideId [[Paragraph]]
+                               , stSpeakerNotes :: SpeakerNotes
                                } deriving (Show, Eq)
 
 instance Default WriterState where
@@ -119,7 +122,7 @@ instance Default WriterState where
                     -- we reserve this s
                     , stSlideIdSet = reservedSlideIds
                     , stLog = []
-                    , stSpeakerNotesMap = mempty
+                    , stSpeakerNotes = mempty
                     }
 
 metadataSlideId :: SlideId
@@ -183,7 +186,7 @@ data DocProps = DocProps { dcTitle :: Maybe String
 
 data Slide = Slide { slideId :: SlideId
                    , slideLayout :: Layout
-                   , slideSpeakerNotes :: Maybe SpeakerNotes
+                   , slideSpeakerNotes :: SpeakerNotes
                    } deriving (Show, Eq)
 
 newtype SlideId = SlideId String
@@ -193,7 +196,7 @@ newtype SlideId = SlideId String
 -- designed mainly for one textbox, so we'll just put in the contents
 -- of that textbox, to avoid other shapes that won't work as well.
 newtype SpeakerNotes = SpeakerNotes {fromSpeakerNotes :: [Paragraph]}
-  deriving (Show, Eq)
+  deriving (Show, Eq, Monoid, Semigroup)
 
 data Layout = MetadataSlide { metadataSlideTitle :: [ParaElem]
                             , metadataSlideSubtitle :: [ParaElem]
@@ -229,7 +232,6 @@ data Paragraph = Paragraph { paraProps :: ParaProps
                            , paraElems  :: [ParaElem]
                            } deriving (Show, Eq)
 
-
 data BulletType = Bullet
                 | AutoNumbering ListAttributes
   deriving (Show, Eq)
@@ -374,9 +376,20 @@ inlineToParElems (Note blks) = do
     modify $ \st -> st { stNoteIds = M.insert curNoteId blks notes }
     local (\env -> env{envRunProps = (envRunProps env){rLink = Just $ InternalTarget endNotesSlideId}}) $
       inlineToParElems $ Superscript [Str $ show curNoteId]
-inlineToParElems (Span _ ils) = concatMapM inlineToParElems ils
+inlineToParElems (Span _ ils) = inlinesToParElems ils
+inlineToParElems (Quoted quoteType ils) =
+  inlinesToParElems $ [Str open] ++ ils ++ [Str close]
+  where (open, close) = case quoteType of
+                          SingleQuote -> ("\x2018", "\x2019")
+                          DoubleQuote -> ("\x201C", "\x201D")
 inlineToParElems (RawInline _ _) = return []
-inlineToParElems _ = return []
+inlineToParElems (Cite _ ils) = inlinesToParElems ils
+-- Note: we shouldn't reach this, because images should be handled at
+-- the shape level, but should that change in the future, we render
+-- the alt text.
+inlineToParElems (Image _ alt _) = inlinesToParElems alt
+
+
 
 isListType :: Block -> Bool
 isListType (OrderedList _ _) = True
@@ -399,10 +412,7 @@ noteSize :: Pixels
 noteSize = 18
 
 blockToParagraphs :: Block -> Pres [Paragraph]
-blockToParagraphs (Plain ils) = do
-  parElems <- inlinesToParElems ils
-  pProps <- asks envParaProps
-  return [Paragraph pProps parElems]
+blockToParagraphs (Plain ils) = blockToParagraphs (Para ils)
 blockToParagraphs (Para ils) = do
   parElems <- inlinesToParElems ils
   pProps <- asks envParaProps
@@ -475,16 +485,6 @@ blockToParagraphs (DefinitionList entries) = do
         definition <- concatMapM (blockToParagraphs . BlockQuote) blksLst
         return $ term ++ definition
   concatMapM go entries
-blockToParagraphs (Div (_, "notes" : [], _) blks) =
-  local (\env -> env{envInSpeakerNotes=True}) $ do
-  sldId <- asks envCurSlideId
-  spkNotesMap <- gets stSpeakerNotesMap
-  paras <- concatMapM blockToParagraphs blks
-  let spkNotesMap' = case M.lookup sldId spkNotesMap of
-        Just lst -> M.insert sldId (paras : lst) spkNotesMap
-        Nothing  -> M.insert sldId [paras] spkNotesMap
-  modify $ \st -> st{stSpeakerNotesMap = spkNotesMap'}
-  return []
 blockToParagraphs (Div _ blks)  = concatMapM blockToParagraphs blks
 blockToParagraphs blk = do
   addLogMessage $ BlockNotRendered blk
@@ -527,14 +527,9 @@ withAttr attr (Pic picPr url caption) =
 withAttr _ sp = sp
 
 blockToShape :: Block -> Pres Shape
-blockToShape (Plain (il:_)) | Image attr ils (url, _) <- il =
-      (withAttr attr . Pic def url) <$> inlinesToParElems ils
+blockToShape (Plain ils) = blockToShape (Para ils)
 blockToShape (Para (il:_))  | Image attr ils (url, _) <- il =
       (withAttr attr . Pic def url) <$> inlinesToParElems ils
-blockToShape (Plain (il:_)) | Link _ (il':_) target <- il
-                            , Image attr ils (url, _) <- il' =
-      (withAttr attr . Pic def {picPropLink = Just $ ExternalTarget target} url) <$>
-      inlinesToParElems ils
 blockToShape (Para (il:_))  | Link _ (il':_) target <- il
                             , Image attr ils (url, _) <- il' =
       (withAttr attr . Pic def{picPropLink = Just $ ExternalTarget target} url) <$>
@@ -558,20 +553,23 @@ blockToShape blk = do paras <- blockToParagraphs blk
 
 combineShapes :: [Shape] -> [Shape]
 combineShapes [] = []
-combineShapes[s] = [s]
-combineShapes (pic@(Pic{}) : ss) = pic : combineShapes ss
+combineShapes (pic@Pic{} : ss) = pic : combineShapes ss
 combineShapes (TextBox [] : ss) = combineShapes ss
 combineShapes (s : TextBox [] : ss) = combineShapes (s : ss)
 combineShapes (TextBox (p:ps) : TextBox (p':ps') : ss) =
   combineShapes $ TextBox ((p:ps) ++ (p':ps')) : ss
 combineShapes (s:ss) = s : combineShapes ss
 
+isNotesDiv :: Block -> Bool
+isNotesDiv (Div (_, ["notes"], _) _) = True
+isNotesDiv _ = False
+
 blocksToShapes :: [Block] -> Pres [Shape]
 blocksToShapes blks = combineShapes <$> mapM blockToShape blks
 
 isImage :: Inline -> Bool
-isImage (Image{}) = True
-isImage (Link _ (Image _ _ _ : _) _) = True
+isImage Image{} = True
+isImage (Link _ (Image{} : _) _) = True
 isImage _ = False
 
 splitBlocks' :: [Block] -> [[Block]] -> [Block] -> Pres [[Block]]
@@ -589,64 +587,60 @@ splitBlocks' cur acc (h@(Header n _ _) : blks) = do
 splitBlocks' cur acc (Plain ils : blks) = splitBlocks' cur acc (Para ils : blks)
 splitBlocks' cur acc (Para (il:ils) : blks) | isImage il = do
   slideLevel <- asks envSlideLevel
+  let (nts, blks') = if null ils
+                     then span isNotesDiv blks
+                     else ([], blks)
   case cur of
-    [(Header n _ _)] | n == slideLevel ->
+    [Header n _ _] | n == slideLevel ->
                             splitBlocks' []
-                            (acc ++ [cur ++ [Para [il]]])
-                            (if null ils then blks else Para ils : blks)
+                            (acc ++ [cur ++ [Para [il]] ++ nts])
+                            (if null ils then blks' else Para ils : blks')
     _ -> splitBlocks' []
-         (acc ++ (if null cur then [] else [cur]) ++ [[Para [il]]])
-         (if null ils then blks else Para ils : blks)
-splitBlocks' cur acc (tbl@(Table{}) : blks) = do
+         (acc ++ (if null cur then [] else [cur]) ++ [[Para [il]] ++ nts])
+         (if null ils then blks' else Para ils : blks')
+splitBlocks' cur acc (tbl@Table{} : blks) = do
   slideLevel <- asks envSlideLevel
+  let (nts, blks') = span isNotesDiv blks
   case cur of
-    [(Header n _ _)] | n == slideLevel ->
-                            splitBlocks' [] (acc ++ [cur ++ [tbl]]) blks
-    _ ->  splitBlocks' [] (acc ++ (if null cur then [] else [cur]) ++ [[tbl]]) blks
+    [Header n _ _] | n == slideLevel ->
+                            splitBlocks' [] (acc ++ [cur ++ [tbl] ++ nts]) blks'
+    _ ->  splitBlocks' [] (acc ++ (if null cur then [] else [cur]) ++ [[tbl] ++ nts]) blks'
 splitBlocks' cur acc (d@(Div (_, classes, _) _): blks) | "columns" `elem` classes =  do
   slideLevel <- asks envSlideLevel
+  let (nts, blks') = span isNotesDiv blks
   case cur of
-    [(Header n _ _)] | n == slideLevel ->
-                            splitBlocks' [] (acc ++ [cur ++ [d]]) blks
-    _ ->  splitBlocks' [] (acc ++ (if null cur then [] else [cur]) ++ [[d]]) blks
+    [Header n _ _] | n == slideLevel ->
+                            splitBlocks' [] (acc ++ [cur ++ [d] ++ nts]) blks'
+    _ ->  splitBlocks' [] (acc ++ (if null cur then [] else [cur]) ++ [[d] ++ nts]) blks'
 splitBlocks' cur acc (blk : blks) = splitBlocks' (cur ++ [blk]) acc blks
 
 splitBlocks :: [Block] -> Pres [[Block]]
 splitBlocks = splitBlocks' [] []
 
-getSpeakerNotes :: Pres (Maybe SpeakerNotes)
-getSpeakerNotes = do
-  sldId <- asks envCurSlideId
-  spkNtsMap <- gets stSpeakerNotesMap
-  return $ (SpeakerNotes . concat . reverse) <$> (M.lookup sldId spkNtsMap)
-
-blocksToSlide' :: Int -> [Block] -> Pres Slide
-blocksToSlide' lvl (Header n (ident, _, _) ils : blks)
+blocksToSlide' :: Int -> [Block] -> SpeakerNotes -> Pres Slide
+blocksToSlide' lvl (Header n (ident, _, _) ils : blks) spkNotes
   | n < lvl = do
       registerAnchorId ident
       sldId <- asks envCurSlideId
       hdr <- inlinesToParElems ils
-      return $ Slide sldId TitleSlide {titleSlideHeader = hdr} Nothing
+      return $ Slide sldId TitleSlide {titleSlideHeader = hdr} spkNotes
   | n == lvl = do
       registerAnchorId ident
       hdr <- inlinesToParElems ils
       -- Now get the slide without the header, and then add the header
       -- in.
-      slide <- blocksToSlide' lvl blks
+      slide <- blocksToSlide' lvl blks spkNotes
       let layout = case slideLayout slide of
             ContentSlide _ cont          -> ContentSlide hdr cont
             TwoColumnSlide _ contL contR -> TwoColumnSlide hdr contL contR
             layout'                     -> layout'
       return $ slide{slideLayout = layout}
-blocksToSlide' _ (blk : blks)
+blocksToSlide' _ (blk : blks) spkNotes
   | Div (_, classes, _) divBlks <- blk
   , "columns" `elem` classes
   , Div (_, clsL, _) blksL : Div (_, clsR, _) blksR : remaining <- divBlks
   , "column" `elem` clsL, "column" `elem` clsR = do
-      unless (null blks)
-        (mapM (addLogMessage . BlockNotRendered) blks >> return ())
-      unless (null remaining)
-        (mapM (addLogMessage . BlockNotRendered) remaining >> return ())
+      mapM_ (addLogMessage . BlockNotRendered) (blks ++ remaining)
       mbSplitBlksL <- splitBlocks blksL
       mbSplitBlksR <- splitBlocks blksR
       let blksL' = case mbSplitBlksL of
@@ -664,8 +658,8 @@ blocksToSlide' _ (blk : blks)
                        , twoColumnSlideLeft = shapesL
                        , twoColumnSlideRight = shapesR
                        }
-        Nothing
-blocksToSlide' _ (blk : blks) = do
+        spkNotes
+blocksToSlide' _ (blk : blks) spkNotes = do
       inNoteSlide <- asks envInNoteSlide
       shapes <- if inNoteSlide
                 then forceFontSize noteSize $ blocksToShapes (blk : blks)
@@ -677,8 +671,8 @@ blocksToSlide' _ (blk : blks) = do
         ContentSlide { contentSlideHeader = []
                      , contentSlideContent = shapes
                      }
-        Nothing
-blocksToSlide' _ [] = do
+        spkNotes
+blocksToSlide' _ [] spkNotes = do
   sldId <- asks envCurSlideId
   return $
     Slide
@@ -686,14 +680,32 @@ blocksToSlide' _ [] = do
     ContentSlide { contentSlideHeader = []
                  , contentSlideContent = []
                  }
-    Nothing
+    spkNotes
+
+handleNotes :: Block -> Pres ()
+handleNotes (Div (_, ["notes"], _) blks) =
+  local (\env -> env{envInSpeakerNotes=True}) $ do
+  spNotes <- SpeakerNotes <$> concatMapM blockToParagraphs blks
+  modify $ \st -> st{stSpeakerNotes = (stSpeakerNotes st) <> spNotes}
+handleNotes _ = return ()
+
+handleAndFilterNotes' :: [Block] -> Pres [Block]
+handleAndFilterNotes' blks = do
+  mapM_ handleNotes blks
+  return $ filter (not . isNotesDiv) blks
+
+handleAndFilterNotes :: [Block] -> Pres ([Block], SpeakerNotes)
+handleAndFilterNotes blks = do
+  modify $ \st -> st{stSpeakerNotes = mempty}
+  blks' <- walkM handleAndFilterNotes' blks
+  spkNotes <- gets stSpeakerNotes
+  return (blks', spkNotes)
 
 blocksToSlide :: [Block] -> Pres Slide
 blocksToSlide blks = do
+  (blks', spkNotes) <- handleAndFilterNotes blks
   slideLevel <- asks envSlideLevel
-  sld <- blocksToSlide' slideLevel blks
-  spkNotes <- getSpeakerNotes
-  return $ sld{slideSpeakerNotes = spkNotes}
+  blocksToSlide' slideLevel blks' spkNotes
 
 makeNoteEntry :: Int -> [Block] -> [Block]
 makeNoteEntry n blks =
@@ -719,15 +731,14 @@ makeEndNotesSlideBlocks = do
   anchorSet <- M.keysSet <$> gets stAnchorMap
   if M.null noteIds
     then return []
-    else do let title = case lookupMeta "notes-title" meta of
-                  Just val -> metaValueToInlines val
-                  Nothing  -> [Str "Notes"]
-                ident = Shared.uniqueIdent title anchorSet
-                hdr = Header slideLevel (ident, [], []) title
-            blks <- return $
-                    concatMap (\(n, bs) -> makeNoteEntry n bs) $
+    else let title = case lookupMeta "notes-title" meta of
+                       Just val -> metaValueToInlines val
+                       Nothing  -> [Str "Notes"]
+             ident = Shared.uniqueIdent title anchorSet
+             hdr = Header slideLevel (ident, [], []) title
+             blks = concatMap (\(n, bs) -> makeNoteEntry n bs) $
                     M.toList noteIds
-            return $ hdr : blks
+         in return $ hdr : blks
 
 getMetaSlide :: Pres (Maybe Slide)
 getMetaSlide  = do
@@ -753,7 +764,7 @@ getMetaSlide  = do
                        , metadataSlideAuthors = authors
                        , metadataSlideDate = date
                        }
-         Nothing
+         mempty
 
 -- adapted from the markdown writer
 elementToListItem :: Shared.Element -> Pres [Block]
@@ -778,8 +789,7 @@ makeTOCSlide blks = local (\env -> env{envCurSlideId = tocSlideId}) $ do
                    Just val -> metaValueToInlines val
                    Nothing  -> [Str "Table of Contents"]
       hdr = Header slideLevel nullAttr tocTitle
-  sld <- blocksToSlide [hdr, contents]
-  return sld
+  blocksToSlide [hdr, contents]
 
 combineParaElems' :: Maybe ParaElem -> [ParaElem] -> [ParaElem]
 combineParaElems' mbPElem [] = maybeToList mbPElem
@@ -802,15 +812,9 @@ applyToParagraph f para = do
   return $ para {paraElems = paraElems'}
 
 applyToShape :: Monad m => (ParaElem -> m ParaElem) -> Shape -> m Shape
-applyToShape f (Pic pPr fp pes) = do
-  pes' <- mapM f pes
-  return $ Pic pPr fp pes'
-applyToShape f (GraphicFrame gfx pes) = do
-  pes' <- mapM f pes
-  return $ GraphicFrame gfx pes'
-applyToShape f (TextBox paras) = do
-  paras' <- mapM (applyToParagraph f) paras
-  return $ TextBox paras'
+applyToShape f (Pic pPr fp pes) = Pic pPr fp <$> mapM f pes
+applyToShape f (GraphicFrame gfx pes) = GraphicFrame gfx <$> mapM f pes
+applyToShape f (TextBox paras) = TextBox <$> mapM (applyToParagraph f) paras
 
 applyToLayout :: Monad m => (ParaElem -> m ParaElem) -> Layout -> m Layout
 applyToLayout f (MetadataSlide title subtitle authors date) = do
@@ -819,9 +823,7 @@ applyToLayout f (MetadataSlide title subtitle authors date) = do
   authors' <- mapM (mapM f) authors
   date' <- mapM f date
   return $ MetadataSlide title' subtitle' authors' date'
-applyToLayout f (TitleSlide title) = do
-  title' <- mapM f title
-  return $ TitleSlide title'
+applyToLayout f (TitleSlide title) = TitleSlide <$> mapM f title
 applyToLayout f (ContentSlide hdr content) = do
   hdr' <- mapM f hdr
   content' <- mapM (applyToShape f) content
@@ -835,11 +837,9 @@ applyToLayout f (TwoColumnSlide hdr contentL contentR) = do
 applyToSlide :: Monad m => (ParaElem -> m ParaElem) -> Slide -> m Slide
 applyToSlide f slide = do
   layout' <- applyToLayout f $ slideLayout slide
-  mbNotes' <- case slideSpeakerNotes slide of
-                Just (SpeakerNotes notes) -> (Just . SpeakerNotes) <$>
-                                             mapM (applyToParagraph f) notes
-                Nothing -> return Nothing
-  return slide{slideLayout = layout', slideSpeakerNotes = mbNotes'}
+  let paras = fromSpeakerNotes $ slideSpeakerNotes slide
+  notes' <- SpeakerNotes <$> mapM (applyToParagraph f) paras
+  return slide{slideLayout = layout', slideSpeakerNotes = notes'}
 
 replaceAnchor :: ParaElem -> Pres ParaElem
 replaceAnchor (Run rProps s)
@@ -853,6 +853,40 @@ replaceAnchor (Run rProps s)
       return $ Run rProps' s
 replaceAnchor pe = return pe
 
+emptyParaElem :: ParaElem -> Bool
+emptyParaElem (Run _ s) =
+  null $ Shared.trim s
+emptyParaElem (MathElem _ ts) =
+  null $ Shared.trim $ unTeXString ts
+emptyParaElem _ = False
+
+emptyParagraph :: Paragraph -> Bool
+emptyParagraph para = all emptyParaElem $ paraElems para
+
+
+emptyShape :: Shape -> Bool
+emptyShape (TextBox paras) = all emptyParagraph paras
+emptyShape _ = False
+
+emptyLayout :: Layout -> Bool
+emptyLayout layout = case layout of
+  MetadataSlide title subtitle authors date ->
+    all emptyParaElem title &&
+    all emptyParaElem subtitle &&
+    all (all emptyParaElem) authors &&
+    all emptyParaElem date
+  TitleSlide hdr -> all emptyParaElem hdr
+  ContentSlide hdr shapes ->
+    all emptyParaElem hdr &&
+    all emptyShape shapes
+  TwoColumnSlide hdr shapes1 shapes2 ->
+    all emptyParaElem hdr &&
+    all emptyShape shapes1 &&
+    all emptyShape shapes2
+
+emptySlide :: Slide -> Bool
+emptySlide (Slide _ layout notes) = (notes == mempty) && (emptyLayout layout)
+
 blocksToPresentationSlides :: [Block] -> Pres [Slide]
 blocksToPresentationSlides blks = do
   opts <- asks envOpts
@@ -893,7 +927,8 @@ blocksToPresentationSlides blks = do
                             return [endNotesSlide]
 
   let slides = metadataslides ++ tocSlides ++ bodyslides ++ endNotesSlides
-  mapM (applyToSlide replaceAnchor) slides
+      slides' = filter (not . emptySlide) slides
+  mapM (applyToSlide replaceAnchor) slides'
 
 metaToDocProps :: Meta -> DocProps
 metaToDocProps meta =
diff --git a/src/Text/Pandoc/Writers/RST.hs b/src/Text/Pandoc/Writers/RST.hs
index 95cb46643..f82597c55 100644
--- a/src/Text/Pandoc/Writers/RST.hs
+++ b/src/Text/Pandoc/Writers/RST.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-
 Copyright (C) 2006-2018 John MacFarlane <jgm@berkeley.edu>
@@ -30,7 +31,8 @@ Conversion of 'Pandoc' documents to reStructuredText.
 
 reStructuredText:  <http://docutils.sourceforge.net/rst.html>
 -}
-module Text.Pandoc.Writers.RST ( writeRST ) where
+module Text.Pandoc.Writers.RST ( writeRST, flatten ) where
+import Prelude
 import Control.Monad.State.Strict
 import Data.Char (isSpace, toLower)
 import Data.List (isPrefixOf, stripPrefix)
@@ -46,6 +48,7 @@ import Text.Pandoc.Pretty
 import Text.Pandoc.Shared
 import Text.Pandoc.Templates (renderTemplate')
 import Text.Pandoc.Writers.Shared
+import Text.Pandoc.Walk
 
 type Refs = [([Inline], Target)]
 
@@ -260,7 +263,6 @@ blockToRST (Header level (name,classes,_) inlines) = do
           return $ nowrap $ hang 3 ".. " (rub $$ name' $$ cls) $$ blankline
 blockToRST (CodeBlock (_,classes,kvs) str) = do
   opts <- gets stOptions
-  let tabstop = writerTabStop opts
   let startnum = maybe "" (\x -> " " <> text x) $ lookup "startFrom" kvs
   let numberlines = if "numberLines" `elem` classes
                        then "   :number-lines:" <> startnum
@@ -273,11 +275,10 @@ blockToRST (CodeBlock (_,classes,kvs) str) = do
                      c `notElem` ["sourceCode","literate","numberLines"]] of
              []       -> "::"
              (lang:_) -> (".. code:: " <> text lang) $$ numberlines)
-          $+$ nest tabstop (text str) $$ blankline
+          $+$ nest 3 (text str) $$ blankline
 blockToRST (BlockQuote blocks) = do
-  tabstop <- gets $ writerTabStop . stOptions
   contents <- blockListToRST blocks
-  return $ nest tabstop contents <> blankline
+  return $ nest 3 contents <> blankline
 blockToRST (Table caption aligns widths headers rows) = do
   caption' <- inlineListToRST caption
   let blocksToDoc opts bs = do
@@ -335,8 +336,7 @@ definitionListItemToRST :: PandocMonad m => ([Inline], [[Block]]) -> RST m Doc
 definitionListItemToRST (label, defs) = do
   label' <- inlineListToRST label
   contents <- liftM vcat $ mapM blockListToRST defs
-  tabstop <- gets $ writerTabStop . stOptions
-  return $ nowrap label' $$ nest tabstop (nestle contents <> cr)
+  return $ nowrap label' $$ nest 3 (nestle contents <> cr)
 
 -- | Format a list of lines as line block.
 linesToLineBlock :: PandocMonad m => [[Inline]] -> RST m Doc
@@ -376,12 +376,27 @@ blockListToRST :: PandocMonad m
                -> RST m Doc
 blockListToRST = blockListToRST' False
 
--- | Convert list of Pandoc inline elements to RST.
-inlineListToRST :: PandocMonad m => [Inline] -> RST m Doc
-inlineListToRST lst =
-  mapM inlineToRST (removeSpaceAfterDisplayMath $ insertBS lst) >>=
-    return . hcat
-  where -- remove spaces after displaymath, as they screw up indentation:
+transformInlines :: [Inline] -> [Inline]
+transformInlines =  insertBS .
+                    filter hasContents .
+                    removeSpaceAfterDisplayMath .
+                    concatMap (transformNested . flatten)
+  where -- empty inlines are not valid RST syntax
+        hasContents :: Inline -> Bool
+        hasContents (Str "")              = False
+        hasContents (Emph [])             = False
+        hasContents (Strong [])           = False
+        hasContents (Strikeout [])        = False
+        hasContents (Superscript [])      = False
+        hasContents (Subscript [])        = False
+        hasContents (SmallCaps [])        = False
+        hasContents (Quoted _ [])         = False
+        hasContents (Cite _ [])           = False
+        hasContents (Span _ [])           = False
+        hasContents (Link _ [] ("", ""))  = False
+        hasContents (Image _ [] ("", "")) = False
+        hasContents _                     = True
+        -- remove spaces after displaymath, as they screw up indentation:
         removeSpaceAfterDisplayMath (Math DisplayMath x : zs) =
               Math DisplayMath x : dropWhile (==Space) zs
         removeSpaceAfterDisplayMath (x:xs) = x : removeSpaceAfterDisplayMath xs
@@ -399,6 +414,8 @@ inlineListToRST lst =
               x : insertBS (y : zs)
         insertBS (x:ys) = x : insertBS ys
         insertBS [] = []
+        transformNested :: [Inline] -> [Inline]
+        transformNested = map (mapNested stripLeadingTrailingSpace)
         surroundComplex :: Inline -> Inline -> Bool
         surroundComplex (Str s@(_:_)) (Str s'@(_:_)) =
           case (last s, head s') of
@@ -436,44 +453,122 @@ inlineListToRST lst =
         isComplex (Span _ (x:_))  = isComplex x
         isComplex _               = False
 
+-- | Flattens nested inlines. Extracts nested inlines and goes through
+-- them either collapsing them in the outer inline container or
+-- pulling them out of it
+flatten :: Inline -> [Inline]
+flatten outer
+  | null contents = [outer]
+  | otherwise     = combineAll contents
+  where contents = dropInlineParent outer
+        combineAll = foldl combine []
+
+        combine :: [Inline] -> Inline -> [Inline]
+        combine f i = 
+          case (outer, i) of
+          -- quotes are not rendered using RST inlines, so we can keep
+          -- them and they will be readable and parsable
+          (Quoted _ _, _)          -> keep f i
+          (_, Quoted _ _)          -> keep f i
+          -- parent inlines would prevent links from being correctly
+          -- parsed, in this case we prioritise the content over the
+          -- style
+          (_, Link _ _ _)          -> emerge f i
+          -- always give priority to strong text over emphasis
+          (Emph _, Strong _)       -> emerge f i
+          -- drop all other nested styles
+          (_, _)                   -> collapse f i
+
+        emerge f i = f <> [i]
+        keep f i = appendToLast f [i]
+        collapse f i = appendToLast f $ dropInlineParent i
+
+        appendToLast :: [Inline] -> [Inline] -> [Inline]
+        appendToLast [] toAppend = [setInlineChildren outer toAppend]
+        appendToLast flattened toAppend
+          | isOuter lastFlat = init flattened <> [appendTo lastFlat toAppend]
+          | otherwise =  flattened <> [setInlineChildren outer toAppend]
+          where lastFlat = last flattened
+                appendTo o i = mapNested (<> i) o
+                isOuter i = emptyParent i == emptyParent outer
+                emptyParent i = setInlineChildren i []
+
+mapNested :: ([Inline] -> [Inline]) -> Inline -> Inline
+mapNested f i = setInlineChildren i (f (dropInlineParent i))
+
+dropInlineParent :: Inline -> [Inline]
+dropInlineParent (Link _ i _)    = i
+dropInlineParent (Emph i)        = i
+dropInlineParent (Strong i)      = i
+dropInlineParent (Strikeout i)   = i
+dropInlineParent (Superscript i) = i
+dropInlineParent (Subscript i)   = i
+dropInlineParent (SmallCaps i)   = i
+dropInlineParent (Cite _ i)      = i
+dropInlineParent (Image _ i _)   = i
+dropInlineParent (Span _ i)      = i
+dropInlineParent (Quoted _ i)    = i
+dropInlineParent i               = [i] -- not a parent, like Str or Space
+
+setInlineChildren :: Inline -> [Inline] -> Inline
+setInlineChildren (Link a _ t) i    = Link a i t
+setInlineChildren (Emph _) i        = Emph i
+setInlineChildren (Strong _) i      = Strong i
+setInlineChildren (Strikeout _) i   = Strikeout i
+setInlineChildren (Superscript _) i = Superscript i
+setInlineChildren (Subscript _) i   = Subscript i
+setInlineChildren (SmallCaps _) i   = SmallCaps i
+setInlineChildren (Quoted q _) i    = Quoted q i
+setInlineChildren (Cite c _) i      = Cite c i
+setInlineChildren (Image a _ t) i   = Image a i t
+setInlineChildren (Span a _) i      = Span a i
+setInlineChildren leaf _            = leaf
+
+inlineListToRST :: PandocMonad m => [Inline] -> RST m Doc
+inlineListToRST = writeInlines . walk transformInlines
+
+-- | Convert list of Pandoc inline elements to RST.
+writeInlines :: PandocMonad m => [Inline] -> RST m Doc
+writeInlines lst = mapM inlineToRST lst >>= return . hcat
+
 -- | Convert Pandoc inline element to RST.
 inlineToRST :: PandocMonad m => Inline -> RST m Doc
 inlineToRST (Span (_,_,kvs) ils) = do
-  contents <- inlineListToRST ils
+  contents <- writeInlines ils
   return $
     case lookup "role" kvs of
           Just role -> ":" <> text role <> ":`" <> contents <> "`"
           Nothing   -> contents
 inlineToRST (Emph lst) = do
-  contents <- inlineListToRST lst
+  contents <- writeInlines lst
   return $ "*" <> contents <> "*"
 inlineToRST (Strong lst) = do
-  contents <- inlineListToRST lst
+  contents <- writeInlines lst
   return $ "**" <> contents <> "**"
 inlineToRST (Strikeout lst) = do
-  contents <- inlineListToRST lst
+  contents <- writeInlines lst
   return $ "[STRIKEOUT:" <> contents <> "]"
 inlineToRST (Superscript lst) = do
-  contents <- inlineListToRST lst
+  contents <- writeInlines lst
   return $ ":sup:`" <> contents <> "`"
 inlineToRST (Subscript lst) = do
-  contents <- inlineListToRST lst
+  contents <- writeInlines lst
   return $ ":sub:`" <> contents <> "`"
-inlineToRST (SmallCaps lst) = inlineListToRST lst
+inlineToRST (SmallCaps lst) = writeInlines lst
 inlineToRST (Quoted SingleQuote lst) = do
-  contents <- inlineListToRST lst
+  contents <- writeInlines lst
   opts <- gets stOptions
   if isEnabled Ext_smart opts
      then return $ "'" <> contents <> "'"
      else return $ "‘" <> contents <> "’"
 inlineToRST (Quoted DoubleQuote lst) = do
-  contents <- inlineListToRST lst
+  contents <- writeInlines lst
   opts <- gets stOptions
   if isEnabled Ext_smart opts
      then return $ "\"" <> contents <> "\""
      else return $ "“" <> contents <> "”"
 inlineToRST (Cite _  lst) =
-  inlineListToRST lst
+  writeInlines lst
 inlineToRST (Code _ str) = do
   opts <- gets stOptions
   -- we trim the string because the delimiters must adjoin a
@@ -524,7 +619,7 @@ inlineToRST (Link _ [Image attr alt (imgsrc,imgtit)] (src, _tit)) = do
   return $ "|" <> label <> "|"
 inlineToRST (Link _ txt (src, tit)) = do
   useReferenceLinks <- gets $ writerReferenceLinks . stOptions
-  linktext <- inlineListToRST $ B.toList . B.trimInlines . B.fromList $ txt
+  linktext <- writeInlines $ B.toList . B.trimInlines . B.fromList $ txt
   if useReferenceLinks
     then do refs <- gets stLinks
             case lookup txt refs of
diff --git a/src/Text/Pandoc/Writers/RTF.hs b/src/Text/Pandoc/Writers/RTF.hs
index 7006b58d1..3045c1c10 100644
--- a/src/Text/Pandoc/Writers/RTF.hs
+++ b/src/Text/Pandoc/Writers/RTF.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-
 Copyright (C) 2006-2018 John MacFarlane <jgm@berkeley.edu>
@@ -30,6 +31,7 @@ Conversion of 'Pandoc' documents to RTF (rich text format).
 -}
 module Text.Pandoc.Writers.RTF ( writeRTF
                                ) where
+import Prelude
 import Control.Monad.Except (catchError, throwError)
 import Control.Monad
 import qualified Data.ByteString as B
diff --git a/src/Text/Pandoc/Writers/Shared.hs b/src/Text/Pandoc/Writers/Shared.hs
index ae4cc5cc5..2edce7deb 100644
--- a/src/Text/Pandoc/Writers/Shared.hs
+++ b/src/Text/Pandoc/Writers/Shared.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-
 Copyright (C) 2013-2018 John MacFarlane <jgm@berkeley.edu>
@@ -41,8 +42,10 @@ module Text.Pandoc.Writers.Shared (
                      , unsmartify
                      , gridTable
                      , metaValueToInlines
+                     , stripLeadingTrailingSpace
                      )
 where
+import Prelude
 import Control.Monad (zipWithM)
 import Data.Aeson (FromJSON (..), Result (..), ToJSON (..), Value (Object),
                    encode, fromJSON)
@@ -240,40 +243,58 @@ gridTable :: Monad m
           -> [[[Block]]]
           -> m Doc
 gridTable opts blocksToDoc headless aligns widths headers rows = do
+  -- the number of columns will be used in case of even widths
   let numcols = maximum (length aligns : length widths :
                            map length (headers:rows))
+  -- handleGivenWidths wraps the given blocks in order for them to fit
+  -- in cells with given widths. the returned content can be
+  -- concatenated with borders and frames
   let handleGivenWidths widths' = do
         let widthsInChars' = map (
                       (\x -> if x < 1 then 1 else x) .
                       (\x -> x - 3) . floor .
                       (fromIntegral (writerColumns opts) *)
                       ) widths'
-        rawHeaders' <- zipWithM blocksToDoc
-            (map (\w -> opts{writerColumns =
-                      min (w - 2) (writerColumns opts)}) widthsInChars')
-            headers
+            -- replace page width (in columns) in the options with a
+            -- given width if smaller (adjusting by two)
+            useWidth w = opts{writerColumns = min (w - 2) (writerColumns opts)}
+            -- prepare options to use with header and row cells
+            columnOptions = map useWidth widthsInChars'
+        rawHeaders' <- zipWithM blocksToDoc columnOptions headers
         rawRows' <- mapM
-             (\cs -> zipWithM blocksToDoc
-               (map (\w -> opts{writerColumns =
-                         min (w - 2) (writerColumns opts)}) widthsInChars')
-               cs)
+             (\cs -> zipWithM blocksToDoc columnOptions cs)
              rows
         return (widthsInChars', rawHeaders', rawRows')
-  let handleZeroWidths = do
+  -- handleFullWidths tries to wrap cells to the page width or even
+  -- more in cases where `--wrap=none`. thus the content here is left
+  -- as wide as possible
+  let handleFullWidths = do
         rawHeaders' <- mapM (blocksToDoc opts) headers
         rawRows' <- mapM (mapM (blocksToDoc opts)) rows
         let numChars [] = 0
             numChars xs = maximum . map offset $ xs
         let widthsInChars' =
                 map numChars $ transpose (rawHeaders' : rawRows')
+        return (widthsInChars', rawHeaders', rawRows')
+  -- handleZeroWidths calls handleFullWidths to check whether a wide
+  -- table would fit in the page. if the produced table is too wide,
+  -- it calculates even widths and passes the content to
+  -- handleGivenWidths
+  let handleZeroWidths = do
+        (widthsInChars', rawHeaders', rawRows') <- handleFullWidths
         if sum widthsInChars' > writerColumns opts
            then -- use even widths
                 handleGivenWidths
                   (replicate numcols (1.0 / fromIntegral numcols) :: [Double])
            else return (widthsInChars', rawHeaders', rawRows')
-  (widthsInChars, rawHeaders, rawRows) <- if all (== 0) widths
-                                             then handleZeroWidths
-                                             else handleGivenWidths widths
+  -- render the contents of header and row cells differently depending
+  -- on command line options, widths given in this specific table, and
+  -- cells' contents
+  let handleWidths
+        | writerWrapText opts == WrapNone  = handleFullWidths
+        | all (== 0) widths                  = handleZeroWidths
+        | otherwise                          = handleGivenWidths widths
+  (widthsInChars, rawHeaders, rawRows) <- handleWidths
   let hpipeBlocks blocks = hcat [beg, middle, end]
         where h       = maximum (1 : map height blocks)
               sep'    = lblock 3 $ vcat (replicate h (text " | "))
diff --git a/src/Text/Pandoc/Writers/TEI.hs b/src/Text/Pandoc/Writers/TEI.hs
index 4936c743e..e461f5715 100644
--- a/src/Text/Pandoc/Writers/TEI.hs
+++ b/src/Text/Pandoc/Writers/TEI.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE PatternGuards     #-}
 {-
@@ -30,6 +31,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Conversion of 'Pandoc' documents to Docbook XML.
 -}
 module Text.Pandoc.Writers.TEI (writeTEI) where
+import Prelude
 import Data.Char (toLower)
 import Data.List (isPrefixOf, stripPrefix)
 import Data.Text (Text)
diff --git a/src/Text/Pandoc/Writers/Texinfo.hs b/src/Text/Pandoc/Writers/Texinfo.hs
index bf434642e..305b41206 100644
--- a/src/Text/Pandoc/Writers/Texinfo.hs
+++ b/src/Text/Pandoc/Writers/Texinfo.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-
 Copyright (C) 2008-2018 John MacFarlane
@@ -31,6 +32,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Conversion of 'Pandoc' format into Texinfo.
 -}
 module Text.Pandoc.Writers.Texinfo ( writeTexinfo ) where
+import Prelude
 import Control.Monad.Except (throwError)
 import Control.Monad.State.Strict
 import Data.Char (chr, ord)
diff --git a/src/Text/Pandoc/Writers/Textile.hs b/src/Text/Pandoc/Writers/Textile.hs
index f46eb43bc..0ed79d2df 100644
--- a/src/Text/Pandoc/Writers/Textile.hs
+++ b/src/Text/Pandoc/Writers/Textile.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2010-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -30,6 +31,7 @@ Conversion of 'Pandoc' documents to Textile markup.
 Textile:  <http://thresholdstate.com/articles/4312/the-textile-reference-manual>
 -}
 module Text.Pandoc.Writers.Textile ( writeTextile ) where
+import Prelude
 import Control.Monad.State.Strict
 import Data.Char (isSpace)
 import Data.List (intercalate)
diff --git a/src/Text/Pandoc/Writers/ZimWiki.hs b/src/Text/Pandoc/Writers/ZimWiki.hs
index dec1f9d4a..a583b07b1 100644
--- a/src/Text/Pandoc/Writers/ZimWiki.hs
+++ b/src/Text/Pandoc/Writers/ZimWiki.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2008-2018 John MacFarlane <jgm@berkeley.edu>
               2017-2018 Alex Ivkin
@@ -32,6 +33,7 @@ http://zim-wiki.org/manual/Help/Wiki_Syntax.html
 -}
 
 module Text.Pandoc.Writers.ZimWiki ( writeZimWiki ) where
+import Prelude
 import Control.Monad (zipWithM)
 import Control.Monad.State.Strict (StateT, evalStateT, gets, modify)
 import Data.Default (Default (..))
diff --git a/src/Text/Pandoc/XML.hs b/src/Text/Pandoc/XML.hs
index 62874f0b9..add46bd6c 100644
--- a/src/Text/Pandoc/XML.hs
+++ b/src/Text/Pandoc/XML.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-
 Copyright (C) 2006-2018 John MacFarlane <jgm@berkeley.edu>
 
@@ -36,6 +37,7 @@ module Text.Pandoc.XML ( escapeCharForXML,
                          toEntities,
                          fromEntities ) where
 
+import Prelude
 import Data.Char (isAscii, isSpace, ord)
 import Data.Text (Text)
 import qualified Data.Text as T
diff --git a/stack.lts9.yaml b/stack.lts9.yaml
index 936fb4ac4..9507d961d 100644
--- a/stack.lts9.yaml
+++ b/stack.lts9.yaml
@@ -2,7 +2,6 @@ flags:
   pandoc:
     trypandoc: false
     embed_data_files: true
-    old-locale: false
     network-uri: true
   pandoc-citeproc:
     bibutils: true
@@ -13,19 +12,20 @@ flags:
 packages:
 - '.'
 extra-deps:
-- pandoc-types-1.17.3
-- hslua-0.9.5
-- hslua-module-text-0.1.2
-- skylighting-0.6
-- ansi-terminal-0.7.1.1
-- texmath-0.10.1.1
-- cmark-gfm-0.1.1
-- QuickCheck-2.10.0.1
+- hslua-0.9.5.1
+- hslua-module-text-0.1.2.1
+- skylighting-0.7.0.2
+- skylighting-core-0.7.0.2
+- ansi-terminal-0.8.0.2
+- cmark-gfm-0.1.3
+- QuickCheck-2.11.3
+- tasty-1.0.1.1
 - tasty-quickcheck-0.9.1
-- doctemplates-0.2.1
-- haddock-library-1.4.3
-- tagsoup-0.14.2
+- doctemplates-0.2.2.1
 - hs-bibutils-6.2.0.1
-- pandoc-citeproc-0.14.1.2
-- tagsoup-0.14.3
+- pandoc-citeproc-0.14.3.1
+- tagsoup-0.14.6
+- pandoc-types-1.17.4.2
+- haddock-library-1.5.0.1
+- texmath-0.10.1.2
 resolver: lts-9.14
diff --git a/stack.yaml b/stack.yaml
index 5098fe20b..9c59e5e44 100644
--- a/stack.yaml
+++ b/stack.yaml
@@ -2,7 +2,6 @@ flags:
   pandoc:
     trypandoc: false
     embed_data_files: true
-    old-locale: false
     network-uri: true
   pandoc-citeproc:
     bibutils: true
@@ -13,13 +12,16 @@ flags:
 packages:
 - '.'
 extra-deps:
-- pandoc-citeproc-0.14.1.2
-- hslua-0.9.5
-- skylighting-0.6
-- ansi-terminal-0.7.1.1
-- tasty-1.0.0.1
-- texmath-0.10.1.1
-- tagsoup-0.14.3
+- pandoc-citeproc-0.14.3.1
+- skylighting-0.7.0.2
+- skylighting-core-0.7.0.2
+- ansi-terminal-0.8.0.2
+- tasty-1.0.1.1
+- test-framework-0.8.2.0
+- pandoc-types-1.17.4.2
+- cmark-gfm-0.1.3
+- hslua-module-text-0.1.2.1
+- texmath-0.10.1.2
 ghc-options:
-   "$locals": -fhide-source-paths
-resolver: lts-10.3
+   "$locals": -fhide-source-paths -XNoImplicitPrelude
+resolver: lts-10.10
diff --git a/test/Tests/Command.hs b/test/Tests/Command.hs
index de83d0639..89ea9a741 100644
--- a/test/Tests/Command.hs
+++ b/test/Tests/Command.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 module Tests.Command (findPandoc, runTest, tests)
 where
 
+import Prelude
 import Data.Algorithm.Diff
 import qualified Data.ByteString as BS
 import Data.List (isSuffixOf)
diff --git a/test/Tests/Command.hs.orig b/test/Tests/Command.hs.orig
new file mode 100644
index 000000000..de83d0639
--- /dev/null
+++ b/test/Tests/Command.hs.orig
@@ -0,0 +1,95 @@
+module Tests.Command (findPandoc, runTest, tests)
+where
+
+import Data.Algorithm.Diff
+import qualified Data.ByteString as BS
+import Data.List (isSuffixOf)
+import Prelude hiding (readFile)
+import System.Directory
+import System.Exit
+import System.FilePath (joinPath, splitDirectories, takeDirectory, (</>))
+import System.IO (hPutStr, stderr)
+import System.IO.Unsafe (unsafePerformIO)
+import System.Process
+import Test.Tasty
+import Test.Tasty.HUnit
+import Tests.Helpers
+import Text.Pandoc
+import qualified Text.Pandoc.UTF8 as UTF8
+
+-- | Run a test with normalize function, return True if test passed.
+runTest :: String    -- ^ Title of test
+        -> FilePath  -- ^ Path to pandoc
+        -> String    -- ^ Shell command
+        -> String    -- ^ Input text
+        -> String    -- ^ Expected output
+        -> TestTree
+runTest testname pandocpath cmd inp norm = testCase testname $ do
+  let findDynlibDir []           = Nothing
+      findDynlibDir ("build":xs) = Just $ joinPath (reverse xs) </> "build"
+      findDynlibDir (_:xs)       = findDynlibDir xs
+  let mbDynlibDir = findDynlibDir (reverse $ splitDirectories $
+                                   takeDirectory $ takeWhile (/=' ') cmd)
+  let dynlibEnv = case mbDynlibDir of
+                       Nothing  -> []
+                       Just d   -> [("DYLD_LIBRARY_PATH", d),
+                                    ("LD_LIBRARY_PATH", d)]
+  let env' = dynlibEnv ++ [("PATH",takeDirectory pandocpath),("TMP","."),("LANG","en_US.UTF-8"),("HOME", "./"),("pandoc_datadir", "..")]
+  let pr = (shell cmd){ env = Just env' }
+  (ec, out', err') <- readCreateProcessWithExitCode pr inp
+  -- filter \r so the tests will work on Windows machines
+  let out = filter (/= '\r') $ err' ++ out'
+  result  <- if ec == ExitSuccess
+                then
+                  if out == norm
+                     then return TestPassed
+                     else return
+                          $ TestFailed cmd "expected"
+                          $ getDiff (lines out) (lines norm)
+                else do
+                  hPutStr stderr err'
+                  return $ TestError ec
+  assertBool (show result) (result == TestPassed)
+
+tests :: TestTree
+{-# NOINLINE tests #-}
+tests = unsafePerformIO $ do
+  pandocpath <- findPandoc
+  files <- filter (".md" `isSuffixOf`) <$>
+               getDirectoryContents "command"
+  let cmds = map (extractCommandTest pandocpath) files
+  return $ testGroup "Command:" cmds
+
+isCodeBlock :: Block -> Bool
+isCodeBlock (CodeBlock _ _) = True
+isCodeBlock _               = False
+
+extractCode :: Block -> String
+extractCode (CodeBlock _ code) = code
+extractCode _                  = ""
+
+dropPercent :: String -> String
+dropPercent ('%':xs) = dropWhile (== ' ') xs
+dropPercent xs       = xs
+
+runCommandTest :: FilePath -> (Int, String) -> TestTree
+runCommandTest pandocpath (num, code) =
+  let codelines = lines code
+      (continuations, r1) = span ("\\" `isSuffixOf`) codelines
+      (cmd, r2) = (dropPercent (unwords (map init continuations ++ take 1 r1)),
+                   drop 1 r1)
+      (inplines, r3) = break (=="^D") r2
+      normlines = takeWhile (/=".") (drop 1 r3)
+      input = unlines inplines
+      norm = unlines normlines
+      shcmd = cmd -- trimr $ takeDirectory pandocpath </> cmd
+  in  runTest ("#" ++ show num) pandocpath shcmd input norm
+
+extractCommandTest :: FilePath -> FilePath -> TestTree
+extractCommandTest pandocpath fp = unsafePerformIO $ do
+  contents <- UTF8.toText <$> BS.readFile ("command" </> fp)
+  Pandoc _ blocks <- runIOorExplode (readMarkdown
+                        def{ readerExtensions = pandocExtensions } contents)
+  let codeblocks = map extractCode $ filter isCodeBlock blocks
+  let cases = map (runCommandTest pandocpath) $ zip [1..] codeblocks
+  return $ testGroup fp cases
diff --git a/test/Tests/Helpers.hs b/test/Tests/Helpers.hs
index 2a6543ea0..1c031aa64 100644
--- a/test/Tests/Helpers.hs
+++ b/test/Tests/Helpers.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE FlexibleInstances    #-}
 {-# LANGUAGE TypeSynonymInstances #-}
 -- Utility functions for the test suite.
@@ -13,6 +14,7 @@ module Tests.Helpers ( test
                      )
                      where
 
+import Prelude
 import Data.Algorithm.Diff
 import qualified Data.Map as M
 import Data.Text (Text, unpack)
diff --git a/test/Tests/Helpers.hs.orig b/test/Tests/Helpers.hs.orig
new file mode 100644
index 000000000..2a6543ea0
--- /dev/null
+++ b/test/Tests/Helpers.hs.orig
@@ -0,0 +1,138 @@
+{-# LANGUAGE FlexibleInstances    #-}
+{-# LANGUAGE TypeSynonymInstances #-}
+-- Utility functions for the test suite.
+
+module Tests.Helpers ( test
+                     , TestResult(..)
+                     , showDiff
+                     , findPandoc
+                     , (=?>)
+                     , purely
+                     , ToString(..)
+                     , ToPandoc(..)
+                     )
+                     where
+
+import Data.Algorithm.Diff
+import qualified Data.Map as M
+import Data.Text (Text, unpack)
+import System.Directory
+import System.Environment.Executable (getExecutablePath)
+import System.Exit
+import System.FilePath
+import Test.Tasty
+import Test.Tasty.HUnit
+import Text.Pandoc.Builder (Blocks, Inlines, doc, plain)
+import Text.Pandoc.Class
+import Text.Pandoc.Definition
+import Text.Pandoc.Options
+import Text.Pandoc.Shared (trimr)
+import Text.Pandoc.Writers.Native (writeNative)
+import Text.Printf
+
+test :: (ToString a, ToString b, ToString c)
+     => (a -> b)  -- ^ function to test
+     -> String    -- ^ name of test case
+     -> (a, c)    -- ^ (input, expected value)
+     -> TestTree
+test fn name (input, expected) =
+  testCase name' $ assertBool msg (actual' == expected')
+     where msg = nl ++ dashes "input" ++ nl ++ input' ++ nl ++
+                 dashes "result" ++ nl ++
+                 unlines (map vividize diff) ++
+                 dashes ""
+           nl = "\n"
+           name'   = if length name > 54
+                        then take 52 name ++ "..."  -- avoid wide output
+                        else name
+           input'  = toString input
+           actual' = lines $ toString $ fn input
+           expected' = lines $ toString expected
+           diff = getDiff expected' actual'
+           dashes "" = replicate 72 '-'
+           dashes x  = replicate (72 - length x - 5) '-' ++ " " ++ x ++ " ---"
+
+data TestResult = TestPassed
+                | TestError ExitCode
+                | TestFailed String FilePath [Diff String]
+     deriving (Eq)
+
+instance Show TestResult where
+  show TestPassed     = "PASSED"
+  show (TestError ec) = "ERROR " ++ show ec
+  show (TestFailed cmd file d) = '\n' : dash ++
+                                 "\n--- " ++ file ++
+                                 "\n+++ " ++ cmd ++ "\n" ++ showDiff (1,1) d ++
+                                 dash
+    where dash = replicate 72 '-'
+
+showDiff :: (Int,Int) -> [Diff String] -> String
+showDiff _ []             = ""
+showDiff (l,r) (First ln : ds) =
+  printf "+%4d " l ++ ln ++ "\n" ++ showDiff (l+1,r) ds
+showDiff (l,r) (Second ln : ds) =
+  printf "-%4d " r ++ ln ++ "\n" ++ showDiff (l,r+1) ds
+showDiff (l,r) (Both _ _ : ds) =
+  showDiff (l+1,r+1) ds
+
+-- | Find pandoc executable relative to test-pandoc
+-- First, try in same directory (e.g. if both in ~/.cabal/bin)
+-- Second, try ../pandoc (e.g. if in dist/XXX/build/test-pandoc)
+findPandoc :: IO FilePath
+findPandoc = do
+  testExePath <- getExecutablePath
+  let testExeDir = takeDirectory testExePath
+  found <- doesFileExist (testExeDir </> "pandoc")
+  return $ if found
+              then testExeDir </> "pandoc"
+              else case splitDirectories testExeDir of
+                         [] -> error "test-pandoc: empty testExeDir"
+                         xs -> joinPath (init xs) </> "pandoc" </> "pandoc"
+
+
+vividize :: Diff String -> String
+vividize (Both s _) = "  " ++ s
+vividize (First s)  = "- " ++ s
+vividize (Second s) = "+ " ++ s
+
+purely :: (b -> PandocPure a) -> b -> a
+purely f = either (error . show) id . runPure . f
+
+infix 5 =?>
+(=?>) :: a -> b -> (a,b)
+x =?> y = (x, y)
+
+class ToString a where
+  toString :: a -> String
+
+instance ToString Pandoc where
+  toString d = unpack $
+     purely (writeNative def{ writerTemplate = s }) $ toPandoc d
+   where s = case d of
+                  (Pandoc (Meta m) _)
+                    | M.null m  -> Nothing
+                    | otherwise -> Just "" -- need this to get meta output
+
+instance ToString Blocks where
+  toString = unpack . purely (writeNative def) . toPandoc
+
+instance ToString Inlines where
+  toString = trimr . unpack . purely (writeNative def) . toPandoc
+
+instance ToString String where
+  toString = id
+
+instance ToString Text where
+  toString = unpack
+
+class ToPandoc a where
+  toPandoc :: a -> Pandoc
+
+instance ToPandoc Pandoc where
+  toPandoc = id
+
+instance ToPandoc Blocks where
+  toPandoc = doc
+
+instance ToPandoc Inlines where
+  toPandoc = doc . plain
diff --git a/test/Tests/Lua.hs b/test/Tests/Lua.hs
index b25a6fa4a..28a691715 100644
--- a/test/Tests/Lua.hs
+++ b/test/Tests/Lua.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Lua ( tests ) where
 
+import Prelude
 import Control.Monad (when)
 import Data.Version (Version (versionBranch))
 import System.FilePath ((</>))
@@ -10,7 +12,8 @@ import Test.Tasty.QuickCheck (QuickCheckTests (..), ioProperty, testProperty)
 import Text.Pandoc.Arbitrary ()
 import Text.Pandoc.Builder (bulletList, divWith, doc, doubleQuoted, emph,
                             header, linebreak, para, plain, rawBlock,
-                            singleQuoted, space, str, strong, (<>))
+                            singleQuoted, space, str, strong,
+                            math, displayMath)
 import Text.Pandoc.Class (runIOorExplode, setUserDataDir)
 import Text.Pandoc.Definition (Block (BlockQuote, Div, Para), Inline (Emph, Str),
                                Attr, Meta, Pandoc, pandocTypesVersion)
@@ -46,6 +49,12 @@ tests = map (localOption (QuickCheckTests 20))
       (doc $ bulletList [plain (str "alfa"), plain (str "bravo")])
       (doc $ bulletList [para (str "alfa"), para (str "bravo")])
 
+  , testCase "convert display math to inline math" $
+    assertFilterConversion "display math becomes inline math"
+      "math.lua"
+      (doc $ para (displayMath "5+5"))
+      (doc $ para (math "5+5"))
+
   , testCase "make hello world document" $
     assertFilterConversion "Document contains 'Hello, World!'"
       "hello-world-doc.lua"
@@ -111,6 +120,12 @@ tests = map (localOption (QuickCheckTests 20))
                      , plain (str "to_roman_numeral: OK")
                      ])
 
+  , testCase "Script filename is set" $
+    assertFilterConversion "unexpected script name"
+      "script-name.lua"
+      (doc $ para "ignored")
+      (doc $ para (str $ "lua" </> "script-name.lua"))
+
   , testCase "Pandoc version is set" . runPandocLua' $ do
       Lua.getglobal' "table.concat"
       Lua.getglobal "PANDOC_VERSION"
diff --git a/test/Tests/Lua.hs.orig b/test/Tests/Lua.hs.orig
new file mode 100644
index 000000000..5fe015265
--- /dev/null
+++ b/test/Tests/Lua.hs.orig
@@ -0,0 +1,196 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Lua ( tests ) where
+
+import Control.Monad (when)
+import Data.Version (Version (versionBranch))
+import System.FilePath ((</>))
+import Test.Tasty (TestTree, localOption)
+import Test.Tasty.HUnit (Assertion, assertEqual, testCase)
+import Test.Tasty.QuickCheck (QuickCheckTests (..), ioProperty, testProperty)
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder (bulletList, divWith, doc, doubleQuoted, emph,
+                            header, linebreak, para, plain, rawBlock,
+                            singleQuoted, space, str, strong)
+import Text.Pandoc.Class (runIOorExplode, setUserDataDir)
+import Text.Pandoc.Definition (Block (BlockQuote, Div, Para), Inline (Emph, Str),
+                               Attr, Meta, Pandoc, pandocTypesVersion)
+import Text.Pandoc.Lua (runLuaFilter, runPandocLua)
+import Text.Pandoc.Options (def)
+import Text.Pandoc.Shared (pandocVersion)
+
+import qualified Foreign.Lua as Lua
+
+tests :: [TestTree]
+tests = map (localOption (QuickCheckTests 20))
+  [ testProperty "inline elements can be round-tripped through the lua stack" $
+    \x -> ioProperty (roundtripEqual (x::Inline))
+
+  , testProperty "block elements can be round-tripped through the lua stack" $
+    \x -> ioProperty (roundtripEqual (x::Block))
+
+  , testProperty "meta blocks can be round-tripped through the lua stack" $
+    \x -> ioProperty (roundtripEqual (x::Meta))
+
+  , testProperty "documents can be round-tripped through the lua stack" $
+    \x -> ioProperty (roundtripEqual (x::Pandoc))
+
+  , testCase "macro expansion via filter" $
+    assertFilterConversion "a '{{helloworld}}' string is expanded"
+      "strmacro.lua"
+      (doc . para $ str "{{helloworld}}")
+      (doc . para . emph $ str "Hello, World")
+
+  , testCase "convert all plains to paras" $
+    assertFilterConversion "plains become para"
+      "plain-to-para.lua"
+      (doc $ bulletList [plain (str "alfa"), plain (str "bravo")])
+      (doc $ bulletList [para (str "alfa"), para (str "bravo")])
+
+  , testCase "make hello world document" $
+    assertFilterConversion "Document contains 'Hello, World!'"
+      "hello-world-doc.lua"
+      (doc . para $ str "Hey!" <> linebreak <> str "What's up?")
+      (doc . para $ str "Hello," <> space <> str "World!")
+
+  , testCase "implicit doc filter" $
+    assertFilterConversion "Document contains 'Hello, World!'"
+      "implicit-doc-filter.lua"
+      (doc . plain $ linebreak)
+      (doc . para $ str "Hello," <> space <> str "World!")
+
+  , testCase "parse raw markdown blocks" $
+    assertFilterConversion "raw markdown block is converted"
+      "markdown-reader.lua"
+      (doc $ rawBlock "markdown" "*charly* **delta**")
+      (doc . para $ emph "charly" <> space <> strong "delta")
+
+  , testCase "allow shorthand functions for quote types" $
+    assertFilterConversion "single quoted becomes double quoted string"
+      "single-to-double-quoted.lua"
+      (doc . para . singleQuoted $ str "simple")
+      (doc . para . doubleQuoted $ str "simple")
+
+  , testCase "Count inlines via metatable catch-all" $
+    assertFilterConversion "filtering with metatable catch-all failed"
+      "metatable-catch-all.lua"
+      (doc . para $ "four words, three spaces")
+      (doc . para $ str "7")
+
+  , testCase "Count blocks via Block-specific catch-all" $
+    assertFilterConversion "filtering with Block catch-all failed"
+      "block-count.lua"
+      (doc $ para "one" <> para "two")
+      (doc $ para "2")
+
+  , testCase "Convert header upper case" $
+    assertFilterConversion "converting header to upper case failed"
+      "uppercase-header.lua"
+      (doc $ header 1 "les états-unis" <> para "text")
+      (doc $ header 1 "LES ÉTATS-UNIS" <> para "text")
+
+  , testCase "Attribute lists are convenient to use" $
+    let kv_before = [("one", "1"), ("two", "2"), ("three", "3")]
+        kv_after  = [("one", "eins"), ("three", "3"), ("five", "5")]
+    in assertFilterConversion "Attr doesn't behave as expected"
+      "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")
+                     ])
+
+  , testCase "Script filename is set" $
+    assertFilterConversion "unexpected script name"
+      "script-name.lua"
+      (doc $ para "ignored")
+      (doc $ para (str $ "lua" </> "script-name.lua"))
+
+  , testCase "Pandoc version is set" . runPandocLua' $ do
+      Lua.getglobal' "table.concat"
+      Lua.getglobal "PANDOC_VERSION"
+      Lua.push ("." :: String) -- seperator
+      Lua.call 2 1
+      Lua.liftIO . assertEqual "pandoc version is wrong" pandocVersion
+        =<< Lua.peek Lua.stackTop
+
+  , testCase "Pandoc types version is set" . runPandocLua' $ do
+      let versionNums = versionBranch pandocTypesVersion
+      Lua.getglobal "PANDOC_API_VERSION"
+      Lua.liftIO . assertEqual "pandoc-types version is wrong" versionNums
+        =<< Lua.peek Lua.stackTop
+
+  , testCase "Allow singleton inline in constructors" . runPandocLua' $ do
+      Lua.liftIO . assertEqual "Not the exptected Emph" (Emph [Str "test"])
+        =<< Lua.callFunc "pandoc.Emph" (Str "test")
+      Lua.liftIO . assertEqual "Unexpected element" (Para [Str "test"])
+        =<< Lua.callFunc "pandoc.Para" ("test" :: String)
+      Lua.liftIO . assertEqual "Unexptected element"
+        (BlockQuote [Para [Str "foo"]]) =<< (
+        do
+          Lua.getglobal' "pandoc.BlockQuote"
+          Lua.push (Para [Str "foo"])
+          _ <- Lua.call 1 1
+          Lua.peek Lua.stackTop
+        )
+
+  , testCase "Elements with Attr have `attr` accessor" . runPandocLua' $ do
+      Lua.push (Div ("hi", ["moin"], [])
+                [Para [Str "ignored"]])
+      Lua.getfield Lua.stackTop "attr"
+      Lua.liftIO . assertEqual "no accessor" (("hi", ["moin"], []) :: Attr)
+        =<< Lua.peek Lua.stackTop
+
+  , testCase "informative error messages" . runPandocLua' $ do
+      Lua.pushboolean True
+      err <- Lua.peekEither Lua.stackTop :: Lua.Lua (Either String Pandoc)
+      case err of
+        Left msg -> do
+          let expectedMsg = "Could not get Pandoc value: "
+                            ++ "expected table but got boolean."
+          Lua.liftIO $ assertEqual "unexpected error message" expectedMsg msg
+        Right _ -> error "Getting a Pandoc element from a bool should fail."
+  ]
+
+assertFilterConversion :: String -> FilePath -> Pandoc -> Pandoc -> Assertion
+assertFilterConversion msg filterPath docIn docExpected = do
+  docEither <- runIOorExplode $ do
+    setUserDataDir (Just "../data")
+    runLuaFilter def ("lua" </> filterPath) [] docIn
+  case docEither of
+    Left _       -> fail "lua filter failed"
+    Right docRes -> assertEqual msg docExpected docRes
+
+roundtripEqual :: (Eq a, Lua.FromLuaStack a, Lua.ToLuaStack a) => a -> IO Bool
+roundtripEqual x = (x ==) <$> roundtripped
+ where
+  roundtripped :: (Lua.FromLuaStack a, Lua.ToLuaStack a) => IO a
+  roundtripped = 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 e -> error (show e)
+      Right y -> return y
+
+runPandocLua' :: Lua.Lua a -> IO a
+runPandocLua' op = runIOorExplode $ do
+  setUserDataDir (Just "../data")
+  res <- runPandocLua op
+  case res of
+    Left e -> error (show e)
+    Right x -> return x
diff --git a/test/Tests/Old.hs b/test/Tests/Old.hs
index b82251a56..b426ffd07 100644
--- a/test/Tests/Old.hs
+++ b/test/Tests/Old.hs
@@ -1,5 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 module Tests.Old (tests) where
 
+import Prelude
 import Data.Algorithm.Diff
 import Prelude hiding (readFile)
 import System.Exit
@@ -57,7 +59,7 @@ tests = [ testGroup "markdown"
           ]
         , testGroup "s5"
           [ s5WriterTest "basic" ["-s"] "s5"
-          , s5WriterTest "fancy" ["-s","-m","-i"] "s5"
+          , s5WriterTest "fancy" ["-s","--mathjax","-i"] "s5"
           , s5WriterTest "fragment" [] "html4"
           , s5WriterTest "inserts"  ["-s", "-H", "insert",
             "-B", "insert", "-A", "insert", "-c", "main.css"] "html4"
@@ -93,6 +95,7 @@ tests = [ testGroup "markdown"
           , fb2WriterTest "images" [] "fb2/images.markdown" "fb2/images.fb2"
           , fb2WriterTest "images-embedded" [] "fb2/images-embedded.html" "fb2/images-embedded.fb2"
           , fb2WriterTest "math" [] "fb2/math.markdown" "fb2/math.fb2"
+          , fb2WriterTest "meta" [] "fb2/meta.markdown" "fb2/meta.fb2"
           , fb2WriterTest "tables" [] "tables.native" "tables.fb2"
           , fb2WriterTest "testsuite" [] "testsuite.native" "writer.fb2"
           ]
@@ -286,4 +289,3 @@ findDynlibDir :: [FilePath] -> Maybe FilePath
 findDynlibDir []           = Nothing
 findDynlibDir ("build":xs) = Just $ joinPath (reverse xs) </> "build"
 findDynlibDir (_:xs)       = findDynlibDir xs
-
diff --git a/test/Tests/Old.hs.orig b/test/Tests/Old.hs.orig
new file mode 100644
index 000000000..ed4dcc076
--- /dev/null
+++ b/test/Tests/Old.hs.orig
@@ -0,0 +1,288 @@
+module Tests.Old (tests) where
+
+import Data.Algorithm.Diff
+import Prelude hiding (readFile)
+import System.Exit
+import System.FilePath (joinPath, splitDirectories, (<.>), (</>))
+import System.IO.Temp (withTempFile)
+import System.Process (runProcess, waitForProcess)
+import Test.Tasty (TestTree, testGroup)
+import Test.Tasty.Golden.Advanced (goldenTest)
+import Tests.Helpers hiding (test)
+import qualified Text.Pandoc.UTF8 as UTF8
+
+tests :: [TestTree]
+tests = [ testGroup "markdown"
+          [ testGroup "writer"
+            $ writerTests "markdown" ++ lhsWriterTests "markdown"
+          , testGroup "reader"
+            [ test "basic" ["-r", "markdown", "-w", "native", "-s"]
+              "testsuite.txt" "testsuite.native"
+            , test "tables" ["-r", "markdown", "-w", "native", "--columns=80"]
+              "tables.txt" "tables.native"
+            , test "pipe tables" ["-r", "markdown", "-w", "native", "--columns=80"]
+              "pipe-tables.txt" "pipe-tables.native"
+            , test "more" ["-r", "markdown", "-w", "native", "-s"]
+              "markdown-reader-more.txt" "markdown-reader-more.native"
+            , lhsReaderTest "markdown+lhs"
+            ]
+          , testGroup "citations"
+            [ test "citations" ["-r", "markdown", "-w", "native"]
+              "markdown-citations.txt" "markdown-citations.native"
+            ]
+          ]
+        , testGroup "rst"
+          [ testGroup "writer" (writerTests "rst" ++ lhsWriterTests "rst")
+          , testGroup "reader"
+            [ test "basic" ["-r", "rst+smart", "-w", "native",
+              "-s", "--columns=80"] "rst-reader.rst" "rst-reader.native"
+            , test "tables" ["-r", "rst", "-w", "native", "--columns=80"]
+              "tables.rst" "tables-rstsubset.native"
+            , lhsReaderTest "rst+lhs"
+            ]
+          ]
+        , testGroup "latex"
+          [ testGroup "writer" (writerTests "latex" ++ lhsWriterTests "latex")
+          , testGroup "reader"
+            [ test "basic" ["-r", "latex+raw_tex", "-w", "native", "-s"]
+              "latex-reader.latex" "latex-reader.native"
+            , lhsReaderTest "latex+lhs"
+            ]
+          ]
+        , testGroup "html"
+          [ testGroup "writer" (writerTests "html4" ++ writerTests "html5" ++
+                                lhsWriterTests "html")
+          , test "reader" ["-r", "html", "-w", "native", "-s"]
+            "html-reader.html" "html-reader.native"
+          ]
+        , testGroup "s5"
+          [ s5WriterTest "basic" ["-s"] "s5"
+          , s5WriterTest "fancy" ["-s","-m","-i"] "s5"
+          , s5WriterTest "fragment" [] "html4"
+          , s5WriterTest "inserts"  ["-s", "-H", "insert",
+            "-B", "insert", "-A", "insert", "-c", "main.css"] "html4"
+          ]
+        , testGroup "textile"
+          [ testGroup "writer" $ writerTests "textile"
+          , test "reader" ["-r", "textile", "-w", "native", "-s"]
+            "textile-reader.textile" "textile-reader.native"
+          ]
+        , testGroup "docbook"
+          [ testGroup "writer" $ writerTests "docbook4"
+          , test "reader" ["-r", "docbook", "-w", "native", "-s"]
+            "docbook-reader.docbook" "docbook-reader.native"
+          , test "reader" ["-r", "docbook", "-w", "native", "-s"]
+            "docbook-xref.docbook" "docbook-xref.native"
+          ]
+        , testGroup "docbook5"
+          [ testGroup "writer" $ writerTests "docbook5"
+          ]
+        , 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"
+          , test "reader" ["-r", "native", "-w", "native", "-s"]
+            "testsuite.native" "testsuite.native"
+          ]
+        , testGroup "fb2"
+          [ fb2WriterTest "basic" [] "fb2/basic.markdown" "fb2/basic.fb2"
+          , fb2WriterTest "titles" [] "fb2/titles.markdown" "fb2/titles.fb2"
+          , fb2WriterTest "images" [] "fb2/images.markdown" "fb2/images.fb2"
+          , fb2WriterTest "images-embedded" [] "fb2/images-embedded.html" "fb2/images-embedded.fb2"
+          , fb2WriterTest "math" [] "fb2/math.markdown" "fb2/math.fb2"
+          , fb2WriterTest "tables" [] "tables.native" "tables.fb2"
+          , fb2WriterTest "testsuite" [] "testsuite.native" "writer.fb2"
+          ]
+        , testGroup "mediawiki"
+          [ testGroup "writer" $ writerTests "mediawiki"
+          , test "reader" ["-r", "mediawiki", "-w", "native", "-s"]
+            "mediawiki-reader.wiki" "mediawiki-reader.native"
+          ]
+        , testGroup "vimwiki"
+          [ test "reader" ["-r", "vimwiki", "-w", "native", "-s"]
+            "vimwiki-reader.wiki" "vimwiki-reader.native"
+          ]
+        , testGroup "dokuwiki"
+          [ testGroup "writer" $ writerTests "dokuwiki"
+          , test "inline_formatting" ["-r", "native", "-w", "dokuwiki", "-s"]
+            "dokuwiki_inline_formatting.native" "dokuwiki_inline_formatting.dokuwiki"
+          , test "multiblock table" ["-r", "native", "-w", "dokuwiki", "-s"]
+            "dokuwiki_multiblock_table.native" "dokuwiki_multiblock_table.dokuwiki"
+          , test "external images" ["-r", "native", "-w", "dokuwiki", "-s"]
+            "dokuwiki_external_images.native" "dokuwiki_external_images.dokuwiki"
+          ]
+        , testGroup "opml"
+          [ test "basic" ["-r", "native", "-w", "opml", "--columns=78", "-s"]
+             "testsuite.native" "writer.opml"
+          , test "reader" ["-r", "opml", "-w", "native", "-s"]
+            "opml-reader.opml" "opml-reader.native"
+          ]
+        , testGroup "haddock"
+          [ testGroup "writer" $ writerTests "haddock"
+          , test "reader" ["-r", "haddock", "-w", "native", "-s"]
+            "haddock-reader.haddock" "haddock-reader.native"
+          ]
+        , testGroup "txt2tags"
+          [ test "reader" ["-r", "t2t", "-w", "native", "-s"]
+              "txt2tags.t2t" "txt2tags.native" ]
+        , testGroup "epub" [
+            test "features" ["-r", "epub", "-w", "native"]
+              "epub/features.epub" "epub/features.native"
+          , test "wasteland" ["-r", "epub", "-w", "native"]
+              "epub/wasteland.epub" "epub/wasteland.native"
+          , test "formatting" ["-r", "epub", "-w", "native"]
+              "epub/formatting.epub" "epub/formatting.native"
+          ]
+        , testGroup "twiki"
+          [ test "reader" ["-r", "twiki", "-w", "native", "-s"]
+              "twiki-reader.twiki" "twiki-reader.native" ]
+        , testGroup "tikiwiki"
+          [ test "reader" ["-r", "tikiwiki", "-w", "native", "-s"]
+              "tikiwiki-reader.tikiwiki" "tikiwiki-reader.native" ]
+        , testGroup "other writers" $ map (\f -> testGroup f $ writerTests f)
+          [ "opendocument" , "context" , "texinfo", "icml", "tei"
+          , "man" , "plain" , "rtf", "org", "asciidoc", "zimwiki"
+          ]
+        , testGroup "writers-lang-and-dir"
+          [ test "latex" ["-f", "native", "-t", "latex", "-s"]
+            "writers-lang-and-dir.native" "writers-lang-and-dir.latex"
+          , test "context" ["-f", "native", "-t", "context", "-s"]
+            "writers-lang-and-dir.native" "writers-lang-and-dir.context"
+          ]
+        , testGroup "muse"
+          [ testGroup "writer" $ writerTests "muse"
+          ]
+        , testGroup "ms"
+          [ testGroup "writer" $ writerTests "ms"
+          ]
+        , 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"
+          ]
+        ]
+
+-- makes sure file is fully closed after reading
+readFile' :: FilePath -> IO String
+readFile' f = do s <- UTF8.readFile f
+                 return $! (length s `seq` s)
+
+lhsWriterTests :: String -> [TestTree]
+lhsWriterTests format
+  = [ t "lhs to normal" format
+    , t "lhs to lhs"    (format ++ "+lhs")
+    ]
+  where
+    t n f = test n ["--wrap=preserve", "-r", "native", "-s", "-w", f]
+             "lhs-test.native" ("lhs-test" <.> f)
+
+lhsReaderTest :: String -> TestTree
+lhsReaderTest format =
+  test "lhs" ["-r", format, "-w", "native"]
+    ("lhs-test" <.> format) norm
+   where norm = if format == "markdown+lhs"
+                   then "lhs-test-markdown.native"
+                   else "lhs-test.native"
+
+writerTests :: String -> [TestTree]
+writerTests format
+  = [ test "basic"  (opts ++ ["-s"]) "testsuite.native" ("writer" <.> format)
+    , test "tables" opts             "tables.native"    ("tables" <.> format)
+    ]
+  where
+    opts = ["-r", "native", "-w", format, "--columns=78",
+            "--variable", "pandoc-version="]
+
+s5WriterTest :: String -> [String] -> String -> TestTree
+s5WriterTest modifier opts format
+  = test (format ++ " writer (" ++ modifier ++ ")")
+    (["-r", "native", "-w", format] ++ opts)
+    "s5.native"  ("s5-" ++ modifier <.> "html")
+
+fb2WriterTest :: String -> [String] -> String -> String -> TestTree
+fb2WriterTest title opts inputfile normfile =
+  testWithNormalize (ignoreBinary . formatXML)
+                    title (["-t", "fb2"]++opts) inputfile normfile
+  where
+    formatXML xml = splitTags $ zip xml (drop 1 xml)
+    splitTags []               = []
+    splitTags [end]            = fst end : snd end : []
+    splitTags (('>','<'):rest) = ">\n" ++ splitTags rest
+    splitTags ((c,_):rest)     = c : splitTags rest
+    ignoreBinary = unlines . filter (not . startsWith "<binary ") . lines
+    startsWith tag str = all (uncurry (==)) $ zip tag str
+
+-- | Run a test without normalize function, return True if test passed.
+test :: String    -- ^ Title of test
+     -> [String]  -- ^ Options to pass to pandoc
+     -> String    -- ^ Input filepath
+     -> FilePath  -- ^ Norm (for test results) filepath
+     -> TestTree
+test = testWithNormalize id
+
+-- | Run a test with normalize function, return True if test passed.
+testWithNormalize  :: (String -> String) -- ^ Normalize function for output
+                   -> String    -- ^ Title of test
+                   -> [String]  -- ^ Options to pass to pandoc
+                   -> String    -- ^ Input filepath
+                   -> FilePath  -- ^ Norm (for test results) filepath
+                   -> TestTree
+testWithNormalize normalizer testname opts inp norm =
+  goldenTest testname getExpected getActual
+    (compareValues norm options) updateGolden
+  where getExpected = normalizer <$> readFile' norm
+        getActual   =
+          withTempFile "." "pandoc-test" $ \outputPath hOut -> do
+            withTempFile "." "pandoc-test" $ \errorPath hErr -> do
+              pandocPath <- findPandoc
+              let mbDynlibDir = findDynlibDir (reverse $
+                                 splitDirectories pandocPath)
+              let dynlibEnv = case mbDynlibDir of
+                                   Nothing  -> []
+                                   Just d   -> [("DYLD_LIBRARY_PATH", d),
+                                                ("LD_LIBRARY_PATH", d)]
+              let env = dynlibEnv ++
+                        [("TMP","."),("LANG","en_US.UTF-8"),("HOME", "./"),
+                         ("pandoc_datadir","..")]
+              ph <- runProcess pandocPath options Nothing
+                    (Just env) Nothing (Just hOut) (Just hErr)
+              ec <- waitForProcess ph
+              if ec == ExitSuccess
+                 then
+                   -- filter \r so the tests will work on Windows machines
+                   (filter (/='\r') . normalizer) <$> readFile' outputPath
+                 else do
+                   errcontents <- UTF8.readFile errorPath
+                   fail $ "Pandoc failed with " ++ show ec ++
+                           if null errcontents
+                              then ""
+                              else '\n':errcontents
+        updateGolden = UTF8.writeFile norm
+        options = ["--quiet"] ++ [inp] ++ opts
+
+compareValues :: FilePath -> [String] -> String -> String -> IO (Maybe String)
+compareValues norm options expected actual = do
+  pandocPath <- findPandoc
+  let cmd  = pandocPath ++ " " ++ unwords options
+  let dash = replicate 72 '-'
+  let diff = getDiff (lines actual) (lines expected)
+  if expected == actual
+     then return Nothing
+     else return $ Just $
+        '\n' : dash ++
+        "\n--- " ++ norm ++
+        "\n+++ " ++ cmd ++ "\n" ++
+        showDiff (1,1) diff ++ dash
+
+findDynlibDir :: [FilePath] -> Maybe FilePath
+findDynlibDir []           = Nothing
+findDynlibDir ("build":xs) = Just $ joinPath (reverse xs) </> "build"
+findDynlibDir (_:xs)       = findDynlibDir xs
diff --git a/test/Tests/Readers/Creole.hs b/test/Tests/Readers/Creole.hs
index 3f60a523d..eb50b2b9a 100644
--- a/test/Tests/Readers/Creole.hs
+++ b/test/Tests/Readers/Creole.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Readers.Creole (tests) where
 
+import Prelude
 import Data.Text (Text)
 import qualified Data.Text as T
 import Test.Tasty
diff --git a/test/Tests/Readers/Creole.hs.orig b/test/Tests/Readers/Creole.hs.orig
new file mode 100644
index 000000000..3f60a523d
--- /dev/null
+++ b/test/Tests/Readers/Creole.hs.orig
@@ -0,0 +1,286 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.Creole (tests) where
+
+import Data.Text (Text)
+import qualified Data.Text as T
+import Test.Tasty
+import Tests.Helpers
+import Text.Pandoc
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder
+
+creole :: Text -> Pandoc
+creole = purely $ readCreole def{ readerStandalone = True }
+
+infix 4 =:
+(=:) :: ToString c
+     => String -> (Text, c) -> TestTree
+(=:) = test creole
+
+tests :: [TestTree]
+tests = [
+  testGroup "Basic Text Formatting" [
+          "bold, single line, fully delimited" =:
+          "only **bold** is bold"
+          =?> para ("only " <> strong "bold" <> " is bold")
+        , "italics, single line, fully delimited" =:
+          "only //this// is in italics"
+          =?> para ("only " <> emph "this" <> " is in italics")
+        , "bold in italics, fully delimited" =:
+          "//**this**// is in bold italics"
+          =?> para (emph (strong "this") <> " is in bold italics")
+        , "italics in bold, fully delimited" =:
+          "**//this//** is in bold italics"
+          =?> para (strong (emph "this") <> " is in bold italics")
+
+        , "escape bold marker" =:
+          "~**not bold" =?> para "**not bold"
+        , "escape italics marker" =:
+          "~//not in italics" =?> para "//not in italics"
+
+        , "inline nowiki, simple" =:
+          "this is {{{**not** ~interpreted}}} at all"
+          =?> para ("this is " <> code "**not** ~interpreted" <> " at all")
+        , "inline nowiki, curly braces inside" =:
+          "this is {{{{{{//including// some `}' chars}}}}}}"
+          =?> para ("this is " <> code "{{{//including// some `}' chars}}}")
+
+        , "placeholder" =:
+          "foo <<<place holder>>> bar"
+          =?> para "foo bar"
+        , "placeholder escaped" =:
+          "foo ~<<<no place holder>>> bar"
+          =?> para "foo <<<no place holder>>> bar"
+        ]
+  , testGroup "Headers" [
+          "header level 1, no space, no trailing =" =:
+          "= Top-Level Header"
+          =?> header 1 (str "Top-Level Header")
+        , "header level 1, leading space, trailing =" =:
+          " = Top-Level Header = "
+          =?> header 1 (str "Top-Level Header")
+        , "header level 2, no space, no trailing =" =:
+          "== Second Level"
+          =?> header 2 (str "Second Level")
+        , "header level 2, leading space, no trailing =" =:
+          "   == Second Level"
+          =?> header 2 (str "Second Level")
+        , "header level 3, no space, no trailing =" =:
+          "=== Third"
+          =?> header 3 (str "Third")
+        , "header level 3, no space, > 3 trailing =" =:
+          "=== Third ======="
+          =?> header 3 (str "Third")
+        , "header level 4, no space, no trailing =" =:
+          "==== Fourth Level Heading"
+          =?> header 4 (str "Fourth Level Heading")
+        , "header level 4, no space, < 4 trailing =" =:
+          "==== Fourth Level Heading =="
+          =?> header 4 (str "Fourth Level Heading")
+        , "header level 5, no space, no trailing =" =:
+          "===== Fifth"
+          =?> header 5 (str "Fifth")
+        , "header level 6, no space, no trailing =" =:
+          "====== Sixth"
+          =?> header 6 (str "Sixth")
+        ]
+  , testGroup "Paragraphs" [
+          "paragraphs: multiple, one line" =:
+          "first line\n\nanother line\n"
+          =?> para "first line" <> para "another line"
+          ]
+  , testGroup "Lists" [
+          "unordered list, two entries, one separating space" =:
+          "* foo\n* bar"
+          =?> bulletList [ plain "foo", plain "bar" ]
+        , "unordered list, three entries, one separating space" =:
+          "* foo\n* bar\n* baz"
+          =?> bulletList [ plain "foo", plain "bar", plain "baz" ]
+        , "para followed by, unordered list, two entries, one separating space" =:
+          "blubber\n* foo\n* bar"
+          =?> para "blubber" <> bulletList [ plain "foo", plain "bar" ]
+        , "nested unordered list, one separating space" =:
+          "* foo\n** bar\n** baz\n* blubb"
+          =?> bulletList [ plain "foo"
+                         <> bulletList [ plain "bar", plain "baz" ]
+                         , plain "blubb" ]
+        , "nested many unordered lists, one separating space" =:
+          ("* foo\n** bar\n*** third\n*** third two\n** baz\n*** third again\n"
+           <> "**** fourth\n***** fith\n* blubb")
+          =?> bulletList [ plain "foo"
+                           <> bulletList [ plain "bar"
+                                           <> bulletList [ plain "third"
+                                                         , plain "third two"]
+                                         , plain "baz"
+                                           <> bulletList [ plain "third again"
+                                                         <> bulletList [
+                                                             plain "fourth"
+                                                             <> bulletList [
+                                                                 plain "fith"
+                                                                 ]
+                                                             ]
+                                                         ]
+                                         ]
+                         , plain "blubb" ]
+        , "nested unordered list, mixed separating space" =:
+          "*foo\n   **   bar\n    **baz\n *      blubb"
+          =?> bulletList [ plain "foo"
+                         <> bulletList [ plain "bar", plain "baz" ]
+                         , plain "blubb" ]
+        , "nested unordered list, one separating space, trailing space" =:
+          "* foo \n** bar  \n** baz \n* blubb  "
+          =?> bulletList [ plain "foo"
+                         <> bulletList [ plain "bar", plain "baz" ]
+                         , plain "blubb" ]
+        , "ordered list, two entries, one separating space" =:
+          "# foo\n# bar"
+          =?> orderedList [ plain "foo", plain "bar" ]
+        , "ordered list, three entries, one separating space" =:
+          "# foo\n# bar\n# baz"
+          =?> orderedList [ plain "foo", plain "bar", plain "baz" ]
+        , "para followed by, ordered list, two entries, one separating space" =:
+          "blubber\n# foo\n# bar"
+          =?> para "blubber" <> orderedList [ plain "foo", plain "bar" ]
+        , "nested ordered list, one separating space" =:
+          "# foo\n## bar\n## baz\n# blubb"
+          =?> orderedList [ plain "foo"
+                         <> orderedList [ plain "bar", plain "baz" ]
+                         , plain "blubb" ]
+        , "nested ordered list, one separating space, trailing space" =:
+          "# foo \n## bar  \n## baz \n# blubb  "
+          =?> orderedList [ plain "foo"
+                         <> orderedList [ plain "bar", plain "baz" ]
+                         , plain "blubb" ]
+        , "nested many ordered lists, one separating space" =:
+          ("# foo\n## bar\n### third\n### third two\n## baz\n### third again\n"
+           <> "#### fourth\n##### fith\n# blubb")
+          =?> orderedList [ plain "foo"
+                           <> orderedList [ plain "bar"
+                                           <> orderedList [ plain "third"
+                                                         , plain "third two"]
+                                         , plain "baz"
+                                           <> orderedList [ plain "third again"
+                                                         <> orderedList [
+                                                             plain "fourth"
+                                                             <> orderedList [
+                                                                 plain "fith"
+                                                                 ]
+                                                             ]
+                                                         ]
+                                         ]
+                         , plain "blubb" ]
+        , "nested ordered list, mixed separating space" =:
+          "#foo\n   ##   bar\n    ##baz\n #      blubb"
+          =?> orderedList [ plain "foo"
+                         <> orderedList [ plain "bar", plain "baz" ]
+                         , plain "blubb" ]
+        , "mixed nested ordered and unordered lists, one separating space" =:
+          ("# foo\n** bar\n### third\n### third two\n** baz\n### third again\n"
+           <> "#### fourth\n***** fith\n# blubb")
+          =?> orderedList [ plain "foo"
+                           <> bulletList [ plain "bar"
+                                           <> orderedList [ plain "third"
+                                                         , plain "third two"]
+                                         , plain "baz"
+                                           <> orderedList [ plain "third again"
+                                                         <> orderedList [
+                                                             plain "fourth"
+                                                             <> bulletList [
+                                                                 plain "fith"
+                                                                 ]
+                                                             ]
+                                                         ]
+                                         ]
+                         , plain "blubb" ]
+        ]
+  , testGroup "NoWiki" [
+          "quoted block, simple" =:
+          "{{{\nfoo bar\n  //baz//\n}}}"
+          =?> codeBlock "foo bar\n  //baz//"
+        , "quoted block, curly bracket exception" =:
+          "{{{\nfoo bar\n  }}}\nbaz\n }}}\n}}}"
+          =?> codeBlock "foo bar\n }}}\nbaz\n}}}"
+        , "forced line breaks" =:
+          "{{{no break!\\\\here}}} but a break\\\\here!"
+          =?> para (code "no break!\\\\here" <> " but a break"
+                    <> linebreak <> "here!"),
+          "quoted block, after trailing white space" =:
+          "this is a paragraph  \n{{{\nfoo bar\n  //baz//\n}}}"
+          =?> para "this is a paragraph" <> codeBlock "foo bar\n  //baz//"
+        ]
+  , testGroup "Images and Links" [
+          "image simple" =:
+          "{{foo.png}}" =?> para (image "foo.png" "" (str ""))
+        , "image with alt text" =:
+          "Image of a bar: {{/path/to/bar.png|A Bar}} look at it!"
+          =?> para ("Image of a bar: "
+                    <> image "/path/to/bar.png" "" (str "A Bar") <> " look at it!")
+
+        , "auto link" =:
+          "foo http://foo.example.com/bar/baz.html bar"
+          =?> para ("foo "
+                    <> link "http://foo.example.com/bar/baz.html" ""
+                     (str "http://foo.example.com/bar/baz.html")
+                    <> " bar")
+        , "escaped auto link" =:
+          "foo ~http://foo.example.com/bar/baz.html bar"
+          =?> para "foo http://foo.example.com/bar/baz.html bar"
+        , "wiki link simple" =:
+          "foo [[http://foo.example.com/foo.png]] bar"
+          =?> para ("foo "
+                    <> link "http://foo.example.com/foo.png" ""
+                     (str "http://foo.example.com/foo.png")
+                    <> " bar")
+        , "wiki link with name" =:
+          "foo [[http://foo.example.com/foo.png|my link]] bar"
+          =?> para ("foo "
+                    <> link "http://foo.example.com/foo.png" ""
+                     (str "my link")
+                    <> " bar")
+        , "image link" =:
+          "[[http://foo.example.com/|{{foo.png}}]]"
+          =?> para (link "http://foo.example.com/" "" (image "foo.png" "" (str "")))
+        ]
+  , testGroup "Table" [
+          "Table with Header" =:
+          T.unlines [ "|= Foo |= Bar |= Baz  |"
+                    , "| One  | Two  | Three |"
+                    , "| 1    | 2    | 3     |"
+                    , "| A    | B    | C     |"
+                    ]
+          =?> simpleTable
+            [plain "Foo", plain "Bar" , plain "Baz"]
+            [[plain "One", plain "Two" , plain "Three"]
+            ,[plain "1", plain "2" , plain "3"]
+            ,[plain "A", plain "B" , plain "C"]]
+        , "Table without Header" =:
+          T.unlines [ "| One  | Two  | Three |"
+                    , "| 1    | 2    | 3     |"
+                    , "| A    | B    | C     |"
+                    ]
+          =?> simpleTable [mempty]
+            [[plain "One", plain "Two" , plain "Three"]
+            ,[plain "1", plain "2" , plain "3"]
+            ,[plain "A", plain "B" , plain "C"]]
+        , "Table without Header, no markers at line ends" =:
+          T.unlines [ "| One  | Two  | Three"
+                    , "| 1    | 2    | 3"
+                    , "| A    | B    | C  "
+                    ]
+          =?> simpleTable [mempty]
+            [[plain "One", plain "Two" , plain "Three"]
+            ,[plain "1", plain "2" , plain "3"]
+            ,[plain "A", plain "B" , plain "C"]]
+        , "Table with Header, with formatting" =:
+          T.unlines [ "|= **Foo**        |= **Bar** |= **Baz**  |"
+                    , "|//one// element  |//second// elt|Three  |"
+                    , "| {{{1}}}    | {{{{}}}}    | [[link]]    |"
+                    ]
+          =?> simpleTable
+            [plain $ strong "Foo", plain $ strong "Bar" , plain $ strong "Baz"]
+            [[plain (emph "one" <> " element"), plain (emph "second" <> " elt")
+             ,plain "Three"]
+            ,[plain $ code "1", plain $ code "{}"
+             ,plain $ link "link" "" (str "link")]]
+        ]
+  ]
diff --git a/test/Tests/Readers/Docx.hs b/test/Tests/Readers/Docx.hs
index cef80d6d1..a02e1f35a 100644
--- a/test/Tests/Readers/Docx.hs
+++ b/test/Tests/Readers/Docx.hs
@@ -1,5 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 module Tests.Readers.Docx (tests) where
 
+import Prelude
 import Codec.Archive.Zip
 import qualified Data.ByteString as BS
 import qualified Data.ByteString.Lazy as B
@@ -178,6 +180,14 @@ tests = [ testGroup "inlines"
             "inlines inside of Structured Document Tags"
             "docx/sdt_elements.docx"
             "docx/sdt_elements.native"
+          , testCompare
+            "nested Structured Document Tags"
+            "docx/nested_sdt.docx"
+            "docx/nested_sdt.native"
+          , testCompare
+            "nested Smart Tags"
+            "docx/nested_smart_tags.docx"
+            "docx/nested_smart_tags.native"
           , testCompare
             "remove anchor spans with nothing pointing to them"
             "docx/unused_anchors.docx"
@@ -280,6 +290,10 @@ tests = [ testGroup "inlines"
             "code block"
             "docx/codeblock.docx"
             "docx/codeblock.native"
+          , testCompare
+            "combine adjacent code blocks"
+            "docx/adjacent_codeblocks.docx"
+            "docx/adjacent_codeblocks.native"
           , testCompare
             "dropcap paragraphs"
             "docx/drop_cap.docx"
diff --git a/test/Tests/Readers/Docx.hs.orig b/test/Tests/Readers/Docx.hs.orig
new file mode 100644
index 000000000..9bbe85cba
--- /dev/null
+++ b/test/Tests/Readers/Docx.hs.orig
@@ -0,0 +1,405 @@
+module Tests.Readers.Docx (tests) where
+
+import Codec.Archive.Zip
+import qualified Data.ByteString as BS
+import qualified Data.ByteString.Lazy as B
+import qualified Data.Map as M
+import qualified Data.Text as T
+import Data.Maybe
+import System.IO.Unsafe
+import Test.Tasty
+import Test.Tasty.HUnit
+import Tests.Helpers
+import Text.Pandoc
+import qualified Text.Pandoc.Class as P
+import Text.Pandoc.MediaBag (MediaBag, lookupMedia, mediaDirectory)
+import Text.Pandoc.UTF8 as UTF8
+
+-- We define a wrapper around pandoc that doesn't normalize in the
+-- tests. Since we do our own normalization, we want to make sure
+-- we're doing it right.
+
+data NoNormPandoc = NoNormPandoc {unNoNorm :: Pandoc}
+                 deriving Show
+
+noNorm :: Pandoc -> NoNormPandoc
+noNorm = NoNormPandoc
+
+defopts :: ReaderOptions
+defopts = def{ readerExtensions = getDefaultExtensions "docx" }
+
+instance ToString NoNormPandoc where
+  toString d = T.unpack $ purely (writeNative def{ writerTemplate = s }) $ toPandoc d
+   where s = case d of
+                  NoNormPandoc (Pandoc (Meta m) _)
+                    | M.null m  -> Nothing
+                    | otherwise -> Just "" -- need this to get meta output
+
+instance ToPandoc NoNormPandoc where
+  toPandoc = unNoNorm
+
+compareOutput :: ReaderOptions
+                 -> FilePath
+                 -> FilePath
+                 -> IO (NoNormPandoc, NoNormPandoc)
+compareOutput opts docxFile nativeFile = do
+  df <- B.readFile docxFile
+  nf <- UTF8.toText <$> BS.readFile nativeFile
+  p <- runIOorExplode $ readDocx opts df
+  df' <- runIOorExplode $ readNative def nf
+  return (noNorm p, noNorm df')
+
+testCompareWithOptsIO :: ReaderOptions -> String -> FilePath -> FilePath -> IO TestTree
+testCompareWithOptsIO opts name docxFile nativeFile = do
+  (dp, np) <- compareOutput opts docxFile nativeFile
+  return $ test id name (dp, np)
+
+testCompareWithOpts :: ReaderOptions -> String -> FilePath -> FilePath -> TestTree
+testCompareWithOpts opts name docxFile nativeFile =
+  unsafePerformIO $ testCompareWithOptsIO opts name docxFile nativeFile
+
+testCompare :: String -> FilePath -> FilePath -> TestTree
+testCompare = testCompareWithOpts defopts
+
+testForWarningsWithOptsIO :: ReaderOptions -> String -> FilePath -> [String] -> IO TestTree
+testForWarningsWithOptsIO opts name docxFile expected = do
+  df <- B.readFile docxFile
+  logs <-  runIOorExplode $ setVerbosity ERROR >> readDocx opts df >> P.getLog
+  let warns = [m | DocxParserWarning m <- logs]
+  return $ test id name (unlines warns, unlines expected)
+
+testForWarningsWithOpts :: ReaderOptions -> String -> FilePath -> [String] -> TestTree
+testForWarningsWithOpts opts name docxFile expected =
+  unsafePerformIO $ testForWarningsWithOptsIO opts name docxFile expected
+
+-- testForWarnings :: String -> FilePath -> [String] -> TestTree
+-- testForWarnings = testForWarningsWithOpts defopts
+
+getMedia :: FilePath -> FilePath -> IO (Maybe B.ByteString)
+getMedia archivePath mediaPath = do
+  zf <- B.readFile archivePath >>= return . toArchive
+  return $ findEntryByPath ("word/" ++ mediaPath) zf >>= (Just . fromEntry)
+
+compareMediaPathIO :: FilePath -> MediaBag -> FilePath -> IO Bool
+compareMediaPathIO mediaPath mediaBag docxPath = do
+  docxMedia <- getMedia docxPath mediaPath
+  let mbBS   = case lookupMedia mediaPath mediaBag of
+                 Just (_, bs) -> bs
+                 Nothing      -> error ("couldn't find " ++
+                                        mediaPath ++
+                                        " in media bag")
+      docxBS = fromMaybe (error ("couldn't find " ++
+                        mediaPath ++
+                        " in media bag")) docxMedia
+  return $ mbBS == docxBS
+
+compareMediaBagIO :: FilePath -> IO Bool
+compareMediaBagIO docxFile = do
+    df <- B.readFile docxFile
+    mb <- runIOorExplode $ readDocx defopts df >> P.getMediaBag
+    bools <- mapM
+             (\(fp, _, _) -> compareMediaPathIO fp mb docxFile)
+             (mediaDirectory mb)
+    return $ and bools
+
+testMediaBagIO :: String -> FilePath -> IO TestTree
+testMediaBagIO name docxFile = do
+  outcome <- compareMediaBagIO docxFile
+  return $ testCase name (assertBool
+                          ("Media didn't match media bag in file " ++ docxFile)
+                          outcome)
+
+testMediaBag :: String -> FilePath -> TestTree
+testMediaBag name docxFile = unsafePerformIO $ testMediaBagIO name docxFile
+
+tests :: [TestTree]
+tests = [ testGroup "inlines"
+          [ testCompare
+            "font formatting"
+            "docx/inline_formatting.docx"
+            "docx/inline_formatting.native"
+          , testCompare
+            "font formatting with character styles"
+            "docx/char_styles.docx"
+            "docx/char_styles.native"
+          , testCompare
+            "hyperlinks"
+            "docx/links.docx"
+            "docx/links.native"
+          , testCompare
+            "hyperlinks in <w:instrText> tag"
+            "docx/instrText_hyperlink.docx"
+            "docx/instrText_hyperlink.native"
+          , testCompare
+            "inline image"
+            "docx/image.docx"
+            "docx/image_no_embed.native"
+          , testCompare
+            "VML image"
+            "docx/image_vml.docx"
+            "docx/image_vml.native"
+          , testCompare
+            "inline image in links"
+            "docx/inline_images.docx"
+            "docx/inline_images.native"
+          , testCompare
+            "handling unicode input"
+            "docx/unicode.docx"
+            "docx/unicode.native"
+          , testCompare
+            "literal tabs"
+            "docx/tabs.docx"
+            "docx/tabs.native"
+          , testCompare
+            "special punctuation"
+            "docx/special_punctuation.docx"
+            "docx/special_punctuation.native"
+          , testCompare
+            "normalizing inlines"
+            "docx/normalize.docx"
+            "docx/normalize.native"
+          , testCompare
+            "normalizing inlines deep inside blocks"
+            "docx/deep_normalize.docx"
+            "docx/deep_normalize.native"
+          , testCompare
+            "move trailing spaces outside of formatting"
+            "docx/trailing_spaces_in_formatting.docx"
+            "docx/trailing_spaces_in_formatting.native"
+          , testCompare
+            "inline code (with VerbatimChar style)"
+            "docx/inline_code.docx"
+            "docx/inline_code.native"
+          , testCompare
+            "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"
+          , testCompare
+            "nested Structured Document Tags"
+            "docx/nested_sdt.docx"
+            "docx/nested_sdt.native"
+          , testCompare
+            "nested Smart Tags"
+            "docx/nested_smart_tags.docx"
+            "docx/nested_smart_tags.native"
+          , testCompare
+            "remove anchor spans with nothing pointing to them"
+            "docx/unused_anchors.docx"
+            "docx/unused_anchors.native"
+          , testCompare
+            "collapse overlapping targets (anchor spans)"
+            "docx/overlapping_targets.docx"
+            "docx/overlapping_targets.native"
+          ]
+        , testGroup "blocks"
+          [ testCompare
+            "headers"
+            "docx/headers.docx"
+            "docx/headers.native"
+          , testCompare
+            "headers already having auto identifiers"
+            "docx/already_auto_ident.docx"
+            "docx/already_auto_ident.native"
+          , testCompare
+            "avoid zero-level headers"
+            "docx/0_level_headers.docx"
+            "docx/0_level_headers.native"
+          , testCompare
+            "nested anchor spans in header"
+            "docx/nested_anchors_in_header.docx"
+            "docx/nested_anchors_in_header.native"
+          , testCompare
+            "single numbered item not made into list"
+            "docx/numbered_header.docx"
+            "docx/numbered_header.native"
+          , testCompare
+            "enumerated headers not made into numbered list"
+            "docx/enumerated_headings.docx"
+            "docx/enumerated_headings.native"
+          , testCompare
+            "i18n blocks (headers and blockquotes)"
+            "docx/i18n_blocks.docx"
+            "docx/i18n_blocks.native"
+          , testCompare
+            "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"
+            "docx/definition_list.native"
+          , testCompare
+            "custom defined lists in styles"
+            "docx/german_styled_lists.docx"
+            "docx/german_styled_lists.native"
+          , testCompare
+            "user deletes bullet after list item (=> part of item par)"
+            "docx/dummy_item_after_list_item.docx"
+            "docx/dummy_item_after_list_item.native"
+          , testCompare
+            "user deletes bullet after par (=> new par)"
+            "docx/dummy_item_after_paragraph.docx"
+            "docx/dummy_item_after_paragraph.native"
+          , testCompare
+            "footnotes and endnotes"
+            "docx/notes.docx"
+            "docx/notes.native"
+          , testCompare
+            "links in footnotes and endnotes"
+            "docx/link_in_notes.docx"
+            "docx/link_in_notes.native"
+          , testCompare
+            "blockquotes (parsing indent as blockquote)"
+            "docx/block_quotes.docx"
+            "docx/block_quotes_parse_indent.native"
+          , testCompare
+            "hanging indents"
+            "docx/hanging_indent.docx"
+            "docx/hanging_indent.native"
+          , testCompare
+            "tables"
+            "docx/tables.docx"
+            "docx/tables.native"
+          , testCompare
+            "tables with lists in cells"
+            "docx/table_with_list_cell.docx"
+            "docx/table_with_list_cell.native"
+          , testCompare
+            "tables with one row"
+            "docx/table_one_row.docx"
+            "docx/table_one_row.native"
+          , testCompare
+            "tables with variable width"
+            "docx/table_variable_width.docx"
+            "docx/table_variable_width.native"
+          , testCompare
+            "code block"
+            "docx/codeblock.docx"
+            "docx/codeblock.native"
+          , testCompare
+            "dropcap paragraphs"
+            "docx/drop_cap.docx"
+            "docx/drop_cap.native"
+          ]
+        , testGroup "track changes"
+          [ testCompare
+            "insertion (default)"
+            "docx/track_changes_insertion.docx"
+            "docx/track_changes_insertion_accept.native"
+          , testCompareWithOpts def{readerTrackChanges=AcceptChanges}
+            "insert insertion (accept)"
+            "docx/track_changes_insertion.docx"
+            "docx/track_changes_insertion_accept.native"
+          , testCompareWithOpts def{readerTrackChanges=RejectChanges}
+            "remove insertion (reject)"
+            "docx/track_changes_insertion.docx"
+            "docx/track_changes_insertion_reject.native"
+          , testCompare
+            "deletion (default)"
+            "docx/track_changes_deletion.docx"
+            "docx/track_changes_deletion_accept.native"
+          , testCompareWithOpts def{readerTrackChanges=AcceptChanges}
+            "remove deletion (accept)"
+            "docx/track_changes_deletion.docx"
+            "docx/track_changes_deletion_accept.native"
+          , testCompareWithOpts def{readerTrackChanges=RejectChanges}
+            "insert deletion (reject)"
+            "docx/track_changes_deletion.docx"
+            "docx/track_changes_deletion_reject.native"
+          , testCompareWithOpts def{readerTrackChanges=AllChanges}
+            "keep insertion (all)"
+            "docx/track_changes_deletion.docx"
+            "docx/track_changes_deletion_all.native"
+          , testCompareWithOpts def{readerTrackChanges=AllChanges}
+            "keep deletion (all)"
+            "docx/track_changes_deletion.docx"
+            "docx/track_changes_deletion_all.native"
+          , testCompareWithOpts def{readerTrackChanges=AcceptChanges}
+            "move text (accept)"
+            "docx/track_changes_move.docx"
+            "docx/track_changes_move_accept.native"
+          , testCompareWithOpts def{readerTrackChanges=RejectChanges}
+            "move text (reject)"
+            "docx/track_changes_move.docx"
+            "docx/track_changes_move_reject.native"
+          , testCompareWithOpts def{readerTrackChanges=AllChanges}
+            "move text (all)"
+            "docx/track_changes_move.docx"
+            "docx/track_changes_move_all.native"
+          , testCompareWithOpts def{readerTrackChanges=AcceptChanges}
+            "comments (accept -- no comments)"
+            "docx/comments.docx"
+            "docx/comments_no_comments.native"
+          , testCompareWithOpts def{readerTrackChanges=RejectChanges}
+            "comments (reject -- comments)"
+            "docx/comments.docx"
+            "docx/comments_no_comments.native"
+          , testCompareWithOpts def{readerTrackChanges=AllChanges}
+            "comments (all comments)"
+            "docx/comments.docx"
+            "docx/comments.native"
+          , testCompareWithOpts def{readerTrackChanges=AcceptChanges}
+            "paragraph insertion/deletion (accept)"
+            "docx/paragraph_insertion_deletion.docx"
+            "docx/paragraph_insertion_deletion_accept.native"
+          , testCompareWithOpts def{readerTrackChanges=RejectChanges}
+            "paragraph insertion/deletion (reject)"
+            "docx/paragraph_insertion_deletion.docx"
+            "docx/paragraph_insertion_deletion_reject.native"
+          , testCompareWithOpts def{readerTrackChanges=AllChanges}
+            "paragraph insertion/deletion (all)"
+            "docx/paragraph_insertion_deletion.docx"
+            "docx/paragraph_insertion_deletion_all.native"
+          , testForWarningsWithOpts def{readerTrackChanges=AcceptChanges}
+            "comment warnings (accept -- no warnings)"
+            "docx/comments_warning.docx"
+            []
+          , testForWarningsWithOpts def{readerTrackChanges=RejectChanges}
+            "comment warnings (reject -- no warnings)"
+            "docx/comments_warning.docx"
+            []
+          , testForWarningsWithOpts def{readerTrackChanges=AllChanges}
+            "comment warnings (all)"
+            "docx/comments_warning.docx"
+            ["Docx comment 1 will not retain formatting"]
+          ]
+        , testGroup "media"
+          [ testMediaBag
+            "image extraction"
+            "docx/image.docx"
+          ]
+        , testGroup "custom styles"
+          [ testCompare
+            "custom styles (`+styles`) not enabled (default)"
+            "docx/custom-style-reference.docx"
+            "docx/custom-style-no-styles.native"
+          , testCompareWithOpts
+            def{readerExtensions=extensionsFromList [Ext_styles]}
+            "custom styles (`+styles`) enabled"
+            "docx/custom-style-reference.docx"
+            "docx/custom-style-with-styles.native"
+          ]
+        , testGroup "metadata"
+          [ testCompareWithOpts def{readerStandalone=True}
+            "metadata fields"
+            "docx/metadata.docx"
+            "docx/metadata.native"
+          , testCompareWithOpts def{readerStandalone=True}
+            "stop recording metadata with normal text"
+            "docx/metadata_after_normal.docx"
+            "docx/metadata_after_normal.native"
+          ]
+
+        ]
diff --git a/test/Tests/Readers/EPUB.hs b/test/Tests/Readers/EPUB.hs
index 1337a9c11..285efedbf 100644
--- a/test/Tests/Readers/EPUB.hs
+++ b/test/Tests/Readers/EPUB.hs
@@ -1,5 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 module Tests.Readers.EPUB (tests) where
 
+import Prelude
 import qualified Data.ByteString.Lazy as BL
 import Test.Tasty
 import Test.Tasty.HUnit
diff --git a/test/Tests/Readers/EPUB.hs.orig b/test/Tests/Readers/EPUB.hs.orig
new file mode 100644
index 000000000..1337a9c11
--- /dev/null
+++ b/test/Tests/Readers/EPUB.hs.orig
@@ -0,0 +1,40 @@
+module Tests.Readers.EPUB (tests) where
+
+import qualified Data.ByteString.Lazy as BL
+import Test.Tasty
+import Test.Tasty.HUnit
+import qualified Text.Pandoc.Class as P
+import Text.Pandoc.MediaBag (MediaBag, mediaDirectory)
+import Text.Pandoc.Options
+import Text.Pandoc.Readers.EPUB
+
+getMediaBag :: FilePath -> IO MediaBag
+getMediaBag fp = do
+  bs <- BL.readFile fp
+  P.runIOorExplode $ do
+    readEPUB def bs
+    P.getMediaBag
+
+testMediaBag :: FilePath -> [(String, String, Int)] -> IO ()
+testMediaBag fp bag = do
+  actBag <- mediaDirectory <$> getMediaBag fp
+  assertBool (show "MediaBag did not match:\nExpected: "
+             ++ show bag
+             ++ "\nActual: "
+             ++ show actBag)
+             (actBag == bag)
+
+featuresBag :: [(String, String, Int)]
+featuresBag = [("img/check.gif","image/gif",1340)
+              ,("img/check.jpg","image/jpeg",2661)
+              ,("img/check.png","image/png",2815)
+              ,("img/multiscripts_and_greek_alphabet.png","image/png",10060)
+              ]
+
+tests :: [TestTree]
+tests =
+  [ testGroup "EPUB Mediabag"
+    [ testCase "features bag"
+      (testMediaBag "epub/img.epub" featuresBag)
+    ]
+  ]
diff --git a/test/Tests/Readers/FB2.hs b/test/Tests/Readers/FB2.hs
new file mode 100644
index 000000000..9b2983d57
--- /dev/null
+++ b/test/Tests/Readers/FB2.hs
@@ -0,0 +1,29 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Tests.Readers.FB2 (tests) where
+
+import Prelude
+import Test.Tasty
+import Tests.Helpers
+import Test.Tasty.Golden (goldenVsString)
+import qualified Data.ByteString as BS
+import Text.Pandoc
+import Text.Pandoc.UTF8 (toText, fromTextLazy)
+import Data.Text (Text)
+import Data.Text.Lazy (fromStrict)
+import System.FilePath (replaceExtension)
+
+fb2ToNative :: Text -> Text
+fb2ToNative = purely (writeNative def{ writerTemplate = Just "" }) . purely (readFB2 def)
+
+fb2Test :: TestName -> FilePath -> TestTree
+fb2Test name path = goldenVsString name native (fromTextLazy . fromStrict . fb2ToNative . toText <$> BS.readFile path)
+  where native = replaceExtension path ".native"
+
+tests :: [TestTree]
+tests = [ fb2Test "Emphasis" "fb2/reader/emphasis.fb2"
+        , fb2Test "Titles" "fb2/reader/titles.fb2"
+        , fb2Test "Epigraph" "fb2/reader/epigraph.fb2"
+        , fb2Test "Poem" "fb2/reader/poem.fb2"
+        , fb2Test "Meta" "fb2/reader/meta.fb2"
+        ]
diff --git a/test/Tests/Readers/HTML.hs b/test/Tests/Readers/HTML.hs
index 70f33d2b2..f61f1f497 100644
--- a/test/Tests/Readers/HTML.hs
+++ b/test/Tests/Readers/HTML.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Readers.HTML (tests) where
 
+import Prelude
 import Data.Text (Text)
 import Test.Tasty
 import Tests.Helpers
diff --git a/test/Tests/Readers/HTML.hs.orig b/test/Tests/Readers/HTML.hs.orig
new file mode 100644
index 000000000..70f33d2b2
--- /dev/null
+++ b/test/Tests/Readers/HTML.hs.orig
@@ -0,0 +1,54 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.HTML (tests) where
+
+import Data.Text (Text)
+import Test.Tasty
+import Tests.Helpers
+import Text.Pandoc
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder
+
+html :: Text -> Pandoc
+html = purely $ readHtml def
+
+htmlNativeDivs :: Text -> Pandoc
+htmlNativeDivs = purely $ readHtml def { readerExtensions = enableExtension Ext_native_divs $ readerExtensions def }
+
+tests :: [TestTree]
+tests = [ testGroup "base tag"
+          [ test html "simple" $
+            "<head><base href=\"http://www.w3schools.com/images/foo\" ></head><body><img src=\"stickman.gif\" alt=\"Stickman\"></head>" =?>
+            plain (image "http://www.w3schools.com/images/stickman.gif" "" (text "Stickman"))
+          , test html "slash at end of base" $
+            "<head><base href=\"http://www.w3schools.com/images/\" ></head><body><img src=\"stickman.gif\" alt=\"Stickman\"></head>" =?>
+            plain (image "http://www.w3schools.com/images/stickman.gif" "" (text "Stickman"))
+          , test html "slash at beginning of href" $
+            "<head><base href=\"http://www.w3schools.com/images/\" ></head><body><img src=\"/stickman.gif\" alt=\"Stickman\"></head>" =?>
+            plain (image "http://www.w3schools.com/stickman.gif" "" (text "Stickman"))
+          , test html "absolute URL" $
+            "<head><base href=\"http://www.w3schools.com/images/\" ></head><body><img src=\"http://example.com/stickman.gif\" alt=\"Stickman\"></head>" =?>
+            plain (image "http://example.com/stickman.gif" "" (text "Stickman"))
+          ]
+        , testGroup "anchors"
+          [ test html "anchor without href" $ "<a name=\"anchor\"/>" =?>
+            plain (spanWith ("anchor",[],[]) mempty)
+          ]
+        , testGroup "lang"
+          [ test html "lang on <html>" $ "<html lang=\"es\">hola" =?>
+            setMeta "lang" (text "es") (doc (plain (text "hola")))
+          , test html "xml:lang on <html>" $ "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"es\"><head></head><body>hola</body></html>" =?>
+            setMeta "lang" (text "es") (doc (plain (text "hola")))
+          ]
+        , testGroup "main"
+          [ test htmlNativeDivs "<main> becomes <div role=main>" $ "<main>hello</main>" =?>
+            doc (divWith ("", [], [("role", "main")]) (plain (text "hello")))
+          , test htmlNativeDivs "<main role=X> becomes <div role=X>" $ "<main role=foobar>hello</main>" =?>
+            doc (divWith ("", [], [("role", "foobar")]) (plain (text "hello")))
+          , test htmlNativeDivs "<main> has attributes preserved" $ "<main id=foo class=bar data-baz=qux>hello</main>" =?>
+            doc (divWith ("foo", ["bar"], [("role", "main"), ("data-baz", "qux")]) (plain (text "hello")))
+          , test htmlNativeDivs "<main> closes <p>" $ "<p>hello<main>main content</main>" =?>
+            doc (para (text "hello") <> divWith ("", [], [("role", "main")]) (plain (text "main content")))
+          , test htmlNativeDivs "<main> followed by text" $ "<main>main content</main>non-main content" =?>
+            doc (divWith ("", [], [("role", "main")]) (plain (text "main content")) <> plain (text "non-main content"))
+          ]
+        ]
diff --git a/test/Tests/Readers/JATS.hs b/test/Tests/Readers/JATS.hs
index 5c7dfa77c..83c7c0da5 100644
--- a/test/Tests/Readers/JATS.hs
+++ b/test/Tests/Readers/JATS.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Readers.JATS (tests) where
 
+import Prelude
 import Data.Text (Text)
 import Test.Tasty
 import Tests.Helpers
diff --git a/test/Tests/Readers/JATS.hs.orig b/test/Tests/Readers/JATS.hs.orig
new file mode 100644
index 000000000..5c7dfa77c
--- /dev/null
+++ b/test/Tests/Readers/JATS.hs.orig
@@ -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
index 4396d550f..1538b6b0a 100644
--- a/test/Tests/Readers/LaTeX.hs
+++ b/test/Tests/Readers/LaTeX.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Readers.LaTeX (tests) where
 
+import Prelude
 import Data.Text (Text)
 import qualified Data.Text as T
 import qualified Text.Pandoc.UTF8 as UTF8
diff --git a/test/Tests/Readers/LaTeX.hs.orig b/test/Tests/Readers/LaTeX.hs.orig
new file mode 100644
index 000000000..4396d550f
--- /dev/null
+++ b/test/Tests/Readers/LaTeX.hs.orig
@@ -0,0 +1,341 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.LaTeX (tests) where
+
+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 ()
+import Text.Pandoc.Builder
+
+latex :: Text -> Pandoc
+latex = purely $ readLaTeX def{
+                   readerExtensions = getDefaultExtensions "latex" }
+
+infix 4 =:
+(=:) :: ToString c
+     => String -> (Text, c) -> TestTree
+(=:) = test latex
+
+simpleTable' :: [Alignment] -> [[Blocks]] -> Blocks
+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 "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" =:
+            "some text" =?> para "some text"
+          , "emphasized" =:
+            "\\emph{emphasized}" =?> para (emph "emphasized")
+          ]
+
+        , testGroup "headers"
+          [ "level 1" =:
+            "\\section{header}" =?> headerWith ("header",[],[]) 1 "header"
+          , "level 2" =:
+            "\\subsection{header}" =?> headerWith ("header",[],[]) 2 "header"
+          , "level 3" =:
+            "\\subsubsection{header}" =?> headerWith ("header",[],[]) 3 "header"
+          , "emph" =:
+            "\\section{text \\emph{emph}}" =?>
+             headerWith ("text-emph",[],[]) 1 ("text" <> space <> emph "emph")
+          , "link" =:
+            "\\section{text \\href{/url}{link}}" =?>
+              headerWith ("text-link",[],[]) 1 ("text" <> space <> link "/url" "" "link")
+          ]
+
+        , testGroup "math"
+          [ "escaped $" =:
+            "$x=\\$4$" =?> para (math "x=\\$4")
+          ]
+
+        , testGroup "space and comments"
+          [ "blank lines + space at beginning" =:
+            "\n  \n  hi" =?> para "hi"
+          , "blank lines + space + comments" =:
+            "% my comment\n\n  \n  % another\n\nhi" =?> para "hi"
+          , "comment in paragraph" =:
+            "hi % this is a comment\nthere\n" =?>
+                para ("hi" <> softbreak <> "there")
+          ]
+
+        , testGroup "code blocks"
+          [ "identifier" =:
+            "\\begin{lstlisting}[label=test]\\end{lstlisting}" =?> codeBlockWith ("test", [], [("label","test")]) ""
+          , "no identifier" =:
+            "\\begin{lstlisting}\\end{lstlisting}" =?> codeBlock ""
+          ]
+
+        , testGroup "tables"
+          [ "Single cell table" =:
+            "\\begin{tabular}{|l|}Test\\\\\\end{tabular}" =?>
+            simpleTable' [AlignLeft] [[plain "Test"]]
+          , "Multi cell table" =:
+            "\\begin{tabular}{|rl|}One & Two\\\\ \\end{tabular}" =?>
+            simpleTable' [AlignRight,AlignLeft] [[plain "One", plain "Two"]]
+          , "Multi line table" =:
+            T.unlines [ "\\begin{tabular}{|c|}"
+                    , "One\\\\"
+                    , "Two\\\\"
+                    , "Three\\\\"
+                    , "\\end{tabular}" ] =?>
+            simpleTable' [AlignCenter]
+                         [[plain "One"], [plain "Two"], [plain "Three"]]
+          , "Empty table" =:
+            "\\begin{tabular}{}\\end{tabular}" =?>
+            simpleTable' [] []
+          , "Table with fixed column width" =:
+            "\\begin{tabular}{|p{5cm}r|}One & Two\\\\ \\end{tabular}" =?>
+            simpleTable' [AlignLeft,AlignRight] [[plain "One", plain "Two"]]
+          , "Table with empty column separators" =:
+            "\\begin{tabular}{@{}r@{}l}One & Two\\\\ \\end{tabular}" =?>
+            simpleTable' [AlignRight,AlignLeft] [[plain "One", plain "Two"]]
+          , "Table with custom column separators" =:
+            T.unlines [ "\\begin{tabular}{@{($\\to$)}r@{\\hspace{2cm}}l}"
+                    , "One&Two\\\\"
+                    , "\\end{tabular}" ] =?>
+            simpleTable' [AlignRight,AlignLeft] [[plain "One", plain "Two"]]
+          , "Table with vertical alignment argument" =:
+            "\\begin{tabular}[t]{r|r}One & Two\\\\ \\end{tabular}" =?>
+            simpleTable' [AlignRight,AlignRight] [[plain "One", plain "Two"]]
+          ]
+
+        , testGroup "citations"
+          [ natbibCitations
+          , biblatexCitations
+          ]
+
+        , testGroup "images"
+          [ "Basic image" =:
+            "\\includegraphics{foo.png}" =?>
+            para (image "foo.png" "" (text "image"))
+          , "Basic image with blank options" =:
+            "\\includegraphics[]{foo.png}" =?>
+            para (image "foo.png" "" (text "image"))
+          , "Image with both width and height" =:
+            "\\includegraphics[width=17cm,height=5cm]{foo.png}" =?>
+            para (imageWith ("", [], [("width", "17cm"), ("height", "5cm")]) "foo.png" "" "image")
+          , "Image with width and height and a bunch of other options" =:
+            "\\includegraphics[width=17cm,height=5cm,clip,keepaspectratio]{foo.png}" =?>
+            para (imageWith ("", [], [("width", "17cm"), ("height", "5cm")]) "foo.png" "" "image")
+          , "Image with just width" =:
+            "\\includegraphics[width=17cm]{foo.png}" =?>
+            para (imageWith ("", [], [("width", "17cm")]) "foo.png" "" "image")
+          , "Image with just height" =:
+            "\\includegraphics[height=17cm]{foo.png}" =?>
+            para (imageWith ("", [], [("height", "17cm")]) "foo.png" "" "image")
+          , "Image width relative to textsize" =:
+            "\\includegraphics[width=0.6\\textwidth]{foo.png}" =?>
+            para (imageWith ("", [], [("width", "60%")]) "foo.png" "" "image")
+          , "Image with options with spaces" =:
+            "\\includegraphics[width=12cm, height = 5cm]{foo.png}" =?>
+            para (imageWith ("", [], [("width", "12cm"), ("height", "5cm")]) "foo.png" "" "image")
+          ]
+
+        , let hex = ['0'..'9']++['a'..'f'] in
+          testGroup "Character Escapes"
+          [ "Two-character escapes" =:
+            mconcat ["^^" <> T.pack [i,j] | i <- hex, j <- hex] =?>
+            para (str ['\0'..'\255'])
+          , "One-character escapes" =:
+            mconcat ["^^" <> T.pack [i] | i <- hex] =?>
+            para (str $ ['p'..'y']++['!'..'&'])
+          ]
+        , testGroup "memoir scene breaks"
+          [ "plainbreak" =:
+            "hello\\plainbreak{2}goodbye" =?>
+            para (str "hello") <> horizontalRule <> para (str "goodbye")
+          , "plainbreak*" =:
+            "hello\\plainbreak*{2}goodbye" =?>
+            para (str "hello") <> horizontalRule <> para (str "goodbye")
+          , "fancybreak" =:
+            "hello\\fancybreak{b r e a k}goodbye" =?>
+            para (str "hello") <> horizontalRule <> para (str "goodbye")
+          , "fancybreak*" =:
+            "hello\\fancybreak*{b r e a k}goodbye" =?>
+            para (str "hello") <> horizontalRule <> para (str "goodbye")
+          , "plainfancybreak" =:
+            "hello\\plainfancybreak{4}{2}{b r e a k}goodbye" =?>
+            para (str "hello") <> horizontalRule <> para (str "goodbye")
+          , "plainfancybreak*" =:
+            "hello\\plainfancybreak*{4}{2}{b r e a k}goodbye" =?>
+            para (str "hello") <> horizontalRule <> para (str "goodbye")
+          , "pfbreak" =:
+            "hello\\pfbreak{}goodbye" =?>
+            para (str "hello") <> horizontalRule <> para (str "goodbye")
+          , "pfbreak*" =:
+            "hello\\pfbreak*{}goodbye" =?>
+            para (str "hello") <> horizontalRule <> para (str "goodbye")
+          ]
+        , testGroup "biblatex roman numerals"
+          [ "upper" =:
+            "number \\RN{12}" =?>
+            para (str "number" <> space <> str "XII")
+          , "lower" =:
+            "number \\Rn{29}" =?>
+            para (str "number" <> space <> str "xxix")
+          , "leading zero" =:
+            "\\Rn{014}" =?>
+            para (str "xiv")
+          , "surrounding spaces" =:
+            "number \\Rn{ 41 }" =?>
+            para (str "number" <> space <> str "xli")
+          , "zero" =:
+            "\\RN{0}" =?>
+            para (str "")
+          , "space then unbraced argument" =:
+            "\\RN 7 ok" =?>
+            para (str "VII" <> space <> str "ok")
+          , "space before braced argument" =:
+            "\\Rn {13}ok" =?>
+            para (str "xiiiok")
+          ]
+        , testGroup "polyglossia language spans"
+          [ "french" =:
+            "hello \\textfrench{bonjour}" =?>
+            para (str "hello" <> space <> spanWith ("", [], [("lang", "fr")]) (str "bonjour"))
+          , "nested" =:
+            "\\textfrench{quelle c'est \\textlatin{primus}?}" =?>
+            para (spanWith ("", [], [("lang", "fr")]) $
+                    str "quelle" <> space <> str "c\8217est" <> space <>
+                    spanWith ("", [], [("lang", "la")]) (str "primus") <> str "?")
+          , "with formatting" =:
+            "\\textgerman{wie \\emph{spaet} ist es?}" =?>
+            para (spanWith ("", [], [("lang", "de")]) $
+                    str "wie" <> space <> emph (str "spaet") <> space <> str "ist" <> space <> str "es?")
+          , "language options" =:
+            "\\textgerman[variant=swiss]{hoechdeutsche}" =?>
+            para (spanWith ("", [], [("lang", "de-CH")]) $ str "hoechdeutsche")
+          , "unknown option fallback" =:
+            "\\textgerman[variant=moon]{ueberhoechdeutsche}" =?>
+            para (spanWith ("", [], [("lang", "de")]) $ str "ueberhoechdeutsche")
+          ]
+        ]
+
+baseCitation :: Citation
+baseCitation = Citation{ citationId      = "item1"
+                       , citationPrefix  = []
+                       , citationSuffix  = []
+                       , citationMode    = AuthorInText
+                       , citationNoteNum = 0
+                       , citationHash    = 0
+                       }
+
+rt :: String -> Inlines
+rt = rawInline "latex"
+
+natbibCitations :: TestTree
+natbibCitations = testGroup "natbib"
+  [ "citet" =: "\\citet{item1}"
+    =?> para (cite [baseCitation] (rt "\\citet{item1}"))
+  , "suffix" =: "\\citet[p.~30]{item1}"
+    =?> para
+        (cite [baseCitation{ citationSuffix = toList $ text "p.\160\&30" }] (rt "\\citet[p.~30]{item1}"))
+  , "suffix long" =: "\\citet[p.~30, with suffix]{item1}"
+    =?> para (cite [baseCitation{ citationSuffix =
+                       toList $ text "p.\160\&30, with suffix" }] (rt "\\citet[p.~30, with suffix]{item1}"))
+  , "multiple" =: "\\citeauthor{item1} \\citetext{\\citeyear{item1}; \\citeyear[p.~30]{item2}; \\citealp[see also][]{item3}}"
+    =?> para (cite [baseCitation{ citationMode = AuthorInText }
+                   ,baseCitation{ citationMode = SuppressAuthor
+                                , citationSuffix = [Str "p.\160\&30"]
+                                , citationId = "item2" }
+                   ,baseCitation{ citationId = "item3"
+                                , citationPrefix = [Str "see",Space,Str "also"]
+                                , citationMode = NormalCitation }
+                   ] (rt "\\citetext{\\citeyear{item1}; \\citeyear[p.~30]{item2}; \\citealp[see also][]{item3}}"))
+  , "group" =: "\\citetext{\\citealp[see][p.~34--35]{item1}; \\citealp[also][chap. 3]{item3}}"
+    =?> para (cite [baseCitation{ citationMode = NormalCitation
+                                , citationPrefix = [Str "see"]
+                                , citationSuffix = [Str "p.\160\&34\8211\&35"] }
+                   ,baseCitation{ citationMode = NormalCitation
+                                , citationId = "item3"
+                                , citationPrefix = [Str "also"]
+                                , citationSuffix = [Str "chap.",Space,Str "3"] }
+                   ] (rt "\\citetext{\\citealp[see][p.~34--35]{item1}; \\citealp[also][chap. 3]{item3}}"))
+  , "suffix and locator" =: "\\citep[pp.~33, 35--37, and nowhere else]{item1}"
+    =?> para (cite [baseCitation{ citationMode = NormalCitation
+                                , citationSuffix = [Str "pp.\160\&33,",Space,Str "35\8211\&37,",Space,Str "and",Space,Str "nowhere",Space, Str "else"] }] (rt "\\citep[pp.~33, 35--37, and nowhere else]{item1}"))
+  , "suffix only" =: "\\citep[and nowhere else]{item1}"
+    =?> para (cite [baseCitation{ citationMode = NormalCitation
+                                , citationSuffix = toList $ text "and nowhere else" }] (rt "\\citep[and nowhere else]{item1}"))
+  , "no author" =: "\\citeyearpar{item1}, and now Doe with a locator \\citeyearpar[p.~44]{item2}"
+    =?> para (cite [baseCitation{ citationMode = SuppressAuthor }] (rt "\\citeyearpar{item1}") <>
+              text ", and now Doe with a locator " <>
+              cite [baseCitation{ citationMode = SuppressAuthor
+                                , citationSuffix = [Str "p.\160\&44"]
+                                , citationId = "item2" }] (rt "\\citeyearpar[p.~44]{item2}"))
+  , "markup" =: "\\citep[\\emph{see}][p. \\textbf{32}]{item1}"
+    =?> para (cite [baseCitation{ citationMode = NormalCitation
+                                , citationPrefix = [Emph [Str "see"]]
+                                , citationSuffix = [Str "p.",Space,
+                                    Strong [Str "32"]] }] (rt "\\citep[\\emph{see}][p. \\textbf{32}]{item1}"))
+  ]
+
+biblatexCitations :: TestTree
+biblatexCitations = testGroup "biblatex"
+  [ "textcite" =: "\\textcite{item1}"
+    =?> para (cite [baseCitation] (rt "\\textcite{item1}"))
+  , "suffix" =: "\\textcite[p.~30]{item1}"
+    =?> para
+        (cite [baseCitation{ citationSuffix = toList $ text "p.\160\&30" }] (rt "\\textcite[p.~30]{item1}"))
+  , "suffix long" =: "\\textcite[p.~30, with suffix]{item1}"
+    =?> para (cite [baseCitation{ citationSuffix =
+                       toList $ text "p.\160\&30, with suffix" }] (rt "\\textcite[p.~30, with suffix]{item1}"))
+  , "multiple" =: "\\textcites{item1}[p.~30]{item2}[see also][]{item3}"
+    =?> para (cite [baseCitation{ citationMode = AuthorInText }
+                   ,baseCitation{ citationMode = NormalCitation
+                                , citationSuffix = [Str "p.\160\&30"]
+                                , citationId = "item2" }
+                   ,baseCitation{ citationId = "item3"
+                                , citationPrefix = [Str "see",Space,Str "also"]
+                                , citationMode = NormalCitation }
+                   ] (rt "\\textcites{item1}[p.~30]{item2}[see also][]{item3}"))
+  , "group" =: "\\autocites[see][p.~34--35]{item1}[also][chap. 3]{item3}"
+    =?> para (cite [baseCitation{ citationMode = NormalCitation
+                                , citationPrefix = [Str "see"]
+                                , citationSuffix = [Str "p.\160\&34\8211\&35"] }
+                   ,baseCitation{ citationMode = NormalCitation
+                                , citationId = "item3"
+                                , citationPrefix = [Str "also"]
+                                , citationSuffix = [Str "chap.",Space,Str "3"] }
+                   ] (rt "\\autocites[see][p.~34--35]{item1}[also][chap. 3]{item3}"))
+  , "suffix and locator" =: "\\autocite[pp.~33, 35--37, and nowhere else]{item1}"
+    =?> para (cite [baseCitation{ citationMode = NormalCitation
+                                , citationSuffix = [Str "pp.\160\&33,",Space,Str "35\8211\&37,",Space,Str "and",Space,Str "nowhere",Space, Str "else"] }] (rt "\\autocite[pp.~33, 35--37, and nowhere else]{item1}"))
+  , "suffix only" =: "\\autocite[and nowhere else]{item1}"
+    =?> para (cite [baseCitation{ citationMode = NormalCitation
+                                , citationSuffix = toList $ text "and nowhere else" }] (rt "\\autocite[and nowhere else]{item1}"))
+  , "no author" =: "\\autocite*{item1}, and now Doe with a locator \\autocite*[p.~44]{item2}"
+    =?> para (cite [baseCitation{ citationMode = SuppressAuthor }] (rt "\\autocite*{item1}") <>
+              text ", and now Doe with a locator " <>
+              cite [baseCitation{ citationMode = SuppressAuthor
+                                , citationSuffix = [Str "p.\160\&44"]
+                                , citationId = "item2" }] (rt "\\autocite*[p.~44]{item2}"))
+  , "markup" =: "\\autocite[\\emph{see}][p. \\textbf{32}]{item1}"
+    =?> para (cite [baseCitation{ citationMode = NormalCitation
+                                , citationPrefix = [Emph [Str "see"]]
+                                , citationSuffix = [Str "p.",Space,
+                                    Strong [Str "32"]] }] (rt "\\autocite[\\emph{see}][p. \\textbf{32}]{item1}"))
+  , "parencite" =: "\\parencite{item1}"
+    =?> para (cite [baseCitation{ citationMode = NormalCitation }] (rt "\\parencite{item1}"))
+  ]
diff --git a/test/Tests/Readers/Markdown.hs b/test/Tests/Readers/Markdown.hs
index 1cd32b87d..e44c7fc19 100644
--- a/test/Tests/Readers/Markdown.hs
+++ b/test/Tests/Readers/Markdown.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Readers.Markdown (tests) where
 
+import Prelude
 import Data.Text (Text, unpack)
 import qualified Data.Text as T
 import Test.Tasty
@@ -293,6 +295,9 @@ tests = [ testGroup "inline code"
           , test markdownSmart "apostrophe after math" $ -- issue #1909
               "The value of the $x$'s and the systems' condition." =?>
               para (text "The value of the " <> math "x" <> text "\8217s and the systems\8217 condition.")
+          , test markdownSmart "unclosed double quote"
+            ("**this should \"be bold**"
+            =?> para (strong "this should \"be bold"))
           ]
         , testGroup "footnotes"
           [ "indent followed by newline and flush-left text" =:
diff --git a/test/Tests/Readers/Markdown.hs.orig b/test/Tests/Readers/Markdown.hs.orig
new file mode 100644
index 000000000..1cd32b87d
--- /dev/null
+++ b/test/Tests/Readers/Markdown.hs.orig
@@ -0,0 +1,462 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.Markdown (tests) where
+
+import Data.Text (Text, unpack)
+import qualified Data.Text as T
+import Test.Tasty
+import Tests.Helpers
+import Text.Pandoc
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder
+
+markdown :: Text -> Pandoc
+markdown = purely $ readMarkdown def { readerExtensions =
+                            disableExtension Ext_smart pandocExtensions }
+
+markdownSmart :: Text -> Pandoc
+markdownSmart = purely $  readMarkdown def { readerExtensions =
+                             enableExtension Ext_smart pandocExtensions }
+
+markdownCDL :: Text -> Pandoc
+markdownCDL = purely $ readMarkdown def { readerExtensions = enableExtension
+                 Ext_compact_definition_lists pandocExtensions }
+
+markdownGH :: Text -> Pandoc
+markdownGH = purely $ readMarkdown def {
+                readerExtensions = githubMarkdownExtensions }
+
+infix 4 =:
+(=:) :: ToString c
+     => String -> (Text, c) -> TestTree
+(=:) = test markdown
+
+testBareLink :: (Text, Inlines) -> TestTree
+testBareLink (inp, ils) =
+  test (purely $ readMarkdown def{ readerExtensions =
+             extensionsFromList [Ext_autolink_bare_uris, Ext_raw_html] })
+       (unpack inp) (inp, doc $ para ils)
+
+autolink :: String -> Inlines
+autolink = autolinkWith nullAttr
+
+autolinkWith :: Attr -> String -> Inlines
+autolinkWith attr s = linkWith attr s "" (str s)
+
+bareLinkTests :: [(Text, Inlines)]
+bareLinkTests =
+  [ ("http://google.com is a search engine.",
+     autolink "http://google.com" <> " is a search engine.")
+  , ("<a href=\"http://foo.bar.baz\">http://foo.bar.baz</a>",
+     rawInline "html" "<a href=\"http://foo.bar.baz\">" <>
+     "http://foo.bar.baz" <> rawInline "html" "</a>")
+  , ("Try this query: http://google.com?search=fish&time=hour.",
+     "Try this query: " <> autolink "http://google.com?search=fish&time=hour" <> ".")
+  , ("HTTPS://GOOGLE.COM,",
+      autolink "HTTPS://GOOGLE.COM" <> ",")
+  , ("http://el.wikipedia.org/wiki/Τεχνολογία,",
+      autolink "http://el.wikipedia.org/wiki/Τεχνολογία" <> ",")
+  , ("doi:10.1000/182,",
+      autolink "doi:10.1000/182" <> ",")
+  , ("git://github.com/foo/bar.git,",
+      autolink "git://github.com/foo/bar.git" <> ",")
+  , ("file:///Users/joe/joe.txt, and",
+      autolink "file:///Users/joe/joe.txt" <> ", and")
+  , ("mailto:someone@somedomain.com.",
+      autolink "mailto:someone@somedomain.com" <> ".")
+  , ("Use http: this is not a link!",
+      "Use http: this is not a link!")
+  , ("(http://google.com).",
+      "(" <> autolink "http://google.com" <> ").")
+  , ("http://en.wikipedia.org/wiki/Sprite_(computer_graphics)",
+      autolink "http://en.wikipedia.org/wiki/Sprite_(computer_graphics)")
+  , ("http://en.wikipedia.org/wiki/Sprite_[computer_graphics]",
+      link "http://en.wikipedia.org/wiki/Sprite_%5Bcomputer_graphics%5D" ""
+        (str "http://en.wikipedia.org/wiki/Sprite_[computer_graphics]"))
+  , ("http://en.wikipedia.org/wiki/Sprite_{computer_graphics}",
+      link "http://en.wikipedia.org/wiki/Sprite_%7Bcomputer_graphics%7D" ""
+        (str "http://en.wikipedia.org/wiki/Sprite_{computer_graphics}"))
+  , ("http://example.com/Notification_Center-GitHub-20101108-140050.jpg",
+      autolink "http://example.com/Notification_Center-GitHub-20101108-140050.jpg")
+  , ("https://github.com/github/hubot/blob/master/scripts/cream.js#L20-20",
+      autolink "https://github.com/github/hubot/blob/master/scripts/cream.js#L20-20")
+  , ("http://www.rubyonrails.com",
+      autolink "http://www.rubyonrails.com")
+  , ("http://www.rubyonrails.com:80",
+      autolink "http://www.rubyonrails.com:80")
+  , ("http://www.rubyonrails.com/~minam",
+      autolink "http://www.rubyonrails.com/~minam")
+  , ("https://www.rubyonrails.com/~minam",
+      autolink "https://www.rubyonrails.com/~minam")
+  , ("http://www.rubyonrails.com/~minam/url%20with%20spaces",
+      autolink "http://www.rubyonrails.com/~minam/url%20with%20spaces")
+  , ("http://www.rubyonrails.com/foo.cgi?something=here",
+      autolink "http://www.rubyonrails.com/foo.cgi?something=here")
+  , ("http://www.rubyonrails.com/foo.cgi?something=here&and=here",
+      autolink "http://www.rubyonrails.com/foo.cgi?something=here&and=here")
+  , ("http://www.rubyonrails.com/contact;new",
+      autolink "http://www.rubyonrails.com/contact;new")
+  , ("http://www.rubyonrails.com/contact;new%20with%20spaces",
+      autolink "http://www.rubyonrails.com/contact;new%20with%20spaces")
+  , ("http://www.rubyonrails.com/contact;new?with=query&string=params",
+      autolink "http://www.rubyonrails.com/contact;new?with=query&string=params")
+  , ("http://www.rubyonrails.com/~minam/contact;new?with=query&string=params",
+      autolink "http://www.rubyonrails.com/~minam/contact;new?with=query&string=params")
+  , ("http://en.wikipedia.org/wiki/Wikipedia:Today%27s_featured_picture_%28animation%29/January_20%2C_2007",
+      autolink "http://en.wikipedia.org/wiki/Wikipedia:Today%27s_featured_picture_%28animation%29/January_20%2C_2007")
+  , ("http://www.mail-archive.com/rails@lists.rubyonrails.org/",
+      autolink "http://www.mail-archive.com/rails@lists.rubyonrails.org/")
+  , ("http://www.amazon.com/Testing-Equal-Sign-In-Path/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1198861734&sr=8-1",
+      autolink "http://www.amazon.com/Testing-Equal-Sign-In-Path/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1198861734&sr=8-1")
+  , ("http://en.wikipedia.org/wiki/Texas_hold%27em",
+      autolink "http://en.wikipedia.org/wiki/Texas_hold%27em")
+  , ("https://www.google.com/doku.php?id=gps:resource:scs:start",
+      autolink "https://www.google.com/doku.php?id=gps:resource:scs:start")
+  , ("http://www.rubyonrails.com",
+      autolink "http://www.rubyonrails.com")
+  , ("http://manuals.ruby-on-rails.com/read/chapter.need_a-period/103#page281",
+      autolink "http://manuals.ruby-on-rails.com/read/chapter.need_a-period/103#page281")
+  , ("http://foo.example.com/controller/action?parm=value&p2=v2#anchor123",
+      autolink "http://foo.example.com/controller/action?parm=value&p2=v2#anchor123")
+  , ("http://foo.example.com:3000/controller/action",
+      autolink "http://foo.example.com:3000/controller/action")
+  , ("http://foo.example.com:3000/controller/action+pack",
+      autolink "http://foo.example.com:3000/controller/action+pack")
+  , ("http://business.timesonline.co.uk/article/0,,9065-2473189,00.html",
+      autolink "http://business.timesonline.co.uk/article/0,,9065-2473189,00.html")
+  , ("http://www.mail-archive.com/ruby-talk@ruby-lang.org/",
+      autolink "http://www.mail-archive.com/ruby-talk@ruby-lang.org/")
+  , ("https://example.org/?anchor=lala-",
+      autolink "https://example.org/?anchor=lala-")
+  , ("https://example.org/?anchor=-lala",
+      autolink "https://example.org/?anchor=-lala")
+  ]
+
+{-
+p_markdown_round_trip :: Block -> Bool
+p_markdown_round_trip b = matches d' d''
+  where d'  = normalize $ Pandoc (Meta [] [] []) [b]
+        d'' = normalize
+              $ readMarkdown def { readerSmart = True }
+              $ writeMarkdown def d'
+        matches (Pandoc _ [Plain []]) (Pandoc _ []) = True
+        matches (Pandoc _ [Para []]) (Pandoc _ []) = True
+        matches (Pandoc _ [Plain xs]) (Pandoc _ [Para xs']) = xs == xs'
+        matches x y = x == y
+-}
+
+tests :: [TestTree]
+tests = [ testGroup "inline code"
+          [ "with attribute" =:
+            "`document.write(\"Hello\");`{.javascript}"
+            =?> para
+                (codeWith ("",["javascript"],[]) "document.write(\"Hello\");")
+          , "with attribute space" =:
+            "`*` {.haskell .special x=\"7\"}"
+            =?> para (code "*" <> space <> str "{.haskell" <> space <>
+                      str ".special" <> space <> str "x=\"7\"}")
+          ]
+        , testGroup "emph and strong"
+          [ "two strongs in emph" =:
+             "***a**b **c**d*" =?> para (emph (strong (str "a") <> str "b" <> space
+                                         <> strong (str "c") <> str "d"))
+          , "emph and strong emph alternating" =:
+            "*xxx* ***xxx*** xxx\n*xxx* ***xxx*** xxx"
+            =?> para (emph "xxx" <> space <> strong (emph "xxx") <>
+                      space <> "xxx" <> softbreak <>
+                      emph "xxx" <> space <> strong (emph "xxx") <>
+                      space <> "xxx")
+          , "emph with spaced strong" =:
+            "*x **xx** x*"
+            =?> para (emph ("x" <> space <> strong "xx" <> space <> "x"))
+          , "intraword underscore with opening underscore (#1121)" =:
+            "_foot_ball_" =?> para (emph (text "foot_ball"))
+          ]
+        , testGroup "raw LaTeX"
+          [ "in URL" =:
+            "\\begin\n" =?> para (text "\\begin")
+          ]
+        , testGroup "raw HTML"
+          [ "nesting (issue #1330)" =:
+            "<del>test</del>" =?>
+            rawBlock "html" "<del>" <> plain (str "test") <>
+            rawBlock "html" "</del>"
+          , "invalid tag (issue #1820" =:
+            "</ div></.div>" =?>
+            para (text "</ div></.div>")
+          , "technically invalid comment" =:
+            "<!-- pandoc --help -->" =?>
+            rawBlock "html" "<!-- pandoc --help -->"
+          , test markdownGH "issue 2469" $
+            "<\n\na>" =?>
+            para (text "<") <> para (text "a>")
+          ]
+        , testGroup "raw email addresses"
+          [ test markdownGH "issue 2940" $
+            "**@user**" =?>
+            para (strong (text "@user"))
+          ]
+        , testGroup "emoji"
+          [ test markdownGH "emoji symbols" $
+            ":smile: and :+1:" =?> para (text "😄 and 👍")
+          ]
+        , "unbalanced brackets" =:
+            "[[[[[[[[[[[[hi" =?> para (text "[[[[[[[[[[[[hi")
+        , testGroup "backslash escapes"
+          [ "in URL" =:
+            "[hi](/there\\))"
+            =?> para (link "/there)" "" "hi")
+          , "in title" =:
+            "[hi](/there \"a\\\"a\")"
+            =?> para (link "/there" "a\"a" "hi")
+          , "in reference link title" =:
+            "[hi]\n\n[hi]: /there (a\\)a)"
+            =?> para (link "/there" "a)a" "hi")
+          , "in reference link URL" =:
+            "[hi]\n\n[hi]: /there\\.0"
+            =?> para (link "/there.0" "" "hi")
+          ]
+        , testGroup "bare URIs"
+             (map testBareLink bareLinkTests)
+        , testGroup "autolinks"
+          [ "with unicode dash following" =:
+            "<http://foo.bar>\8212" =?> para (autolink "http://foo.bar" <>
+                                         str "\8212")
+          , "a partial URL (#2277)" =:
+            "<www.boe.es/buscar/act.php?id=BOE-A-1996-8930#a66>" =?>
+            para (text "<www.boe.es/buscar/act.php?id=BOE-A-1996-8930#a66>")
+          , "with some attributes" =:
+            "<http://foo.bar>{#i .j .z k=v}" =?>
+            para (autolinkWith ("i", ["j", "z"], [("k", "v")]) "http://foo.bar")
+          , "with some attributes and spaces" =:
+            "<http://foo.bar> {#i .j .z k=v}" =?>
+            para (autolink "http://foo.bar" <> space <> text "{#i .j .z k=v}")
+          ]
+        , testGroup "links"
+          [ "no autolink inside link" =:
+            "[<https://example.org>](url)" =?>
+            para (link "url" "" (text "<https://example.org>"))
+          , "no inline link inside link" =:
+            "[[a](url2)](url)" =?>
+            para (link "url" "" (text "[a](url2)"))
+          , "no bare URI inside link" =:
+            "[https://example.org(](url)" =?>
+            para (link "url" "" (text "https://example.org("))
+          ]
+        , testGroup "Headers"
+          [ "blank line before header" =:
+            "\n# Header\n"
+            =?> headerWith ("header",[],[]) 1 "Header"
+          , "bracketed text (#2062)" =:
+            "# [hi]\n"
+            =?> headerWith ("hi",[],[]) 1 "[hi]"
+          , "ATX header without trailing #s" =:
+            "# Foo bar\n\n" =?>
+            headerWith ("foo-bar",[],[]) 1 "Foo bar"
+          , "ATX header without trailing #s" =:
+            "# Foo bar with # #" =?>
+            headerWith ("foo-bar-with",[],[]) 1 "Foo bar with #"
+          , "setext header" =:
+            "Foo bar\n=\n\n Foo bar 2 \n=" =?>
+            headerWith ("foo-bar",[],[]) 1 "Foo bar"
+            <> headerWith ("foo-bar-2",[],[]) 1 "Foo bar 2"
+          ]
+        , testGroup "Implicit header references"
+          [ "ATX header without trailing #s" =:
+            "# Header\n[header]\n\n[header ]\n\n[ header]" =?>
+            headerWith ("header",[],[]) 1 "Header"
+            <> para (link "#header" "" (text "header"))
+            <> para (link "#header" "" (text "header"))
+            <> para (link "#header" "" (text "header"))
+          , "ATX header with trailing #s" =:
+            "# Foo bar #\n[foo bar]\n\n[foo bar ]\n\n[ foo bar]" =?>
+            headerWith ("foo-bar",[],[]) 1 "Foo bar"
+            <> para (link "#foo-bar" "" (text "foo bar"))
+            <> para (link "#foo-bar" "" (text "foo bar"))
+            <> para (link "#foo-bar" "" (text "foo bar"))
+          , "setext header" =:
+            " Header \n=\n\n[header]\n\n[header ]\n\n[ header]" =?>
+            headerWith ("header",[],[]) 1 "Header"
+            <> para (link "#header" "" (text "header"))
+            <> para (link "#header" "" (text "header"))
+            <> para (link "#header" "" (text "header"))
+          ]
+        , testGroup "smart punctuation"
+          [ test markdownSmart "quote before ellipses"
+            ("'...hi'"
+            =?> para (singleQuoted "…hi"))
+          , test markdownSmart "apostrophe before emph"
+            ("D'oh! A l'*aide*!"
+            =?> para ("D’oh! A l’" <> emph "aide" <> "!"))
+          , test markdownSmart "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 markdownSmart "apostrophe after math" $ -- issue #1909
+              "The value of the $x$'s and the systems' condition." =?>
+              para (text "The value of the " <> math "x" <> text "\8217s and the systems\8217 condition.")
+          ]
+        , testGroup "footnotes"
+          [ "indent followed by newline and flush-left text" =:
+            "[^1]\n\n[^1]: my note\n\n     \nnot in note\n"
+            =?> para (note (para "my note")) <> para "not in note"
+          , "indent followed by newline and indented text" =:
+            "[^1]\n\n[^1]: my note\n     \n    in note\n"
+            =?> para (note (para "my note" <> para "in note"))
+          , "recursive note" =:
+            "[^1]\n\n[^1]: See [^1]\n"
+            =?> para (note (para "See [^1]"))
+          ]
+        , testGroup "lhs"
+          [ test (purely $ readMarkdown def{ readerExtensions = enableExtension
+                       Ext_literate_haskell pandocExtensions })
+              "inverse bird tracks and html" $
+              "> a\n\n< b\n\n<div>\n"
+              =?> codeBlockWith ("",["sourceCode","literate","haskell"],[]) "a"
+                  <>
+                  codeBlockWith ("",["sourceCode","haskell"],[]) "b"
+                  <>
+                  rawBlock "html" "<div>\n\n"
+          ]
+-- the round-trip properties frequently fail
+--        , testGroup "round trip"
+--          [ property "p_markdown_round_trip" p_markdown_round_trip
+--          ]
+        , testGroup "definition lists"
+          [ "no blank space" =:
+            "foo1\n  :  bar\n\nfoo2\n  : bar2\n  : bar3\n" =?>
+            definitionList [ (text "foo1", [plain (text "bar")])
+                           , (text "foo2", [plain (text "bar2"),
+                                            plain (text "bar3")])
+                           ]
+          , "blank space before first def" =:
+            "foo1\n\n  :  bar\n\nfoo2\n\n  : bar2\n  : bar3\n" =?>
+            definitionList [ (text "foo1", [para (text "bar")])
+                           , (text "foo2", [para (text "bar2"),
+                                            plain (text "bar3")])
+                           ]
+          , "blank space before second def" =:
+            "foo1\n  :  bar\n\nfoo2\n  : bar2\n\n  : bar3\n" =?>
+            definitionList [ (text "foo1", [plain (text "bar")])
+                           , (text "foo2", [plain (text "bar2"),
+                                            para (text "bar3")])
+                           ]
+          , "laziness" =:
+            "foo1\n  :  bar\nbaz\n  : bar2\n" =?>
+            definitionList [ (text "foo1", [plain (text "bar" <>
+                                                 softbreak <> text "baz"),
+                                            plain (text "bar2")])
+                           ]
+          , "no blank space before first of two paragraphs" =:
+            "foo1\n  : bar\n\n    baz\n" =?>
+            definitionList [ (text "foo1", [para (text "bar") <>
+                                            para (text "baz")])
+                           ]
+          , "first line not indented" =:
+            "foo\n: bar\n" =?>
+            definitionList [ (text "foo", [plain (text "bar")]) ]
+          , "list in definition" =:
+            "foo\n:   - bar\n" =?>
+            definitionList [ (text "foo", [bulletList [plain (text "bar")]]) ]
+          , "in div" =:
+            "<div>foo\n:   - bar\n</div>" =?>
+            divWith nullAttr (definitionList
+              [ (text "foo", [bulletList [plain (text "bar")]]) ])
+          ]
+        , testGroup "+compact_definition_lists"
+          [ test markdownCDL "basic compact list" $
+            "foo1\n:   bar\n    baz\nfoo2\n:   bar2\n" =?>
+            definitionList [ (text "foo1", [plain (text "bar" <> softbreak <>
+                                                     text "baz")])
+                           , (text "foo2", [plain (text "bar2")])
+                           ]
+          ]
+        , testGroup "lists"
+          [ "issue #1154" =:
+              " -  <div>\n    first div breaks\n    </div>\n\n    <button>if this button exists</button>\n\n    <div>\n    with this div too.\n    </div>\n"
+              =?> bulletList [divWith nullAttr (para $ text "first div breaks") <>
+                              rawBlock "html" "<button>" <>
+                              plain (text "if this button exists") <>
+                              rawBlock "html" "</button>" <>
+                              divWith nullAttr (para $ text "with this div too.")]
+          , test markdownGH "issue #1636" $
+              T.unlines [ "* a"
+                        , "* b"
+                        , "* c"
+                        , "    * d" ]
+              =?>
+              bulletList [ plain "a"
+                         , plain "b"
+                         , plain "c" <> bulletList [plain "d"] ]
+          ]
+        , testGroup "entities"
+          [ "character references" =:
+            "&lang; &ouml;" =?> para (text "\10216 ö")
+          , "numeric" =:
+            "&#44;&#x44;&#X44;" =?> para (text ",DD")
+          , "in link title" =:
+            "[link](/url \"title &lang; &ouml; &#44;\")" =?>
+               para (link "/url" "title \10216 ö ," (text "link"))
+          ]
+        , testGroup "citations"
+          [ "simple" =:
+            "@item1" =?> para (cite [
+                Citation{ citationId      = "item1"
+                        , citationPrefix  = []
+                        , citationSuffix  = []
+                        , citationMode    = AuthorInText
+                        , citationNoteNum = 0
+                        , citationHash    = 0
+                        }
+                ] "@item1")
+          , "key starts with digit" =:
+            "@1657:huyghens" =?> para (cite [
+                Citation{ citationId      = "1657:huyghens"
+                        , citationPrefix  = []
+                        , citationSuffix  = []
+                        , citationMode    = AuthorInText
+                        , citationNoteNum = 0
+                        , citationHash    = 0
+                        }
+                ] "@1657:huyghens")
+          ]
+        , let citation = cite [Citation "cita" [] [] AuthorInText 0 0] (str "@cita")
+          in testGroup "footnote/link following citation" -- issue #2083
+          [ "footnote" =:
+              T.unlines [ "@cita[^note]"
+                        , ""
+                        , "[^note]: note" ] =?>
+              para (
+                citation <> note (para $ str "note")
+              )
+          , "normal link" =:
+              "@cita [link](http://www.com)" =?>
+              para (
+                citation <> space <> link "http://www.com" "" (str "link")
+              )
+          , "reference link" =:
+              T.unlines [ "@cita [link][link]"
+                        , ""
+                        , "[link]: http://www.com" ] =?>
+              para (
+                citation <> space <> link "http://www.com" "" (str "link")
+              )
+          , "short reference link" =:
+              T.unlines [ "@cita [link]"
+                        , ""
+                        , "[link]: http://www.com" ] =?>
+              para (
+                citation <> space <> link "http://www.com" "" (str "link")
+              )
+          , "implicit header link" =:
+              T.unlines [ "# Header"
+                        , "@cita [Header]" ] =?>
+              headerWith ("header",[],[]) 1 (str "Header") <> para (
+                citation <> space <> link "#header" "" (str "Header")
+              )
+          , "regular citation" =:
+              "@cita [foo]" =?>
+              para (
+                cite [Citation "cita" [] [Str "foo"] AuthorInText 0 0]
+                  (str "@cita" <> space <> str "[foo]")
+              )
+          ]
+        ]
diff --git a/test/Tests/Readers/Muse.hs b/test/Tests/Readers/Muse.hs
index c0ebf33cc..ecdd5fdb0 100644
--- a/test/Tests/Readers/Muse.hs
+++ b/test/Tests/Readers/Muse.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Readers.Muse (tests) where
 
+import Prelude
 import Data.List (intersperse)
 import Data.Text (Text)
 import qualified Data.Text as T
@@ -31,17 +33,17 @@ spcSep = mconcat . intersperse space
 --
 makeRoundTrip :: Block -> Block
 makeRoundTrip Table{} = Para [Str "table was here"]
+makeRoundTrip (OrderedList (start, LowerAlpha, _) items) = OrderedList (start, Decimal, Period) items
+makeRoundTrip (OrderedList (start, UpperAlpha, _) items) = OrderedList (start, Decimal, Period) items
 makeRoundTrip x = x
 
 -- Demand that any AST produced by Muse reader and written by Muse writer can be read back exactly the same way.
--- Currently we remove tables and compare third rewrite to the second.
--- First and second rewrites are not equal yet.
+-- Currently we remove tables and compare first rewrite to the second.
 roundTrip :: Block -> Bool
-roundTrip b = d'' == d'''
+roundTrip b = d' == d''
   where d = walk makeRoundTrip $ Pandoc nullMeta [b]
         d' = rewrite d
         d'' = rewrite d'
-        d''' = rewrite d''
         rewrite = amuse . T.pack . (++ "\n") . T.unpack .
                   purely (writeMuse def { writerExtensions = extensionsFromList [Ext_amuse]
                                           , writerWrapText = WrapPreserve
@@ -165,14 +167,19 @@ tests =
 
       , "Code tag" =: "<code>foo(bar)</code>" =?> para (code "foo(bar)")
 
+      , "Math tag" =: "<math>\\sum_{i=0}^n i^2</math>" =?> para (math "\\sum_{i=0}^n i^2")
+
       , "Verbatim tag" =: "*<verbatim>*</verbatim>*" =?> para (emph "*")
 
       , "Verbatim inside code" =: "<code><verbatim>foo</verbatim></code>" =?> para (code "<verbatim>foo</verbatim>")
 
       , "Verbatim tag after text" =: "Foo <verbatim>bar</verbatim>" =?> para "Foo bar"
 
+      , "Class tag" =: "<class name=\"foo\">bar</class>" =?> para (spanWith ("", ["foo"], []) "bar")
+      , "Class tag without name" =: "<class>foobar</class>" =?> para (spanWith ("", [], []) "foobar")
+
       -- <em> tag should match with the last </em> tag, not verbatim one
-      , "Nested \"</em>\" inside em tag" =: "<em>foo<verbatim></em></verbatim>bar</em>" =?> para (emph ("foo</em>bar"))
+      , "Nested \"</em>\" inside em tag" =: "<em>foo<verbatim></em></verbatim>bar</em>" =?> para (emph "foo</em>bar")
 
       , testGroup "Links"
         [ "Link without description" =:
@@ -181,6 +188,9 @@ tests =
         , "Link with description" =:
           "[[https://amusewiki.org/][A Muse Wiki]]" =?>
           para (link "https://amusewiki.org/" "" (text "A Muse Wiki"))
+        , "Link with empty description" =:
+          "[[https://amusewiki.org/][]]" =?>
+          para (link "https://amusewiki.org/" "" (text ""))
         , "Image" =:
           "[[image.jpg]]" =?>
           para (image "image.jpg" "" mempty)
@@ -199,21 +209,25 @@ tests =
         -- This test also makes sure '=' without whitespace is not treated as code markup
         , "No implicit links" =: "http://example.org/index.php?action=view&id=1"
                =?> para "http://example.org/index.php?action=view&id=1"
+        , "Link with empty URL" =: "[[][empty URL]]" =?> para (link "" "" (text "empty URL"))
+        , "No footnotes inside links" =:
+          "[[https://amusewiki.org/][foo[1]]" =?>
+          para (link "https://amusewiki.org/" "" (text "foo[1"))
         ]
 
       , testGroup "Literal"
         [ test emacsMuse "Inline literal"
           ("Foo<literal style=\"html\">lit</literal>bar" =?>
           para (text "Foo" <> rawInline "html" "lit" <> text "bar"))
-        , "No literal in Text::Amuse" =:
-          "Foo<literal style=\"html\">lit</literal>bar" =?>
-          para "Foo<literal style=\"html\">lit</literal>bar"
+        , test emacsMuse "Single inline literal in paragraph"
+          ("<literal style=\"html\">lit</literal>" =?>
+          para (rawInline "html" "lit"))
         ]
       ]
 
-  , testGroup "Blocks"
-      [ testProperty "Round trip" roundTrip,
-        "Block elements end paragraphs" =:
+  , testGroup "Blocks" $
+      [ testProperty "Round trip" roundTrip
+      , "Block elements end paragraphs" =:
         T.unlines [ "First paragraph"
                   , "----"
                   , "Second paragraph"
@@ -271,6 +285,23 @@ tests =
                       ] =?>
             divWith ("foo", [], []) (para "Foo bar")
           ]
+        , "Biblio" =:
+          T.unlines [ "<biblio>"
+                    , ""
+                    , "Author, *Title*, description"
+                    , ""
+                    , "Another author, *Another title*, another description"
+                    , ""
+                    , "</biblio>"
+                    ] =?>
+          divWith ("", ["biblio"], []) (para (text "Author, " <> emph "Title" <> ", description") <>
+                                        para (text "Another author, " <> emph "Another title" <> text ", another description"))
+        , "Play" =:
+          T.unlines [ "<play>"
+                    , "Foo bar"
+                    , "</play>"
+                    ] =?>
+          divWith ("", ["play"], []) (para "Foo bar")
         , "Verse" =:
           T.unlines [ "> This is"
                     , "> First stanza"
@@ -297,6 +328,7 @@ tests =
                     ]
         ]
       , "Verse in list" =: " - > foo" =?> bulletList [ lineBlock [ "foo" ] ]
+      , "Verse line starting with emphasis" =: "> *foo* bar" =?> lineBlock [ emph "foo" <> text " bar" ]
       , "Multiline verse in list" =:
         T.unlines [ " - > foo"
                   , "   > bar"
@@ -328,6 +360,12 @@ tests =
                   , "</quote>"
                   ] =?>
         blockQuote (para "foo" <> blockQuote (para "bar") <> para "baz")
+      , "Indented quote inside list" =:
+        T.unlines [ " -  <quote>"
+                  , "    foo"
+                  , "    </quote>"
+                  ] =?>
+        bulletList [ blockQuote (para "foo") ]
       , "Verse tag" =:
         T.unlines [ "<verse>"
                   , ""
@@ -341,6 +379,12 @@ tests =
                   , text "\160\160One two three"
                   , ""
                   ]
+      , "Verse tag with empty line inside" =:
+        T.unlines [ "<verse>"
+                  , ""
+                  , "</verse>"
+                  ] =?>
+        lineBlock [ "" ]
       , testGroup "Example"
         [ "Braces on separate lines" =:
           T.unlines [ "{{{"
@@ -461,12 +505,6 @@ tests =
                     , "</literal>"
                     ] =?>
           rawBlock "latex" "\\newpage")
-        , "No literal blocks in Text::Amuse" =:
-          T.unlines [ "<literal style=\"latex\">"
-                    , "\\newpage"
-                    , "</literal>"
-                    ] =?>
-          para "<literal style=\"latex\">\n\\newpage\n</literal>"
         ]
       , "Center" =:
         T.unlines [ "<center>"
@@ -487,6 +525,7 @@ tests =
         , "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")
+        , "Not a comment (semicolon not in the first column)" =: " - ; foo" =?> bulletList [para "; foo"]
         ]
       , testGroup "Headers"
         [ "Part" =:
@@ -518,23 +557,38 @@ tests =
                     ] =?>
           blockQuote (para "* Hi")
         , "Headers consume anchors" =:
-          T.unlines [ "** Foo"
+          T.unlines [ "; A comment to make sure anchor is not parsed as a directive"
                     , "#bar"
+                    , "** Foo"
                     ] =?>
           headerWith ("bar",[],[]) 2 "Foo"
         , "Headers don't consume anchors separated with a blankline" =:
-          T.unlines [ "** Foo"
-                    , ""
+          T.unlines [ "; A comment to make sure anchor is not parsed as a directive"
                     , "#bar"
+                    , ""
+                    , "** Foo"
                     ] =?>
-          header 2 "Foo" <>
-          para (spanWith ("bar", [], []) mempty)
+          para (spanWith ("bar", [], []) mempty) <>
+          header 2 "Foo"
+        , "Headers terminate paragraph" =:
+          T.unlines [ "foo"
+                    , "* bar"
+                    ] =?>
+          para "foo" <> header 1 "bar"
         , "Headers terminate lists" =:
           T.unlines [ " - foo"
                     , "* bar"
                     ] =?>
           bulletList [ para "foo" ] <>
           header 1 "bar"
+        , test emacsMuse "Paragraphs terminate Emacs Muse headers"
+          (T.unlines [ "* Foo"
+                    , "bar"
+                    ] =?> header 1 "Foo" <> para "bar")
+        , "Paragraphs don't terminate Text::Amuse headers" =:
+          T.unlines [ "* Foo"
+                    , "bar"
+                    ] =?> header 1 "Foo\nbar"
         ]
       , testGroup "Directives"
         [ "Title" =:
@@ -583,6 +637,11 @@ tests =
                     , "#anchor and ends here."
                     ] =?>
           para ("Paragraph starts here\n" <> spanWith ("anchor", [], []) mempty <> "and ends here.")
+        , "Anchor with \"-\"" =:
+          T.unlines [ "; A comment to make sure anchor is not parsed as a directive"
+                    , "#anchor-id Target"
+                    ] =?>
+          para (spanWith ("anchor-id", [], []) mempty <> "Target")
         ]
       , testGroup "Footnotes"
         [ "Simple footnote" =:
@@ -600,6 +659,15 @@ tests =
                     ] =?>
           para (text "Start recursion here" <>
                 note (para "Recursion continues here[1]"))
+        , "Nested footnotes" =:
+          T.unlines [ "Footnote: [1]"
+                    , ""
+                    , "[1] Nested: [2]"
+                    , ""
+                    , "[2] No recursion: [1]"
+                    ] =?>
+          para (text "Footnote: " <>
+                note (para (text "Nested: " <> note (para $ text "No recursion: [1]"))))
         , "No zero footnotes" =:
           T.unlines [ "Here is a footnote[0]."
                     , ""
@@ -632,6 +700,16 @@ tests =
                   text " footnotes" <>
                   note (para "Second footnote")) <>
             para (text "Not a note")
+
+          -- Verse requires precise indentation, so it is good to test indentation requirements
+          , "Note continuation with verse" =:
+            T.unlines [ "Foo[1]"
+                      , ""
+                      , "[1] Bar"
+                      , ""
+                      , "    > Baz"
+                      ] =?>
+            para ("Foo" <> note (para "Bar" <> lineBlock ["Baz"]))
           , test emacsMuse "Emacs multiparagraph footnotes"
             (T.unlines
               [ "First footnote reference[1] and second footnote reference[2]."
@@ -1073,6 +1151,9 @@ tests =
         definitionList [ ("Bar", [ para "baz" ]) ]
       , "One-line definition list" =: " foo :: bar" =?>
         definitionList [ ("foo", [ para "bar" ]) ]
+      , "Definition list term may include single colon" =:
+        " foo:bar :: baz" =?>
+        definitionList [ ("foo:bar", [ para "baz" ]) ]
       , "Definition list term with emphasis" =: " *Foo* :: bar\n" =?>
         definitionList [ (emph "Foo", [ para "bar" ]) ]
       , "Definition list term with :: inside code" =: " foo <code> :: </code> :: bar <code> :: </code> baz\n" =?>
@@ -1086,6 +1167,24 @@ tests =
         definitionList [ ("First term", [ para "Definition of first term\nand its continuation." ])
                        , ("Second term", [ para "Definition of second term." ])
                        ]
+      , "Definition list with verse" =:
+        T.unlines
+          [ " First term :: Definition of first term"
+          , "  > First verse"
+          , "  > Second line of first verse"
+          , ""
+          , "               > Second verse"
+          , "               > Second line of second verse"
+          ] =?>
+        definitionList [ ("First term", [ para "Definition of first term" <>
+                                          lineBlock [ text "First verse"
+                                                    , text "Second line of first verse"
+                                                    ] <>
+                                          lineBlock [ text "Second verse"
+                                                    , text "Second line of second verse"
+                                                    ]
+                                        ])
+                       ]
       , test emacsMuse "Multi-line definition lists from Emacs Muse manual"
         (T.unlines
           [ "Term1 ::"
@@ -1191,5 +1290,52 @@ tests =
                                                          , para "Second"
                                                          , para "Third"
                                                          ])
+      -- Regression test for a bug caught by round-trip test
+      , "Do not consume whitespace while looking for end tag" =:
+        T.unlines
+          [ "<quote>"
+          , " - <quote>"
+          , "   foo"
+          , "   </quote>"
+          , " bar" -- Do not consume whitespace while looking for arbitrarily indented </quote>
+          , "</quote>"
+          ] =?>
+        blockQuote (bulletList [ blockQuote $ para "foo" ] <> para "bar")
+
+      , "Unclosed quote tag" =:
+        T.unlines
+          [ "<quote>"
+          , "<verse>"
+          , "</quote>"
+          , "</verse>"
+          ] =?>
+        para "<quote>" <> lineBlock [ "</quote>" ]
+
+      , "Unclosed quote tag inside list" =:
+        T.unlines
+          [ " - <quote>"
+          , "   <verse>"
+          , "   </quote>"
+          , "   </verse>"
+          ] =?>
+        bulletList [ para "<quote>" <> lineBlock [ "</quote>" ] ]
+
+      -- Allowing indented closing tags is dangerous,
+      -- as they may terminate lists
+      , "No indented closing tags" =:
+        T.unlines
+          [ "<quote>"
+          , ""
+          , " - Foo"
+          , ""
+          , "   </quote>"
+          , ""
+          , "   bar"
+          , ""
+          , "   <verse>"
+          , "   </quote>"
+          , "   </verse>"
+          ] =?>
+        para "<quote>" <> bulletList [ para "Foo" <> para "</quote>" <> para "bar" <> lineBlock [ "</quote>" ] ]
       ]
   ]
diff --git a/test/Tests/Readers/Muse.hs.orig b/test/Tests/Readers/Muse.hs.orig
new file mode 100644
index 000000000..89dbbc345
--- /dev/null
+++ b/test/Tests/Readers/Muse.hs.orig
@@ -0,0 +1,1262 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.Muse (tests) where
+
+import Data.List (intersperse)
+import Data.Text (Text)
+import qualified Data.Text as T
+import Test.Tasty
+import Test.Tasty.QuickCheck
+import Tests.Helpers
+import Text.Pandoc
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder
+import Text.Pandoc.Shared (underlineSpan)
+import Text.Pandoc.Walk (walk)
+
+amuse :: Text -> Pandoc
+amuse = purely $ readMuse def { readerExtensions = extensionsFromList [Ext_amuse]}
+
+emacsMuse :: Text -> Pandoc
+emacsMuse = purely $ readMuse def { readerExtensions = emptyExtensions }
+
+infix 4 =:
+(=:) :: ToString c
+     => String -> (Text, c) -> TestTree
+(=:) = test amuse
+
+spcSep :: [Inlines] -> Inlines
+spcSep = mconcat . intersperse space
+
+-- Tables don't round-trip yet
+--
+makeRoundTrip :: Block -> Block
+makeRoundTrip Table{} = Para [Str "table was here"]
+makeRoundTrip (OrderedList (start, LowerAlpha, _) items) = OrderedList (start, Decimal, Period) items
+makeRoundTrip (OrderedList (start, UpperAlpha, _) items) = OrderedList (start, Decimal, Period) items
+makeRoundTrip x = x
+
+-- Demand that any AST produced by Muse reader and written by Muse writer can be read back exactly the same way.
+-- Currently we remove tables and compare first rewrite to the second.
+roundTrip :: Block -> Bool
+roundTrip b = d' == d''
+  where d = walk makeRoundTrip $ Pandoc nullMeta [b]
+        d' = rewrite d
+        d'' = rewrite d'
+        rewrite = amuse . T.pack . (++ "\n") . T.unpack .
+                  purely (writeMuse def { writerExtensions = extensionsFromList [Ext_amuse]
+                                          , writerWrapText = WrapPreserve
+                                          })
+
+tests :: [TestTree]
+tests =
+  [ testGroup "Inlines"
+      [ "Plain String" =:
+          "Hello, World" =?>
+          para "Hello, World"
+
+      , "Muse is not XML" =: "&lt;" =?> para "&lt;"
+
+      , "Emphasis" =:
+        "*Foo bar*" =?>
+        para (emph . spcSep $ ["Foo", "bar"])
+
+      , "Comma after closing *" =:
+        "Foo *bar*, baz" =?>
+        para ("Foo " <> emph "bar" <> ", baz")
+
+      , "Letter after closing *" =:
+        "Foo *bar*x baz" =?>
+        para "Foo *bar*x baz"
+
+      , "Letter before opening *" =:
+        "Foo x*bar* baz" =?>
+        para "Foo x*bar* baz"
+
+      , "Emphasis tag" =:
+        "<em>Foo bar</em>" =?>
+        para (emph . spcSep $ ["Foo", "bar"])
+
+      , "Strong" =:
+          "**Cider**" =?>
+          para (strong "Cider")
+
+      , "Strong tag" =: "<strong>Strong</strong>" =?> para (strong "Strong")
+
+      , "Strong Emphasis" =:
+          "***strength***" =?>
+          para (strong . emph $ "strength")
+
+      , test emacsMuse "Underline"
+        ("_Underline_" =?> para (underlineSpan "Underline"))
+
+      , "Superscript tag" =: "<sup>Superscript</sup>" =?> para (superscript "Superscript")
+
+      , "Subscript tag" =: "<sub>Subscript</sub>" =?> para (subscript "Subscript")
+
+      , "Strikeout tag" =: "<del>Strikeout</del>" =?> para (strikeout "Strikeout")
+
+      , "Opening inline tags" =: "foo <em> bar <strong>baz" =?> para "foo <em> bar <strong>baz"
+
+      , "Closing inline tags" =: "foo </em> bar </strong>baz" =?> para "foo </em> bar </strong>baz"
+
+      , "Tag soup" =: "foo <em> bar </strong>baz" =?> para "foo <em> bar </strong>baz"
+
+      -- Both inline tags must be within the same paragraph
+      , "No multiparagraph inline tags" =:
+        T.unlines [ "First line"
+                  , "<em>Second line"
+                  , ""
+                  , "Fourth line</em>"
+                  ] =?>
+        para "First line\n<em>Second line" <>
+        para "Fourth line</em>"
+
+      , "Linebreak" =: "Line <br>  break" =?> para ("Line" <> linebreak <> "break")
+
+      , "Trailing whitespace inside paragraph" =:
+        T.unlines [ "First line " -- trailing whitespace here
+                  , "second line"
+                  ]
+        =?> para "First line\nsecond line"
+
+      , "Non-breaking space" =: "Foo~~bar" =?> para "Foo\160bar"
+      , "Single ~" =: "Foo~bar" =?> para "Foo~bar"
+
+      , testGroup "Code markup"
+        [ "Code" =: "=foo(bar)=" =?> para (code "foo(bar)")
+
+        , "Not code" =: "a=b= =c=d" =?> para (text "a=b= =c=d")
+
+        -- Emacs Muse 3.20 parses this as code, we follow Amusewiki
+        , "Not code if closing = is detached" =: "=this is not a code =" =?> para "=this is not a code ="
+
+        , "Not code if opening = is detached" =: "= this is not a code=" =?> para "= this is not a code="
+
+        , "Code if followed by comma" =:
+          "Foo =bar=, baz" =?>
+          para (text "Foo " <> code "bar" <> text ", baz")
+
+        , "One character code" =: "=c=" =?> para (code "c")
+
+        , "Three = characters is not a code" =: "===" =?> para "==="
+
+        , "Multiline code markup" =:
+          "foo =bar\nbaz= end of code" =?>
+          para (text "foo " <> code "bar\nbaz" <> text " end of code")
+
+{- Emacs Muse 3.20 has a bug: it publishes
+ - <p>foo <code>bar
+ -
+ - baz</code> foo</p>
+ - which is displayed as one paragraph by browsers.
+ - We follow Amusewiki here and avoid joining paragraphs.
+ -}
+        , "No multiparagraph code" =:
+          T.unlines [ "foo =bar"
+                    , ""
+                    , "baz= foo"
+                    ] =?>
+          para "foo =bar" <>
+          para "baz= foo"
+
+        , "Code at the beginning of paragraph but not first column" =:
+          " - =foo=" =?> bulletList [ para $ code "foo" ]
+        ]
+
+      , "Code tag" =: "<code>foo(bar)</code>" =?> para (code "foo(bar)")
+
+      , "Verbatim tag" =: "*<verbatim>*</verbatim>*" =?> para (emph "*")
+
+      , "Verbatim inside code" =: "<code><verbatim>foo</verbatim></code>" =?> para (code "<verbatim>foo</verbatim>")
+
+      , "Verbatim tag after text" =: "Foo <verbatim>bar</verbatim>" =?> para "Foo bar"
+
+      , "Class tag" =: "<class name=\"foo\">bar</class>" =?> para (spanWith ("", ["foo"], []) "bar")
+      , "Class tag without name" =: "<class>foobar</class>" =?> para (spanWith ("", [], []) "foobar")
+
+      -- <em> tag should match with the last </em> tag, not verbatim one
+      , "Nested \"</em>\" inside em tag" =: "<em>foo<verbatim></em></verbatim>bar</em>" =?> para (emph "foo</em>bar")
+
+      , testGroup "Links"
+        [ "Link without description" =:
+          "[[https://amusewiki.org/]]" =?>
+          para (link "https://amusewiki.org/" "" (str "https://amusewiki.org/"))
+        , "Link with description" =:
+          "[[https://amusewiki.org/][A Muse Wiki]]" =?>
+          para (link "https://amusewiki.org/" "" (text "A Muse Wiki"))
+        , "Image" =:
+          "[[image.jpg]]" =?>
+          para (image "image.jpg" "" mempty)
+        , "Image with description" =:
+          "[[image.jpg][Image]]" =?>
+          para (image "image.jpg" "" (text "Image"))
+        , "Image link" =:
+          "[[URL:image.jpg]]" =?>
+          para (link "image.jpg" "" (str "image.jpg"))
+        , "Image link with description" =:
+          "[[URL:image.jpg][Image]]" =?>
+          para (link "image.jpg" "" (text "Image"))
+        -- Implicit links are supported in Emacs Muse, but not in Amusewiki:
+        -- https://github.com/melmothx/text-amuse/issues/18
+        --
+        -- This test also makes sure '=' without whitespace is not treated as code markup
+        , "No implicit links" =: "http://example.org/index.php?action=view&id=1"
+               =?> para "http://example.org/index.php?action=view&id=1"
+        ]
+
+      , testGroup "Literal"
+        [ test emacsMuse "Inline literal"
+          ("Foo<literal style=\"html\">lit</literal>bar" =?>
+          para (text "Foo" <> rawInline "html" "lit" <> text "bar"))
+        ]
+      ]
+
+  , testGroup "Blocks"
+      [ testProperty "Round trip" roundTrip,
+        "Block elements end paragraphs" =:
+        T.unlines [ "First paragraph"
+                  , "----"
+                  , "Second paragraph"
+                  ] =?> para (text "First paragraph") <> horizontalRule <> para (text "Second paragraph")
+      , testGroup "Horizontal rule"
+        [ "Less than 4 dashes is not a horizontal rule" =: "---" =?> para (text "---")
+        , "4 dashes is a horizontal rule" =: "----" =?> horizontalRule
+        , "5 dashes is a horizontal rule" =: "-----" =?> horizontalRule
+        , "4 dashes with spaces is a horizontal rule" =: "----  " =?> horizontalRule
+        ]
+      , testGroup "Paragraphs"
+        [ "Simple paragraph" =:
+          T.unlines [ "First line"
+                    , "second line."
+                    ] =?>
+          para "First line\nsecond line."
+        , "Indented paragraph" =:
+          T.unlines [ " First line"
+                    , "second line."
+                    ] =?>
+          para "First line\nsecond line."
+        -- Emacs Muse starts a blockquote on the second line.
+        -- We copy Amusewiki behavior and require a blank line to start a blockquote.
+        , "Indentation in the middle of paragraph" =:
+           T.unlines [ "First line"
+                     , "  second line"
+                     , "third line"
+                     ] =?>
+           para "First line\nsecond line\nthird line"
+        , "Quote" =:
+          "  This is a quotation\n" =?>
+          blockQuote (para "This is a quotation")
+        , "Indentation does not indicate quote inside quote tag" =:
+          T.unlines [ "<quote>"
+                    , "  Not a nested quote"
+                    , "</quote>"
+                    ] =?>
+          blockQuote (para "Not a nested quote")
+        , "Multiline quote" =:
+          T.unlines [ "  This is a quotation"
+                    , "  with a continuation"
+                    ] =?>
+          blockQuote (para "This is a quotation\nwith a continuation")
+        , testGroup "Div"
+          [ "Div without id" =:
+            T.unlines [ "<div>"
+                      , "Foo bar"
+                      , "</div>"
+                      ] =?>
+            divWith nullAttr (para "Foo bar")
+          , "Div with id" =:
+            T.unlines [ "<div id=\"foo\">"
+                      , "Foo bar"
+                      , "</div>"
+                      ] =?>
+            divWith ("foo", [], []) (para "Foo bar")
+          ]
+        , "Verse" =:
+          T.unlines [ "> This is"
+                    , "> First stanza"
+                    , ">" -- Emacs produces verbatim ">" here, we follow Amusewiki
+                    , "> And this is"
+                    , ">   Second stanza"
+                    , ">"
+                    , ""
+                    , ">"
+                    , ""
+                    , "> Another verse"
+                    , ">    is here"
+                    ] =?>
+          lineBlock [ "This is"
+                    , "First stanza"
+                    , ""
+                    , "And this is"
+                    , "\160\160Second stanza"
+                    , ""
+                    ] <>
+          lineBlock [ "" ] <>
+          lineBlock [ "Another verse"
+                    , "\160\160\160is here"
+                    ]
+        ]
+      , "Verse in list" =: " - > foo" =?> bulletList [ lineBlock [ "foo" ] ]
+      , "Verse line starting with emphasis" =: "> *foo* bar" =?> lineBlock [ emph "foo" <> text " bar" ]
+      , "Multiline verse in list" =:
+        T.unlines [ " - > foo"
+                  , "   > bar"
+                  ] =?>
+        bulletList [ lineBlock [ "foo", "bar" ] ]
+      , "Paragraph after verse in list" =:
+        T.unlines [ " - > foo"
+                  , "   bar"
+                  ] =?>
+        bulletList [ lineBlock [ "foo" ] <> para "bar" ]
+      , "Empty quote tag" =:
+        T.unlines [ "<quote>"
+                  , "</quote>"
+                  ]
+        =?> blockQuote mempty
+      , "Quote tag" =:
+        T.unlines [ "<quote>"
+                  , "Hello, world"
+                  , "</quote>"
+                  ]
+        =?> blockQuote (para $ text "Hello, world")
+      , "Nested quote tag" =:
+        T.unlines [ "<quote>"
+                  , "foo"
+                  , "<quote>"
+                  , "bar"
+                  , "</quote>"
+                  , "baz"
+                  , "</quote>"
+                  ] =?>
+        blockQuote (para "foo" <> blockQuote (para "bar") <> para "baz")
+      , "Indented quote inside list" =:
+        T.unlines [ " -  <quote>"
+                  , "    foo"
+                  , "    </quote>"
+                  ] =?>
+        bulletList [ blockQuote (para "foo") ]
+      , "Verse tag" =:
+        T.unlines [ "<verse>"
+                  , ""
+                  , "Foo bar baz"
+                  , "  One two three"
+                  , ""
+                  , "</verse>"
+                  ] =?>
+        lineBlock [ ""
+                  , text "Foo bar baz"
+                  , text "\160\160One two three"
+                  , ""
+                  ]
+      , "Verse tag with empty line inside" =:
+        T.unlines [ "<verse>"
+                  , ""
+                  , "</verse>"
+                  ] =?>
+        lineBlock [ "" ]
+      , testGroup "Example"
+        [ "Braces on separate lines" =:
+          T.unlines [ "{{{"
+                    , "Example line"
+                    , "}}}"
+                    ] =?>
+          codeBlock "Example line"
+        , "Spaces after opening braces" =:
+          T.unlines [ "{{{  "
+                    , "Example line"
+                    , "}}}"
+                    ] =?>
+          codeBlock "Example line"
+        , "One blank line in the beginning" =:
+          T.unlines [ "{{{"
+                    , ""
+                    , "Example line"
+                    , "}}}"
+                    ] =?>
+          codeBlock "\nExample line"
+        , "One blank line in the end" =:
+          T.unlines [ "{{{"
+                    , "Example line"
+                    , ""
+                    , "}}}"
+                    ] =?>
+          codeBlock "Example line\n"
+        -- Amusewiki requires braces to be on separate line,
+        -- this is an extension.
+        , "One line" =:
+          "{{{Example line}}}" =?>
+          codeBlock "Example line"
+        ]
+      , testGroup "Example tag"
+        [ "Tags on separate lines" =:
+          T.unlines [ "<example>"
+                    , "Example line"
+                    , "</example>"
+                    ] =?>
+          codeBlock "Example line"
+        , "One line" =:
+          "<example>Example line</example>" =?>
+          codeBlock "Example line"
+        , "One blank line in the beginning" =:
+          T.unlines [ "<example>"
+                    , ""
+                    , "Example line"
+                    , "</example>"
+                    ] =?>
+          codeBlock "\nExample line"
+        , "One blank line in the end" =:
+          T.unlines [ "<example>"
+                    , "Example line"
+                    , ""
+                    , "</example>"
+                    ] =?>
+          codeBlock "Example line\n"
+        , "Example inside list" =:
+          T.unlines [ " - <example>"
+                    , "   foo"
+                    , "   </example>"
+                    ] =?>
+          bulletList [ codeBlock "foo" ]
+        , "Empty example inside list" =:
+          T.unlines [ " - <example>"
+                    , "   </example>"
+                    ] =?>
+          bulletList [ codeBlock "" ]
+        , "Example inside list with empty lines" =:
+          T.unlines [ " - <example>"
+                    , "   foo"
+                    , "   </example>"
+                    , ""
+                    , "   bar"
+                    , ""
+                    , "   <example>"
+                    , "   baz"
+                    , "   </example>"
+                    ] =?>
+          bulletList [ codeBlock "foo" <> para "bar" <> codeBlock "baz" ]
+        , "Indented example inside list" =:
+          T.unlines [ " -  <example>"
+                    , "    foo"
+                    , "    </example>"
+                    ] =?>
+          bulletList [ codeBlock "foo" ]
+        , "Example inside definition list" =:
+          T.unlines [ " foo :: <example>"
+                    , "        bar"
+                    , "        </example>"
+                    ] =?>
+          definitionList [ ("foo", [codeBlock "bar"]) ]
+        , "Example inside list definition with empty lines" =:
+          T.unlines [ " term :: <example>"
+                    , "         foo"
+                    , "         </example>"
+                    , ""
+                    , "         bar"
+                    , ""
+                    , "         <example>"
+                    , "         baz"
+                    , "         </example>"
+                    ] =?>
+          definitionList [ ("term", [codeBlock "foo" <> para "bar" <> codeBlock "baz"]) ]
+        , "Example inside note" =:
+          T.unlines [ "Foo[1]"
+                    , ""
+                    , "[1] <example>"
+                    , "    bar"
+                    , "    </example>"
+                    ] =?>
+          para ("Foo" <> note (codeBlock "bar"))
+        ]
+      , testGroup "Literal blocks"
+        [ test emacsMuse "Literal block"
+          (T.unlines [ "<literal style=\"latex\">"
+                    , "\\newpage"
+                    , "</literal>"
+                    ] =?>
+          rawBlock "latex" "\\newpage")
+        ]
+      , "Center" =:
+        T.unlines [ "<center>"
+                  , "Hello, world"
+                  , "</center>"
+                  ] =?>
+        para (text "Hello, world")
+      , "Right" =:
+        T.unlines [ "<right>"
+                  , "Hello, world"
+                  , "</right>"
+                  ] =?>
+        para (text "Hello, world")
+      , 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")
+        ]
+      , testGroup "Headers"
+        [ "Part" =:
+          "* First level" =?>
+          header 1 "First level"
+        , "Chapter" =:
+          "** Second level" =?>
+          header 2 "Second level"
+        , "Section" =:
+          "*** Third level" =?>
+          header 3 "Third level"
+        , "Subsection" =:
+          "**** Fourth level" =?>
+          header 4 "Fourth level"
+        , "Subsubsection" =:
+          "***** Fifth level" =?>
+          header 5 "Fifth level"
+        , "Whitespace is required after *" =: "**Not a header" =?> para "**Not a header"
+        , "No headers in footnotes" =:
+          T.unlines [ "Foo[1]"
+                    , "[1] * Bar"
+                    ] =?>
+          para (text "Foo" <>
+                note (para "* Bar"))
+        , "No headers in quotes" =:
+          T.unlines [ "<quote>"
+                    , "* Hi"
+                    , "</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)
+        , "Headers terminate lists" =:
+          T.unlines [ " - foo"
+                    , "* bar"
+                    ] =?>
+          bulletList [ para "foo" ] <>
+          header 1 "bar"
+        ]
+      , testGroup "Directives"
+        [ "Title" =:
+          "#title Document title" =?>
+          let titleInline = toList "Document title"
+              meta = setMeta "title" (MetaInlines titleInline) nullMeta
+          in Pandoc meta mempty
+        -- Emacs Muse documentation says that "You can use any combination
+        -- of uppercase and lowercase letters for directives",
+        -- but also allows '-', which is not documented, but used for disable-tables.
+        , test emacsMuse "Disable tables"
+          ("#disable-tables t" =?>
+          Pandoc (setMeta "disable-tables" (MetaInlines $ toList "t") nullMeta) mempty)
+        , "Multiple directives" =:
+          T.unlines [ "#title Document title"
+                    , "#subtitle Document subtitle"
+                    ] =?>
+          Pandoc (setMeta "title" (MetaInlines $ toList "Document title") $
+                  setMeta "subtitle" (MetaInlines $ toList "Document subtitle") nullMeta) mempty
+        , "Multiline directive" =:
+          T.unlines [ "#title Document title"
+                    , "#notes First line"
+                    , "and second line"
+                    , "#author Name"
+                    ] =?>
+          Pandoc (setMeta "title" (MetaInlines $ toList "Document title") $
+                  setMeta "notes" (MetaInlines $ toList "First line\nand second line") $
+                  setMeta "author" (MetaInlines $ toList "Name") nullMeta) mempty
+        ]
+      , testGroup "Anchors"
+        [ "Anchor" =:
+          T.unlines [ "; A comment to make sure anchor is not parsed as a directive"
+                    , "#anchor Target"
+                    ] =?>
+          para (spanWith ("anchor", [], []) mempty <> "Target")
+        , "Anchor cannot start with a number" =:
+          T.unlines [ "; A comment to make sure anchor is not parsed as a directive"
+                    , "#0notanchor Target"
+                    ] =?>
+          para "#0notanchor Target"
+        , "Not anchor if starts with a space" =:
+          " #notanchor Target" =?>
+          para "#notanchor Target"
+        , "Anchor inside a paragraph" =:
+          T.unlines [ "Paragraph starts here"
+                    , "#anchor and ends here."
+                    ] =?>
+          para ("Paragraph starts here\n" <> spanWith ("anchor", [], []) mempty <> "and ends here.")
+        ]
+      , testGroup "Footnotes"
+        [ "Simple footnote" =:
+          T.unlines [ "Here is a footnote[1]."
+                    , ""
+                    , "[1] Footnote contents"
+                    ] =?>
+          para (text "Here is a footnote" <>
+                note (para "Footnote contents") <>
+                str ".")
+        , "Recursive footnote" =:
+          T.unlines [ "Start recursion here[1]"
+                    , ""
+                    , "[1] Recursion continues here[1]"
+                    ] =?>
+          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]"
+                      , ""
+                      , "[1] First footnote paragraph"
+                      , ""
+                      , "    Second footnote paragraph"
+                      , "with continuation"
+                      , ""
+                      , "Not a note"
+                      , "[2] Second footnote"
+                      ] =?>
+            para (text "Multiparagraph" <>
+                  note (para "First footnote paragraph" <>
+                        para "Second footnote paragraph\nwith continuation") <>
+                  text " footnotes" <>
+                  note (para "Second footnote")) <>
+            para (text "Not a note")
+
+          -- Verse requires precise indentation, so it is good to test indentation requirements
+          , "Note continuation with verse" =:
+            T.unlines [ "Foo[1]"
+                      , ""
+                      , "[1] Bar"
+                      , ""
+                      , "    > Baz"
+                      ] =?>
+            para ("Foo" <> note (para "Bar" <> lineBlock ["Baz"]))
+          , test emacsMuse "Emacs multiparagraph footnotes"
+            (T.unlines
+              [ "First footnote reference[1] and second footnote reference[2]."
+              , ""
+              , "[1] First footnote paragraph"
+              , ""
+              , "Second footnote"
+              , "paragraph"
+              , ""
+              , "[2] Third footnote paragraph"
+              , ""
+              , "Fourth footnote paragraph"
+              ] =?>
+            para (text "First footnote reference" <>
+                  note (para "First footnote paragraph" <>
+                        para "Second footnote\nparagraph") <>
+                  text " and second footnote reference" <>
+                  note (para "Third footnote paragraph" <>
+                        para "Fourth footnote paragraph") <>
+                  text "."))
+          ]
+        ]
+      ]
+    , testGroup "Tables"
+        [ "Two cell table" =:
+          "One | Two" =?>
+          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]
+                       []
+                       [[plain "One", plain "Two"]]
+        , "Table with multiple words" =:
+          "One two | three four" =?>
+          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]
+                       []
+                       [[plain "One two", plain "three four"]]
+        , "Not a table" =:
+          "One| Two" =?>
+          para (text "One| Two")
+        , "Not a table again" =:
+          "One |Two" =?>
+          para (text "One |Two")
+        , "Two line table" =:
+          T.unlines
+            [ "One |  Two"
+            , "Three  | Four"
+            ] =?>
+          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]
+                       []
+                       [[plain "One", plain "Two"],
+                       [plain "Three", plain "Four"]]
+        , "Table with one header" =:
+          T.unlines
+            [ "First || Second"
+            , "Third | Fourth"
+            ] =?>
+          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]
+            [plain "First", plain "Second"]
+            [[plain "Third", plain "Fourth"]]
+        , "Table with two headers" =:
+          T.unlines
+            [ "First || header"
+            , "Second || header"
+            , "Foo | bar"
+            ] =?>
+          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]
+            [plain "First", plain "header"]
+            [[plain "Second", plain "header"],
+             [plain "Foo", plain "bar"]]
+        , "Header and footer reordering" =:
+          T.unlines
+            [ "Foo ||| bar"
+            , "Baz || foo"
+            , "Bar | baz"
+            ] =?>
+          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]
+            [plain "Baz", plain "foo"]
+            [[plain "Bar", plain "baz"],
+             [plain "Foo", plain "bar"]]
+        , "Table with caption" =:
+          T.unlines
+            [ "Foo || bar || baz"
+            , "First | row | here"
+            , "Second | row | there"
+            , "|+ Table caption +|"
+            ] =?>
+          table (text "Table caption") (replicate 3 (AlignDefault, 0.0))
+            [plain "Foo", plain "bar", plain "baz"]
+            [[plain "First", plain "row", plain "here"],
+             [plain "Second", plain "row", plain "there"]]
+        , "Caption without table" =:
+          "|+ Foo bar baz +|" =?>
+          table (text "Foo bar baz") [] [] []
+        , "Table indented with space" =:
+          T.unlines
+            [ " Foo | bar"
+            , " Baz | foo"
+            , " Bar | baz"
+            ] =?>
+          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]
+            []
+            [[plain "Foo", plain "bar"],
+             [plain "Baz", plain "foo"],
+             [plain "Bar", plain "baz"]]
+        , "Empty cells" =:
+          T.unlines
+            [ " | Foo"
+            , " |"
+            , " bar |"
+            , " || baz"
+            ] =?>
+          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]
+            [plain "", plain "baz"]
+            [[plain "", plain "Foo"],
+             [plain "", plain ""],
+             [plain "bar", plain ""]]
+        ]
+    , testGroup "Lists"
+      [ "Bullet list" =:
+        T.unlines
+           [ " - Item1"
+           , ""
+           , " - Item2"
+           ] =?>
+        bulletList [ para "Item1"
+                   , para "Item2"
+                   ]
+      , "Ordered list" =:
+        T.unlines
+          [ " 1. Item1"
+          , ""
+          , " 2. Item2"
+          ] =?>
+        orderedListWith (1, Decimal, Period) [ para "Item1"
+                                             , para "Item2"
+                                             ]
+      , "Ordered list with implicit numbers" =:
+        T.unlines
+          [ " 1. Item1"
+          , ""
+          , " 1. Item2"
+          , ""
+          , " 1. Item3"
+          ] =?>
+        orderedListWith (1, Decimal, Period) [ para "Item1"
+                                             , para "Item2"
+                                             , para "Item3"
+                                             ]
+      , "Ordered list with roman numerals" =:
+        T.unlines
+          [ " i. First"
+          , " ii. Second"
+          , " iii. Third"
+          , " iv. Fourth"
+          ] =?>
+        orderedListWith (1, LowerRoman, Period) [ para "First"
+                                                , para "Second"
+                                                , para "Third"
+                                                , para "Fourth"
+                                                ]
+      , "Bullet list with empty items" =:
+        T.unlines
+          [ " -"
+          , ""
+          , " - Item2"
+          ] =?>
+        bulletList [ mempty
+                   , para "Item2"
+                   ]
+      , "Ordered list with empty items" =:
+        T.unlines
+          [ " 1."
+          , ""
+          , " 2."
+          , ""
+          , " 3. Item3"
+          ] =?>
+        orderedListWith (1, Decimal, Period) [ mempty
+                                             , mempty
+                                             , para "Item3"
+                                             ]
+      , "Bullet list with last item empty" =:
+        T.unlines
+          [ " -"
+          , ""
+          , "foo"
+          ] =?>
+        bulletList [ mempty ] <>
+        para "foo"
+      , testGroup "Nested lists"
+        [ "Nested bullet list" =:
+          T.unlines [ " - Item1"
+                    , "   - Item2"
+                    , "     - Item3"
+                    , "   - Item4"
+                    , "     - Item5"
+                    , " - Item6"
+                    ] =?>
+          bulletList [ para "Item1" <>
+                       bulletList [ para "Item2" <>
+                                    bulletList [ para "Item3" ]
+                                  , para "Item4" <>
+                                    bulletList [ para "Item5" ]
+                                  ]
+                     , para "Item6"
+                     ]
+        , "Nested ordered list" =:
+          T.unlines [ " 1. Item1"
+                    , "    1. Item2"
+                    , "       1. Item3"
+                    , "    2. Item4"
+                    , "       1. Item5"
+                    , " 2. Item6"
+                    ] =?>
+          orderedListWith (1, Decimal, Period) [ para "Item1" <>
+                                                 orderedListWith (1, Decimal, Period) [ para "Item2" <>
+                                                                                        orderedListWith (1, Decimal, Period) [ para "Item3" ]
+                                                                                      , para "Item4" <>
+                                                                                        orderedListWith (1, Decimal, Period) [ para "Item5" ]
+                                                                                      ]
+                                               , para "Item6"
+                                               ]
+        , "Mixed nested list" =:
+          T.unlines
+            [ " - Item1"
+            , "   - Item2"
+            , "   - Item3"
+            , " - Item4"
+            , "   1. Nested"
+            , "   2. Ordered"
+            , "   3. List"
+            ] =?>
+          bulletList [ mconcat [ para "Item1"
+                               , bulletList [ para "Item2"
+                                            , para "Item3"
+                                            ]
+                               ]
+                     , mconcat [ para "Item4"
+                               , orderedListWith (1, Decimal, Period) [ para "Nested"
+                                                                      , para "Ordered"
+                                                                      , para "List"
+                                                                      ]
+                               ]
+                     ]
+        , "Text::Amuse includes only one space in list marker" =:
+          T.unlines
+            [ " -    First item"
+            , "   - Nested item"
+            ] =?>
+          bulletList [ para "First item" <> bulletList [ para "Nested item"]]
+        ]
+      , "List continuation" =:
+         T.unlines
+           [ " - a"
+           , ""
+           , "   b"
+           , ""
+           , "   c"
+           ] =?>
+         bulletList [ mconcat [ para "a"
+                              , para "b"
+                              , para "c"
+                              ]
+                    ]
+      , "List continuation afeter nested list" =:
+         T.unlines
+           [ " - - foo"
+           , ""
+           , "   bar"
+           ] =?>
+         bulletList [ bulletList [ para "foo" ] <>
+                      para "bar"
+                    ]
+      -- Emacs Muse allows to separate lists with two or more blank lines.
+      -- Text::Amuse (Amusewiki engine) always creates a single list as of version 0.82.
+      -- pandoc follows Emacs Muse behavior
+      , testGroup "Blank lines"
+        [ "Blank lines between list items are not required" =:
+          T.unlines
+            [ " - Foo"
+            , " - Bar"
+            ] =?>
+          bulletList [ para "Foo"
+                     , para "Bar"
+                     ]
+        , "One blank line between list items is allowed" =:
+          T.unlines
+            [ " - Foo"
+            , ""
+            , " - Bar"
+            ] =?>
+          bulletList [ para "Foo"
+                     , para "Bar"
+                     ]
+        , "Two blank lines separate lists" =:
+          T.unlines
+            [ " - Foo"
+            , ""
+            , ""
+            , " - Bar"
+            ] =?>
+          bulletList [ para "Foo" ] <> bulletList [ para "Bar" ]
+        , "No blank line after multiline first item" =:
+          T.unlines
+            [ " - Foo"
+            , "   bar"
+            , " - Baz"
+            ] =?>
+          bulletList [ para "Foo\nbar"
+                     , para "Baz"
+                     ]
+        , "One blank line after multiline first item" =:
+          T.unlines
+            [ " - Foo"
+            , "   bar"
+            , ""
+            , " - Baz"
+            ] =?>
+          bulletList [ para "Foo\nbar"
+                     , para "Baz"
+                     ]
+        , "Two blank lines after multiline first item" =:
+          T.unlines
+            [ " - Foo"
+            , "   bar"
+            , ""
+            , ""
+            , " - Baz"
+            ] =?>
+          bulletList [ para "Foo\nbar" ] <> bulletList [ para "Baz" ]
+        , "No blank line after list continuation" =:
+          T.unlines
+            [ " - Foo"
+            , ""
+            , "   bar"
+            , " - Baz"
+            ] =?>
+          bulletList [ para "Foo" <> para "bar"
+                     , para "Baz"
+                     ]
+        , "One blank line after list continuation" =:
+          T.unlines
+            [ " - Foo"
+            , ""
+            , "   bar"
+            , ""
+            , " - Baz"
+            ] =?>
+          bulletList [ para "Foo" <> para "bar"
+                     , para "Baz"
+                     ]
+        , "Two blank lines after list continuation" =:
+          T.unlines
+            [ " - Foo"
+            , ""
+            , "   bar"
+            , ""
+            , ""
+            , " - Baz"
+            ] =?>
+          bulletList [ para "Foo" <> para "bar" ] <> bulletList [ para "Baz" ]
+        , "No blank line after blockquote" =:
+          T.unlines
+            [ " - <quote>"
+            , "   foo"
+            , "   </quote>"
+            , " - bar"
+            ] =?>
+          bulletList [ blockQuote $ para "foo", para "bar" ]
+        , "One blank line after blockquote" =:
+          T.unlines
+            [ " - <quote>"
+            , "   foo"
+            , "   </quote>"
+            , ""
+            , " - bar"
+            ] =?>
+          bulletList [ blockQuote $ para "foo", para "bar" ]
+        , "Two blank lines after blockquote" =:
+          T.unlines
+            [ " - <quote>"
+            , "   foo"
+            , "   </quote>"
+            , ""
+            , ""
+            , " - bar"
+            ] =?>
+          bulletList [ blockQuote $ para "foo" ] <> bulletList [ para "bar" ]
+        , "No blank line after verse" =:
+          T.unlines
+            [ " - > foo"
+            , " - bar"
+            ] =?>
+          bulletList [ lineBlock [ "foo" ], para "bar" ]
+        , "One blank line after verse" =:
+          T.unlines
+            [ " - > foo"
+            , ""
+            , " - bar"
+            ] =?>
+          bulletList [ lineBlock [ "foo" ], para "bar" ]
+        , "Two blank lines after verse" =:
+          T.unlines
+            [ " - > foo"
+            , ""
+            , ""
+            , " - bar"
+            ] =?>
+          bulletList [ lineBlock [ "foo" ] ] <> bulletList [ para "bar" ]
+        ]
+      -- Test that definition list requires a leading space.
+      -- Emacs Muse does not require a space, we follow Amusewiki here.
+      , "Not a definition list" =:
+        T.unlines
+          [ "First :: second"
+          , "Foo :: bar"
+          ] =?>
+        para "First :: second\nFoo :: bar"
+      , test emacsMuse "Emacs Muse definition list"
+        (T.unlines
+          [ "First :: second"
+          , "Foo :: bar"
+          ] =?>
+        definitionList [ ("First", [ para "second" ])
+                       , ("Foo", [ para "bar" ])
+                       ])
+      , "Definition list" =:
+        T.unlines
+          [ " First :: second"
+          , " Foo :: bar"
+          ] =?>
+        definitionList [ ("First", [ para "second" ])
+                       , ("Foo", [ para "bar" ])
+                       ]
+      , "Definition list term cannot include newline" =:
+        T.unlines
+          [ " Foo" -- "Foo" is not a part of the definition list term
+          , " Bar :: baz"
+          ] =?>
+        para "Foo" <>
+        definitionList [ ("Bar", [ para "baz" ]) ]
+      , "One-line definition list" =: " foo :: bar" =?>
+        definitionList [ ("foo", [ para "bar" ]) ]
+      , "Definition list term may include single colon" =:
+        " foo:bar :: baz" =?>
+        definitionList [ ("foo:bar", [ para "baz" ]) ]
+      , "Definition list term with emphasis" =: " *Foo* :: bar\n" =?>
+        definitionList [ (emph "Foo", [ para "bar" ]) ]
+      , "Definition list term with :: inside code" =: " foo <code> :: </code> :: bar <code> :: </code> baz\n" =?>
+        definitionList [ ("foo " <> code " :: ", [ para $ "bar " <> code " :: " <> " baz" ]) ]
+      , "Multi-line definition lists" =:
+        T.unlines
+          [ " First term :: Definition of first term"
+          , "and its continuation."
+          , " Second term :: Definition of second term."
+          ] =?>
+        definitionList [ ("First term", [ para "Definition of first term\nand its continuation." ])
+                       , ("Second term", [ para "Definition of second term." ])
+                       ]
+      , test emacsMuse "Multi-line definition lists from Emacs Muse manual"
+        (T.unlines
+          [ "Term1 ::"
+          , "  This is a first definition"
+          , "  And it has two lines;"
+          , "no, make that three."
+          , ""
+          , "Term2 :: This is a second definition"
+          ] =?>
+         definitionList [ ("Term1", [ para "This is a first definition\nAnd it has two lines;\nno, make that three."])
+                        , ("Term2", [ para "This is a second definition"])
+                        ])
+      -- Text::Amuse requires indentation with one space
+      , "Multi-line definition lists from Emacs Muse manual with initial space" =:
+        (T.unlines
+          [ " Term1 ::"
+          , "  This is a first definition"
+          , "  And it has two lines;"
+          , "no, make that three."
+          , ""
+          , " Term2 :: This is a second definition"
+          ] =?>
+         definitionList [ ("Term1", [ para "This is a first definition\nAnd it has two lines;\nno, make that three."])
+                        , ("Term2", [ para "This is a second definition"])
+                        ])
+      , "One-line nested definition list" =:
+        " Foo :: bar :: baz" =?>
+        definitionList [ ("Foo", [ definitionList [ ("bar", [ para "baz" ])]])]
+      , "Nested definition list" =:
+        T.unlines
+        [ " First :: Second :: Third"
+        , "          Fourth :: Fifth :: Sixth"
+        , " Seventh :: Eighth"
+        ] =?>
+        definitionList [ ("First", [ definitionList [ ("Second", [ para "Third" ]),
+                                                      ("Fourth", [ definitionList [ ("Fifth", [ para "Sixth"] ) ] ] ) ] ] )
+                       , ("Seventh", [ para "Eighth" ])
+                       ]
+      , testGroup "Definition lists with multiple descriptions"
+        [ "Correctly indented second description" =:
+          T.unlines
+          [ " First term :: first description"
+          , "  :: second description"
+          ] =?>
+          definitionList [ ("First term", [ para "first description"
+                                          , para "second description"
+                                          ])
+                         ]
+        , "Incorrectly indented second description" =:
+          T.unlines
+          [ " First term :: first description"
+          , " :: second description"
+          ] =?>
+          definitionList [ ("First term", [ para "first description" ])
+                         , ("", [ para "second description" ])
+                         ]
+        ]
+      , "Two blank lines separate definition lists" =:
+        T.unlines
+          [ " First :: list"
+          , ""
+          , ""
+          , " Second :: list"
+          ] =?>
+        definitionList [ ("First", [ para "list" ]) ] <>
+        definitionList [ ("Second", [ para "list" ]) ]
+      -- Headers in first column of list continuation are not allowed
+      , "No headers in list continuation" =:
+        T.unlines
+          [ " - Foo"
+          , ""
+          , "   * Bar"
+          ] =?>
+        bulletList [ mconcat [ para "Foo"
+                             , para "* Bar"
+                             ]
+                   ]
+      , "Bullet list inside a tag" =:
+        T.unlines
+          [ "<quote>"
+          , " - First"
+          , ""
+          , " - Second"
+          , ""
+          , " - Third"
+          , "</quote>"
+          ] =?>
+        blockQuote (bulletList [ para "First"
+                               , para "Second"
+                               , para "Third"
+                               ])
+      , "Ordered list inside a tag" =:
+        T.unlines
+          [ "<quote>"
+          , " 1. First"
+          , ""
+          , " 2. Second"
+          , ""
+          , " 3. Third"
+          , "</quote>"
+          ] =?>
+        blockQuote (orderedListWith (1, Decimal, Period) [ para "First"
+                                                         , para "Second"
+                                                         , para "Third"
+                                                         ])
+      -- Regression test for a bug caught by round-trip test
+      , "Do not consume whitespace while looking for end tag" =:
+        T.unlines
+          [ "<quote>"
+          , " - <quote>"
+          , "   foo"
+          , "   </quote>"
+          , " bar" -- Do not consume whitespace while looking for arbitraritly indented </quote>
+          , "</quote>"
+          ] =?>
+        blockQuote (bulletList [ blockQuote $ para "foo" ] <> para "bar")
+
+      , "Unclosed quote tag" =:
+        T.unlines
+          [ "<quote>"
+          , "<verse>"
+          , "</quote>"
+          , "</verse>"
+          ] =?>
+        para "<quote>" <> lineBlock [ "</quote>" ]
+
+      , "Unclosed quote tag inside list" =:
+        T.unlines
+          [ " - <quote>"
+          , "   <verse>"
+          , "   </quote>"
+          , "   </verse>"
+          ] =?>
+        bulletList [ para "<quote>" <> lineBlock [ "</quote>" ] ]
+
+      -- Allowing indented closing tags is dangerous,
+      -- as they may terminate lists
+      , "No indented closing tags" =:
+        T.unlines
+          [ "<quote>"
+          , ""
+          , " - Foo"
+          , ""
+          , "   </quote>"
+          , ""
+          , "   bar"
+          , ""
+          , "   <verse>"
+          , "   </quote>"
+          , "   </verse>"
+          ] =?>
+        para "<quote>" <> bulletList [ para "Foo" <> para "</quote>" <> para "bar" <> lineBlock [ "</quote>" ] ]
+      ]
+  ]
diff --git a/test/Tests/Readers/Odt.hs b/test/Tests/Readers/Odt.hs
index 4b7058cf9..c7f9a0725 100644
--- a/test/Tests/Readers/Odt.hs
+++ b/test/Tests/Readers/Odt.hs
@@ -1,5 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 module Tests.Readers.Odt (tests) where
 
+import Prelude
 import Control.Monad (liftM)
 import qualified Data.ByteString as BS
 import qualified Data.ByteString.Lazy as B
diff --git a/test/Tests/Readers/Odt.hs.orig b/test/Tests/Readers/Odt.hs.orig
new file mode 100644
index 000000000..4b7058cf9
--- /dev/null
+++ b/test/Tests/Readers/Odt.hs.orig
@@ -0,0 +1,170 @@
+module Tests.Readers.Odt (tests) where
+
+import Control.Monad (liftM)
+import qualified Data.ByteString as BS
+import qualified Data.ByteString.Lazy as B
+import qualified Data.Map as M
+import Data.Text (unpack)
+import System.IO.Unsafe (unsafePerformIO)
+import Test.Tasty
+import Tests.Helpers
+import Text.Pandoc
+import qualified Text.Pandoc.UTF8 as UTF8
+
+defopts :: ReaderOptions
+defopts = def{ readerExtensions = getDefaultExtensions "odt" }
+
+tests :: [TestTree]
+tests = testsComparingToMarkdown ++ testsComparingToNative
+
+testsComparingToMarkdown :: [TestTree]
+testsComparingToMarkdown    = map nameToTest namesOfTestsComparingToMarkdown
+  where nameToTest     name = createTest
+                                compareOdtToMarkdown
+                                name
+                                (toOdtPath      name)
+                                (toMarkdownPath name)
+        toOdtPath      name = "odt/odt/"      ++ name ++ ".odt"
+        toMarkdownPath name = "odt/markdown/" ++ name ++ ".md"
+
+testsComparingToNative   :: [TestTree]
+testsComparingToNative      = map nameToTest namesOfTestsComparingToNative
+  where nameToTest     name = createTest
+                                compareOdtToNative
+                                name
+                                (toOdtPath      name)
+                                (toNativePath   name)
+        toOdtPath      name = "odt/odt/"      ++ name ++ ".odt"
+        toNativePath   name = "odt/native/"   ++ name ++ ".native"
+
+
+newtype NoNormPandoc = NoNormPandoc {unNoNorm :: Pandoc}
+  deriving ( Show )
+
+instance ToString NoNormPandoc where
+  toString d = unpack $
+               purely (writeNative def{ writerTemplate = s }) $ toPandoc d
+   where s = case d of
+                  NoNormPandoc (Pandoc (Meta m) _)
+                    | M.null m  -> Nothing
+                    | otherwise -> Just "" -- need this for Meta output
+
+instance ToPandoc NoNormPandoc where
+  toPandoc = unNoNorm
+
+getNoNormVia :: (a -> Pandoc) -> String -> Either PandocError a -> NoNormPandoc
+getNoNormVia _ readerName (Left  _) = error (readerName ++ " reader failed")
+getNoNormVia f _          (Right a) = NoNormPandoc (f a)
+
+type TestCreator =  ReaderOptions
+                 -> FilePath -> FilePath
+                 -> IO (NoNormPandoc, NoNormPandoc)
+
+compareOdtToNative   :: TestCreator
+compareOdtToNative opts odtPath nativePath = do
+   nativeFile   <- UTF8.toText <$> BS.readFile nativePath
+   odtFile      <- B.readFile       odtPath
+   native       <- getNoNormVia id  "native" <$> runIO (readNative def nativeFile)
+   odt          <- getNoNormVia id  "odt"    <$> runIO (readOdt  opts odtFile)
+   return (odt,native)
+
+compareOdtToMarkdown :: TestCreator
+compareOdtToMarkdown opts odtPath markdownPath = do
+   markdownFile <- UTF8.toText <$> BS.readFile markdownPath
+   odtFile      <- B.readFile       odtPath
+   markdown     <- getNoNormVia id "markdown" <$>
+                      runIO (readMarkdown def{ readerExtensions = pandocExtensions }
+                              markdownFile)
+   odt          <- getNoNormVia id "odt"      <$> runIO (readOdt      opts odtFile)
+   return (odt,markdown)
+
+
+createTest :: TestCreator
+           -> TestName
+           -> FilePath -> FilePath
+           -> TestTree
+createTest   creator name path1 path2 =
+  unsafePerformIO $ liftM (test id name) (creator defopts path1 path2)
+
+{-
+--
+
+getMedia :: FilePath -> FilePath -> IO (Maybe B.ByteString)
+getMedia archivePath mediaPath = do
+  zf <- B.readFile archivePath >>= return . toArchive
+  return $ findEntryByPath ("Pictures/" ++ mediaPath) zf >>= (Just . fromEntry)
+
+compareMediaPathIO :: FilePath -> MediaBag -> FilePath -> IO Bool
+compareMediaPathIO mediaPath mediaBag odtPath = do
+  odtMedia <- getMedia odtPath mediaPath
+  let mbBS   = case lookupMedia mediaPath mediaBag of
+                 Just (_, bs) -> bs
+                 Nothing      -> error ("couldn't find " ++
+                                        mediaPath ++
+                                        " in media bag")
+      odtBS = case odtMedia of
+                 Just bs -> bs
+                 Nothing -> error ("couldn't find " ++
+                                   mediaPath ++
+                                   " in media bag")
+  return $ mbBS == odtBS
+
+compareMediaBagIO :: FilePath -> IO Bool
+compareMediaBagIO odtFile = do
+    df <- B.readFile odtFile
+    let (_, mb) = readOdt def df
+    bools <- mapM
+             (\(fp, _, _) -> compareMediaPathIO fp mb odtFile)
+             (mediaDirectory mb)
+    return $ and bools
+
+testMediaBagIO :: String -> FilePath -> IO TestTree
+testMediaBagIO name odtFile = do
+  outcome <- compareMediaBagIO odtFile
+  return $ testCase name (assertBool
+                          ("Media didn't match media bag in file " ++ odtFile)
+                          outcome)
+
+testMediaBag :: String -> FilePath -> TestTree
+testMediaBag name odtFile = buildTest $ testMediaBagIO name odtFile
+-}
+--
+
+
+
+namesOfTestsComparingToMarkdown :: [ String ]
+namesOfTestsComparingToMarkdown  = [ "bold"
+--                                 , "citation"
+                                   , "endnote"
+                                   , "externalLink"
+                                   , "footnote"
+                                   , "headers"
+--                                 , "horizontalRule"
+                                   , "italic"
+--                                 , "listBlocks"
+                                   , "paragraph"
+                                   , "strikeout"
+--                                 , "trackedChanges"
+                                   , "underlined"
+                                   ]
+
+namesOfTestsComparingToNative  :: [ String ]
+namesOfTestsComparingToNative   = [ "blockquote"
+                                  , "image"
+                                  , "imageIndex"
+                                  , "imageWithCaption"
+                                  , "inlinedCode"
+                                  , "orderedListMixed"
+                                  , "orderedListRoman"
+                                  , "orderedListSimple"
+                                  , "referenceToChapter"
+                                  , "referenceToListItem"
+                                  , "referenceToText"
+                                  , "simpleTable"
+                                  , "simpleTableWithCaption"
+--                                , "table"
+                                  , "textMixedStyles"
+                                  , "tableWithContents"
+                                  , "unicode"
+                                  , "unorderedList"
+                                  ]
diff --git a/test/Tests/Readers/Org.hs.orig b/test/Tests/Readers/Org.hs.orig
new file mode 100644
index 000000000..de7f14e32
--- /dev/null
+++ b/test/Tests/Readers/Org.hs.orig
@@ -0,0 +1,16 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.Org (tests) where
+
+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
index 15dc63554..b1c86eada 100644
--- a/test/Tests/Readers/Org/Block.hs
+++ b/test/Tests/Readers/Org/Block.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Readers.Org.Block (tests) where
 
+import Prelude
 import Test.Tasty (TestTree, testGroup)
 import Tests.Helpers ((=?>))
 import Tests.Readers.Org.Shared ((=:), spcSep)
diff --git a/test/Tests/Readers/Org/Block.hs.orig b/test/Tests/Readers/Org/Block.hs.orig
new file mode 100644
index 000000000..15dc63554
--- /dev/null
+++ b/test/Tests/Readers/Org/Block.hs.orig
@@ -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
index 8fa822089..a54ef6a17 100644
--- a/test/Tests/Readers/Org/Block/CodeBlock.hs
+++ b/test/Tests/Readers/Org/Block/CodeBlock.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Readers.Org.Block.CodeBlock (tests) where
 
+import Prelude
 import Test.Tasty (TestTree)
 import Tests.Helpers ((=?>))
 import Tests.Readers.Org.Shared ((=:), spcSep)
diff --git a/test/Tests/Readers/Org/Block/CodeBlock.hs.orig b/test/Tests/Readers/Org/Block/CodeBlock.hs.orig
new file mode 100644
index 000000000..8fa822089
--- /dev/null
+++ b/test/Tests/Readers/Org/Block/CodeBlock.hs.orig
@@ -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
index cae6ef179..bead135e9 100644
--- a/test/Tests/Readers/Org/Block/Figure.hs
+++ b/test/Tests/Readers/Org/Block/Figure.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Readers.Org.Block.Figure (tests) where
 
+import Prelude
 import Test.Tasty (TestTree)
 import Tests.Helpers ((=?>))
 import Tests.Readers.Org.Shared ((=:))
diff --git a/test/Tests/Readers/Org/Block/Figure.hs.orig b/test/Tests/Readers/Org/Block/Figure.hs.orig
new file mode 100644
index 000000000..cae6ef179
--- /dev/null
+++ b/test/Tests/Readers/Org/Block/Figure.hs.orig
@@ -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
index e8ad88558..3b0d7dda9 100644
--- a/test/Tests/Readers/Org/Block/Header.hs
+++ b/test/Tests/Readers/Org/Block/Header.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Readers.Org.Block.Header (tests) where
 
+import Prelude
 import Test.Tasty (TestTree, testGroup)
 import Tests.Helpers ((=?>))
 import Tests.Readers.Org.Shared ((=:), spcSep, tagSpan)
diff --git a/test/Tests/Readers/Org/Block/Header.hs.orig b/test/Tests/Readers/Org/Block/Header.hs.orig
new file mode 100644
index 000000000..e8ad88558
--- /dev/null
+++ b/test/Tests/Readers/Org/Block/Header.hs.orig
@@ -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
index 343682a80..f273b684d 100644
--- a/test/Tests/Readers/Org/Block/List.hs
+++ b/test/Tests/Readers/Org/Block/List.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Readers.Org.Block.List (tests) where
 
+import Prelude
 import Test.Tasty (TestTree)
 import Tests.Helpers ((=?>))
 import Tests.Readers.Org.Shared ((=:), spcSep)
diff --git a/test/Tests/Readers/Org/Block/List.hs.orig b/test/Tests/Readers/Org/Block/List.hs.orig
new file mode 100644
index 000000000..343682a80
--- /dev/null
+++ b/test/Tests/Readers/Org/Block/List.hs.orig
@@ -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
index db6e756f8..3cb6bb0f0 100644
--- a/test/Tests/Readers/Org/Block/Table.hs
+++ b/test/Tests/Readers/Org/Block/Table.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Readers.Org.Block.Table (tests) where
 
+import Prelude
 import Test.Tasty (TestTree)
 import Tests.Helpers ((=?>))
 import Tests.Readers.Org.Shared ((=:), spcSep)
diff --git a/test/Tests/Readers/Org/Block/Table.hs.orig b/test/Tests/Readers/Org/Block/Table.hs.orig
new file mode 100644
index 000000000..db6e756f8
--- /dev/null
+++ b/test/Tests/Readers/Org/Block/Table.hs.orig
@@ -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
index 7e2c0fb8d..bb9c52e69 100644
--- a/test/Tests/Readers/Org/Directive.hs
+++ b/test/Tests/Readers/Org/Directive.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Readers.Org.Directive (tests) where
 
+import Prelude
 import Data.Time (UTCTime (UTCTime), secondsToDiffTime)
 import Data.Time.Calendar (Day (ModifiedJulianDay))
 import Test.Tasty (TestTree, testGroup)
diff --git a/test/Tests/Readers/Org/Directive.hs.orig b/test/Tests/Readers/Org/Directive.hs.orig
new file mode 100644
index 000000000..7e2c0fb8d
--- /dev/null
+++ b/test/Tests/Readers/Org/Directive.hs.orig
@@ -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
index da0d1db0b..07fe2d2e9 100644
--- a/test/Tests/Readers/Org/Inline.hs
+++ b/test/Tests/Readers/Org/Inline.hs
@@ -1,14 +1,16 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Readers.Org.Inline (tests) where
 
+import Prelude
 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.Citation as Citation
 import qualified Tests.Readers.Org.Inline.Note as Note
 import qualified Tests.Readers.Org.Inline.Smart as Smart
 
@@ -288,161 +290,6 @@ tests =
                        )
                        "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 "…"
@@ -483,17 +330,6 @@ tests =
       "\\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)}}}"
@@ -512,6 +348,7 @@ tests =
                 ] =?>
       para "Foo Bar"
 
+  , testGroup "Citations" Citation.tests
   , testGroup "Footnotes" Note.tests
   , testGroup "Smart punctuation" Smart.tests
   ]
diff --git a/test/Tests/Readers/Org/Inline.hs.orig b/test/Tests/Readers/Org/Inline.hs.orig
new file mode 100644
index 000000000..9bf5556d2
--- /dev/null
+++ b/test/Tests/Readers/Org/Inline.hs.orig
@@ -0,0 +1,352 @@
+{-# 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.Builder
+import Text.Pandoc.Shared (underlineSpan)
+import qualified Data.Text as T
+import qualified Tests.Readers.Org.Inline.Citation as Citation
+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")
+
+  , "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 "∀ Ä"
+
+  , "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 "Citations" Citation.tests
+  , testGroup "Footnotes" Note.tests
+  , testGroup "Smart punctuation" Smart.tests
+  ]
diff --git a/test/Tests/Readers/Org/Inline/Citation.hs b/test/Tests/Readers/Org/Inline/Citation.hs
new file mode 100644
index 000000000..c7974efa0
--- /dev/null
+++ b/test/Tests/Readers/Org/Inline/Citation.hs
@@ -0,0 +1,181 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.Org.Inline.Citation (tests) where
+
+import Prelude
+import Test.Tasty (TestTree, testGroup)
+import Tests.Helpers ((=?>))
+import Tests.Readers.Org.Shared ((=:))
+import Text.Pandoc.Builder
+
+tests :: [TestTree]
+tests =
+  [ testGroup "Markdown-style citations"
+    [ "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]")
+    ]
+
+  , testGroup "org-ref citations"
+    [ "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")
+
+    , "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")
+
+    , "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 ",")
+
+    , "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 ".")
+
+    , "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 ":")
+
+    , "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")
+
+    , "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")
+    ]
+
+  , "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}")
+
+  ]
diff --git a/test/Tests/Readers/Org/Inline/Citation.hs.orig b/test/Tests/Readers/Org/Inline/Citation.hs.orig
new file mode 100644
index 000000000..d7e38a6b0
--- /dev/null
+++ b/test/Tests/Readers/Org/Inline/Citation.hs.orig
@@ -0,0 +1,179 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.Org.Inline.Citation (tests) where
+
+import Test.Tasty (TestTree, testGroup)
+import Tests.Helpers ((=?>))
+import Tests.Readers.Org.Shared ((=:))
+import Text.Pandoc.Builder
+
+tests :: [TestTree]
+tests =
+  [ testGroup "Markdown-style citations"
+    [ "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]")
+    ]
+
+  , testGroup "org-ref citations"
+    [ "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")
+
+    , "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")
+
+    , "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 ",")
+
+    , "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 ".")
+
+    , "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 ":")
+
+    , "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")
+
+    , "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")
+    ]
+
+  , "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}")
+
+  ]
diff --git a/test/Tests/Readers/Org/Inline/Note.hs b/test/Tests/Readers/Org/Inline/Note.hs
index 9eb1d02d6..1e0a59cb4 100644
--- a/test/Tests/Readers/Org/Inline/Note.hs
+++ b/test/Tests/Readers/Org/Inline/Note.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Readers.Org.Inline.Note (tests) where
 
+import Prelude
 import Test.Tasty (TestTree)
 import Tests.Helpers ((=?>))
 import Tests.Readers.Org.Shared ((=:))
diff --git a/test/Tests/Readers/Org/Inline/Note.hs.orig b/test/Tests/Readers/Org/Inline/Note.hs.orig
new file mode 100644
index 000000000..9eb1d02d6
--- /dev/null
+++ b/test/Tests/Readers/Org/Inline/Note.hs.orig
@@ -0,0 +1,86 @@
+{-# 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
index 77f10699d..b2889f8fe 100644
--- a/test/Tests/Readers/Org/Inline/Smart.hs
+++ b/test/Tests/Readers/Org/Inline/Smart.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Readers.Org.Inline.Smart (tests) where
 
+import Prelude
 import Data.Text (Text)
 import Test.Tasty (TestTree)
 import Tests.Helpers ((=?>), purely, test)
diff --git a/test/Tests/Readers/Org/Inline/Smart.hs.orig b/test/Tests/Readers/Org/Inline/Smart.hs.orig
new file mode 100644
index 000000000..77f10699d
--- /dev/null
+++ b/test/Tests/Readers/Org/Inline/Smart.hs.orig
@@ -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
index 6bd1b02e7..b17a05fe1 100644
--- a/test/Tests/Readers/Org/Meta.hs
+++ b/test/Tests/Readers/Org/Meta.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Readers.Org.Meta (tests) where
 
+import Prelude
 import Test.Tasty (TestTree, testGroup)
 import Tests.Helpers ((=?>))
 import Tests.Readers.Org.Shared ((=:), spcSep)
diff --git a/test/Tests/Readers/Org/Meta.hs.orig b/test/Tests/Readers/Org/Meta.hs.orig
new file mode 100644
index 000000000..6bd1b02e7
--- /dev/null
+++ b/test/Tests/Readers/Org/Meta.hs.orig
@@ -0,0 +1,191 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.Org.Meta (tests) where
+
+import Test.Tasty (TestTree, testGroup)
+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")
+
+  , testGroup "emphasis config"
+    [ "Changing pre and post chars for emphasis" =:
+        T.unlines [ "#+pandoc-emphasis-pre: \"[)\""
+                  , "#+pandoc-emphasis-post: \"]\\n\""
+                  , "([/emph/])*foo*"
+                  ] =?>
+        para ("([" <> emph "emph" <> "])" <> strong "foo")
+
+    , "setting an invalid value restores the default" =:
+        T.unlines [ "#+pandoc-emphasis-pre: \"[\""
+                  , "#+pandoc-emphasis-post: \"]\""
+                  , "#+pandoc-emphasis-pre:"
+                  , "#+pandoc-emphasis-post:"
+                  , "[/noemph/]"
+                  ] =?>
+        para ("[/noemph/]")
+    ]
+  ]
diff --git a/test/Tests/Readers/Org/Shared.hs b/test/Tests/Readers/Org/Shared.hs
index 5e8f6dd54..ea2a97e49 100644
--- a/test/Tests/Readers/Org/Shared.hs
+++ b/test/Tests/Readers/Org/Shared.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 module Tests.Readers.Org.Shared
   ( (=:)
   , org
@@ -5,6 +6,7 @@ module Tests.Readers.Org.Shared
   , tagSpan
   ) where
 
+import Prelude
 import Data.List (intersperse)
 import Data.Text (Text)
 import Tests.Helpers (ToString, purely, test)
diff --git a/test/Tests/Readers/Org/Shared.hs.orig b/test/Tests/Readers/Org/Shared.hs.orig
new file mode 100644
index 000000000..5e8f6dd54
--- /dev/null
+++ b/test/Tests/Readers/Org/Shared.hs.orig
@@ -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/Readers/RST.hs b/test/Tests/Readers/RST.hs
index 3753fbf12..906ed4ff9 100644
--- a/test/Tests/Readers/RST.hs
+++ b/test/Tests/Readers/RST.hs
@@ -1,7 +1,9 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 module Tests.Readers.RST (tests) where
 
+import Prelude
 import Data.Text (Text)
 import qualified Data.Text as T
 import Test.Tasty
@@ -184,6 +186,6 @@ tests = [ "line block with blank line" =:
             , ".. [1]"
             , "   bar"
             ] =?>
-              para ("foo" <> (note $ para "bar"))
+              para ("foo" <> note (para "bar"))
           ]
         ]
diff --git a/test/Tests/Readers/RST.hs.orig b/test/Tests/Readers/RST.hs.orig
new file mode 100644
index 000000000..305c7060b
--- /dev/null
+++ b/test/Tests/Readers/RST.hs.orig
@@ -0,0 +1,189 @@
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+module Tests.Readers.RST (tests) where
+
+import Data.Text (Text)
+import qualified Data.Text as T
+import Test.Tasty
+import Tests.Helpers
+import Text.Pandoc
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder
+
+rst :: Text -> Pandoc
+rst = purely $ readRST def{ readerStandalone = True }
+
+infix 4 =:
+(=:) :: ToString c
+     => String -> (Text, c) -> TestTree
+(=:) = test rst
+
+tests :: [TestTree]
+tests = [ "line block with blank line" =:
+          "| a\n|\n|  b" =?> lineBlock [ "a", mempty, "\160b" ]
+        , testGroup "field list"
+          [ "general" =: T.unlines
+             [ "para"
+             , ""
+             , ":Hostname: media08"
+             , ":IP address: 10.0.0.19"
+             , ":Size: 3ru"
+             , ":Version: 1"
+             , ":Indentation: Since the field marker may be quite long, the second"
+             , "   and subsequent lines of the field body do not have to line up"
+             , "   with the first line, but they must be indented relative to the"
+             , "   field name marker, and they must line up with each other."
+             , ":Parameter i: integer"
+             , ":Final: item"
+             , "  on two lines" ]
+             =?>
+              doc (para "para" <>
+                   definitionList [ (str "Hostname", [para "media08"])
+                                  , (text "IP address", [para "10.0.0.19"])
+                                  , (str "Size", [para "3ru"])
+                                  , (str "Version", [para "1"])
+                                  , (str "Indentation", [para "Since the field marker may be quite long, the second\nand subsequent lines of the field body do not have to line up\nwith the first line, but they must be indented relative to the\nfield name marker, and they must line up with each other."])
+                                  , (text "Parameter i", [para "integer"])
+                                  , (str "Final", [para "item\non two lines"])
+                                  ])
+          , "metadata" =: T.unlines
+             [ "====="
+             , "Title"
+             , "====="
+             , "--------"
+             , "Subtitle"
+             , "--------"
+             , ""
+             , ":Version: 1"
+             ]
+             =?>
+              setMeta "version" (para "1") (setMeta "title" ("Title" :: Inlines)
+                 $ setMeta "subtitle" ("Subtitle" :: Inlines)
+                 $ doc mempty)
+          , "with inline markup" =: T.unlines
+             [ ":*Date*: today"
+             , ""
+             , ".."
+             , ""
+             , ":*one*: emphasis"
+             , ":two_: reference"
+             , ":`three`_: another one"
+             , ":``four``: literal"
+             , ""
+             , ".. _two: http://example.com"
+             , ".. _three: http://example.org"
+             ]
+             =?>
+              setMeta "date" (str "today") (doc
+                 $ definitionList [ (emph "one", [para "emphasis"])
+                                  , (link "http://example.com" "" "two", [para "reference"])
+                                  , (link "http://example.org" "" "three", [para "another one"])
+                                  , (code "four", [para "literal"])
+                                  ])
+          ]
+        , "URLs with following punctuation" =:
+          ("http://google.com, http://yahoo.com; http://foo.bar.baz.\n" <>
+           "http://foo.bar/baz_(bam) (http://foo.bar)") =?>
+          para (link "http://google.com" "" "http://google.com" <> ", " <>
+                link "http://yahoo.com" "" "http://yahoo.com" <> "; " <>
+                link "http://foo.bar.baz" "" "http://foo.bar.baz" <> ". " <>
+                softbreak <>
+                link "http://foo.bar/baz_(bam)" "" "http://foo.bar/baz_(bam)"
+                <> " (" <> link "http://foo.bar" "" "http://foo.bar" <> ")")
+        , "Reference names with special characters" =:
+                   ("A-1-B_2_C:3:D+4+E.5.F_\n\n" <>
+                   ".. _A-1-B_2_C:3:D+4+E.5.F: https://example.com\n") =?>
+                   para (link "https://example.com" "" "A-1-B_2_C:3:D+4+E.5.F")
+        , "Code directive with class and number-lines" =: T.unlines
+            [ ".. code::python"
+            , "   :number-lines: 34"
+            , "   :class: class1 class2 class3"
+            , ""
+            , "  def func(x):"
+            , "    return y"
+            ]  =?>
+              doc (codeBlockWith
+                  ( ""
+                  , ["sourceCode", "python", "numberLines", "class1", "class2", "class3"]
+                  , [ ("startFrom", "34") ]
+                  )
+                  "def func(x):\n  return y")
+        , "Code directive with number-lines, no line specified" =: T.unlines
+            [ ".. code::python"
+            , "   :number-lines: "
+            , ""
+            , "  def func(x):"
+            , "    return y"
+            ]  =?>
+              doc (codeBlockWith
+                  ( ""
+                  , ["sourceCode", "python", "numberLines"]
+                  , [ ("startFrom", "") ]
+                  )
+                  "def func(x):\n  return y")
+        , testGroup "literal / line / code blocks"
+          [ "indented literal block" =: T.unlines
+            [ "::"
+            , ""
+            , "  block quotes"
+            , ""
+            , "  can go on for many lines"
+            , "but must stop here"]
+            =?>
+              doc (
+                 codeBlock "block quotes\n\ncan go on for many lines" <>
+                 para "but must stop here")
+          , "line block with 3 lines" =: "| a\n| b\n| c"
+            =?> lineBlock ["a", "b", "c"]
+          , "line blocks with blank lines" =: T.unlines
+            [ "|"
+            , ""
+            , "|"
+            , "| a"
+            , "| b"
+            , "|"
+            , ""
+            , "|"
+            ] =?>
+            lineBlock [""] <>
+            lineBlock ["", "a", "b", ""] <>
+            lineBlock [""]
+          , "quoted literal block using >" =: "::\n\n> quoted\n> block\n\nOrdinary paragraph"
+            =?> codeBlock "> quoted\n> block" <> para "Ordinary paragraph"
+          , "quoted literal block using | (not  a line block)" =: "::\n\n| quoted\n| block\n\nOrdinary paragraph"
+            =?> codeBlock "| quoted\n| block" <> para "Ordinary paragraph"
+          , "class directive with single paragraph" =: ".. class:: special\n\nThis is a \"special\" paragraph."
+            =?> divWith ("", ["special"], []) (para "This is a \"special\" paragraph.")
+          , "class directive with two paragraphs" =: ".. class:: exceptional remarkable\n\n    First paragraph.\n\n    Second paragraph."
+            =?> divWith ("", ["exceptional", "remarkable"], []) (para "First paragraph." <> para "Second paragraph.")
+          , "class directive around literal block" =: ".. class:: classy\n\n::\n\n    a\n    b"
+            =?> divWith ("", ["classy"], []) (codeBlock "a\nb")]
+        , testGroup "interpreted text roles"
+          [ "literal role prefix" =: ":literal:`a`" =?> para (code "a")
+          , "literal role postfix" =: "`a`:literal:" =?> para (code "a")
+          , "literal text" =: "``text``" =?> para (code "text")
+          , "code role" =: ":code:`a`" =?> para (codeWith ("", ["sourceCode"], []) "a")
+          , "inherited code role" =: ".. role:: codeLike(code)\n\n:codeLike:`a`"
+            =?> para (codeWith ("", ["codeLike", "sourceCode"], []) "a")
+          , "custom code role with language field"
+            =: ".. role:: lhs(code)\n    :language: haskell\n\n:lhs:`a`"
+            =?> para (codeWith ("", ["lhs", "haskell","sourceCode"], []) "a")
+          , "custom role with unspecified parent role"
+            =: ".. role:: classy\n\n:classy:`text`"
+            =?> para (spanWith ("", ["classy"], []) "text")
+          , "role with recursive inheritance"
+            =: ".. role:: haskell(code)\n.. role:: lhs(haskell)\n\n:lhs:`text`"
+            =?> para (codeWith ("", ["lhs", "haskell", "sourceCode"], []) "text")
+          , "unknown role" =: ":unknown:`text`" =?>
+              para (spanWith ("",[],[("role","unknown")]) (str "text"))
+          ]
+        , testGroup "footnotes"
+          [ "remove space before note" =: T.unlines
+            [ "foo [1]_"
+            , ""
+            , ".. [1]"
+            , "   bar"
+            ] =?>
+              para ("foo" <> note (para "bar"))
+          ]
+        ]
diff --git a/test/Tests/Readers/Txt2Tags.hs b/test/Tests/Readers/Txt2Tags.hs
index 435d983a1..f0efbb02e 100644
--- a/test/Tests/Readers/Txt2Tags.hs
+++ b/test/Tests/Readers/Txt2Tags.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Readers.Txt2Tags (tests) where
 
+import Prelude
 import Data.List (intersperse)
 import Data.Text (Text)
 import qualified Data.Text as T
@@ -143,7 +145,7 @@ tests =
 
       , "Header with label" =:
           "= header =[label]" =?>
-            headerWith ("label", [], []) 1 ("header")
+            headerWith ("label", [], []) 1 "header"
 
       , "Invalid header, mismatched delimiters" =:
           "== header =" =?>
diff --git a/test/Tests/Readers/Txt2Tags.hs.orig b/test/Tests/Readers/Txt2Tags.hs.orig
new file mode 100644
index 000000000..e3646e95e
--- /dev/null
+++ b/test/Tests/Readers/Txt2Tags.hs.orig
@@ -0,0 +1,437 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Readers.Txt2Tags (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.Arbitrary ()
+import Text.Pandoc.Builder
+import Text.Pandoc.Shared (underlineSpan)
+
+t2t :: Text -> Pandoc
+-- t2t = handleError . readTxt2Tags (T2TMeta "date" "mtime" "in" "out") def
+t2t = purely $ \s -> do
+  setInputFiles ["in"]
+  setOutputFile (Just "out")
+  readTxt2Tags def s
+
+infix 4 =:
+(=:) :: ToString c
+     => String -> (Text, c) -> TestTree
+(=:) = test t2t
+
+spcSep :: [Inlines] -> Inlines
+spcSep = mconcat . intersperse space
+
+simpleTable' :: Int
+             -> [Blocks]
+             -> [[Blocks]]
+             -> Blocks
+simpleTable' n = table "" (replicate n (AlignCenter, 0.0))
+
+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")
+
+      , "Strikeout" =:
+          "--Kill Bill--" =?>
+          para (strikeout . spcSep $ [ "Kill", "Bill" ])
+
+      , "Verbatim" =:
+          "``Robot.rock()``" =?>
+          para (code "Robot.rock()")
+
+      , "Symbol" =:
+          "A * symbol" =?>
+          para (str "A" <> space <> str "*" <> space <> "symbol")
+
+      , "No empty markup" =:
+          "//// **** ____ ---- ```` \"\"\"\" ''''" =?>
+          para (spcSep [ "////", "****", "____", "----", "````", "\"\"\"\"", "''''" ])
+
+      , "Inline markup is greedy" =:
+          "***** ///// _____ ----- ````` \"\"\"\"\" '''''" =?>
+          para (spcSep [strong "*", emph "/", underlineSpan "_"
+                       , strikeout "-", code "`", text "\""
+                       , rawInline "html" "'"])
+      , "Markup must be greedy" =:
+          "**********    //////////    __________    ----------    ``````````   \"\"\"\"\"\"\"\"\"\"   ''''''''''" =?>
+                      para (spcSep [strong "******", emph "//////", underlineSpan "______"
+                       , strikeout "------", code "``````", text "\"\"\"\"\"\""
+                       , rawInline "html" "''''''"])
+      , "Inlines must be glued" =:
+          "** a** **a ** ** a **" =?>
+          para (text "** a** **a ** ** a **")
+
+      , "Macros: Date" =:
+          "%%date" =?>
+            para "1970-01-01"
+      , "Macros: Mod Time" =:
+          "%%mtime" =?>
+            para (str "")
+      , "Macros: Infile" =:
+          "%%infile" =?>
+            para "in"
+      , "Macros: Outfile" =:
+          "%%outfile" =?>
+            para "out"
+      , "Autolink" =:
+          "http://www.google.com" =?>
+            para (link "http://www.google.com" "" (str "http://www.google.com"))
+      , "JPEG Image" =:
+          "[image.jpg]" =?>
+            para (image "image.jpg" "" mempty)
+      , "PNG Image" =:
+          "[image.png]" =?>
+            para (image "image.png" "" mempty)
+
+      , "Link" =:
+          "[title http://google.com]" =?>
+            para (link "http://google.com" "" (str "title"))
+
+      , "Image link" =:
+          "[[image.jpg] abc]" =?>
+            para (link "abc" "" (image "image.jpg" "" mempty))
+      , "Invalid link: No trailing space" =:
+          "[title invalid ]" =?>
+            para (text "[title invalid ]")
+
+
+      ]
+
+  , testGroup "Basic Blocks"
+      ["Paragraph, lines grouped together" =:
+          "A paragraph\n A blank line ends the \n current paragraph\n"
+            =?> para "A paragraph\n A blank line ends the\n current paragraph"
+      , "Paragraph, ignore leading and trailing spaces" =:
+          "   Leading and trailing spaces are ignored.   \n" =?>
+            para "Leading and trailing spaces are ignored."
+      , "Comment line in paragraph" =:
+          "A comment line can be placed inside a paragraph.\n% this comment will be ignored \nIt will not affect it.\n"
+          =?> para "A comment line can be placed inside a paragraph.\nIt will not affect it."
+      , "Paragraph" =:
+          "Paragraph\n" =?>
+          para "Paragraph"
+
+      , "First Level Header" =:
+          "+ Headline +\n" =?>
+          header 1 "Headline"
+
+      , "Third Level Header" =:
+          "=== Third Level Headline ===\n" =?>
+          header 3 ("Third" <> space <>
+                    "Level" <> space <>
+                    "Headline")
+
+      , "Header with label" =:
+          "= header =[label]" =?>
+            headerWith ("label", [], []) 1 "header"
+
+      , "Invalid header, mismatched delimiters" =:
+          "== header =" =?>
+            para (text "== header =")
+
+      , "Invalid header, spaces in label" =:
+          "== header ==[ haha ]" =?>
+            para (text "== header ==[ haha ]")
+
+      , "Invalid header, invalid label character" =:
+          "== header ==[lab/el]" =?>
+            para (text "== header ==[lab/el]")
+      , "Headers not preceded by a blank line" =:
+          T.unlines [ "++ eat dinner ++"
+                  , "Spaghetti and meatballs tonight."
+                  , "== walk dog =="
+                  ] =?>
+          mconcat [ header 2 ("eat" <> space <> "dinner")
+                  , para $ spcSep [ "Spaghetti", "and", "meatballs", "tonight." ]
+                  , header 2 ("walk" <> space <> "dog")
+                  ]
+
+      , "Paragraph starting with an equals" =:
+          "=five" =?>
+          para "=five"
+
+      , "Paragraph containing asterisk at beginning of line" =:
+          T.unlines [ "lucky"
+                  , "*star"
+                  ] =?>
+          para ("lucky" <> softbreak <> "*star")
+
+      , "Horizontal Rule" =:
+          T.unlines [ "before"
+                  , T.replicate 20 "-"
+                  , T.replicate 20 "="
+                  , T.replicate 20 "_"
+                  , "after"
+                  ] =?>
+          mconcat [ para "before"
+                  , horizontalRule
+                  , horizontalRule
+                  , horizontalRule
+                  , para "after"
+                  ]
+
+      , "Comment Block" =:
+          T.unlines [ "%%%"
+                  , "stuff"
+                  , "bla"
+                  , "%%%"] =?>
+          (mempty::Blocks)
+
+
+    ]
+
+  , 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"
+                     ]
+
+
+
+      , "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"
+                       , orderedList [ plain ("One" <> space <>
+                                             "More" <> space <>
+                                             "Time")
+                                    , plain ("Harder," <> space <>
+                                             "Better," <> space <>
+                                             "Faster," <> space <>
+                                             "Stronger")
+                                    ]
+                       ]
+                     , mconcat
+                       [ plain "Homework"
+                       , orderedList [ plain ("Around" <> space <>
+                                             "the" <> space <>
+                                             "World")
+                                    ]
+                       ]
+                     , mconcat
+                       [ plain ("Human" <> space <> "After" <> space <> "All")
+                       , orderedList [ plain "Technologic"
+                                    , plain ("Robot" <> space <> "Rock")
+                                    ]
+                       ]
+                     ]
+
+      , "Simple Ordered List" =:
+          ("+ Item1\n" <>
+           "+ Item2\n") =?>
+          let listStyle = (1, DefaultStyle, DefaultDelim)
+              listStructure = [ plain "Item1"
+                              , plain "Item2"
+                              ]
+          in orderedListWith listStyle listStructure
+
+
+      , "Indented Ordered List" =:
+          (" + Item1\n" <>
+           " + Item2\n") =?>
+          let listStyle = (1, DefaultStyle, DefaultDelim)
+              listStructure = [ plain "Item1"
+                              , plain "Item2"
+                              ]
+          in orderedListWith listStyle listStructure
+
+      , "Nested Ordered Lists" =:
+          ("+ One\n" <>
+           "   + One-One\n" <>
+           "   + One-Two\n" <>
+           "+ Two\n" <>
+           "   + Two-One\n"<>
+           "   + 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" <>
+           "  + Org\n") =?>
+          bulletList [ (plain "Emacs") <>
+                       (orderedList [ plain "Org"])
+                     ]
+
+      , "Bullet List in Ordered List" =:
+          ("+ GNU\n" <>
+           "   - Freedom\n") =?>
+          orderedList [ (plain "GNU") <> bulletList [ (plain "Freedom") ] ]
+
+      , "Definition List" =:
+          T.unlines [ ": PLL"
+                  , "  phase-locked loop"
+                  , ": TTL"
+                  , "  transistor-transistor logic"
+                  , ": PSK"
+                  , "  a digital"
+                  ] =?>
+          definitionList [ ("PLL", [ plain $ "phase-locked" <> space <> "loop" ])
+                         , ("TTL", [ plain $ "transistor-transistor" <> space <> "logic" ])
+                         , ("PSK", [ plain $ "a" <> space <> "digital" ])
+                         ]
+
+
+      , "Loose bullet list" =:
+          T.unlines [ "- apple"
+                  , ""
+                  , "- orange"
+                  , ""
+                  , "- peach"
+                  ] =?>
+          bulletList [ para "apple"
+                     , para "orange"
+                     , para "peach"
+                     ]
+      ]
+
+  , 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 with Header" =:
+          T.unlines [ "|| Species     | Status       |"
+                  , "| cervisiae    | domesticated |"
+                  , "| paradoxus | wild         |"
+                  ] =?>
+          simpleTable [ plain "Species", plain "Status" ]
+                      [ [ plain "cervisiae", plain "domesticated" ]
+                      , [ plain "paradoxus", plain "wild" ]
+                      ]
+
+      , "Table alignment determined by spacing" =:
+          T.unlines [ "| Numbers |     Text | More    |"
+                  , "| 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" ])
+
+
+      , "Table with differing row lengths" =:
+          T.unlines [ "|| Numbers | Text "
+                  , "| 1 | One  | foo  |"
+                  , "| 2 "
+                  ] =?>
+          table "" (zip [AlignCenter, AlignLeft, AlignLeft] [0, 0, 0])
+                [ plain "Numbers", plain "Text" , plain mempty ]
+                [ [ plain "1"      , plain "One"  , plain "foo"  ]
+                , [ plain "2"      , plain mempty , plain mempty  ]
+                ]
+
+      ]
+
+    , testGroup "Blocks and fragments"
+      [ "Source block" =:
+           T.unlines [ "```"
+                   , "main = putStrLn greeting"
+                   , "  where greeting = \"moin\""
+                   , "```" ] =?>
+           let code' = "main = putStrLn greeting\n" <>
+                       "  where greeting = \"moin\"\n"
+           in codeBlock code'
+
+      , "tagged block" =:
+           T.unlines [ "'''"
+                   , "<aside>HTML5 is pretty nice.</aside>"
+                   , "'''"
+                   ] =?>
+           rawBlock "html" "<aside>HTML5 is pretty nice.</aside>\n"
+
+      , "Quote block" =:
+           T.unlines ["\t//Niemand// hat die Absicht, eine Mauer zu errichten!"
+                   ] =?>
+           blockQuote (para (spcSep [ emph "Niemand", "hat", "die", "Absicht,"
+                                    , "eine", "Mauer", "zu", "errichten!"
+                                    ]))
+
+      ]
+  ]
diff --git a/test/Tests/Shared.hs b/test/Tests/Shared.hs
index cc448419c..85f7aae67 100644
--- a/test/Tests/Shared.hs
+++ b/test/Tests/Shared.hs
@@ -1,5 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 module Tests.Shared (tests) where
 
+import Prelude
 import System.FilePath.Posix (joinPath)
 import Test.Tasty
 import Test.Tasty.HUnit (assertBool, testCase, (@?=))
diff --git a/test/Tests/Shared.hs.orig b/test/Tests/Shared.hs.orig
new file mode 100644
index 000000000..cc448419c
--- /dev/null
+++ b/test/Tests/Shared.hs.orig
@@ -0,0 +1,39 @@
+module Tests.Shared (tests) where
+
+import System.FilePath.Posix (joinPath)
+import Test.Tasty
+import Test.Tasty.HUnit (assertBool, testCase, (@?=))
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder
+import Text.Pandoc.Shared
+
+tests :: [TestTree]
+tests = [ testGroup "compactifyDL"
+          [ testCase "compactifyDL with empty def" $
+              assertBool "compactifyDL"
+              (let x = [(str "word", [para (str "def"), mempty])]
+               in  compactifyDL x == x)
+          ]
+        , testGroup "collapseFilePath" testCollapse
+        ]
+
+testCollapse :: [TestTree]
+testCollapse = map (testCase "collapse")
+ [  collapseFilePath (joinPath [ ""]) @?= (joinPath [ ""])
+ ,  collapseFilePath (joinPath [ ".","foo"]) @?= (joinPath [ "foo"])
+ ,  collapseFilePath (joinPath [ ".",".","..","foo"]) @?= (joinPath [ joinPath ["..", "foo"]])
+ ,  collapseFilePath (joinPath [ "..","foo"]) @?= (joinPath [ "..","foo"])
+ ,  collapseFilePath (joinPath [ "","bar","..","baz"]) @?= (joinPath [ "","baz"])
+ ,  collapseFilePath (joinPath [ "","..","baz"]) @?= (joinPath [ "","..","baz"])
+ ,  collapseFilePath (joinPath [ ".","foo","..",".","bar","..",".",".","baz"]) @?= (joinPath [ "baz"])
+ ,  collapseFilePath (joinPath [ ".",""]) @?= (joinPath [ ""])
+ ,  collapseFilePath (joinPath [ ".",".",""]) @?= (joinPath [ ""])
+ ,  collapseFilePath (joinPath [ "..",""]) @?= (joinPath [ ".."])
+ ,  collapseFilePath (joinPath [ "..",".",""]) @?= (joinPath [ ".."])
+ ,  collapseFilePath (joinPath [ ".","..",""]) @?= (joinPath [ ".."])
+ ,  collapseFilePath (joinPath [ "..","..",""]) @?= (joinPath [ "..",".."])
+ ,  collapseFilePath (joinPath [ "parent","foo","baz","..","bar"]) @?= (joinPath [ "parent","foo","bar"])
+ ,  collapseFilePath (joinPath [ "parent","foo","baz","..","..","bar"]) @?= (joinPath [ "parent","bar"])
+ ,  collapseFilePath (joinPath [ "parent","foo",".."]) @?= (joinPath [ "parent"])
+ ,  collapseFilePath (joinPath [ "","parent","foo","..","..","bar"]) @?= (joinPath [ "","bar"])
+ ,  collapseFilePath (joinPath [ "",".","parent","foo"]) @?= (joinPath [ "","parent","foo"])]
diff --git a/test/Tests/Writers/AsciiDoc.hs b/test/Tests/Writers/AsciiDoc.hs
index 6b97c0761..d31d4ffe2 100644
--- a/test/Tests/Writers/AsciiDoc.hs
+++ b/test/Tests/Writers/AsciiDoc.hs
@@ -1,5 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 module Tests.Writers.AsciiDoc (tests) where
 
+import Prelude
 import Data.Text (unpack)
 import Test.Tasty
 import Tests.Helpers
diff --git a/test/Tests/Writers/AsciiDoc.hs.orig b/test/Tests/Writers/AsciiDoc.hs.orig
new file mode 100644
index 000000000..6b97c0761
--- /dev/null
+++ b/test/Tests/Writers/AsciiDoc.hs.orig
@@ -0,0 +1,56 @@
+module Tests.Writers.AsciiDoc (tests) where
+
+import Data.Text (unpack)
+import Test.Tasty
+import Tests.Helpers
+import Text.Pandoc
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder
+
+asciidoc :: (ToPandoc a) => a -> String
+asciidoc = unpack . purely (writeAsciiDoc def{ writerWrapText = WrapNone }) . toPandoc
+
+tests :: [TestTree]
+tests = [ testGroup "emphasis"
+          [ test asciidoc "emph word before" $
+               para (text "foo" <> emph (text "bar")) =?>
+                 "foo__bar__"
+          , test asciidoc "emph word after" $
+               para (emph (text "foo") <> text "bar") =?>
+                 "__foo__bar"
+          , test asciidoc "emph quoted" $
+               para (doubleQuoted (emph (text "foo"))) =?>
+                 "``__foo__''"
+          , test asciidoc "strong word before" $
+               para (text "foo" <> strong (text "bar")) =?>
+                 "foo**bar**"
+          , test asciidoc "strong word after" $
+               para (strong (text "foo") <> text "bar") =?>
+                 "**foo**bar"
+          , test asciidoc "strong quoted" $
+               para (singleQuoted (strong (text "foo"))) =?>
+                 "`**foo**'"
+          ]
+        , testGroup "tables"
+          [ test asciidoc "empty cells" $
+               simpleTable [] [[mempty],[mempty]] =?> unlines
+                                           [ "[cols=\"\",]"
+                                           , "|===="
+                                           , "|"
+                                           , "|"
+                                           , "|===="
+                                           ]
+          , test asciidoc "multiblock cells" $
+               simpleTable [] [[para (text "Para 1") <> para (text "Para 2")]]
+                                           =?> unlines
+                                           [ "[cols=\"\",]"
+                                           , "|====="
+                                           , "a|"
+                                           , "Para 1"
+                                           , ""
+                                           , "Para 2"
+                                           , ""
+                                           , "|====="
+                                           ]
+          ]
+        ]
diff --git a/test/Tests/Writers/ConTeXt.hs b/test/Tests/Writers/ConTeXt.hs
index 812aab4a6..fa1782391 100644
--- a/test/Tests/Writers/ConTeXt.hs
+++ b/test/Tests/Writers/ConTeXt.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Writers.ConTeXt (tests) where
 
+import Prelude
 import Data.Text (unpack)
 import Test.Tasty
 import Test.Tasty.QuickCheck
diff --git a/test/Tests/Writers/ConTeXt.hs.orig b/test/Tests/Writers/ConTeXt.hs.orig
new file mode 100644
index 000000000..812aab4a6
--- /dev/null
+++ b/test/Tests/Writers/ConTeXt.hs.orig
@@ -0,0 +1,149 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Writers.ConTeXt (tests) where
+
+import Data.Text (unpack)
+import Test.Tasty
+import Test.Tasty.QuickCheck
+import Tests.Helpers
+import Text.Pandoc
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder
+
+context :: (ToPandoc a) => a -> String
+context = unpack . purely (writeConTeXt def) . toPandoc
+
+context' :: (ToPandoc a) => a -> String
+context' = unpack . purely (writeConTeXt def{ writerWrapText = WrapNone }) . toPandoc
+
+contextNtb :: (ToPandoc a) => a -> String
+contextNtb = unpack . purely (writeConTeXt def{ writerExtensions = enableExtension Ext_ntb pandocExtensions }) . toPandoc
+
+contextDiv :: (ToPandoc a) => a -> String
+contextDiv = unpack . purely (writeConTeXt def{ writerSectionDivs = True }) . toPandoc
+
+{-
+  "my test" =: X =?> Y
+
+is shorthand for
+
+  test context "my test" $ X =?> Y
+
+which is in turn shorthand for
+
+  test context "my test" (X,Y)
+-}
+
+infix 4 =:
+(=:) :: (ToString a, ToPandoc a)
+     => String -> (a, String) -> TestTree
+(=:) = test context
+
+tests :: [TestTree]
+tests = [ testGroup "inline code"
+          [ "with '}'" =: code "}" =?> "\\mono{\\}}"
+          , "without '}'" =: code "]" =?> "\\type{]}"
+          , testProperty "code property" $ \s -> null s ||
+                if '{' `elem` s || '}' `elem` s
+                   then context' (code s) == "\\mono{" ++
+                             context' (str s) ++ "}"
+                   else context' (code s) == "\\type{" ++ s ++ "}"
+          ]
+        , testGroup "headers"
+          [ "level 1" =:
+            headerWith ("my-header",[],[]) 1 "My header" =?> "\\section[title={My header},reference={my-header}]"
+          , test contextDiv "section-divs" $
+                   (   headerWith ("header1", [], []) 1 (text "Header1")
+                    <> headerWith ("header2", [], []) 2 (text "Header2")
+                    <> headerWith ("header3", [], []) 3 (text "Header3")
+                    <> headerWith ("header4", [], []) 4 (text "Header4")
+                    <> headerWith ("header5", [], []) 5 (text "Header5")
+                    <> headerWith ("header6", [], []) 6 (text "Header6"))
+                   =?>
+              unlines [ "\\startsection[title={Header1},reference={header1}]\n"
+                      , "\\startsubsection[title={Header2},reference={header2}]\n"
+                      , "\\startsubsubsection[title={Header3},reference={header3}]\n"
+                      , "\\startsubsubsubsection[title={Header4},reference={header4}]\n"
+                      , "\\startsubsubsubsubsection[title={Header5},reference={header5}]\n"
+                      , "\\startsubsubsubsubsubsection[title={Header6},reference={header6}]\n"
+                      , "\\stopsubsubsubsubsubsection\n"
+                      , "\\stopsubsubsubsubsection\n"
+                      , "\\stopsubsubsubsection\n"
+                      , "\\stopsubsubsection\n"
+                      , "\\stopsubsection\n"
+                      , "\\stopsection" ]
+          ]
+        , testGroup "bullet lists"
+          [ "nested" =:
+            bulletList [
+               plain (text "top")
+                 <> bulletList [
+                   plain (text "next")
+                    <> bulletList [plain (text "bot")]
+                 ]
+            ] =?> unlines
+                [ "\\startitemize[packed]"
+                , "\\item"
+                , "  top"
+                , "  \\startitemize[packed]"
+                , "  \\item"
+                , "    next"
+                , "    \\startitemize[packed]"
+                , "    \\item"
+                , "      bot"
+                , "    \\stopitemize"
+                , "  \\stopitemize"
+                , "\\stopitemize" ]
+          ]
+        , testGroup "natural tables"
+            [ test contextNtb "table with header and caption" $
+              let caption = text "Table 1"
+                  aligns = [(AlignRight, 0.0), (AlignLeft, 0.0), (AlignCenter, 0.0), (AlignDefault, 0.0)]
+                  headers = [plain $ text "Right",
+                             plain $ text "Left",
+                             plain $ text "Center",
+                             plain $ text "Default"]
+                  rows = [[plain $ text "1.1",
+                           plain $ text "1.2",
+                           plain $ text "1.3",
+                           plain $ text "1.4"]
+                         ,[plain $ text "2.1",
+                           plain $ text "2.2",
+                           plain $ text "2.3",
+                           plain $ text "2.4"]
+                         ,[plain $ text "3.1",
+                           plain $ text "3.2",
+                           plain $ text "3.3",
+                           plain $ text "3.4"]]
+              in table caption aligns headers rows
+              =?> unlines [ "\\startplacetable[title={Table 1}]"
+                          , "\\startTABLE"
+                          , "\\startTABLEhead"
+                          , "\\NC[align=left] Right"
+                          , "\\NC[align=right] Left"
+                          , "\\NC[align=middle] Center"
+                          , "\\NC Default"
+                          , "\\NC\\NR"
+                          , "\\stopTABLEhead"
+                          , "\\startTABLEbody"
+                          , "\\NC[align=left] 1.1"
+                          , "\\NC[align=right] 1.2"
+                          , "\\NC[align=middle] 1.3"
+                          , "\\NC 1.4"
+                          , "\\NC\\NR"
+                          , "\\NC[align=left] 2.1"
+                          , "\\NC[align=right] 2.2"
+                          , "\\NC[align=middle] 2.3"
+                          , "\\NC 2.4"
+                          , "\\NC\\NR"
+                          , "\\stopTABLEbody"
+                          , "\\startTABLEfoot"
+                          , "\\NC[align=left] 3.1"
+                          , "\\NC[align=right] 3.2"
+                          , "\\NC[align=middle] 3.3"
+                          , "\\NC 3.4"
+                          , "\\NC\\NR"
+                          , "\\stopTABLEfoot"
+                          , "\\stopTABLE"
+                          , "\\stopplacetable" ]
+            ]
+        ]
diff --git a/test/Tests/Writers/Docbook.hs b/test/Tests/Writers/Docbook.hs
index 89ea76586..f6a047b0b 100644
--- a/test/Tests/Writers/Docbook.hs
+++ b/test/Tests/Writers/Docbook.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Writers.Docbook (tests) where
 
+import Prelude
 import Data.Text (unpack)
 import Test.Tasty
 import Tests.Helpers
diff --git a/test/Tests/Writers/Docbook.hs.orig b/test/Tests/Writers/Docbook.hs.orig
new file mode 100644
index 000000000..89ea76586
--- /dev/null
+++ b/test/Tests/Writers/Docbook.hs.orig
@@ -0,0 +1,303 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Writers.Docbook (tests) where
+
+import Data.Text (unpack)
+import Test.Tasty
+import Tests.Helpers
+import Text.Pandoc
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder
+
+docbook :: (ToPandoc a) => a -> String
+docbook = docbookWithOpts def{ writerWrapText = WrapNone }
+
+docbookWithOpts :: ToPandoc a => WriterOptions -> a -> String
+docbookWithOpts opts = unpack . purely (writeDocbook4 opts) . toPandoc
+
+{-
+  "my test" =: X =?> Y
+
+is shorthand for
+
+  test docbook "my test" $ X =?> Y
+
+which is in turn shorthand for
+
+  test docbook "my test" (X,Y)
+-}
+
+infix 4 =:
+(=:) :: (ToString a, ToPandoc a)
+     => String -> (a, String) -> TestTree
+(=:) = test docbook
+
+lineblock :: Blocks
+lineblock = para ("some text" <> linebreak <>
+                  "and more lines" <> linebreak <>
+                  "and again")
+lineblock_out :: [String]
+lineblock_out = [ "<literallayout>some text"
+                , "and more lines"
+                , "and again</literallayout>"
+                ]
+
+tests :: [TestTree]
+tests = [ testGroup "line blocks"
+          [ "none"       =: para "This is a test"
+                              =?> unlines
+                                    [ "<para>"
+                                    , "  This is a test"
+                                    , "</para>"
+                                    ]
+          , "basic"      =: lineblock
+                              =?> unlines lineblock_out
+          , "blockquote" =: blockQuote lineblock
+                              =?> unlines
+                                    ( [ "<blockquote>" ] ++
+                                      lineblock_out ++
+                                      [ "</blockquote>" ]
+                                    )
+          , "footnote"   =: para ("This is a test" <>
+                                  note lineblock <>
+                                  " of footnotes")
+                              =?> unlines
+                                    ( [ "<para>"
+                                      , "  This is a test<footnote>" ] ++
+                                      lineblock_out ++
+                                      [ "  </footnote> of footnotes"
+                                      , "</para>" ]
+                                    )
+          ]
+        , testGroup "compact lists"
+          [ testGroup "bullet"
+            [ "compact"    =: bulletList [plain "a", plain "b", plain "c"]
+                                =?> unlines
+                                      [ "<itemizedlist spacing=\"compact\">"
+                                      , "  <listitem>"
+                                      , "    <para>"
+                                      , "      a"
+                                      , "    </para>"
+                                      , "  </listitem>"
+                                      , "  <listitem>"
+                                      , "    <para>"
+                                      , "      b"
+                                      , "    </para>"
+                                      , "  </listitem>"
+                                      , "  <listitem>"
+                                      , "    <para>"
+                                      , "      c"
+                                      , "    </para>"
+                                      , "  </listitem>"
+                                      , "</itemizedlist>"
+                                      ]
+            , "loose"      =: bulletList [para "a", para "b", para "c"]
+                                =?> unlines
+                                      [ "<itemizedlist>"
+                                      , "  <listitem>"
+                                      , "    <para>"
+                                      , "      a"
+                                      , "    </para>"
+                                      , "  </listitem>"
+                                      , "  <listitem>"
+                                      , "    <para>"
+                                      , "      b"
+                                      , "    </para>"
+                                      , "  </listitem>"
+                                      , "  <listitem>"
+                                      , "    <para>"
+                                      , "      c"
+                                      , "    </para>"
+                                      , "  </listitem>"
+                                      , "</itemizedlist>"
+                                      ]
+            ]
+          , testGroup "ordered"
+            [ "compact"    =: orderedList [plain "a", plain "b", plain "c"]
+                                =?> unlines
+                                      [ "<orderedlist spacing=\"compact\">"
+                                      , "  <listitem>"
+                                      , "    <para>"
+                                      , "      a"
+                                      , "    </para>"
+                                      , "  </listitem>"
+                                      , "  <listitem>"
+                                      , "    <para>"
+                                      , "      b"
+                                      , "    </para>"
+                                      , "  </listitem>"
+                                      , "  <listitem>"
+                                      , "    <para>"
+                                      , "      c"
+                                      , "    </para>"
+                                      , "  </listitem>"
+                                      , "</orderedlist>"
+                                      ]
+            , "loose"      =: orderedList [para "a", para "b", para "c"]
+                                =?> unlines
+                                      [ "<orderedlist>"
+                                      , "  <listitem>"
+                                      , "    <para>"
+                                      , "      a"
+                                      , "    </para>"
+                                      , "  </listitem>"
+                                      , "  <listitem>"
+                                      , "    <para>"
+                                      , "      b"
+                                      , "    </para>"
+                                      , "  </listitem>"
+                                      , "  <listitem>"
+                                      , "    <para>"
+                                      , "      c"
+                                      , "    </para>"
+                                      , "  </listitem>"
+                                      , "</orderedlist>"
+                                      ]
+            ]
+          , testGroup "definition"
+            [ "compact"    =: definitionList [ ("an", [plain "apple" ])
+                                             , ("a",  [plain "banana"])
+                                             , ("an", [plain "orange"])]
+                                =?> unlines
+                                      [ "<variablelist spacing=\"compact\">"
+                                      , "  <varlistentry>"
+                                      , "    <term>"
+                                      , "      an"
+                                      , "    </term>"
+                                      , "    <listitem>"
+                                      , "      <para>"
+                                      , "        apple"
+                                      , "      </para>"
+                                      , "    </listitem>"
+                                      , "  </varlistentry>"
+                                      , "  <varlistentry>"
+                                      , "    <term>"
+                                      , "      a"
+                                      , "    </term>"
+                                      , "    <listitem>"
+                                      , "      <para>"
+                                      , "        banana"
+                                      , "      </para>"
+                                      , "    </listitem>"
+                                      , "  </varlistentry>"
+                                      , "  <varlistentry>"
+                                      , "    <term>"
+                                      , "      an"
+                                      , "    </term>"
+                                      , "    <listitem>"
+                                      , "      <para>"
+                                      , "        orange"
+                                      , "      </para>"
+                                      , "    </listitem>"
+                                      , "  </varlistentry>"
+                                      , "</variablelist>"
+                                      ]
+            , "loose"      =: definitionList [ ("an", [para "apple" ])
+                                             , ("a",  [para "banana"])
+                                             , ("an", [para "orange"])]
+                                =?> unlines
+                                      [ "<variablelist>"
+                                      , "  <varlistentry>"
+                                      , "    <term>"
+                                      , "      an"
+                                      , "    </term>"
+                                      , "    <listitem>"
+                                      , "      <para>"
+                                      , "        apple"
+                                      , "      </para>"
+                                      , "    </listitem>"
+                                      , "  </varlistentry>"
+                                      , "  <varlistentry>"
+                                      , "    <term>"
+                                      , "      a"
+                                      , "    </term>"
+                                      , "    <listitem>"
+                                      , "      <para>"
+                                      , "        banana"
+                                      , "      </para>"
+                                      , "    </listitem>"
+                                      , "  </varlistentry>"
+                                      , "  <varlistentry>"
+                                      , "    <term>"
+                                      , "      an"
+                                      , "    </term>"
+                                      , "    <listitem>"
+                                      , "      <para>"
+                                      , "        orange"
+                                      , "      </para>"
+                                      , "    </listitem>"
+                                      , "  </varlistentry>"
+                                      , "</variablelist>"
+                                      ]
+            ]
+          ]
+        , testGroup "writer options"
+          [ testGroup "top-level division" $
+            let
+              headers =  header 1 (text "header1")
+                      <> header 2 (text "header2")
+                      <> header 3 (text "header3")
+
+              docbookTopLevelDiv :: (ToPandoc a)
+                                 => TopLevelDivision -> a -> String
+              docbookTopLevelDiv division =
+                docbookWithOpts def{ writerTopLevelDivision = division }
+            in
+            [ test (docbookTopLevelDiv TopLevelSection) "sections as top-level" $
+              headers =?>
+              unlines [ "<sect1>"
+                      , "  <title>header1</title>"
+                      , "  <sect2>"
+                      , "    <title>header2</title>"
+                      , "    <sect3>"
+                      , "      <title>header3</title>"
+                      , "      <para>"
+                      , "      </para>"
+                      , "    </sect3>"
+                      , "  </sect2>"
+                      , "</sect1>"
+                      ]
+            , test (docbookTopLevelDiv TopLevelChapter) "chapters as top-level" $
+              headers =?>
+              unlines [ "<chapter>"
+                      , "  <title>header1</title>"
+                      , "  <sect1>"
+                      , "    <title>header2</title>"
+                      , "    <sect2>"
+                      , "      <title>header3</title>"
+                      , "      <para>"
+                      , "      </para>"
+                      , "    </sect2>"
+                      , "  </sect1>"
+                      , "</chapter>"
+                      ]
+            , test (docbookTopLevelDiv TopLevelPart) "parts as top-level" $
+              headers =?>
+              unlines [ "<part>"
+                      , "  <title>header1</title>"
+                      , "  <chapter>"
+                      , "    <title>header2</title>"
+                      , "    <sect1>"
+                      , "      <title>header3</title>"
+                      , "      <para>"
+                      , "      </para>"
+                      , "    </sect1>"
+                      , "  </chapter>"
+                      , "</part>"
+                      ]
+            , test (docbookTopLevelDiv TopLevelDefault) "default top-level" $
+              headers =?>
+              unlines [ "<sect1>"
+                      , "  <title>header1</title>"
+                      , "  <sect2>"
+                      , "    <title>header2</title>"
+                      , "    <sect3>"
+                      , "      <title>header3</title>"
+                      , "      <para>"
+                      , "      </para>"
+                      , "    </sect3>"
+                      , "  </sect2>"
+                      , "</sect1>"
+                      ]
+            ]
+          ]
+        ]
diff --git a/test/Tests/Writers/Docx.hs b/test/Tests/Writers/Docx.hs
index 3ded0aa38..d17984d63 100644
--- a/test/Tests/Writers/Docx.hs
+++ b/test/Tests/Writers/Docx.hs
@@ -1,5 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 module Tests.Writers.Docx (tests) where
 
+import Prelude
 import Text.Pandoc
 import Test.Tasty
 import Tests.Writers.OOXML
diff --git a/test/Tests/Writers/Docx.hs.orig b/test/Tests/Writers/Docx.hs.orig
new file mode 100644
index 000000000..3ded0aa38
--- /dev/null
+++ b/test/Tests/Writers/Docx.hs.orig
@@ -0,0 +1,157 @@
+module Tests.Writers.Docx (tests) where
+
+import Text.Pandoc
+import Test.Tasty
+import Tests.Writers.OOXML
+import Test.Tasty.HUnit
+import Data.List (isPrefixOf)
+
+-- we add an extra check to make sure that we're not writing in the
+-- toplevel docx directory. We don't want to accidentally overwrite an
+-- Word-generated docx file used to test the reader.
+docxTest :: String -> WriterOptions -> FilePath -> FilePath -> TestTree
+docxTest testName opts nativeFP goldenFP =
+  if "docx/golden/" `isPrefixOf` goldenFP
+  then ooxmlTest writeDocx testName opts nativeFP goldenFP
+  else testCase testName $
+       assertFailure $
+       goldenFP ++ " is not in `test/docx/golden`"
+
+tests :: [TestTree]
+tests = [ testGroup "inlines"
+          [ docxTest
+            "font formatting"
+            def
+            "docx/inline_formatting.native"
+            "docx/golden/inline_formatting.docx"
+          , docxTest
+            "hyperlinks"
+            def
+            "docx/links.native"
+            "docx/golden/links.docx"
+          , docxTest
+            "inline image"
+            def
+            "docx/image_writer_test.native"
+            "docx/golden/image.docx"
+          , docxTest
+            "inline images"
+            def
+            "docx/inline_images_writer_test.native"
+            "docx/golden/inline_images.docx"
+          , docxTest
+            "handling unicode input"
+            def
+            "docx/unicode.native"
+            "docx/golden/unicode.docx"
+          , docxTest
+            "inline code"
+            def
+            "docx/inline_code.native"
+            "docx/golden/inline_code.docx"
+          , docxTest
+            "inline code in subscript and superscript"
+            def
+            "docx/verbatim_subsuper.native"
+            "docx/golden/verbatim_subsuper.docx"
+          ]
+        , testGroup "blocks"
+          [ docxTest
+            "headers"
+            def
+            "docx/headers.native"
+            "docx/golden/headers.docx"
+          , docxTest
+            "nested anchor spans in header"
+            def
+            "docx/nested_anchors_in_header.native"
+            "docx/golden/nested_anchors_in_header.docx"
+          , docxTest
+            "lists"
+            def
+            "docx/lists.native"
+            "docx/golden/lists.docx"
+          , docxTest
+            "lists continuing after interruption"
+            def
+            "docx/lists_continuing.native"
+            "docx/golden/lists_continuing.docx"
+          , docxTest
+            "lists restarting after interruption"
+            def
+            "docx/lists_restarting.native"
+            "docx/golden/lists_restarting.docx"
+          , docxTest
+            "definition lists"
+            def
+            "docx/definition_list.native"
+            "docx/golden/definition_list.docx"
+          , docxTest
+            "footnotes and endnotes"
+            def
+            "docx/notes.native"
+            "docx/golden/notes.docx"
+          , docxTest
+            "links in footnotes and endnotes"
+            def
+            "docx/link_in_notes.native"
+            "docx/golden/link_in_notes.docx"
+          , docxTest
+            "blockquotes"
+            def
+            "docx/block_quotes_parse_indent.native"
+            "docx/golden/block_quotes.docx"
+          , docxTest
+            "tables"
+            def
+            "docx/tables.native"
+            "docx/golden/tables.docx"
+          , docxTest
+            "tables with lists in cells"
+            def
+            "docx/table_with_list_cell.native"
+            "docx/golden/table_with_list_cell.docx"
+          , docxTest
+            "tables with one row"
+            def
+            "docx/table_one_row.native"
+            "docx/golden/table_one_row.docx"
+          , docxTest
+            "code block"
+            def
+            "docx/codeblock.native"
+            "docx/golden/codeblock.docx"
+          ]
+        , testGroup "track changes"
+          [ docxTest
+            "insertion"
+            def
+            "docx/track_changes_insertion_all.native"
+            "docx/golden/track_changes_insertion.docx"
+          , docxTest
+            "deletion"
+            def
+            "docx/track_changes_deletion_all.native"
+            "docx/golden/track_changes_deletion.docx"
+          , docxTest
+            "move text"
+            def
+            "docx/track_changes_move_all.native"
+            "docx/golden/track_changes_move.docx"
+          , docxTest
+            "comments"
+            def
+            "docx/comments.native"
+            "docx/golden/comments.docx"
+          ]
+        , testGroup "custom styles"
+          [ docxTest "custom styles without reference.docx"
+            def
+            "docx/custom_style.native"
+            "docx/golden/custom_style_no_reference.docx"
+          , docxTest "custom styles with reference.docx"
+            def{writerReferenceDoc = Just "docx/custom-style-reference.docx"}
+            "docx/custom_style.native"
+            "docx/golden/custom_style_reference.docx"
+          ]
+        ]
diff --git a/test/Tests/Writers/FB2.hs b/test/Tests/Writers/FB2.hs
index 6663c42f8..7699c58e9 100644
--- a/test/Tests/Writers/FB2.hs
+++ b/test/Tests/Writers/FB2.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Writers.FB2 (tests) where
 
+import Prelude
 import Test.Tasty
 import Tests.Helpers
 import Text.Pandoc
@@ -23,8 +25,8 @@ tests = [ testGroup "block elements"
           ]
         , testGroup "inlines"
           [
-            "Emphasis"      =:  emph "emphasized"
-                            =?> fb2 "<emphasis>emphasized</emphasis>"
+            "Emphasis"      =:  para (emph "emphasized")
+                            =?> fb2 "<p><emphasis>emphasized</emphasis></p>"
           ]
         , "bullet list" =: bulletList [ plain $ text "first"
                                       , plain $ text "second"
diff --git a/test/Tests/Writers/FB2.hs.orig b/test/Tests/Writers/FB2.hs.orig
new file mode 100644
index 000000000..6663c42f8
--- /dev/null
+++ b/test/Tests/Writers/FB2.hs.orig
@@ -0,0 +1,34 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Writers.FB2 (tests) where
+
+import Test.Tasty
+import Tests.Helpers
+import Text.Pandoc
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder
+
+fb2 :: String -> String
+fb2 x = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ++
+        "<FictionBook xmlns=\"http://www.gribuser.ru/xml/fictionbook/2.0\" xmlns:l=\"http://www.w3.org/1999/xlink\"><description><title-info><genre>unrecognised</genre></title-info><document-info><program-used>pandoc</program-used></document-info></description><body><title><p /></title><section>" ++ x ++ "</section></body></FictionBook>"
+
+infix 4 =:
+(=:) :: (ToString a, ToPandoc a)
+     => String -> (a, String) -> TestTree
+(=:) = test (purely (writeFB2 def) . toPandoc)
+
+tests :: [TestTree]
+tests = [ testGroup "block elements"
+          ["para"          =: para "Lorem ipsum cetera."
+                           =?> fb2 "<p>Lorem ipsum cetera.</p>"
+          ]
+        , testGroup "inlines"
+          [
+            "Emphasis"      =:  emph "emphasized"
+                            =?> fb2 "<emphasis>emphasized</emphasis>"
+          ]
+        , "bullet list" =: bulletList [ plain $ text "first"
+                                      , plain $ text "second"
+                                      , plain $ text "third"
+                                      ]
+                        =?> fb2 "<p>\x2022 first</p><p>\x2022 second</p><p>\x2022 third</p>"
+         ]
diff --git a/test/Tests/Writers/HTML.hs b/test/Tests/Writers/HTML.hs
index 23ff718d3..e771255b3 100644
--- a/test/Tests/Writers/HTML.hs
+++ b/test/Tests/Writers/HTML.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Writers.HTML (tests) where
 
+import Prelude
 import Data.Text (unpack)
 import Test.Tasty
 import Tests.Helpers
diff --git a/test/Tests/Writers/HTML.hs.orig b/test/Tests/Writers/HTML.hs.orig
new file mode 100644
index 000000000..23ff718d3
--- /dev/null
+++ b/test/Tests/Writers/HTML.hs.orig
@@ -0,0 +1,44 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Writers.HTML (tests) where
+
+import Data.Text (unpack)
+import Test.Tasty
+import Tests.Helpers
+import Text.Pandoc
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder
+
+html :: (ToPandoc a) => a -> String
+html = unpack . purely (writeHtml4String def{ writerWrapText = WrapNone }) . toPandoc
+
+{-
+  "my test" =: X =?> Y
+
+is shorthand for
+
+  test html "my test" $ X =?> Y
+
+which is in turn shorthand for
+
+  test html "my test" (X,Y)
+-}
+
+infix 4 =:
+(=:) :: (ToString a, ToPandoc a)
+     => String -> (a, String) -> TestTree
+(=:) = test html
+
+tests :: [TestTree]
+tests = [ testGroup "inline code"
+          [ "basic" =: code "@&" =?> "<code>@&amp;</code>"
+          , "haskell" =: codeWith ("",["haskell"],[]) ">>="
+            =?> "<code class=\"sourceCode haskell\"><span class=\"fu\">&gt;&gt;=</span></code>"
+          , "nolanguage" =: codeWith ("",["nolanguage"],[]) ">>="
+            =?> "<code class=\"nolanguage\">&gt;&gt;=</code>"
+          ]
+        , testGroup "images"
+          [ "alt with formatting" =:
+            image "/url" "title" ("my " <> emph "image")
+            =?> "<img src=\"/url\" title=\"title\" alt=\"my image\" />"
+          ]
+        ]
diff --git a/test/Tests/Writers/JATS.hs b/test/Tests/Writers/JATS.hs
index 572b16451..669220eea 100644
--- a/test/Tests/Writers/JATS.hs
+++ b/test/Tests/Writers/JATS.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Writers.JATS (tests) where
 
+import Prelude
 import Data.Text (unpack)
 import Test.Tasty
 import Tests.Helpers
@@ -30,8 +32,8 @@ infix 4 =:
 
 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>"
+          [ "basic" =: code "@&" =?> "<p><monospace>@&amp;</monospace></p>"
+          , "lang" =: codeWith ("", ["c"], []) "@&" =?> "<p><code language=\"c\">@&amp;</code></p>"
           ]
         , testGroup "block code"
           [ "basic" =: codeBlock "@&" =?> "<preformat>@&amp;</preformat>"
@@ -44,7 +46,7 @@ tests = [ testGroup "inline code"
           ]
         , testGroup "inlines"
           [ "Emphasis" =: emph "emphasized"
-            =?> "<p>\n  <italic>emphasized</italic>\n</p>"
+            =?> "<p><italic>emphasized</italic></p>"
           ]
         , "bullet list" =: bulletList [ plain $ text "first"
                                       , plain $ text "second"
@@ -52,19 +54,13 @@ tests = [ testGroup "inline code"
                                       ]
             =?> "<list list-type=\"bullet\">\n\
                 \  <list-item>\n\
-                \    <p>\n\
-                \      first\n\
-                \    </p>\n\
+                \    <p>first</p>\n\
                 \  </list-item>\n\
                 \  <list-item>\n\
-                \    <p>\n\
-                \      second\n\
-                \    </p>\n\
+                \    <p>second</p>\n\
                 \  </list-item>\n\
                 \  <list-item>\n\
-                \    <p>\n\
-                \      third\n\
-                \    </p>\n\
+                \    <p>third</p>\n\
                 \  </list-item>\n\
                 \</list>"
         , testGroup "definition lists"
@@ -72,24 +68,18 @@ tests = [ testGroup "inline code"
              [plain (text "hi there")])] =?>
             "<def-list>\n\
             \  <def-item>\n\
-            \    <term>\n\
-            \      <xref alt=\"testing\" rid=\"go\">testing</xref>\n\
-            \    </term>\n\
+            \    <term><xref alt=\"testing\" rid=\"go\">testing</xref></term>\n\
             \    <def>\n\
-            \      <p>\n\
-            \        hi there\n\
-            \      </p>\n\
+            \      <p>hi there</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>"
+            "<p><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></p>"
           ]
         , testGroup "headers"
           [ "unnumbered header" =:
@@ -97,9 +87,7 @@ tests = [ testGroup "inline code"
               (text "Header 1" <> note (plain $ text "note")) =?>
             "<sec id=\"foo\">\n\
             \  <title>Header 1<fn>\n\
-            \    <p>\n\
-            \      note\n\
-            \    </p>\n\
+            \    <p>note</p>\n\
             \  </fn></title>\n\
             \</sec>"
           , "unnumbered sub header" =:
diff --git a/test/Tests/Writers/JATS.hs.orig b/test/Tests/Writers/JATS.hs.orig
new file mode 100644
index 000000000..723c0e8a8
--- /dev/null
+++ b/test/Tests/Writers/JATS.hs.orig
@@ -0,0 +1,108 @@
+{-# 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><monospace>@&amp;</monospace></p>"
+          , "lang" =: codeWith ("", ["c"], []) "@&" =?> "<p><code language=\"c\">@&amp;</code></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><italic>emphasized</italic></p>"
+          ]
+        , "bullet list" =: bulletList [ plain $ text "first"
+                                      , plain $ text "second"
+                                      , plain $ text "third"
+                                      ]
+            =?> "<list list-type=\"bullet\">\n\
+                \  <list-item>\n\
+                \    <p>first</p>\n\
+                \  </list-item>\n\
+                \  <list-item>\n\
+                \    <p>second</p>\n\
+                \  </list-item>\n\
+                \  <list-item>\n\
+                \    <p>third</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><xref alt=\"testing\" rid=\"go\">testing</xref></term>\n\
+            \    <def>\n\
+            \      <p>hi there</p>\n\
+            \    </def>\n\
+            \  </def-item>\n\
+            \</def-list>"
+          ]
+        , testGroup "math"
+          [ "escape |" =: para (math "\\sigma|_{\\{x\\}}") =?>
+            "<p><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></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>note</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/LaTeX.hs b/test/Tests/Writers/LaTeX.hs
index 471d9d9e7..00150022f 100644
--- a/test/Tests/Writers/LaTeX.hs
+++ b/test/Tests/Writers/LaTeX.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Writers.LaTeX (tests) where
 
+import Prelude
 import Data.Text (unpack)
 import Test.Tasty
 import Tests.Helpers
diff --git a/test/Tests/Writers/LaTeX.hs.orig b/test/Tests/Writers/LaTeX.hs.orig
new file mode 100644
index 000000000..471d9d9e7
--- /dev/null
+++ b/test/Tests/Writers/LaTeX.hs.orig
@@ -0,0 +1,176 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Writers.LaTeX (tests) where
+
+import Data.Text (unpack)
+import Test.Tasty
+import Tests.Helpers
+import Text.Pandoc
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder
+
+latex :: (ToPandoc a) => a -> String
+latex = latexWithOpts def
+
+latexListing :: (ToPandoc a) => a -> String
+latexListing = latexWithOpts def{ writerListings = True }
+
+latexWithOpts :: (ToPandoc a) => WriterOptions -> a -> String
+latexWithOpts opts = unpack . purely (writeLaTeX opts) . toPandoc
+
+beamerWithOpts :: (ToPandoc a) => WriterOptions -> a -> String
+beamerWithOpts opts = unpack . purely (writeBeamer opts) . toPandoc
+
+{-
+  "my test" =: X =?> Y
+
+is shorthand for
+
+  test latex "my test" $ X =?> Y
+
+which is in turn shorthand for
+
+  test latex "my test" (X,Y)
+-}
+
+infix 4 =:
+(=:) :: (ToString a, ToPandoc a)
+     => String -> (a, String) -> TestTree
+(=:) = test latex
+
+tests :: [TestTree]
+tests = [ testGroup "code blocks"
+          [ "in footnotes" =: note (para "hi" <> codeBlock "hi") =?>
+            "\\footnote{hi\n\n\\begin{Verbatim}\nhi\n\\end{Verbatim}\n}"
+          , test latexListing "identifier" $ codeBlockWith ("id",[],[]) "hi" =?>
+            ("\\begin{lstlisting}[label=id]\nhi\n\\end{lstlisting}" :: String)
+          , test latexListing "no identifier" $ codeBlock "hi" =?>
+            ("\\begin{lstlisting}\nhi\n\\end{lstlisting}" :: String)
+          ]
+        , testGroup "definition lists"
+          [ "with internal link" =: definitionList [(link "#go" "" (str "testing"),
+             [plain (text "hi there")])] =?>
+            "\\begin{description}\n\\tightlist\n\\item[{\\protect\\hyperlink{go}{testing}}]\nhi there\n\\end{description}"
+          ]
+        , testGroup "math"
+          [ "escape |" =: para (math "\\sigma|_{\\{x\\}}") =?>
+            "\\(\\sigma|_{\\{x\\}}\\)"
+          ]
+        , testGroup "headers"
+          [ "unnumbered header" =:
+            headerWith ("foo",["unnumbered"],[]) 1
+              (text "Header 1" <> note (plain $ text "note")) =?>
+            "\\hypertarget{foo}{%\n\\section*{\\texorpdfstring{Header 1\\footnote{note}}{Header 1}}\\label{foo}}\n\\addcontentsline{toc}{section}{Header 1}\n"
+          , "in list item" =:
+            bulletList [header 2 (text "foo")] =?>
+            "\\begin{itemize}\n\\item ~\n  \\subsection{foo}\n\\end{itemize}"
+          , "in definition list item" =:
+            definitionList [(text "foo", [header 2 (text "bar"),
+                                          para $ text "baz"])] =?>
+            "\\begin{description}\n\\item[foo] ~ \n\\subsection{bar}\n\nbaz\n\\end{description}"
+          , "containing image" =:
+            header 1 (image "imgs/foo.jpg" "" (text "Alt text")) =?>
+            "\\section{\\texorpdfstring{\\protect\\includegraphics{imgs/foo.jpg}}{Alt text}}"
+          ]
+        , testGroup "inline code"
+          [ "struck out and highlighted" =:
+            strikeout (codeWith ("",["haskell"],[]) "foo" <> space
+              <> str "bar") =?>
+            "\\sout{\\mbox{\\VERB|\\NormalTok{foo}|} bar}"
+          , "struck out and not highlighted" =:
+            strikeout (code "foo" <> space
+              <> str "bar") =?>
+            "\\sout{\\texttt{foo} bar}"
+          , "single quotes" =:
+              code "dog's" =?> "\\texttt{dog\\textquotesingle{}s}"
+          , "backtick" =:
+              code "`nu?`" =?> "\\texttt{\\textasciigrave{}nu?\\textasciigrave{}}"
+          ]
+        , testGroup "writer options"
+          [ testGroup "top-level division" $
+            let
+              headers =  header 1 (text "header1")
+                      <> header 2 (text "header2")
+                      <> header 3 (text "header3")
+
+              latexTopLevelDiv :: (ToPandoc a) => TopLevelDivision -> a -> String
+              latexTopLevelDiv division =
+                latexWithOpts def{ writerTopLevelDivision = division }
+
+              beamerTopLevelDiv :: (ToPandoc a)
+                                => TopLevelDivision -> a -> String
+              beamerTopLevelDiv division =
+                beamerWithOpts def { writerTopLevelDivision = division }
+            in
+            [ test (latexTopLevelDiv TopLevelSection)
+                   "sections as top-level" $ headers =?>
+              unlines [ "\\section{header1}\n"
+                      , "\\subsection{header2}\n"
+                      , "\\subsubsection{header3}"
+                      ]
+            , test (latexTopLevelDiv TopLevelChapter)
+                   "chapters as top-level" $ headers =?>
+              unlines [ "\\chapter{header1}\n"
+                      , "\\section{header2}\n"
+                      , "\\subsection{header3}"
+                      ]
+            , test (latexTopLevelDiv TopLevelPart)
+                   "parts as top-level" $ headers =?>
+              unlines [ "\\part{header1}\n"
+                      , "\\chapter{header2}\n"
+                      , "\\section{header3}"
+                      ]
+            , test (latexTopLevelDiv TopLevelDefault)
+                   "default top-level" $ headers =?>
+              unlines [ "\\section{header1}\n"
+                      , "\\subsection{header2}\n"
+                      , "\\subsubsection{header3}"
+                      ]
+            , test (beamerTopLevelDiv TopLevelSection)
+                   "sections as top-level in beamer" $ headers =?>
+              unlines [ "\\section{header1}\n"
+                      , "\\subsection{header2}\n"
+                      , "\\subsubsection{header3}"
+                      ]
+            , test (beamerTopLevelDiv TopLevelChapter)
+                   "chapters are as part in beamer" $ headers =?>
+              unlines [ "\\part{header1}\n"
+                      , "\\section{header2}\n"
+                      , "\\subsection{header3}"
+                      ]
+            , test (beamerTopLevelDiv TopLevelPart)
+                   "parts as top-level in beamer" $ headers =?>
+              unlines [ "\\part{header1}\n"
+                      , "\\section{header2}\n"
+                      , "\\subsection{header3}"
+                      ]
+            , test (beamerTopLevelDiv TopLevelDefault)
+                   "default top-level in beamer" $ headers =?>
+              unlines [ "\\section{header1}\n"
+                      , "\\subsection{header2}\n"
+                      , "\\subsubsection{header3}"
+                      ]
+            , test (latexTopLevelDiv TopLevelPart)
+                   "part top-level, section not in toc" $
+                   (   headerWith ("", ["unnumbered"], []) 1 (text "header1")
+                    <> headerWith ("", ["unnumbered"], []) 2 (text "header2")
+                    <> headerWith ("", ["unnumbered"], []) 3 (text "header3")
+                    <> headerWith ("", ["unnumbered"], []) 4 (text "header4")
+                    <> headerWith ("", ["unnumbered"], []) 5 (text "header5")
+                    <> headerWith ("", ["unnumbered"], []) 6 (text "header6"))
+                   =?>
+              unlines [ "\\part*{header1}"
+                      , "\\addcontentsline{toc}{part}{header1}\n"
+                      , "\\chapter*{header2}"
+                      , "\\addcontentsline{toc}{chapter}{header2}\n"
+                      , "\\section*{header3}"
+                      , "\\addcontentsline{toc}{section}{header3}\n"
+                      , "\\subsection*{header4}"
+                      , "\\addcontentsline{toc}{subsection}{header4}\n"
+                      , "\\subsubsection*{header5}"
+                      , "\\addcontentsline{toc}{subsubsection}{header5}\n"
+                      , "\\paragraph{header6}"
+                      , "\\addcontentsline{toc}{paragraph}{header6}"
+                      ]
+            ]
+          ]
+        ]
diff --git a/test/Tests/Writers/Markdown.hs b/test/Tests/Writers/Markdown.hs
index 7f9ac3627..533be268a 100644
--- a/test/Tests/Writers/Markdown.hs
+++ b/test/Tests/Writers/Markdown.hs
@@ -1,7 +1,9 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# OPTIONS_GHC -fno-warn-name-shadowing #-}
 module Tests.Writers.Markdown (tests) where
 
+import Prelude
 import Data.Text (unpack)
 import Test.Tasty
 import Tests.Helpers
diff --git a/test/Tests/Writers/Markdown.hs.orig b/test/Tests/Writers/Markdown.hs.orig
new file mode 100644
index 000000000..7f9ac3627
--- /dev/null
+++ b/test/Tests/Writers/Markdown.hs.orig
@@ -0,0 +1,267 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
+module Tests.Writers.Markdown (tests) where
+
+import Data.Text (unpack)
+import Test.Tasty
+import Tests.Helpers
+import Text.Pandoc
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder
+
+defopts :: WriterOptions
+defopts = def{ writerExtensions = pandocExtensions }
+
+markdown :: (ToPandoc a) => a -> String
+markdown = unpack . purely (writeMarkdown defopts) . toPandoc
+
+markdownWithOpts :: (ToPandoc a) => WriterOptions -> a -> String
+markdownWithOpts opts x = unpack . purely (writeMarkdown opts) $ toPandoc x
+
+{-
+  "my test" =: X =?> Y
+
+is shorthand for
+
+  test markdown "my test" $ X =?> Y
+
+which is in turn shorthand for
+
+  test markdown "my test" (X,Y)
+-}
+
+infix 4 =:
+(=:) :: (ToString a, ToPandoc a)
+     => String -> (a, String) -> TestTree
+(=:) = test markdown
+
+tests :: [TestTree]
+tests = [ "indented code after list"
+             =: (orderedList [ para "one" <> para "two" ] <> codeBlock "test")
+             =?> "1.  one\n\n    two\n\n<!-- -->\n\n    test"
+        , "list with tight sublist"
+             =: bulletList [ plain "foo" <> bulletList [ plain "bar" ],
+                             plain "baz" ]
+             =?> "-   foo\n    -   bar\n-   baz\n"
+        ] ++ [noteTests] ++ [shortcutLinkRefsTests]
+
+{-
+
+Testing with the following text:
+
+First Header
+============
+
+This is a footnote.[^1] And this is a [link](https://www.google.com).
+
+> A note inside a block quote.[^2]
+>
+> A second paragraph.
+
+Second Header
+=============
+
+Some more text.
+
+
+[^1]: Down here.
+
+[^2]: The second note.
+
+-}
+
+noteTestDoc :: Blocks
+noteTestDoc =
+  header 1 "First Header" <>
+  para ("This is a footnote." <>
+        note (para "Down here.") <>
+        " And this is a " <>
+        link "https://www.google.com" "" "link" <>
+        ".") <>
+  blockQuote (para ("A note inside a block quote." <>
+                    note (para "The second note.")) <>
+              para "A second paragraph.") <>
+  header 1 "Second Header" <>
+  para "Some more text."
+
+
+
+noteTests :: TestTree
+noteTests = testGroup "note and reference location"
+  [ test (markdownWithOpts defopts)
+    "footnotes at the end of a document" $
+    noteTestDoc =?>
+    (unlines [ "First Header"
+               , "============"
+               , ""
+               , "This is a footnote.[^1] And this is a [link](https://www.google.com)."
+               , ""
+               , "> A note inside a block quote.[^2]"
+               , ">"
+               , "> A second paragraph."
+               , ""
+               , "Second Header"
+               , "============="
+               , ""
+               , "Some more text."
+               , ""
+               , "[^1]: Down here."
+               , ""
+               , "[^2]: The second note."
+               ])
+  , test (markdownWithOpts defopts{writerReferenceLocation=EndOfBlock})
+    "footnotes at the end of blocks" $
+    noteTestDoc =?>
+    (unlines [ "First Header"
+               , "============"
+               , ""
+               , "This is a footnote.[^1] And this is a [link](https://www.google.com)."
+               , ""
+               , "[^1]: Down here."
+               , ""
+               , "> A note inside a block quote.[^2]"
+               , ">"
+               , "> A second paragraph."
+               , ""
+               , "[^2]: The second note."
+               , ""
+               , "Second Header"
+               , "============="
+               , ""
+               , "Some more text."
+               ])
+  , test (markdownWithOpts defopts{writerReferenceLocation=EndOfBlock, writerReferenceLinks=True})
+    "footnotes and reference links at the end of blocks" $
+    noteTestDoc =?>
+    (unlines [ "First Header"
+               , "============"
+               , ""
+               , "This is a footnote.[^1] And this is a [link]."
+               , ""
+               , "[^1]: Down here."
+               , ""
+               , "  [link]: https://www.google.com"
+               , ""
+               , "> A note inside a block quote.[^2]"
+               , ">"
+               , "> A second paragraph."
+               , ""
+               , "[^2]: The second note."
+               , ""
+               , "Second Header"
+               , "============="
+               , ""
+               , "Some more text."
+               ])
+  , test (markdownWithOpts defopts{writerReferenceLocation=EndOfSection})
+    "footnotes at the end of section" $
+    noteTestDoc =?>
+    (unlines [ "First Header"
+               , "============"
+               , ""
+               , "This is a footnote.[^1] And this is a [link](https://www.google.com)."
+               , ""
+               , "> A note inside a block quote.[^2]"
+               , ">"
+               , "> A second paragraph."
+               , ""
+               , "[^1]: Down here."
+               , ""
+               , "[^2]: The second note."
+               , ""
+               , "Second Header"
+               , "============="
+               , ""
+               , "Some more text."
+               ])
+
+  ]
+
+shortcutLinkRefsTests :: TestTree
+shortcutLinkRefsTests =
+  let infix 4 =:
+      (=:) :: (ToString a, ToPandoc a)
+
+        => String -> (a, String) -> TestTree
+      (=:) = test (purely (writeMarkdown defopts{writerReferenceLinks = True}) . toPandoc)
+  in testGroup "Shortcut reference links"
+     [ "Simple link (shortcutable)"
+           =: para (link "/url" "title" "foo")
+           =?> "[foo]\n\n  [foo]: /url \"title\""
+     , "Followed by another link (unshortcutable)"
+           =: para ((link "/url1" "title1" "first")
+                  <> (link "/url2" "title2" "second"))
+           =?> unlines [ "[first][][second]"
+                       , ""
+                       , "  [first]: /url1 \"title1\""
+                       , "  [second]: /url2 \"title2\""
+                       ]
+     , "Followed by space and another link (unshortcutable)"
+           =: para ((link "/url1" "title1" "first") <> " "
+                  <> (link "/url2" "title2" "second"))
+           =?> unlines [ "[first][] [second]"
+                       , ""
+                       , "  [first]: /url1 \"title1\""
+                       , "  [second]: /url2 \"title2\""
+                       ]
+     , "Reference link is used multiple times (unshortcutable)"
+           =: para ((link "/url1" "" "foo") <> (link "/url2" "" "foo")
+                                             <> (link "/url3" "" "foo"))
+           =?> unlines [ "[foo][][foo][1][foo][2]"
+                       , ""
+                       , "  [foo]: /url1"
+                       , "  [1]: /url2"
+                       , "  [2]: /url3"
+                       ]
+     , "Reference link is used multiple times (unshortcutable)"
+           =: para ((link "/url1" "" "foo") <> " " <> (link "/url2" "" "foo")
+                                             <> " " <> (link "/url3" "" "foo"))
+           =?> unlines [ "[foo][] [foo][1] [foo][2]"
+                       , ""
+                       , "  [foo]: /url1"
+                       , "  [1]: /url2"
+                       , "  [2]: /url3"
+                       ]
+     , "Reference link is followed by text in brackets"
+          =:  para ((link "/url" "" "link") <> "[text in brackets]")
+          =?> unlines [ "[link][]\\[text in brackets\\]"
+                      , ""
+                      , "  [link]: /url"
+                      ]
+     , "Reference link is followed by space and text in brackets"
+          =:  para ((link "/url" "" "link") <> " [text in brackets]")
+          =?> unlines [ "[link][] \\[text in brackets\\]"
+                      , ""
+                      , "  [link]: /url"
+                      ]
+     , "Reference link is followed by RawInline"
+          =: para ((link "/url" "" "link") <> rawInline "markdown" "[rawText]")
+          =?> unlines [ "[link][][rawText]"
+                      , ""
+                      , "  [link]: /url"
+                      ]
+     , "Reference link is followed by space and RawInline"
+          =: para ((link "/url" "" "link") <> space <> rawInline "markdown" "[rawText]")
+          =?> unlines [ "[link][] [rawText]"
+                      , ""
+                      , "  [link]: /url"
+                      ]
+     , "Reference link is followed by RawInline with space"
+          =: para ((link "/url" "" "link") <> rawInline "markdown" " [rawText]")
+          =?> unlines [ "[link][] [rawText]"
+                      , ""
+                      , "  [link]: /url"
+                      ]
+     , "Reference link is followed by citation"
+          =: para ((link "/url" "" "link") <> cite [Citation "author" [] [] NormalCitation 0 0] (str "[@author]"))
+          =?> unlines [ "[link][][@author]"
+                      , ""
+                      , "  [link]: /url"
+                      ]
+     , "Reference link is followed by space and citation"
+          =: para ((link "/url" "" "link") <> space <> cite [Citation "author" [] [] NormalCitation 0 0] (str "[@author]"))
+          =?> unlines [ "[link][] [@author]"
+                      , ""
+                      , "  [link]: /url"
+                      ]
+     ]
diff --git a/test/Tests/Writers/Muse.hs b/test/Tests/Writers/Muse.hs
index 13c457a37..50c0e78eb 100644
--- a/test/Tests/Writers/Muse.hs
+++ b/test/Tests/Writers/Muse.hs
@@ -1,5 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 module Tests.Writers.Muse (tests) where
 
+import Prelude
 import Data.Text (unpack)
 import Test.Tasty
 import Tests.Helpers
@@ -8,7 +10,7 @@ import Text.Pandoc.Arbitrary ()
 import Text.Pandoc.Builder
 
 muse :: (ToPandoc a) => a -> String
-muse = museWithOpts def{ writerWrapText = WrapNone,
+muse = museWithOpts def{ writerWrapText = WrapPreserve,
                          writerExtensions = extensionsFromList [Ext_amuse,
                                                                 Ext_auto_identifiers] }
 
@@ -34,11 +36,9 @@ tests = [ testGroup "block elements"
                                            ]
             ]
           , "line block" =: lineBlock [text "Foo", text "bar", text "baz"]
-                         =?> unlines [ "<verse>"
-                                     , "Foo"
-                                     , "bar"
-                                     , "baz"
-                                     , "</verse>"
+                         =?> unlines [ "> Foo"
+                                     , "> bar"
+                                     , "> baz"
                                      ]
           , "code block" =: codeBlock "int main(void) {\n\treturn 0;\n}"
                          =?> unlines [ "<example>"
@@ -74,8 +74,8 @@ tests = [ testGroup "block elements"
                    , plain $ text "second"
                    , plain $ text "third"
                    ]
-                =?> unlines [ " I.   first"
-                            , " II.  second"
+                =?> unlines [ " I. first"
+                            , " II. second"
                             , " III. third"
                             ]
               , "bullet list" =: bulletList [ plain $ text "first"
@@ -103,6 +103,33 @@ tests = [ testGroup "block elements"
                             , "                  :: second description"
                             , " second definition :: third description"
                             ]
+              , "definition list with empty term" =:
+                definitionList [ (text "first definition", [plain $ text "first description"])
+                               , (mempty, [plain $ text "second description"])
+                               , (str "", [plain $ text "third description"])
+                               ]
+                =?> unlines [ " first definition :: first description"
+                            , " <verbatim></verbatim> :: second description"
+                            , " <verbatim></verbatim> :: third description"
+                            ]
+              , "definition list terms starting with space" =:
+                definitionList [ (text "first definition", [plain $ text "first description"])
+                               , (space <> str "foo", [plain $ text "second description"])
+                               , (str " > bar", [plain $ text "third description"])
+                               ]
+                =?> unlines [ " first definition :: first description"
+                            , " <verbatim></verbatim> foo :: second description"
+                            , " <verbatim></verbatim> > bar :: third description"
+                            ]
+              , "definition list terms starting with list markers" =:
+                definitionList [ (text "first definition", [plain $ text "first description"])
+                               , (str "-", [plain $ text "second description"])
+                               , (str "1.", [plain $ text "third description"])
+                               ]
+                =?> unlines [ " first definition :: first description"
+                            , " <verbatim></verbatim>- :: second description"
+                            , " <verbatim></verbatim>1. :: third description"
+                            ]
               ]
             -- Test that lists of the same type and style are separated with two blanklines
             , testGroup "sequential lists"
@@ -129,11 +156,11 @@ tests = [ testGroup "block elements"
                 orderedListWith (1, UpperRoman, DefaultDelim) [ para $ text "Third"
                                                               , para $ text "Fourth"
                                                               ] =?>
-                unlines [ " I.  First"
+                unlines [ " I. First"
                         , " II. Second"
                         , ""
                         , ""
-                        , " I.  Third"
+                        , " I. Third"
                         , " II. Fourth"
                         ]
               , "ordered lists with equal styles" =:
@@ -160,7 +187,7 @@ tests = [ testGroup "block elements"
                 unlines [ " - First"
                         , " - Second"
                         , ""
-                        , " I.  Third"
+                        , " I. Third"
                         , " II. Fourth"
                         ]
               , "different style ordered lists" =:
@@ -170,7 +197,7 @@ tests = [ testGroup "block elements"
                 orderedListWith (1, Decimal, DefaultDelim) [ para $ text "Third"
                                                            , para $ text "Fourth"
                                                            ] =?>
-                unlines [ " I.  First"
+                unlines [ " I. First"
                         , " II. Second"
                         , ""
                         , " 1. Third"
@@ -217,8 +244,8 @@ tests = [ testGroup "block elements"
                                                             ]
                                           =?> unlines [ " first definition :: first description"
                                                       , " second definition :: second description"
-                                                      , "                       first inner definition :: first inner description"
-                                                      , "                       second inner definition :: second inner description"
+                                                      , "                      first inner definition :: first inner description"
+                                                      , "                      second inner definition :: second inner description"
                                                       ]
               ]
             -- Check that list is intended with one space even inside a quote
@@ -245,18 +272,23 @@ tests = [ testGroup "block elements"
                       ]
             , "heading with ID" =:
                headerWith ("bar", [], []) 2 (text "Foo") =?>
-               unlines [ "** Foo"
-                       , "#bar"
+               unlines [ "#bar"
+                       , "** Foo"
                       ]
+            , "empty heading" =: header 4 (mempty) =?> "**** <verbatim></verbatim>"
             ]
           , "horizontal rule" =: horizontalRule =?> "----"
-          , "escape horizontal rule" =: para (text "----") =?> "<verbatim>----</verbatim>"
+          , "escape horizontal rule" =: para (text "----") =?> "<verbatim></verbatim>----"
+          , "escape long horizontal rule" =: para (text "----------") =?> "<verbatim></verbatim>----------"
+          , "don't escape horizontal inside paragraph" =: para (text "foo ---- bar") =?> "foo ---- bar"
           , "escape nonbreaking space" =: para (text "~~") =?> "<verbatim>~~</verbatim>"
+          , "escape > in the beginning of line" =: para (text "> foo bar") =?> "<verbatim></verbatim>> foo bar"
           , testGroup "tables"
             [ "table without header" =:
               let rows = [[para $ text "Para 1.1", para $ text "Para 1.2"]
                          ,[para $ text "Para 2.1", para $ text "Para 2.2"]]
-              in simpleTable [] rows
+              in table mempty [(AlignDefault,0.0),(AlignDefault,0.0)]
+                       [mempty, mempty] rows
               =?>
               unlines [ " Para 1.1 | Para 1.2"
                       , " Para 2.1 | Para 2.2"
@@ -276,7 +308,8 @@ tests = [ testGroup "block elements"
                   headers = [plain $ text "header 1", plain $ text "header 2"]
                   rows = [[para $ text "Para 1.1", para $ text "Para 1.2"]
                          ,[para $ text "Para 2.1", para $ text "Para 2.2"]]
-              in table caption mempty headers rows
+              in table caption [(AlignDefault,0.0),(AlignDefault,0.0)]
+                        headers rows
               =?> unlines [ " header 1 || header 2"
                           , " Para 1.1 |  Para 1.2"
                           , " Para 2.1 |  Para 2.2"
@@ -292,16 +325,33 @@ tests = [ testGroup "block elements"
           [ testGroup "string"
             [ "string" =: str "foo" =?> "foo"
             , "escape footnote" =: str "[1]" =?> "<verbatim>[1]</verbatim>"
+            , "do not escape brackets" =: str "[12ab]" =?> "[12ab]"
             , "escape verbatim close tag" =: str "foo</verbatim>bar"
                =?> "<verbatim>foo<</verbatim><verbatim>/verbatim>bar</verbatim>"
+            , "escape link-like text" =: str "[[https://www.example.org]]"
+               =?> "<verbatim>[[https://www.example.org]]</verbatim>"
             , "escape pipe to avoid accidental tables" =: str "foo | bar"
                =?> "<verbatim>foo | bar</verbatim>"
             , "escape hash to avoid accidental anchors" =: text "#foo bar"
               =?> "<verbatim>#foo</verbatim> bar"
             , "escape definition list markers" =: str "::" =?> "<verbatim>::</verbatim>"
+            , "normalize strings before escaping" =: fromList [Str ":", Str ":"] =?> "<verbatim>::</verbatim>"
             -- We don't want colons to be escaped if they can't be confused
             -- with definition list item markers.
             , "do not escape colon" =: str ":" =?> ":"
+            , "escape - to avoid accidental unordered lists" =: text " - foo" =?> "<verbatim></verbatim> - foo"
+            , "escape - inside a list to avoid accidental nested unordered lists" =:
+              bulletList [ (para $ text "foo") <>
+                           (para $ text "- bar")
+                         ] =?>
+              unlines [ " - foo"
+                      , ""
+                      , "   <verbatim></verbatim>- bar"
+                      ]
+            , "escape ; to avoid accidental comments" =: text "; foo" =?> "<verbatim></verbatim>; foo"
+            , "escape ; after softbreak" =: text "foo" <> softbreak <> text "; bar" =?> "foo\n<verbatim></verbatim>; bar"
+            , "escape ; after linebreak" =: text "foo" <> linebreak <> text "; bar" =?> "foo<br>\n<verbatim></verbatim>; bar"
+            , "do not escape ; inside paragraph" =: text "foo ; bar" =?> "foo ; bar"
             ]
           , testGroup "emphasis"
             [ "emph" =: emph (text "foo") =?> "<em>foo</em>"
@@ -310,7 +360,8 @@ tests = [ testGroup "block elements"
             ]
           , "superscript" =: superscript (text "foo") =?> "<sup>foo</sup>"
           , "subscript" =: subscript (text "foo") =?> "<sub>foo</sub>"
-          , "smallcaps" =: smallcaps (text "foo") =?> "foo"
+          , "smallcaps" =: smallcaps (text "foo") =?> "<em>foo</em>"
+          , "smallcaps near emphasis" =: emph (str "foo") <> smallcaps (str "bar") =?> "<em>foobar</em>"
           , "single quoted" =: singleQuoted (text "foo") =?> "‘foo’"
           , "double quoted" =: doubleQuoted (text "foo") =?> "“foo”"
           -- Cite is trivial
@@ -319,19 +370,24 @@ tests = [ testGroup "block elements"
             , "escape tag" =: code "<code>foo = bar</code> baz" =?> "<code><code>foo = bar<</code><code>/code> baz</code>"
             , "normalization with attributes" =: codeWith ("",["haskell"],[]) "foo" <> code "bar" =?> "<code>foobar</code>"
             , "normalization" =: code "</co" <> code "de>" =?> "<code><</code><code>/code></code>"
+            , "normalization with empty string" =: code "</co" <> str "" <> code "de>" =?> "<code><</code><code>/code></code>"
             ]
           , testGroup "spaces"
             [ "space" =: text "a" <> space <> text "b" =?> "a b"
-            , "soft break" =: text "a" <> softbreak <> text "b" =?> "a b"
-            , test (museWithOpts def{ writerWrapText = WrapPreserve })
-                   "preserve soft break" $ text "a" <> softbreak <> text "b"
-                   =?> "a\nb"
+            , "soft break" =: text "a" <> softbreak <> text "b" =?> "a\nb"
+            , test (museWithOpts def{ writerWrapText = WrapNone })
+                   "remove soft break" $ text "a" <> softbreak <> text "b"
+                   =?> "a b"
             , "line break" =: text "a" <> linebreak <> text "b" =?> "a<br>\nb"
+            , "no newline after line break in header" =: header 1 (text "a" <> linebreak <> text "b") =?> "* a<br>b"
+            , "no softbreak in header" =: header 1 (text "a" <> softbreak <> text "b") =?> "* a b"
             ]
           , testGroup "math"
             [ "inline math" =: math "2^3" =?> "2<sup>3</sup>"
             , "display math" =: displayMath "2^3" =?> "2<sup>3</sup>"
             , "multiple letters in inline math" =: math "abc" =?> "<em>abc</em>"
+            , "expand math before normalization" =: math "[" <> str "2]" =?> "<verbatim>[2]</verbatim>"
+            , "multiple math expressions inside one inline list" =: math "5_4" <> text ", " <> displayMath "3^2" =?> "5<sub>4</sub>, 3<sup>2</sup>"
             ]
           , "raw inline"
             =: rawInline "html" "<mark>marked text</mark>"
@@ -349,18 +405,53 @@ tests = [ testGroup "block elements"
                                                =?> "[[URL:1.png][Link to image]]"
             , "link to image without description" =: link "1.png" "" (str "1.png")
                                                   =?> "[[URL:1.png]]"
+
+            , testGroup "escape brackets in links"
+              [ "link with description"
+                =: link "https://example.com/foo].txt" "" (str "Description")
+                =?> "[[https://example.com/foo%5D.txt][Description]]"
+              , "link without description"
+                =: link "https://example.com/foo].txt" "" (str "https://example.com/foo].txt")
+                =?> "[[https://example.com/foo%5D.txt][<verbatim>https://example.com/foo].txt</verbatim>]]"
+              , "image link with description"
+                =: link "foo]bar.png" "" (str "Image link")
+                =?> "[[URL:foo%5Dbar.png][Image link]]"
+              , "image link without description"
+                =: link "foo]bar.png" "" (str "foo]bar.png")
+                =?> "[[URL:foo%5Dbar.png][<verbatim>foo]bar.png</verbatim>]]"
+              ]
             ]
           , "image" =: image "image.png" "Image 1" (str "") =?> "[[image.png][Image 1]]"
           , "image with width" =:
             imageWith ("", [], [("width", "60%")]) "image.png" "Image" (str "") =?>
             "[[image.png 60][Image]]"
+          , "left-aligned image with width" =:
+            imageWith ("", ["align-left"], [("width", "60%")]) "image.png" "Image" (str "") =?>
+            "[[image.png 60 l][Image]]"
+          , "right-aligned image with width" =:
+            imageWith ("", ["align-right"], [("width", "60%")]) "image.png" "Image" (str "") =?>
+            "[[image.png 60 r][Image]]"
+          , "escape brackets in image title" =: image "image.png" "Foo]bar" (str "") =?> "[[image.png][<verbatim>Foo]bar</verbatim>]]"
           , "note" =: note (plain (text "Foo"))
                    =?> unlines [ "[1]"
                                , ""
                                , "[1] Foo"
                                ]
-          , "span" =: spanWith ("",["foobar"],[]) (str "Some text")
-                   =?> "<class name=\"foobar\">Some text</class>"
+          , "span with class" =: spanWith ("",["foobar"],[]) (text "Some text")
+                              =?> "<class name=\"foobar\">Some text</class>"
+          , "span without class" =: spanWith ("",[],[]) (text "Some text")
+                                 =?> "<class>Some text</class>"
+          , "span with anchor" =: spanWith ("anchor", [], []) (mempty) <> (text "Foo bar")
+                               =?> "#anchor Foo bar"
+          , "empty span with anchor" =: spanWith ("anchor", [], []) (mempty)
+                                     =?> "#anchor"
+          , "empty span without class and anchor" =: spanWith ("", [], []) (mempty)
+                                                  =?> "<class></class>"
+          , "span with class and anchor" =: spanWith ("anchor", ["foo"], []) (text "bar")
+                                         =?> "#anchor <class name=\"foo\">bar</class>"
+          , "adjacent spans" =: spanWith ("", ["syllable"], []) (str "wa") <>
+                                spanWith ("", ["syllable"], []) (str "ter")
+                             =?> "<class name=\"syllable\">wa</class><class name=\"syllable\">ter</class>"
           , testGroup "combined"
             [ "emph word before" =:
                 para (text "foo" <> emph (text "bar")) =?>
diff --git a/test/Tests/Writers/Muse.hs.orig b/test/Tests/Writers/Muse.hs.orig
new file mode 100644
index 000000000..b86dee5e1
--- /dev/null
+++ b/test/Tests/Writers/Muse.hs.orig
@@ -0,0 +1,410 @@
+module Tests.Writers.Muse (tests) where
+
+import Data.Text (unpack)
+import Test.Tasty
+import Tests.Helpers
+import Text.Pandoc
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder
+
+muse :: (ToPandoc a) => a -> String
+muse = museWithOpts def{ writerWrapText = WrapNone,
+                         writerExtensions = extensionsFromList [Ext_amuse,
+                                                                Ext_auto_identifiers] }
+
+museWithOpts :: (ToPandoc a) => WriterOptions -> a -> String
+museWithOpts opts = unpack . purely (writeMuse opts) . toPandoc
+
+infix 4 =:
+(=:) :: (ToString a, ToPandoc a)
+     => String -> (a, String) -> TestTree
+(=:) = test muse
+
+tests :: [TestTree]
+tests = [ testGroup "block elements"
+          [ "plain" =: plain (text "Foo bar.") =?> "Foo bar."
+          , testGroup "paragraphs"
+            [ "single paragraph" =: para (text "Sample paragraph.")
+                                 =?> "Sample paragraph."
+            , "two paragraphs" =: para (text "First paragraph.") <>
+                                  para (text "Second paragraph.")
+                               =?> unlines [ "First paragraph."
+                                           , ""
+                                           , "Second paragraph."
+                                           ]
+            ]
+          , "line block" =: lineBlock [text "Foo", text "bar", text "baz"]
+                         =?> unlines [ "> Foo"
+                                     , "> bar"
+                                     , "> baz"
+                                     ]
+          , "code block" =: codeBlock "int main(void) {\n\treturn 0;\n}"
+                         =?> unlines [ "<example>"
+                                     , "int main(void) {"
+                                     , "\treturn 0;"
+                                     , "}"
+                                     , "</example>"
+                                     ]
+          , "html raw block" =: rawBlock "html" "<hr>"
+                             =?> unlines [ "<literal style=\"html\">"
+                                         , "<hr>"
+                                         , "</literal>"
+                                         ]
+          , "block quote" =: blockQuote (para (text "Foo"))
+                          =?> unlines [ "<quote>"
+                                      , "Foo"
+                                      , "</quote>"
+                                      ]
+          , testGroup "lists"
+            [ testGroup "simple lists"
+              [
+                "ordered list" =: orderedList [ plain $ text "first"
+                                              , plain $ text "second"
+                                              , plain $ text "third"
+                                              ]
+                               =?> unlines [ " 1. first"
+                                           , " 2. second"
+                                           , " 3. third"
+                                           ]
+              , "ordered list with Roman numerals"
+                =: orderedListWith (1, UpperRoman, DefaultDelim)
+                   [ plain $ text "first"
+                   , plain $ text "second"
+                   , plain $ text "third"
+                   ]
+                =?> unlines [ " I.   first"
+                            , " II.  second"
+                            , " III. third"
+                            ]
+              , "bullet list" =: bulletList [ plain $ text "first"
+                                            , plain $ text "second"
+                                            , plain $ text "third"
+                                            ]
+                              =?> unlines [ " - first"
+                                          , " - second"
+                                          , " - third"
+                                          ]
+              , "definition list" =: definitionList [ (text "first definition", [plain $ text "first description"])
+                                                    , (text "second definition", [plain $ text "second description"])
+                                                    , (text "third definition", [plain $ text "third description"])
+                                                    ]
+                                  =?> unlines [ " first definition :: first description"
+                                              , " second definition :: second description"
+                                              , " third definition :: third description"
+                                              ]
+              , "definition list with multiple descriptions" =:
+                definitionList [ (text "first definition", [plain $ text "first description"
+                                                           ,plain $ text "second description"])
+                               , (text "second definition", [plain $ text "third description"])
+                               ]
+                =?> unlines [ " first definition :: first description"
+                            , "                  :: second description"
+                            , " second definition :: third description"
+                            ]
+              , "definition list with empty term" =:
+                definitionList [ (text "first definition", [plain $ text "first description"])
+                               , (mempty, [plain $ text "second description"])
+                               , (str "", [plain $ text "third description"])
+                               ]
+                =?> unlines [ " first definition :: first description"
+                            , " <verbatim></verbatim> :: second description"
+                            , " <verbatim></verbatim> :: third description"
+                            ]
+              ]
+            -- Test that lists of the same type and style are separated with two blanklines
+            , testGroup "sequential lists"
+              [ "bullet lists" =:
+                bulletList [ para $ text "First"
+                           , para $ text "Second"
+                           , para $ text "Third"
+                           ] <>
+                bulletList [ para $ text "Fourth"
+                           , para $ text "Fifth"
+                           ] =?>
+                unlines [ " - First"
+                        , " - Second"
+                        , " - Third"
+                        , ""
+                        , ""
+                        , " - Fourth"
+                        , " - Fifth"
+                        ]
+              , "ordered lists of the same style" =:
+                orderedListWith (1, UpperRoman, DefaultDelim) [ para $ text "First"
+                                                              , para $ text "Second"
+                                                              ] <>
+                orderedListWith (1, UpperRoman, DefaultDelim) [ para $ text "Third"
+                                                              , para $ text "Fourth"
+                                                              ] =?>
+                unlines [ " I.  First"
+                        , " II. Second"
+                        , ""
+                        , ""
+                        , " I.  Third"
+                        , " II. Fourth"
+                        ]
+              , "ordered lists with equal styles" =:
+                orderedList [ para $ text "First"
+                            , para $ text "Second"
+                            ] <>
+                orderedListWith (1, Decimal, DefaultDelim) [ para $ text "Third"
+                                                           , para $ text "Fourth"
+                                                           ] =?>
+                unlines [ " 1. First"
+                        , " 2. Second"
+                        , ""
+                        , ""
+                        , " 1. Third"
+                        , " 2. Fourth"
+                        ]
+              , "bullet and ordered lists" =:
+                bulletList [ para $ text "First"
+                           , para $ text "Second"
+                           ] <>
+                orderedListWith (1, UpperRoman, DefaultDelim) [ para $ text "Third"
+                                                              , para $ text "Fourth"
+                                                              ] =?>
+                unlines [ " - First"
+                        , " - Second"
+                        , ""
+                        , " I.  Third"
+                        , " II. Fourth"
+                        ]
+              , "different style ordered lists" =:
+                orderedListWith (1, UpperRoman, DefaultDelim) [ para $ text "First"
+                                                              , para $ text "Second"
+                                                              ] <>
+                orderedListWith (1, Decimal, DefaultDelim) [ para $ text "Third"
+                                                           , para $ text "Fourth"
+                                                           ] =?>
+                unlines [ " I.  First"
+                        , " II. Second"
+                        , ""
+                        , " 1. Third"
+                        , " 2. Fourth"
+                        ]
+              ]
+            , testGroup "nested lists"
+              [ "nested ordered list" =: orderedList [ plain $ text "First outer"
+                                                     , plain (text "Second outer:") <>
+                                                       orderedList [ plain $ text "first"
+                                                                   , plain $ text "second"
+                                                                   ]
+                                                     , plain $ text "Third outer"
+                                                     ]
+                                      =?> unlines [ " 1. First outer"
+                                                  , " 2. Second outer:"
+                                                  , "    1. first"
+                                                  , "    2. second"
+                                                  , " 3. Third outer"
+                                                  ]
+              , "nested bullet lists" =: bulletList [ plain $ text "First outer"
+                                                    , plain (text "Second outer:") <>
+                                                      bulletList [ plain $ text "first"
+                                                                 , plain $ text "second"
+                                                                 ]
+                                                    , plain $ text "Third outer"
+                                                    ]
+                                      =?> unlines [ " - First outer"
+                                                  , " - Second outer:"
+                                                  , "   - first"
+                                                  , "   - second"
+                                                  , " - Third outer"
+                                                  ]
+              , "nested definition lists" =: definitionList [ (text "first definition", [plain $ text "first description"])
+                                                            , (text "second definition",
+                                                               [ plain (text "second description") <>
+                                                                 definitionList [ ( text "first inner definition"
+                                                                                  , [plain $ text "first inner description"])
+                                                                                , ( text "second inner definition"
+                                                                                  , [plain $ text "second inner description"])
+                                                                                ]
+                                                               ]
+                                                              )
+                                                            ]
+                                          =?> unlines [ " first definition :: first description"
+                                                      , " second definition :: second description"
+                                                      , "                      first inner definition :: first inner description"
+                                                      , "                      second inner definition :: second inner description"
+                                                      ]
+              ]
+            -- Check that list is intended with one space even inside a quote
+            , "List inside block quote" =: blockQuote (orderedList [ plain $ text "first"
+                                                                   , plain $ text "second"
+                                                                   , plain $ text "third"
+                                                                   ])
+                                        =?> unlines [ "<quote>"
+                                                    , " 1. first"
+                                                    , " 2. second"
+                                                    , " 3. third"
+                                                    , "</quote>"
+                                                    ]
+            ]
+          , testGroup "headings"
+            [ "normal heading" =:
+              header 1 (text "foo") =?> "* foo"
+            , "heading levels" =:
+              header 1 (text "First level") <>
+              header 3 (text "Third level") =?>
+              unlines [ "* First level"
+                      , ""
+                      , "*** Third level"
+                      ]
+            , "heading with ID" =:
+               headerWith ("bar", [], []) 2 (text "Foo") =?>
+               unlines [ "** Foo"
+                       , "#bar"
+                      ]
+            ]
+          , "horizontal rule" =: horizontalRule =?> "----"
+          , "escape horizontal rule" =: para (text "----") =?> "<verbatim>----</verbatim>"
+          , "escape nonbreaking space" =: para (text "~~") =?> "<verbatim>~~</verbatim>"
+          , testGroup "tables"
+            [ "table without header" =:
+              let rows = [[para $ text "Para 1.1", para $ text "Para 1.2"]
+                         ,[para $ text "Para 2.1", para $ text "Para 2.2"]]
+              in simpleTable [] rows
+              =?>
+              unlines [ " Para 1.1 | Para 1.2"
+                      , " Para 2.1 | Para 2.2"
+                      ]
+            , "table with header" =:
+              let headers = [plain $ text "header 1", plain $ text "header 2"]
+                  rows = [[para $ text "Para 1.1", para $ text "Para 1.2"]
+                         ,[para $ text "Para 2.1", para $ text "Para 2.2"]]
+              in simpleTable headers rows
+              =?>
+              unlines [ " header 1 || header 2"
+                      , " Para 1.1 |  Para 1.2"
+                      , " Para 2.1 |  Para 2.2"
+                      ]
+            , "table with header and caption" =:
+              let caption = text "Table 1"
+                  headers = [plain $ text "header 1", plain $ text "header 2"]
+                  rows = [[para $ text "Para 1.1", para $ text "Para 1.2"]
+                         ,[para $ text "Para 2.1", para $ text "Para 2.2"]]
+              in table caption mempty headers rows
+              =?> unlines [ " header 1 || header 2"
+                          , " Para 1.1 |  Para 1.2"
+                          , " Para 2.1 |  Para 2.2"
+                          , " |+ Table 1 +|"
+                          ]
+            ]
+          , "div with bullet list" =:
+            divWith nullAttr (bulletList [para $ text "foo"]) =?>
+            unlines [ " - foo" ] -- Making sure bullets are indented
+          -- Null is trivial
+          ]
+        , testGroup "inline elements"
+          [ testGroup "string"
+            [ "string" =: str "foo" =?> "foo"
+            , "escape footnote" =: str "[1]" =?> "<verbatim>[1]</verbatim>"
+            , "escape verbatim close tag" =: str "foo</verbatim>bar"
+               =?> "<verbatim>foo<</verbatim><verbatim>/verbatim>bar</verbatim>"
+            , "escape pipe to avoid accidental tables" =: str "foo | bar"
+               =?> "<verbatim>foo | bar</verbatim>"
+            , "escape hash to avoid accidental anchors" =: text "#foo bar"
+              =?> "<verbatim>#foo</verbatim> bar"
+            , "escape definition list markers" =: str "::" =?> "<verbatim>::</verbatim>"
+            , "normalize strings before escaping" =: fromList [Str ":", Str ":"] =?> "<verbatim>::</verbatim>"
+            -- We don't want colons to be escaped if they can't be confused
+            -- with definition list item markers.
+            , "do not escape colon" =: str ":" =?> ":"
+            , "escape - to avoid accidental unordered lists" =: text " - foo" =?> " <verbatim>-</verbatim> foo"
+            , "escape - inside a list to avoid accidental nested unordered lists" =:
+              bulletList [ (para $ text "foo") <>
+                           (para $ text "- bar")
+                         ] =?>
+              unlines [ " - foo"
+                      , ""
+                      , "   <verbatim>-</verbatim> bar"
+                      ]
+            ]
+          , testGroup "emphasis"
+            [ "emph" =: emph (text "foo") =?> "<em>foo</em>"
+            , "strong" =: strong (text "foo") =?> "<strong>foo</strong>"
+            , "strikeout" =: strikeout (text "foo") =?> "<del>foo</del>"
+            ]
+          , "superscript" =: superscript (text "foo") =?> "<sup>foo</sup>"
+          , "subscript" =: subscript (text "foo") =?> "<sub>foo</sub>"
+          , "smallcaps" =: smallcaps (text "foo") =?> "<em>foo</em>"
+          , "smallcaps near emphasis" =: emph (str "foo") <> smallcaps (str "bar") =?> "<em>foobar</em>"
+          , "single quoted" =: singleQuoted (text "foo") =?> "‘foo’"
+          , "double quoted" =: doubleQuoted (text "foo") =?> "“foo”"
+          -- Cite is trivial
+          , testGroup "code"
+            [ "simple" =: code "foo" =?> "<code>foo</code>"
+            , "escape tag" =: code "<code>foo = bar</code> baz" =?> "<code><code>foo = bar<</code><code>/code> baz</code>"
+            , "normalization with attributes" =: codeWith ("",["haskell"],[]) "foo" <> code "bar" =?> "<code>foobar</code>"
+            , "normalization" =: code "</co" <> code "de>" =?> "<code><</code><code>/code></code>"
+            , "normalization with empty string" =: code "</co" <> str "" <> code "de>" =?> "<code><</code><code>/code></code>"
+            ]
+          , testGroup "spaces"
+            [ "space" =: text "a" <> space <> text "b" =?> "a b"
+            , "soft break" =: text "a" <> softbreak <> text "b" =?> "a b"
+            , test (museWithOpts def{ writerWrapText = WrapPreserve })
+                   "preserve soft break" $ text "a" <> softbreak <> text "b"
+                   =?> "a\nb"
+            , "line break" =: text "a" <> linebreak <> text "b" =?> "a<br>\nb"
+            ]
+          , testGroup "math"
+            [ "inline math" =: math "2^3" =?> "2<sup>3</sup>"
+            , "display math" =: displayMath "2^3" =?> "2<sup>3</sup>"
+            , "multiple letters in inline math" =: math "abc" =?> "<em>abc</em>"
+            , "expand math before normalization" =: math "[" <> str "2]" =?> "<verbatim>[2]</verbatim>"
+            , "multiple math expressions inside one inline list" =: math "5_4" <> text ", " <> displayMath "3^2" =?> "5<sub>4</sub>, 3<sup>2</sup>"
+            ]
+          , "raw inline"
+            =: rawInline "html" "<mark>marked text</mark>"
+            =?> "<literal style=\"html\"><mark>marked text</mark></literal>"
+          , testGroup "links"
+            [ "link with description" =: link "https://example.com" "" (str "Link 1")
+                                      =?> "[[https://example.com][Link 1]]"
+            , "link without description" =: link "https://example.com" "" (str "https://example.com")
+                                         =?> "[[https://example.com]]"
+            -- Internal links in Muse include '#'
+            , "link to anchor" =: link "#intro" "" (str "Introduction")
+                               =?> "[[#intro][Introduction]]"
+            -- According to Emacs Muse manual, links to images should be prefixed with "URL:"
+            , "link to image with description" =: link "1.png" "" (str "Link to image")
+                                               =?> "[[URL:1.png][Link to image]]"
+            , "link to image without description" =: link "1.png" "" (str "1.png")
+                                                  =?> "[[URL:1.png]]"
+            ]
+          , "image" =: image "image.png" "Image 1" (str "") =?> "[[image.png][Image 1]]"
+          , "image with width" =:
+            imageWith ("", [], [("width", "60%")]) "image.png" "Image" (str "") =?>
+            "[[image.png 60][Image]]"
+          , "note" =: note (plain (text "Foo"))
+                   =?> unlines [ "[1]"
+                               , ""
+                               , "[1] Foo"
+                               ]
+          , "span with class" =: spanWith ("",["foobar"],[]) (text "Some text")
+                   =?> "<class name=\"foobar\">Some text</class>"
+          , "span with anchor" =: spanWith ("anchor", [], []) (text "Foo bar")
+                               =?> "#anchor Foo bar"
+          , "span with class and anchor" =: spanWith ("anchor", ["foo"], []) (text "bar")
+                                         =?> "#anchor <class name=\"foo\">bar</class>"
+          , testGroup "combined"
+            [ "emph word before" =:
+                para (text "foo" <> emph (text "bar")) =?>
+                    "foo<em>bar</em>"
+            , "emph word after" =:
+                para (emph (text "foo") <> text "bar") =?>
+                    "<em>foo</em>bar"
+            , "emph quoted" =:
+                para (doubleQuoted (emph (text "foo"))) =?>
+                    "“<em>foo</em>”"
+            , "strong word before" =:
+                para (text "foo" <> strong (text "bar")) =?>
+                    "foo<strong>bar</strong>"
+            , "strong word after" =:
+                para (strong (text "foo") <> text "bar") =?>
+                    "<strong>foo</strong>bar"
+            , "strong quoted" =:
+                para (singleQuoted (strong (text "foo"))) =?>
+                    "‘<strong>foo</strong>’"
+            ]
+         ]
+       ]
diff --git a/test/Tests/Writers/Native.hs b/test/Tests/Writers/Native.hs
index 0c4bf7623..708b5069c 100644
--- a/test/Tests/Writers/Native.hs
+++ b/test/Tests/Writers/Native.hs
@@ -1,5 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 module Tests.Writers.Native (tests) where
 
+import Prelude
 import Data.Text (unpack)
 import Test.Tasty
 import Test.Tasty.QuickCheck
diff --git a/test/Tests/Writers/Native.hs.orig b/test/Tests/Writers/Native.hs.orig
new file mode 100644
index 000000000..0c4bf7623
--- /dev/null
+++ b/test/Tests/Writers/Native.hs.orig
@@ -0,0 +1,22 @@
+module Tests.Writers.Native (tests) where
+
+import Data.Text (unpack)
+import Test.Tasty
+import Test.Tasty.QuickCheck
+import Tests.Helpers
+import Text.Pandoc
+import Text.Pandoc.Arbitrary ()
+
+p_write_rt :: Pandoc -> Bool
+p_write_rt d =
+  read (unpack $ purely (writeNative def{ writerTemplate = Just "" }) d) == d
+
+p_write_blocks_rt :: [Block] -> Bool
+p_write_blocks_rt bs =
+  read (unpack $ purely (writeNative def) (Pandoc nullMeta bs)) == bs
+
+tests :: [TestTree]
+tests = [ testProperty "p_write_rt" p_write_rt
+        , testProperty "p_write_blocks_rt" $ mapSize
+             (\x -> if x > 3 then 3 else x) p_write_blocks_rt
+        ]
diff --git a/test/Tests/Writers/OOXML.hs b/test/Tests/Writers/OOXML.hs
index c2601eec8..f2762ddfe 100644
--- a/test/Tests/Writers/OOXML.hs
+++ b/test/Tests/Writers/OOXML.hs
@@ -1,8 +1,10 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE PatternGuards     #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module Tests.Writers.OOXML (ooxmlTest) where
 
+import Prelude
 import Text.Pandoc
 import Test.Tasty
 import Test.Tasty.Golden.Advanced
@@ -33,12 +35,10 @@ compareXMLBool (Elem myElem) (Elem goodElem) =
   elName myElem == elName goodElem &&
   elAttribs myElem == elAttribs goodElem &&
   and (zipWith compareXMLBool (elContent myElem) (elContent goodElem))
-
 compareXMLBool (Text myCData) (Text goodCData) =
   cdVerbatim myCData == cdVerbatim goodCData &&
   cdData myCData == cdData goodCData &&
   cdLine myCData == cdLine goodCData
-
 compareXMLBool (CRef myStr) (CRef goodStr) =
   myStr == goodStr
 compareXMLBool _ _ = False
diff --git a/test/Tests/Writers/OOXML.hs.orig b/test/Tests/Writers/OOXML.hs.orig
new file mode 100644
index 000000000..bdfdea145
--- /dev/null
+++ b/test/Tests/Writers/OOXML.hs.orig
@@ -0,0 +1,184 @@
+{-# LANGUAGE PatternGuards     #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module Tests.Writers.OOXML (ooxmlTest) where
+
+import Text.Pandoc
+import Test.Tasty
+import Test.Tasty.Golden.Advanced
+import Codec.Archive.Zip
+import Text.XML.Light
+import qualified Data.ByteString as BS
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Text.IO as T
+import Data.List (isSuffixOf, sort, (\\), intercalate, union)
+import Data.Maybe (catMaybes, mapMaybe)
+import Tests.Helpers
+import Data.Algorithm.Diff
+import System.FilePath.Glob (compile, match)
+
+compareXMLBool :: Content -> Content -> Bool
+-- We make a special exception for times at the moment, and just pass
+-- them because we can't control the utctime when running IO. Besides,
+-- so long as we have two times, we're okay.
+compareXMLBool (Elem myElem) (Elem goodElem)
+  | (QName "created" _ (Just "dcterms")) <- elName myElem
+  , (QName "created" _ (Just "dcterms")) <- elName goodElem =
+      True
+compareXMLBool (Elem myElem) (Elem goodElem)
+  | (QName "modified" _ (Just "dcterms")) <- elName myElem
+  , (QName "modified" _ (Just "dcterms")) <- elName goodElem =
+      True
+compareXMLBool (Elem myElem) (Elem goodElem) =
+  elName myElem == elName goodElem &&
+  elAttribs myElem == elAttribs goodElem &&
+  and (zipWith compareXMLBool (elContent myElem) (elContent goodElem))
+compareXMLBool (Text myCData) (Text goodCData) =
+  cdVerbatim myCData == cdVerbatim goodCData &&
+  cdData myCData == cdData goodCData &&
+  cdLine myCData == cdLine goodCData
+compareXMLBool (CRef myStr) (CRef goodStr) =
+  myStr == goodStr
+compareXMLBool _ _ = False
+
+displayDiff :: Content -> Content -> String
+displayDiff elemA elemB =
+  showDiff (1,1) $ getDiff (lines $ ppContent elemA) (lines $ ppContent elemB)
+
+goldenArchive :: FilePath -> IO Archive
+goldenArchive fp = (toArchive . BL.fromStrict) <$> BS.readFile fp
+
+testArchive :: (WriterOptions -> Pandoc -> PandocIO BL.ByteString)
+            -> WriterOptions
+            -> FilePath
+            -> IO Archive
+testArchive writerFn opts fp = do
+  txt <- T.readFile fp
+  bs <- runIOorExplode $ readNative def txt >>= writerFn opts
+  return $ toArchive bs
+
+compareFileList :: FilePath -> Archive -> Archive -> Maybe String
+compareFileList goldenFP goldenArch testArch =
+  let testFiles = filesInArchive testArch
+      goldenFiles = filesInArchive goldenArch
+      diffTestGolden = testFiles \\ goldenFiles
+      diffGoldenTest = goldenFiles \\ testFiles
+
+      results =
+        [ if null diffGoldenTest
+          then Nothing
+          else Just $
+               "Files in " ++ goldenFP ++ " but not in generated archive:\n" ++
+               intercalate ", " diffGoldenTest
+        , if null diffTestGolden
+          then Nothing
+          else Just $
+               "Files in generated archive but not in " ++ goldenFP ++ ":\n" ++
+               intercalate ", " diffTestGolden
+        ]
+  in
+    if null $ catMaybes results
+    then Nothing
+    else Just $ intercalate "\n" $ catMaybes results
+
+compareXMLFile' :: FilePath -> Archive -> Archive -> Either String ()
+compareXMLFile' fp goldenArch testArch = do
+  testEntry <- case findEntryByPath fp testArch of
+                 Just entry -> Right entry
+                 Nothing -> Left $
+                   "Can't extract " ++ fp ++ " from generated archive"
+  testXMLDoc <- case parseXMLDoc $ fromEntry testEntry of
+                  Just doc -> Right doc
+                  Nothing -> Left $
+                    "Can't parse xml in  " ++ fp ++ " from generated archive"
+
+  goldenEntry <- case findEntryByPath fp goldenArch of
+                 Just entry -> Right entry
+                 Nothing -> Left $
+                   "Can't extract " ++ fp ++ " from archive in stored file"
+  goldenXMLDoc <- case parseXMLDoc $ fromEntry goldenEntry of
+                  Just doc -> Right doc
+                  Nothing -> Left $
+                    "Can't parse xml in  " ++ fp ++ " from archive in stored file"
+
+  let testContent = Elem testXMLDoc
+      goldenContent = Elem goldenXMLDoc
+
+  if compareXMLBool goldenContent testContent
+    then Right ()
+    else Left $
+    "Non-matching xml in " ++ fp ++ ":\n" ++ displayDiff testContent goldenContent
+
+compareXMLFile :: FilePath -> Archive -> Archive -> Maybe String
+compareXMLFile fp goldenArch testArch =
+  case compareXMLFile' fp goldenArch testArch of
+    Right _ -> Nothing
+    Left s -> Just s
+
+compareAllXMLFiles :: Archive -> Archive -> Maybe String
+compareAllXMLFiles goldenArch testArch =
+  let allFiles = filesInArchive goldenArch `union` filesInArchive testArch
+      allXMLFiles = sort $
+        filter
+        (\fp -> ".xml" `isSuffixOf` fp || ".rels" `isSuffixOf` fp)
+        allFiles
+      results =
+        mapMaybe (\fp -> compareXMLFile fp goldenArch testArch) allXMLFiles
+  in
+    if null results
+    then Nothing
+    else Just $ unlines results
+
+compareMediaFile' :: FilePath -> Archive -> Archive -> Either String ()
+compareMediaFile' fp goldenArch testArch = do
+  testEntry <- case findEntryByPath fp testArch of
+                 Just entry -> Right entry
+                 Nothing -> Left $
+                   "Can't extract " ++ fp ++ " from generated archive"
+  goldenEntry <- case findEntryByPath fp goldenArch of
+                 Just entry -> Right entry
+                 Nothing -> Left $
+                   "Can't extract " ++ fp ++ " from archive in stored file"
+
+  if fromEntry testEntry == fromEntry goldenEntry
+    then Right ()
+    else Left $
+    "Non-matching binary file: " ++ fp
+
+compareMediaFile :: FilePath -> Archive -> Archive -> Maybe String
+compareMediaFile fp goldenArch testArch =
+  case compareMediaFile' fp goldenArch testArch of
+    Right _ -> Nothing
+    Left s -> Just s
+
+compareAllMediaFiles :: Archive -> Archive -> Maybe String
+compareAllMediaFiles goldenArch testArch =
+  let allFiles = filesInArchive goldenArch `union` filesInArchive testArch
+      mediaPattern = compile "*/media/*"
+      allMediaFiles = sort $
+        filter (match mediaPattern) allFiles
+      results =
+        mapMaybe (\fp -> compareMediaFile fp goldenArch testArch) allMediaFiles
+  in
+    if null results
+    then Nothing
+    else Just $ unlines results
+
+ooxmlTest :: (WriterOptions -> Pandoc -> PandocIO BL.ByteString)
+          -> String
+          -> WriterOptions
+          -> FilePath
+          -> FilePath
+          -> TestTree
+ooxmlTest writerFn testName opts nativeFP goldenFP =
+  goldenTest
+  testName
+  (goldenArchive goldenFP)
+  (testArchive writerFn opts nativeFP)
+  (\goldenArch testArch ->
+     let res = catMaybes [ compareFileList goldenFP goldenArch testArch
+                         , compareAllXMLFiles goldenArch testArch
+                         , compareAllMediaFiles goldenArch testArch
+                         ]
+     in return $ if null res then Nothing else Just $ unlines res)
+  (\a -> BL.writeFile goldenFP $ fromArchive a)
diff --git a/test/Tests/Writers/Org.hs b/test/Tests/Writers/Org.hs
index 9cbe360da..c99f7344d 100644
--- a/test/Tests/Writers/Org.hs
+++ b/test/Tests/Writers/Org.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Writers.Org (tests) where
 
+import Prelude
 import Test.Tasty
 import Tests.Helpers
 import Text.Pandoc
diff --git a/test/Tests/Writers/Org.hs.orig b/test/Tests/Writers/Org.hs.orig
new file mode 100644
index 000000000..9cbe360da
--- /dev/null
+++ b/test/Tests/Writers/Org.hs.orig
@@ -0,0 +1,25 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Writers.Org (tests) where
+
+import Test.Tasty
+import Tests.Helpers
+import Text.Pandoc
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder
+
+infix 4 =:
+(=:) :: (ToString a, ToPandoc a)
+     => String -> (a, String) -> TestTree
+(=:) = test (purely (writeOrg def . toPandoc))
+
+tests :: [TestTree]
+tests = [ testGroup "links"
+          -- See http://orgmode.org/manual/Internal-links.html#Internal-links
+          [ "simple link"
+              =: link "/url" "" "foo"
+              =?> "[[/url][foo]]"
+          , "internal link to anchor"
+              =: link "#my-custom-id" "" "#my-custom-id"
+              =?> "[[#my-custom-id]]"
+          ]
+        ]
diff --git a/test/Tests/Writers/Plain.hs b/test/Tests/Writers/Plain.hs
index ab09bca26..2a2eb4226 100644
--- a/test/Tests/Writers/Plain.hs
+++ b/test/Tests/Writers/Plain.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Writers.Plain (tests) where
 
+import Prelude
 import Test.Tasty
 import Tests.Helpers
 import Text.Pandoc
diff --git a/test/Tests/Writers/Plain.hs.orig b/test/Tests/Writers/Plain.hs.orig
new file mode 100644
index 000000000..ab09bca26
--- /dev/null
+++ b/test/Tests/Writers/Plain.hs.orig
@@ -0,0 +1,21 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Writers.Plain (tests) where
+
+import Test.Tasty
+import Tests.Helpers
+import Text.Pandoc
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder
+
+
+infix 4 =:
+(=:) :: (ToString a, ToPandoc a)
+     => String -> (a, String) -> TestTree
+(=:) = test (purely (writePlain def) . toPandoc)
+
+
+tests :: [TestTree]
+tests = [ "strongly emphasized text to uppercase"
+             =: strong "Straße"
+             =?> "STRASSE"
+        ]
diff --git a/test/Tests/Writers/Powerpoint.hs b/test/Tests/Writers/Powerpoint.hs
index fc5f9accc..226cd6080 100644
--- a/test/Tests/Writers/Powerpoint.hs
+++ b/test/Tests/Writers/Powerpoint.hs
@@ -1,5 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 module Tests.Writers.Powerpoint (tests) where
 
+import Prelude
 import Tests.Writers.OOXML (ooxmlTest)
 import Text.Pandoc
 import Test.Tasty
@@ -53,6 +55,14 @@ tests = groupPptxTests [ pptxTests "Inline formatting"
                          def{ writerSlideLevel = Just 1 }
                          "pptx/slide_breaks.native"
                          "pptx/slide_breaks_slide_level_1.pptx"
+                       , pptxTests "lists"
+                         def
+                         "pptx/lists.native"
+                         "pptx/lists.pptx"
+                       , pptxTests "tables"
+                         def
+                         "pptx/tables.native"
+                         "pptx/tables.pptx"
                        , pptxTests "table of contents"
                          def{ writerTableOfContents = True }
                          "pptx/slide_breaks.native"
@@ -77,4 +87,13 @@ tests = groupPptxTests [ pptxTests "Inline formatting"
                          def
                          "pptx/speaker_notes.native"
                          "pptx/speaker_notes.pptx"
+                       , pptxTests "speaker notes after a separating block"
+                         def
+                         "pptx/speaker_notes_afterseps.native"
+                         "pptx/speaker_notes_afterseps.pptx"
+                       , pptxTests "remove empty slides"
+                         def
+                         "pptx/remove_empty_slides.native"
+                         "pptx/remove_empty_slides.pptx"
+
                        ]
diff --git a/test/Tests/Writers/Powerpoint.hs.orig b/test/Tests/Writers/Powerpoint.hs.orig
new file mode 100644
index 000000000..9af8fc471
--- /dev/null
+++ b/test/Tests/Writers/Powerpoint.hs.orig
@@ -0,0 +1,93 @@
+module Tests.Writers.Powerpoint (tests) where
+
+import Tests.Writers.OOXML (ooxmlTest)
+import Text.Pandoc
+import Test.Tasty
+import System.FilePath
+
+-- templating is important enough, and can break enough things, that
+-- we want to run all our tests with both default formatting and a
+-- template.
+
+modifyPptxName :: FilePath -> FilePath
+modifyPptxName fp =
+  addExtension (dropExtension fp ++ "_templated") "pptx"
+
+pptxTests :: String -> WriterOptions -> FilePath -> FilePath -> (TestTree, TestTree)
+pptxTests name opts native pptx =
+  let referenceDoc = "pptx/reference_depth.pptx"
+  in
+    ( ooxmlTest
+      writePowerpoint
+      name
+      opts{writerReferenceDoc=Nothing}
+      native
+      pptx
+    , ooxmlTest
+      writePowerpoint
+      name
+      opts{writerReferenceDoc=Just referenceDoc}
+      native
+      (modifyPptxName pptx)
+    )
+
+groupPptxTests :: [(TestTree, TestTree)] -> [TestTree]
+groupPptxTests pairs =
+  let (noRefs, refs) = unzip pairs
+  in
+    [ testGroup "Default slide formatting" noRefs
+    , testGroup "With `--reference-doc` pptx file" refs
+    ]
+
+
+tests :: [TestTree]
+tests = groupPptxTests [ pptxTests "Inline formatting"
+                         def
+                         "pptx/inline_formatting.native"
+                         "pptx/inline_formatting.pptx"
+                       , pptxTests "Slide breaks (default slide-level)"
+                         def
+                         "pptx/slide_breaks.native"
+                         "pptx/slide_breaks.pptx"
+                       , pptxTests "slide breaks (slide-level set to 1)"
+                         def{ writerSlideLevel = Just 1 }
+                         "pptx/slide_breaks.native"
+                         "pptx/slide_breaks_slide_level_1.pptx"
+                       , pptxTests "lists"
+                         def
+                         "pptx/lists.native"
+                         "pptx/lists.pptx"
+                       , pptxTests "tables"
+                         def
+                         "pptx/tables.native"
+                         "pptx/tables.pptx"
+                       , pptxTests "table of contents"
+                         def{ writerTableOfContents = True }
+                         "pptx/slide_breaks.native"
+                         "pptx/slide_breaks_toc.pptx"
+                       , pptxTests "end notes"
+                         def
+                         "pptx/endnotes.native"
+                         "pptx/endnotes.pptx"
+                       , pptxTests "end notes, with table of contents"
+                         def { writerTableOfContents = True }
+                         "pptx/endnotes.native"
+                         "pptx/endnotes_toc.pptx"
+                       , pptxTests "images"
+                         def
+                         "pptx/images.native"
+                         "pptx/images.pptx"
+                       , pptxTests "two-column layout"
+                         def
+                         "pptx/two_column.native"
+                         "pptx/two_column.pptx"
+                       , pptxTests "speaker notes"
+                         def
+                         "pptx/speaker_notes.native"
+                         "pptx/speaker_notes.pptx"
+                       , pptxTests "remove empty slides"
+                         def
+                         "pptx/remove_empty_slides.native"
+                         "pptx/remove_empty_slides.pptx"
+
+                       ]
diff --git a/test/Tests/Writers/RST.hs b/test/Tests/Writers/RST.hs
index 4c0a926bb..a1a4510e0 100644
--- a/test/Tests/Writers/RST.hs
+++ b/test/Tests/Writers/RST.hs
@@ -1,11 +1,15 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Writers.RST (tests) where
 
+import Prelude
 import Test.Tasty
+import Test.Tasty.HUnit
 import Tests.Helpers
 import Text.Pandoc
 import Text.Pandoc.Arbitrary ()
 import Text.Pandoc.Builder
+import Text.Pandoc.Writers.RST
 
 infix 4 =:
 (=:) :: (ToString a, ToPandoc a)
@@ -22,23 +26,23 @@ tests = [ testGroup "rubrics"
                                             para $ text "baz"])] =?>
               unlines
               [ "foo"
-              , "    .. rubric:: bar"
+              , "   .. rubric:: bar"
               , ""
-              , "    baz"]
+              , "   baz"]
           , "in block quote" =:
               blockQuote (header 1 (text "bar")) =?>
-              "    .. rubric:: bar"
+              "   .. rubric:: bar"
           , "with id" =:
               blockQuote (headerWith ("foo",[],[]) 1 (text "bar")) =?>
               unlines
-              [ "    .. rubric:: bar"
-              , "       :name: foo"]
+              [ "   .. rubric:: bar"
+              , "      :name: foo"]
           , "with id class" =:
               blockQuote (headerWith ("foo",["baz"],[]) 1 (text "bar")) =?>
               unlines
-              [ "    .. rubric:: bar"
-              , "       :name: foo"
-              , "       :class: baz"]
+              [ "   .. rubric:: bar"
+              , "      :name: foo"
+              , "      :class: baz"]
           ]
         , testGroup "ligatures" -- handling specific sequences of blocks
           [ "a list is closed by a comment before a quote" =: -- issue 4248
@@ -48,7 +52,45 @@ tests = [ testGroup "rubrics"
               , ""
               , ".."
               , ""
-              , "    quoted"]
+              , "   quoted"]
+          ]
+        , testGroup "flatten"
+          [ testCase "emerges nested styles as expected" $
+            flatten (Emph [Str "1", Strong [Str "2"], Str "3"]) @?=
+            [Emph [Str "1"], Strong [Str "2"], Emph [Str "3"]]
+          , testCase "could introduce trailing spaces" $
+            flatten (Emph [Str "f", Space, Strong [Str "2"]]) @?=
+            [Emph [Str "f", Space], Strong [Str "2"]]
+            -- the test above is the reason why we call
+            -- stripLeadingTrailingSpace through transformNested after
+            -- flatten
+          , testCase "preserves empty parents" $
+            flatten (Image ("",[],[]) [] ("loc","title")) @?=
+            [Image ("",[],[]) [] ("loc","title")]
+          ]
+        , testGroup "inlines"
+          [ "are removed when empty" =: -- #4434
+            plain (strong (str "")) =?> ""
+          , "do not cause the introduction of extra spaces when removed" =:
+            plain (strong (str "") <> emph (str "text")) =?> "*text*"
+          , "spaces are stripped at beginning and end" =:
+            -- pandoc issue 4327 "The text within inline markup may not
+            -- begin or end with whitespace"
+            -- http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#inline-markup
+            strong (space <> str "text" <> space <> space) =?> "**text**"
+          , "single space stripped" =:
+            strong space =?> ""
+          , "give priority to strong style over emphasis" =:
+            strong (emph (strong (str "s"))) =?> "**s**"
+          , "links are not elided by outer style" =:
+            strong (emph (link "loc" "" (str "text"))) =?>
+            "`text <loc>`__"
+          , "RST inlines cannot start nor end with spaces" =:
+            emph (str "f" <> space <> strong (str "d") <> space <> str "l") =?>
+            "*f*\\ **d**\\ *l*"
+          , "keeps quotes" =:
+            strong (str "f" <> doubleQuoted (str "d") <> str "l") =?>
+            "**f“d”l**"
           ]
         , testGroup "headings"
           [ "normal heading" =:
diff --git a/test/Tests/Writers/RST.hs.orig b/test/Tests/Writers/RST.hs.orig
new file mode 100644
index 000000000..e54ce4737
--- /dev/null
+++ b/test/Tests/Writers/RST.hs.orig
@@ -0,0 +1,130 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Writers.RST (tests) where
+
+import Test.Tasty
+import Tests.Helpers
+import Text.Pandoc
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder
+
+infix 4 =:
+(=:) :: (ToString a, ToPandoc a)
+     => String -> (a, String) -> TestTree
+(=:) = test (purely (writeRST def . toPandoc))
+
+tests :: [TestTree]
+tests = [ testGroup "rubrics"
+          [ "in list item" =:
+              bulletList [header 2 (text "foo")] =?>
+              "-  .. rubric:: foo"
+          , "in definition list item" =:
+              definitionList [(text "foo", [header 2 (text "bar"),
+                                            para $ text "baz"])] =?>
+              unlines
+              [ "foo"
+              , "    .. rubric:: bar"
+              , ""
+              , "    baz"]
+          , "in block quote" =:
+              blockQuote (header 1 (text "bar")) =?>
+              "    .. rubric:: bar"
+          , "with id" =:
+              blockQuote (headerWith ("foo",[],[]) 1 (text "bar")) =?>
+              unlines
+              [ "    .. rubric:: bar"
+              , "       :name: foo"]
+          , "with id class" =:
+              blockQuote (headerWith ("foo",["baz"],[]) 1 (text "bar")) =?>
+              unlines
+              [ "    .. rubric:: bar"
+              , "       :name: foo"
+              , "       :class: baz"]
+          ]
+        , testGroup "ligatures" -- handling specific sequences of blocks
+          [ "a list is closed by a comment before a quote" =: -- issue 4248
+            bulletList [plain "bulleted"] <> blockQuote (plain "quoted") =?>
+              unlines
+              [ "-  bulleted"
+              , ""
+              , ".."
+              , ""
+              , "    quoted"]
+          ]
+        , testGroup "inlines"
+          [ "are removed when empty" =: -- #4434
+            plain (strong (str "")) =?> ""
+          , "do not cause the introduction of extra spaces when removed" =:
+            plain (strong (str "") <> emph (str "text")) =?> "*text*"
+          , "spaces are stripped at beginning and end" =:
+            -- pandoc issue 4327 "The text within inline markup may not
+            -- begin or end with whitespace"
+            -- http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#inline-markup
+            strong (space <> str "text" <> space <> space) =?> "**text**"
+          , "single space stripped" =:
+            strong space =?> ""
+          ]
+        , testGroup "headings"
+          [ "normal heading" =:
+              header 1 (text "foo") =?>
+              unlines
+              [ "foo"
+              , "==="]
+          -- note: heading normalization is only done in standalone mode
+          , test (purely (writeRST def{ writerTemplate = Just "$body$\n" }) . toPandoc)
+            "heading levels" $
+              header 1 (text "Header 1") <>
+              header 3 (text "Header 2") <>
+              header 2 (text "Header 2") <>
+              header 1 (text "Header 1") <>
+              header 4 (text "Header 2") <>
+              header 5 (text "Header 3") <>
+              header 3 (text "Header 2") =?>
+              unlines
+              [ "Header 1"
+              , "========"
+              , ""
+              , "Header 2"
+              , "--------"
+              , ""
+              , "Header 2"
+              , "--------"
+              , ""
+              , "Header 1"
+              , "========"
+              , ""
+              , "Header 2"
+              , "--------"
+              , ""
+              , "Header 3"
+              , "~~~~~~~~"
+              , ""
+              , "Header 2"
+              , "--------"]
+          , test (purely (writeRST def{ writerTemplate = Just "$body$\n" }) . toPandoc)
+            "minimal heading levels" $
+              header 2 (text "Header 1") <>
+              header 3 (text "Header 2") <>
+              header 2 (text "Header 1") <>
+              header 4 (text "Header 2") <>
+              header 5 (text "Header 3") <>
+              header 3 (text "Header 2") =?>
+              unlines
+              [ "Header 1"
+              , "========"
+              , ""
+              , "Header 2"
+              , "--------"
+              , ""
+              , "Header 1"
+              , "========"
+              , ""
+              , "Header 2"
+              , "--------"
+              , ""
+              , "Header 3"
+              , "~~~~~~~~"
+              , ""
+              , "Header 2"
+              , "--------"]
+          ]
+        ]
diff --git a/test/Tests/Writers/TEI.hs b/test/Tests/Writers/TEI.hs
index fa372909f..31e970495 100644
--- a/test/Tests/Writers/TEI.hs
+++ b/test/Tests/Writers/TEI.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Tests.Writers.TEI (tests) where
 
+import Prelude
 import Test.Tasty
 import Tests.Helpers
 import Text.Pandoc
diff --git a/test/Tests/Writers/TEI.hs.orig b/test/Tests/Writers/TEI.hs.orig
new file mode 100644
index 000000000..fa372909f
--- /dev/null
+++ b/test/Tests/Writers/TEI.hs.orig
@@ -0,0 +1,43 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Writers.TEI (tests) where
+
+import Test.Tasty
+import Tests.Helpers
+import Text.Pandoc
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder
+
+{-
+  "my test" =: X =?> Y
+
+is shorthand for
+
+  test html "my test" $ X =?> Y
+
+which is in turn shorthand for
+
+  test html "my test" (X,Y)
+-}
+
+infix 4 =:
+(=:) :: (ToString a, ToPandoc a)
+     => String -> (a, String) -> TestTree
+(=:) = test (purely (writeTEI def) . toPandoc)
+
+tests :: [TestTree]
+tests = [ testGroup "block elements"
+          ["para"          =: para "Lorem ipsum cetera."
+                           =?> "<p>Lorem ipsum cetera.</p>"
+          ]
+        , testGroup "inlines"
+          [
+            "Emphasis"      =:  emph "emphasized"
+                            =?> "<p><hi rendition=\"simple:italic\">emphasized</hi></p>"
+           ,"SingleQuoted"  =:  singleQuoted (text "quoted material")
+                            =?> "<p><quote>quoted material</quote></p>"
+           ,"DoubleQuoted"  =:  doubleQuoted (text "quoted material")
+                            =?> "<p><quote>quoted material</quote></p>"
+           ,"NestedQuoted"  =:  doubleQuoted (singleQuoted (text "quoted material"))
+                            =?> "<p><quote><quote>quoted material</quote></quote></p>"
+          ]
+         ]
diff --git a/test/command/1710.md b/test/command/1710.md
index d14f1217f..d20dfe191 100644
--- a/test/command/1710.md
+++ b/test/command/1710.md
@@ -54,9 +54,8 @@ ok
 </div>
 </div>
 ^D
-\begin{frame}{%
-\protect\hypertarget{slide-one}{%
-Slide one}}
+\begin{frame}{Slide one}
+\protect\hypertarget{slide-one}{}
 
 \begin{columns}[T]
 \begin{column}{0.40\textwidth}
diff --git a/test/command/2649.md b/test/command/2649.md
index 8f594cfe1..52ae16ce4 100644
--- a/test/command/2649.md
+++ b/test/command/2649.md
@@ -67,7 +67,8 @@
 ! Aantal
 |-
 | 1
-|align=left| {{FR-VLAG}} [[Sébastien Loeb]] | 78
+|align=left| {{FR-VLAG}} [[Sébastien Loeb]]
+| 78
 |-
 | 2
 |align=left| {{FR-VLAG}} '''[[Sébastien Ogier]]'''
@@ -79,24 +80,25 @@
 |}
 ^D
 <table>
+<thead>
+<tr class="header">
+<th><p>Plaats</p></th>
+<th><p>Rijder</p></th>
+<th><p>Aantal</p></th>
+</tr>
+</thead>
 <tbody>
 <tr class="odd">
-<td></td>
-<td><p>Plaats</p></td>
-<td><p>Rijder</p></td>
-<td><p>Aantal</p></td>
-</tr>
-<tr class="even">
 <td><p>1</p></td>
 <td><p><a href="Sébastien_Loeb" title="wikilink">Sébastien Loeb</a></p></td>
 <td><p>78</p></td>
 </tr>
-<tr class="odd">
+<tr class="even">
 <td><p>2</p></td>
 <td><p><strong><a href="Sébastien_Ogier" title="wikilink">Sébastien Ogier</a></strong></p></td>
 <td><p>38</p></td>
 </tr>
-<tr class="even">
+<tr class="odd">
 <td><p>10</p></td>
 <td><p><a href="Hannu_Mikkola" title="wikilink">Hannu Mikkola</a></p></td>
 <td><p>18</p></td>
diff --git a/test/command/3348.md b/test/command/3348.md
index 1457373c8..6e0c07033 100644
--- a/test/command/3348.md
+++ b/test/command/3348.md
@@ -7,7 +7,7 @@
         line of text
   ----- ------------------------------------------------
 ^D
-[Table [] [AlignRight,AlignLeft] [8.333333333333333e-2,0.6666666666666666]
+[Table [] [AlignRight,AlignLeft] [8.333333333333333e-2,0.6805555555555556]
  [[]
  ,[]]
  [[[Plain [Str "foo"]]
diff --git a/test/command/3510-src.hs.orig b/test/command/3510-src.hs.orig
new file mode 100644
index 000000000..ad5744b80
--- /dev/null
+++ b/test/command/3510-src.hs.orig
@@ -0,0 +1 @@
+putStrLn outString
diff --git a/test/command/3587.md b/test/command/3587.md
index addb6c582..414593b39 100644
--- a/test/command/3587.md
+++ b/test/command/3587.md
@@ -19,3 +19,39 @@
 ^D
 [Para [Str "{}\160{}\160{}"]]
 ```
+
+```
+% pandoc -f latex -t native
+\SI{30}{\milli\meter}
+^D
+[Para [Str "30\160mm"]]
+```
+
+```
+% pandoc -f latex -t native
+\SI{6}{\gram}
+^D
+[Para [Str "6\160g"]]
+```
+
+```
+% pandoc -f latex -t native
+\SI{25}{\square\meter}
+^D
+[Para [Str "25\160m\178"]]
+```
+
+```
+% pandoc -f latex -t native
+\SI{18.2}{\degreeCelsius}
+^D
+[Para [Str "18.2\160\176C"]]
+```
+
+```
+% pandoc -f latex -t native
+\SI{18.2}{\celsius}
+^D
+[Para [Str "18.2\160\176C"]]
+```
+
diff --git a/test/command/3675.md b/test/command/3675.md
index b129c7a63..f75721b56 100644
--- a/test/command/3675.md
+++ b/test/command/3675.md
@@ -7,9 +7,9 @@ print("hello")
 ^D
 .. code:: python
 
-    print("hello")
+   print("hello")
 
 ..
 
-    block quote
+   block quote
 ````
diff --git a/test/command/4016.md b/test/command/4016.md
index 69ad1c911..3918251c6 100644
--- a/test/command/4016.md
+++ b/test/command/4016.md
@@ -13,9 +13,8 @@ pandoc -t beamer
 </div>
 </div>
 ^D
-\begin{frame}{%
-\protect\hypertarget{level-2-blocks}{%
-Level 2 blocks}}
+\begin{frame}{Level 2 blocks}
+\protect\hypertarget{level-2-blocks}{}
 
 \begin{columns}[T]
 \begin{column}{0.40\textwidth}
diff --git a/test/command/4320.md b/test/command/4320.md
new file mode 100644
index 000000000..732b30a3e
--- /dev/null
+++ b/test/command/4320.md
@@ -0,0 +1,15 @@
+```
+% pandoc -f native -t rst --wrap=none
+[Table [] [AlignDefault,AlignDefault] [0.47368421052631576,0.5263157894736842]
+ [[Plain [Str "one"]]
+ ,[Plain [Str "two"]]]
+ [[[Plain [Str "ports"]]
+  ,[BlockQuote
+    [Para [Strong [Str "thisIsGoingToBeTooLongAnyway"]]]]]]]
+^D
++-------+-------------------------------------+
+| one   | two                                 |
++=======+=====================================+
+| ports |    **thisIsGoingToBeTooLongAnyway** |
++-------+-------------------------------------+
+```
diff --git a/test/command/4424.md b/test/command/4424.md
new file mode 100644
index 000000000..b0b95510b
--- /dev/null
+++ b/test/command/4424.md
@@ -0,0 +1,10 @@
+```
+% pandoc -f latex -t native
+\documentclass{article}
+\usepackage[sortlocale=en_GB]{biblatex}
+\begin{document}
+Test
+\end{document}
+^D
+[Para [Str "Test"]]
+```
diff --git a/test/command/4454.md b/test/command/4454.md
new file mode 100644
index 000000000..db0b0a406
--- /dev/null
+++ b/test/command/4454.md
@@ -0,0 +1,9 @@
+```
+% pandoc -f rst -t native
+• a
+• b
+^D
+[BulletList
+ [[Plain [Str "a"]]
+ ,[Plain [Str "b"]]]]
+```
diff --git a/test/command/4513.md b/test/command/4513.md
new file mode 100644
index 000000000..e4a4406e4
--- /dev/null
+++ b/test/command/4513.md
@@ -0,0 +1,9 @@
+```
+% pandoc -f textile -t native
+|_. heading 1 |_. heading 2|
+^D
+[Table [] [AlignDefault,AlignDefault] [0.0,0.0]
+ [[Plain [Str "heading",Space,Str "1"]]
+ ,[Plain [Str "heading",Space,Str "2"]]]
+ []]
+```
diff --git a/test/command/4527.md b/test/command/4527.md
new file mode 100644
index 000000000..984333559
--- /dev/null
+++ b/test/command/4527.md
@@ -0,0 +1,21 @@
+# Raw TeX blocks in CommonMark with and without raw_tex
+
+```
+% pandoc -f latex -t commonmark-raw_tex
+\someunknowncommand
+
+Hello.
+^D
+Hello.
+```
+
+```
+% pandoc -f latex -t commonmark+raw_tex
+\someunknowncommand
+
+Hello.
+^D
+\someunknowncommand
+
+Hello.
+```
diff --git a/test/command/4529.md b/test/command/4529.md
new file mode 100644
index 000000000..4a2125b9c
--- /dev/null
+++ b/test/command/4529.md
@@ -0,0 +1,36 @@
+```
+% pandoc -f latex -t plain
+\chapter{First chapter}\label{sec:chp1}
+The next chapter is Chapter~\ref{sec:chp2}.
+\section{First section}\label{sec:chp1sec1}
+The next section is Section~\ref{sec:chp2sec1}.
+
+\chapter{Second chapter}\label{sec:chp2}
+The previous chapter is Chapter~\ref{sec:chp1}.
+\section{First section}\label{sec:chp2sec1}
+The previous section is Section~\ref{sec:chp1sec1}.
+^D
+
+
+FIRST CHAPTER
+
+
+The next chapter is Chapter 2.
+
+
+First section
+
+The next section is Section 2.1.
+
+
+
+SECOND CHAPTER
+
+
+The previous chapter is Chapter 1.
+
+
+First section
+
+The previous section is Section 1.1.
+```
diff --git a/test/command/4550.md b/test/command/4550.md
new file mode 100644
index 000000000..bf3afce5b
--- /dev/null
+++ b/test/command/4550.md
@@ -0,0 +1,7 @@
+```
+% pandoc -f markdown-smart -t ms
+A ‘simple’ example
+^D
+.LP
+A ‘simple’ example
+```
diff --git a/test/command/4576.md b/test/command/4576.md
new file mode 100644
index 000000000..1c82b96eb
--- /dev/null
+++ b/test/command/4576.md
@@ -0,0 +1,6 @@
+```
+% pandoc -f latex -t native
+$\rho_\text{D$_2$O}=866$
+^D
+[Para [Math InlineMath "\\rho_\\text{D$_2$O}=866"]]
+```
diff --git a/test/command/4578.md b/test/command/4578.md
new file mode 100644
index 000000000..8f12d0bf2
--- /dev/null
+++ b/test/command/4578.md
@@ -0,0 +1,14 @@
+```
+% pandoc -t markdown
+  ------ ------- --------------- ---------------------
+  One    row                12.0 Example of a row that
+                                 spans multiple lines.
+
+  ------ ------- --------------- ---------------------
+^D
+  ------ ------- --------------- ---------------------
+  One    row                12.0 Example of a row that
+                                 spans multiple lines.
+
+  ------ ------- --------------- ---------------------
+```
diff --git a/test/command/4579.md b/test/command/4579.md
new file mode 100644
index 000000000..80f0f58c2
--- /dev/null
+++ b/test/command/4579.md
@@ -0,0 +1,16 @@
+```
+% pandoc -f rst -t native
+.. list-table::
+  :header-rows: 1
+
+  * - Foo
+    - Bar
+  * - spam
+    - ham
+^D
+[Table [] [AlignDefault,AlignDefault] [0.0,0.0]
+ [[Plain [Str "Foo"]]
+ ,[Plain [Str "Bar"]]]
+ [[[Plain [Str "spam"]]
+  ,[Plain [Str "ham"]]]]]
+```
diff --git a/test/command/4589.md b/test/command/4589.md
new file mode 100644
index 000000000..ffbe6fe6f
--- /dev/null
+++ b/test/command/4589.md
@@ -0,0 +1,14 @@
+```
+% pandoc -f markdown -t latex
+\newcommand{\one}[1]{#1}
+\newcommand{\two}[1]{#1}
+
+Formatting *is* working **here**. But sticking \one{two }\two{commands}
+together *breaks* formatting.
+^D
+\newcommand{\one}[1]{#1}
+\newcommand{\two}[1]{#1}
+
+Formatting \emph{is} working \textbf{here}. But sticking two commands
+together \emph{breaks} formatting.
+```
diff --git a/test/command/4594.md b/test/command/4594.md
new file mode 100644
index 000000000..3f08b6c12
--- /dev/null
+++ b/test/command/4594.md
@@ -0,0 +1,24 @@
+```
+% pandoc -f markdown -t latex
+Some **bold** text here.
+
+\begin{figure}[htbp]
+\centering
+\def\svgwidth{\columnwidth}
+\import{img/}{vectors.pdf_tex}
+\caption{Some caption.}
+\end{figure}
+
+Some *italic* text here.
+^D
+Some \textbf{bold} text here.
+
+\begin{figure}[htbp]
+\centering
+\def\svgwidth{\columnwidth}
+\import{img/}{vectors.pdf_tex}
+\caption{Some caption.}
+\end{figure}
+
+Some \emph{italic} text here.
+```
diff --git a/test/command/4598.md b/test/command/4598.md
new file mode 100644
index 000000000..fedfe888a
--- /dev/null
+++ b/test/command/4598.md
@@ -0,0 +1,10 @@
+```
+% pandoc -f rst
+`x`__
+
+__ `xy`_
+
+.. _`xy`: http://xy.org
+^D
+<p><a href="http://xy.org">x</a></p>
+```
diff --git a/test/command/sloppypar.md b/test/command/sloppypar.md
new file mode 100644
index 000000000..e2ff4d550
--- /dev/null
+++ b/test/command/sloppypar.md
@@ -0,0 +1,23 @@
+```
+% pandoc -f latex+raw_tex -t native
+\begin{sloppypar}
+Sequi id qui facere et incidunt ut. Et fuga ut voluptate enim qui. Odit unde magni ipsam dicta modi. Modi soluta velit est aut aut possimus.
+
+Qui et temporibus explicabo. Esse ab ut quidem. Vel qui perspiciatis quae odio consectetur alias non sed. Quo consectetur libero omnis quos eius ad vel.
+\end{sloppypar}
+^D
+[Para [Str "Sequi",Space,Str "id",Space,Str "qui",Space,Str "facere",Space,Str "et",Space,Str "incidunt",Space,Str "ut.",Space,Str "Et",Space,Str "fuga",Space,Str "ut",Space,Str "voluptate",Space,Str "enim",Space,Str "qui.",Space,Str "Odit",Space,Str "unde",Space,Str "magni",Space,Str "ipsam",Space,Str "dicta",Space,Str "modi.",Space,Str "Modi",Space,Str "soluta",Space,Str "velit",Space,Str "est",Space,Str "aut",Space,Str "aut",Space,Str "possimus."]
+,Para [Str "Qui",Space,Str "et",Space,Str "temporibus",Space,Str "explicabo.",Space,Str "Esse",Space,Str "ab",Space,Str "ut",Space,Str "quidem.",Space,Str "Vel",Space,Str "qui",Space,Str "perspiciatis",Space,Str "quae",Space,Str "odio",Space,Str "consectetur",Space,Str "alias",Space,Str "non",Space,Str "sed.",Space,Str "Quo",Space,Str "consectetur",Space,Str "libero",Space,Str "omnis",Space,Str "quos",Space,Str "eius",Space,Str "ad",Space,Str "vel."]]
+```
+
+```
+% pandoc -f latex -t native
+\begin{sloppypar}
+Sequi id qui facere et incidunt ut. Et fuga ut voluptate enim qui. Odit unde magni ipsam dicta modi. Modi soluta velit est aut aut possimus.
+
+Qui et temporibus explicabo. Esse ab ut quidem. Vel qui perspiciatis quae odio consectetur alias non sed. Quo consectetur libero omnis quos eius ad vel.
+\end{sloppypar}
+^D
+[Para [Str "Sequi",Space,Str "id",Space,Str "qui",Space,Str "facere",Space,Str "et",Space,Str "incidunt",Space,Str "ut.",Space,Str "Et",Space,Str "fuga",Space,Str "ut",Space,Str "voluptate",Space,Str "enim",Space,Str "qui.",Space,Str "Odit",Space,Str "unde",Space,Str "magni",Space,Str "ipsam",Space,Str "dicta",Space,Str "modi.",Space,Str "Modi",Space,Str "soluta",Space,Str "velit",Space,Str "est",Space,Str "aut",Space,Str "aut",Space,Str "possimus."]
+,Para [Str "Qui",Space,Str "et",Space,Str "temporibus",Space,Str "explicabo.",Space,Str "Esse",Space,Str "ab",Space,Str "ut",Space,Str "quidem.",Space,Str "Vel",Space,Str "qui",Space,Str "perspiciatis",Space,Str "quae",Space,Str "odio",Space,Str "consectetur",Space,Str "alias",Space,Str "non",Space,Str "sed.",Space,Str "Quo",Space,Str "consectetur",Space,Str "libero",Space,Str "omnis",Space,Str "quos",Space,Str "eius",Space,Str "ad",Space,Str "vel."]]
+```
diff --git a/test/docx/adjacent_codeblocks.docx b/test/docx/adjacent_codeblocks.docx
new file mode 100644
index 000000000..d61fb45d5
Binary files /dev/null and b/test/docx/adjacent_codeblocks.docx differ
diff --git a/test/docx/adjacent_codeblocks.native b/test/docx/adjacent_codeblocks.native
new file mode 100644
index 000000000..ec1e2416e
--- /dev/null
+++ b/test/docx/adjacent_codeblocks.native
@@ -0,0 +1,6 @@
+[Para [Str "Next,",Space,Str "open",Space,Str "the",Space,Str "terminal",Space,Str "window.",Space,Str "Using",Space,Str "the",Space,Str "terminal",Space,Str "window,",Space,Str "run",Space,Str "the",Space,Str "\"ifconfig",Space,Str "-a\"",Space,Str "command",Space,Str "to",Space,Str "list",Space,Str "all",Space,Str "the",Space,Str "interfaces",Space,Str "on",Space,Str "your",Space,Str "system,",Space,Str "as",Space,Str "shown",Space,Str "here."]
+,CodeBlock ("",[],[]) "# ifconfig -a\neth0      Link encap:Ethernet  HWaddr 00:0c:29:69:12:7c  \n          inet addr:172.16.0.108  Bcast:172.16.0.255  Mask:255.255.255.0\n          inet6 addr: fc00:660:0:1:20c:29ff:fe69:127c/64 Scope:Global\n          inet6 addr: fe80::20c:29ff:fe69:127c/64 Scope:Link\n          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1\n          RX packets:9859 errors:0 dropped:0 overruns:0 frame:0\n          TX packets:1399 errors:0 dropped:0 overruns:0 carrier:0\n          collisions:0 txqueuelen:1000 \n          RX bytes:1920894 (1.8 MiB)  TX bytes:233088 (227.6 KiB)\n          Interrupt:19 Base address:0x2000 \n\nlo        Link encap:Local Loopback  \n          inet addr:127.0.0.1  Mask:255.0.0.0\n          inet6 addr: ::1/128 Scope:Host\n          UP LOOPBACK RUNNING  MTU:65536  Metric:1\n          RX packets:372 errors:0 dropped:0 overruns:0 frame:0\n          TX packets:372 errors:0 dropped:0 overruns:0 carrier:0\n          collisions:0 txqueuelen:0 \n          RX bytes:22320 (21.7 KiB)  TX bytes:22320 (21.7 KiB)\n\nwlan0     Link encap:Ethernet  HWaddr 00:c0:ca:85:00:ba  \n          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1\n          RX packets:0 errors:0 dropped:0 overruns:0 frame:0\n          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0\n          collisions:0 txqueuelen:1000 \n          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)"
+,Para [Str "The",Space,Str "ALFA",Space,Str "wireless",Space,Str "card",Space,Str "is",Space,Str "represented",Space,Str "by",Space,Str "the",Space,Str "\"wlan0\"",Space,Str "interface."]
+,Para [Str "In",Space,Str "addition",Space,Str "to",Space,Str "the",Space,Str "interfaces",Space,Str "shown",Space,Str "in",Space,Str "the",Space,Str "ifconfig",Space,Str "output,",Space,Str "there",Space,Str "is",Space,Str "another",Space,Str "interface",Space,Str "known",Space,Str "as",Space,Str "the",Space,Emph [Str "wireless",Space,Str "physical",Space,Str "interface"],Str ".",Space,Str "We",Space,Str "can",Space,Str "identify",Space,Str "this",Space,Str "interface",Space,Str "by",Space,Str "listing",Space,Str "the",Space,Str "contents",Space,Str "of",Space,Str "the",Space,Str "/sys/class/ieee80211",Space,Str "directory,",Space,Str "as",Space,Str "shown."]
+,CodeBlock ("",[],[]) "# ls /sys/class/ieee80211/\nphy0"
+,Para [Str "The",Space,Str "\"phy0\"",Space,Str "interface",Space,Str "is",Space,Str "the",Space,Str "parent",Space,Str "interface",Space,Str "used",Space,Str "to",Space,Str "create",Space,Str "child",Space,Str "interfaces.",Space,Str "Note",Space,Str "that",Space,Str "if",Space,Str "you",Space,Str "unplug",Space,Str "and",Space,Str "replug",Space,Str "the",Space,Str "USB",Space,Str "interface,",Space,Str "the",Space,Str "\"phy\"",Space,Str "interface",Space,Str "number",Space,Str "will",Space,Str "increment",Space,Str "by",Space,Str "one",Space,Str "until",Space,Str "you",Space,Str "reboot",Space,Str "your",Space,Str "system."]]
diff --git a/test/docx/block_quotes.docx b/test/docx/block_quotes.docx
index 729ae1f43..aa2fef00e 100644
Binary files a/test/docx/block_quotes.docx and b/test/docx/block_quotes.docx differ
diff --git a/test/docx/char_styles.docx b/test/docx/char_styles.docx
index 05979b9a7..ef6106215 100644
Binary files a/test/docx/char_styles.docx and b/test/docx/char_styles.docx differ
diff --git a/test/docx/custom-style-with-styles.native b/test/docx/custom-style-with-styles.native
index 6b0381408..61f11911d 100644
--- a/test/docx/custom-style-with-styles.native
+++ b/test/docx/custom-style-with-styles.native
@@ -1,7 +1,7 @@
 [Div ("",[],[("custom-style","FirstParagraph")])
  [Para [Str "This",Space,Str "is",Space,Str "some",Space,Str "text."]]
 ,Div ("",[],[("custom-style","BodyText")])
- [Para [Str "This",Space,Str "is",Space,Str "text",Space,Str "with",Space,Str "an",Space,Span ("",[],[("custom-style","Emphatic")]) [Emph [Str "emphasized"]],Space,Str "text",Space,Str "style.",Space,Str "And",Space,Str "this",Space,Str "is",Space,Str "text",Space,Str "with",Space,Str "a",Space,Span ("",[],[("custom-style","Strengthened")]) [Strong [Str "strengthened"]],Space,Str "text",Space,Str "style."]]
+ [Para [Str "This",Space,Str "is",Space,Str "text",Space,Str "with",Space,Str "an",Space,Span ("",[],[("custom-style","Emphatic")]) [Str "emphasized"],Space,Str "text",Space,Str "style.",Space,Str "And",Space,Str "this",Space,Str "is",Space,Str "text",Space,Str "with",Space,Str "a",Space,Span ("",[],[("custom-style","Strengthened")]) [Str "strengthened"],Space,Str "text",Space,Str "style."]]
 ,Div ("",[],[("custom-style","MyBlockStyle")])
  [BlockQuote
   [Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "styled",Space,Str "paragraph",Space,Str "that",Space,Str "inherits",Space,Str "from",Space,Str "Block",Space,Str "Text."]]]]
diff --git a/test/docx/deep_normalize.docx b/test/docx/deep_normalize.docx
index 7626d59ce..4905ebe14 100644
Binary files a/test/docx/deep_normalize.docx and b/test/docx/deep_normalize.docx differ
diff --git a/test/docx/drop_cap.docx b/test/docx/drop_cap.docx
index 19fab4a52..2f14c2c1d 100644
Binary files a/test/docx/drop_cap.docx and b/test/docx/drop_cap.docx differ
diff --git a/test/docx/golden/image.docx b/test/docx/golden/image.docx
index dc49f266b..95a28a098 100644
Binary files a/test/docx/golden/image.docx and b/test/docx/golden/image.docx differ
diff --git a/test/docx/golden/inline_formatting.docx b/test/docx/golden/inline_formatting.docx
index 367654e53..9e07bd25d 100644
Binary files a/test/docx/golden/inline_formatting.docx and b/test/docx/golden/inline_formatting.docx differ
diff --git a/test/docx/golden/inline_images.docx b/test/docx/golden/inline_images.docx
index 6bd4b3a34..62c5943ba 100644
Binary files a/test/docx/golden/inline_images.docx and b/test/docx/golden/inline_images.docx differ
diff --git a/test/docx/hanging_indent.docx b/test/docx/hanging_indent.docx
index 6f62dc731..62d41fdad 100644
Binary files a/test/docx/hanging_indent.docx and b/test/docx/hanging_indent.docx differ
diff --git a/test/docx/headers.docx b/test/docx/headers.docx
index e1fbbcc75..6c4701716 100644
Binary files a/test/docx/headers.docx and b/test/docx/headers.docx differ
diff --git a/test/docx/image_writer_test.native b/test/docx/image_writer_test.native
index a568cbca0..a0fb3ee3a 100644
--- a/test/docx/image_writer_test.native
+++ b/test/docx/image_writer_test.native
@@ -1,5 +1,8 @@
-Pandoc (Meta {unMeta = fromList []})
-[Para [Image ("",[],[]) [] ("lalune.jpg","")]
-,Para [Image ("",[],[]) [Str "The",Space,Str "Moon"] ("lalune.jpg","fig:")]
-,Header 1 ("one-more",[],[]) [Str "One",Space,Str "More"]
-,Para [Image ("",[],[]) [Str "The",Space,Str "Moon"] ("lalune.jpg","fig:")]]
\ No newline at end of file
+[Para [Str "No",Space,Str "width",Space,Str "given:"]
+,Para [Image ("",[],[]) [Str "testimg"] ("lalune.jpg","fig:")]
+,Para [Str "With",Space,Str "height",Space,Str "10cm:"]
+,Para [Image ("",[],[("height","10cm")]) [Str "2testimg"] ("lalune.jpg","fig:")]
+,Para [Str "With",Space,Str "width",Space,Str "6cm:"]
+,Para [Image ("",[],[("width","6cm")]) [Str "3testimg"] ("lalune.jpg","fig:")]
+,Header 1 ("with-height-3in-and-width-6in",[],[]) [Str "With",Space,Str "height",Space,Str "3in",Space,Str "and",Space,Str "width",Space,Str "6in:"]
+,Para [Image ("",[],[("width","6in"),("height","3in")]) [Str "4testimg"] ("lalune.jpg","fig:")]]
\ No newline at end of file
diff --git a/test/docx/inline_formatting.docx b/test/docx/inline_formatting.docx
index eccf26425..49f383e73 100644
Binary files a/test/docx/inline_formatting.docx and b/test/docx/inline_formatting.docx differ
diff --git a/test/docx/inline_images.docx b/test/docx/inline_images.docx
index 2f01a251e..af433bb79 100644
Binary files a/test/docx/inline_images.docx and b/test/docx/inline_images.docx differ
diff --git a/test/docx/link_in_notes.docx b/test/docx/link_in_notes.docx
index f3398f438..b5e4e2bf6 100644
Binary files a/test/docx/link_in_notes.docx and b/test/docx/link_in_notes.docx differ
diff --git a/test/docx/links.docx b/test/docx/links.docx
index 80fecacaf..f23007f11 100644
Binary files a/test/docx/links.docx and b/test/docx/links.docx differ
diff --git a/test/docx/lists.docx b/test/docx/lists.docx
index bf7fd8ae4..8b46351d9 100644
Binary files a/test/docx/lists.docx and b/test/docx/lists.docx differ
diff --git a/test/docx/metadata.docx b/test/docx/metadata.docx
index ccf50b475..d5a4fb255 100644
Binary files a/test/docx/metadata.docx and b/test/docx/metadata.docx differ
diff --git a/test/docx/metadata_after_normal.docx b/test/docx/metadata_after_normal.docx
index b94a016cb..f43110e96 100644
Binary files a/test/docx/metadata_after_normal.docx and b/test/docx/metadata_after_normal.docx differ
diff --git a/test/docx/nested_sdt.docx b/test/docx/nested_sdt.docx
new file mode 100644
index 000000000..1a0827db3
Binary files /dev/null and b/test/docx/nested_sdt.docx differ
diff --git a/test/docx/nested_sdt.native b/test/docx/nested_sdt.native
new file mode 100644
index 000000000..d0adc05ac
--- /dev/null
+++ b/test/docx/nested_sdt.native
@@ -0,0 +1,3 @@
+[Para [Str "Test",Space,Str "Paragraph1"]
+,Para [Str "Test",Space,Str "Paragraph2"]
+,Para [Str "Test",Space,Str "Paragraph3"]]
diff --git a/test/docx/nested_smart_tags.docx b/test/docx/nested_smart_tags.docx
new file mode 100644
index 000000000..6719c44a8
Binary files /dev/null and b/test/docx/nested_smart_tags.docx differ
diff --git a/test/docx/nested_smart_tags.native b/test/docx/nested_smart_tags.native
new file mode 100644
index 000000000..e6c776a63
--- /dev/null
+++ b/test/docx/nested_smart_tags.native
@@ -0,0 +1,7 @@
+[Header 2 ("and-it-came-to-pass-in-the-course-of-those-many-days",["Myheading2"],[]) [Str "159.",Space,Str "And",Space,Str "It",Space,Str "Came",Space,Str "to",Space,Str "Pass",Space,Str "in",Space,Str "the",Space,Str "Course",Space,Str "of",Space,Str "Those",Space,Str "Many",Space,Str "Days"]
+,Para [Str "I",Space,Str "heard"]
+,Para [Str "\8220And",Space,Str "it",Space,Str "came",Space,Str "to",Space,Str "pass",Space,Str "in",Space,Str "the",Space,Str "course",Space,Str "of",Space,Str "those",Space,Str "many",Space,Str "days",Space,Str "that",Space,Str "the",Space,Str "king",Space,Str "of",Space,Str "Egypt",Space,Str "died;",Space,Str "and",Space,Str "the",Space,Str "children",Space,Str "of",Space,Str "Israel",Space,Str "sighed",Space,Str "by",Space,Str "reason",Space,Str "of",Space,Str "the",Space,Str "bondage,",Space,Str "and",Space,Str "they",Space,Str "cried,",Space,Str "and",Space,Str "their",Space,Str "cry",Space,Str "came",Space,Str "up",Space,Str "unto",Space,Str "God",Space,Str "by",Space,Str "reason",Space,Str "of",Space,Str "the",Space,Str "bondage.",Space,Str "And",Space,Str "God",Space,Str "heard",Space,Str "their",Space,Str "groaning\8221",Space,Str "(Exodus",Space,Str "2:23-4).",Space,Str "This",Space,Str "means",Space,Str "that",Space,Str "they",Space,Str "suffered",Space,Str "so",Space,Str "much",Space,Str "that",Space,Str "they",Space,Str "could",Space,Str "not",Space,Str "bear",Space,Str "it",Space,Str "any",Space,Str "longer.",Space,Str "And",Space,Str "they",Space,Str "so",Space,Str "pleaded",Space,Str "with",Space,Str "prayer,",Space,Str "that",Space,Str "\8220their",Space,Str "cry",Space,Str "came",Space,Str "up",Space,Str "unto",Space,Str "God.\8221"]
+,Para [Str "But",Space,Str "we",Space,Str "can",Space,Str "see",Space,Str "that",Space,Str "they",Space,Str "were",Space,Str "saying,",Space,Str "\8220Would",Space,Str "that",Space,Str "we",Space,Str "had\8230",Space,Str "when",Space,Str "we",Space,Str "sat",Space,Str "by",Space,Str "the",Space,Str "flesh-pots,",Space,Str "when",Space,Str "we",Space,Str "did",Space,Str "eat",Space,Str "bread",Space,Str "to",Space,Str "the",Space,Str "full.\8221",Space,Str "And",Space,Str "they",Space,Str "also",Space,Str "said,",Space,Str "\8220We",Space,Str "remember",Space,Str "the",Space,Str "fish,",Space,Str "which",Space,Str "we",Space,Str "would",Space,Str "eat",Space,Str "in",Space,Str "Egypt",Space,Str "for",Space,Str "naught;",Space,Str "the",Space,Str "cucumbers,",Space,Str "and",Space,Str "the",Space,Str "melons,",Space,Str "and",Space,Str "the",Space,Str "leeks,",Space,Str "and",Space,Str "the",Space,Str "onions,",Space,Str "and",Space,Str "the",Space,Str "garlic.\8221"]
+,Para [Str "The",Space,Str "thing",Space,Str "is",Space,Str "that,",Space,Str "indeed,",Space,Str "they",Space,Str "were",Space,Str "very",Space,Str "fond",Space,Str "of",Space,Str "the",Space,Str "work",Space,Str "in",Space,Str "Egypt.",Space,Str "This",Space,Str "is",Space,Str "the",Space,Str "meaning",Space,Str "of",Space,Str "\8220But",Space,Str "mingled",Space,Str "themselves",Space,Str "with",Space,Str "the",Space,Str "nations,",Space,Str "and",Space,Str "learned",Space,Str "their",Space,Str "works.\8221",Space,Str "It",Space,Str "means",Space,Str "that",Space,Str "if",Space,Str "Israel",Space,Str "are",Space,Str "under",Space,Str "the",Space,Str "dominion",Space,Str "of",Space,Str "a",Space,Str "certain",Space,Str "nation,",Space,Str "that",Space,Str "nation",Space,Str "controls",Space,Str "them",Space,Str "and",Space,Str "they",Space,Str "cannot",Space,Str "retire",Space,Str "from",Space,Str "their",Space,Str "dominion.",Space,Str "Thus,",Space,Str "they",Space,Str "tasted",Space,Str "sufficient",Space,Str "flavor",Space,Str "in",Space,Str "that",Space,Str "work",Space,Str "and",Space,Str "could",Space,Str "not",Space,Str "be",Space,Str "redeemed."]
+,Para [Str "So",Space,Str "what",Space,Str "did",Space,Str "the",Space,Str "Creator",Space,Str "do?",Space,Str "\8220The",Space,Str "king",Space,Str "of",Space,Str "Egypt",Space,Str "died,\8221",Space,Str "meaning",Space,Str "they",Space,Str "had",Space,Str "lost",Space,Str "this",Space,Str "servitude.",Space,Str "Thus",Space,Str "they",Space,Str "could",Space,Str "no",Space,Str "longer",Space,Str "work;",Space,Str "they",Space,Str "understood",Space,Str "that",Space,Str "if",Space,Str "there",Space,Str "is",Space,Str "no",Space,Str "perfection",Space,Str "of",Space,Str "the",Space,Emph [Str "Mochin"],Str ",",Space,Str "the",Space,Str "servitude",Space,Str "is",Space,Str "also",Space,Str "incomplete.",Space,Str "Hence,",Space,Str "\8220and",Space,Str "the",Space,Str "children",Space,Str "of",Space,Str "Israel",Space,Str "sighed",Space,Str "by",Space,Str "reason",Space,Str "of",Space,Str "the",Space,Str "bondage.\8221",Space,Str "The",Space,Str "work",Space,Str "means",Space,Str "that",Space,Str "they",Space,Str "did",Space,Str "not",Space,Str "suffice",Space,Str "for",Space,Str "the",Space,Str "work,",Space,Str "that",Space,Str "they",Space,Str "had",Space,Str "no",Space,Str "liveliness",Space,Str "in",Space,Str "the",Space,Str "servitude."]
+,Para [Str "This",Space,Str "is",Space,Str "the",Space,Str "meaning",Space,Str "of",Space,Str "\8220the",Space,Str "king",Space,Str "of",Space,Str "Egypt",Space,Str "died,\8221",Space,Str "that",Space,Str "all",Space,Str "the",Space,Str "dominations",Space,Str "of",Space,Str "the",Space,Str "king",Space,Str "of",Space,Str "Egypt,",Space,Str "which",Space,Str "he",Space,Str "was",Space,Str "providing",Space,Str "for",Space,Str "and",Space,Str "nourishing,",Space,Str "had",Space,Str "died.",Space,Str "This",Space,Str "is",Space,Str "why",Space,Str "they",Space,Str "had",Space,Str "room",Space,Str "for",Space,Str "prayer.",Space,Str "And",Space,Str "they",Space,Str "were",Space,Str "immediately",Space,Str "salvaged.",Space,Str "And",Space,Str "afterwards,",Space,Str "when",Space,Str "they",Space,Str "walked",Space,Str "in",Space,Str "the",Space,Str "desert",Space,Str "and",Space,Str "came",Space,Str "to",Space,Str "a",Space,Str "state",Space,Str "of",Space,Emph [Str "Katnut"],Space,Str "(smallness),",Space,Str "they",Space,Str "craved",Space,Str "the",Space,Str "servitude",Space,Str "that",Space,Str "they",Space,Str "had",Space,Str "had",Space,Str "prior",Space,Str "to",Space,Str "the",Space,Str "death",Space,Str "of",Space,Str "the",Space,Str "king",Space,Str "of",Space,Str "Egypt."]]
diff --git a/test/docx/normalize.docx b/test/docx/normalize.docx
index b4fc55818..a20c5ddd1 100644
Binary files a/test/docx/normalize.docx and b/test/docx/normalize.docx differ
diff --git a/test/docx/notes.docx b/test/docx/notes.docx
index eb6fa12d4..e6a63342d 100644
Binary files a/test/docx/notes.docx and b/test/docx/notes.docx differ
diff --git a/test/docx/numbered_header.docx b/test/docx/numbered_header.docx
index 66ce7648d..b81caea69 100644
Binary files a/test/docx/numbered_header.docx and b/test/docx/numbered_header.docx differ
diff --git a/test/docx/table_variable_width.native b/test/docx/table_variable_width.native
index 9d3b961df..b85e58d41 100644
--- a/test/docx/table_variable_width.native
+++ b/test/docx/table_variable_width.native
@@ -5,9 +5,12 @@
  ,[Plain [Str "h4"]]
  ,[Plain [Str "h5"]]]
  [[[Plain [Str "c11"]]
+  ,[]
+  ,[]
   ,[]
   ,[]]
  ,[[]
   ,[Plain [Str "c22"]]
   ,[Plain [Str "c23"]]
+  ,[]
   ,[]]]]
diff --git a/test/docx/table_with_list_cell.docx b/test/docx/table_with_list_cell.docx
index 1db065770..bf58c1abe 100644
Binary files a/test/docx/table_with_list_cell.docx and b/test/docx/table_with_list_cell.docx differ
diff --git a/test/docx/tables.docx b/test/docx/tables.docx
index 28087ead5..f99ea249d 100644
Binary files a/test/docx/tables.docx and b/test/docx/tables.docx differ
diff --git a/test/dokuwiki_multiblock_table.dokuwiki b/test/dokuwiki_multiblock_table.dokuwiki
index 8b913f1f2..393ebeba0 100644
--- a/test/dokuwiki_multiblock_table.dokuwiki
+++ b/test/dokuwiki_multiblock_table.dokuwiki
@@ -1,4 +1,5 @@
 Sample grid table.
-^Fruit  ^Price^Advantages                     ^
-|Bananas|$1.34|built-in wrapper\\ \\ potassium|
-|Oranges|$2.10|* cures scurvy\\ * tasty       |
+^Fruit  ^Price^Advantages                         ^
+|Bananas|$1.34|built-in wrapper\\ \\ potassium    |
+|Oranges|$2.10|* cures scurvy\\ * tasty           |
+|Apples |$1.10|Some text\\ \\ after two linebreaks|
diff --git a/test/dokuwiki_multiblock_table.native b/test/dokuwiki_multiblock_table.native
index 34824296d..6059efb71 100644
--- a/test/dokuwiki_multiblock_table.native
+++ b/test/dokuwiki_multiblock_table.native
@@ -10,4 +10,9 @@
   ,[Para [Str "$2.10"]]
   ,[BulletList
     [[Plain [Str "cures",Space,Str "scurvy"]]
-    ,[Plain [Str "tasty"]]]]]]]
+    ,[Plain [Str "tasty"]]]]]
+ ,[[Para [Str "Apples"]]
+  ,[Para [Str "$1.10"]]
+  ,[Para [Str "Some",Space,Str "text",LineBreak,LineBreak,Str "after",Space,Str "two",Space,Str "linebreaks"] 
+    ]]
+ ]]
diff --git a/test/fb2/basic.fb2 b/test/fb2/basic.fb2
index b6160a9a5..df71e8456 100644
--- a/test/fb2/basic.fb2
+++ b/test/fb2/basic.fb2
@@ -1,3 +1,75 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink"><description><title-info><genre>unrecognised</genre></title-info><document-info><program-used>pandoc</program-used></document-info></description><body><title><p /></title><section><title><p>Top-level title</p></title><section><title><p>Section</p></title><section><title><p>Subsection</p></title><p>This <emphasis>emphasized</emphasis> <strong>strong</strong> <code>verbatim</code> markdown. See this link<a l:href="#l1" type="note"><sup>[1]</sup></a>.</p><p>Ordered list:</p><p>1. one</p><p>2. two</p><p>3. three</p><cite><p>Blockquote is for citatons.</p></cite><empty-line /><p><code>Code</code></p><p><code>block</code></p><p><code>is</code></p><p><code>for</code></p><p><code>code.</code></p><empty-line /><p><strikethrough>Strikeout</strikethrough> is Pandoc’s extension. Superscript and subscripts too: H<sub>2</sub>O is a liquid<a l:href="#n2" type="note"><sup>[2]</sup></a>. 2<sup>10</sup> is 1024.</p><p>Math is another Pandoc extension: <code>E = m c^2</code>.</p></section></section></section></body><body name="notes"><section id="l1"><title><p>1</p></title><p><code>http://example.com/</code></p></section><section id="n2"><title><p>2</p></title><p>Sometimes.</p></section></body></FictionBook>
-
+<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink">
+<description>
+<title-info>
+<genre>unrecognised</genre>
+</title-info>
+<document-info>
+<program-used>pandoc</program-used>
+</document-info>
+</description>
+<body>
+<title>
+<p />
+</title>
+<section>
+<title>
+<p>Top-level title</p>
+</title>
+<section>
+<title>
+<p>Section</p>
+</title>
+<section>
+<title>
+<p>Subsection</p>
+</title>
+<p>This <emphasis>emphasized</emphasis> <strong>strong</strong> <code>verbatim</code> markdown.
+See this <a l:href="http://example.com/">link</a>.</p>
+<p>Ordered list:</p>
+<p>1. one</p>
+<p>2. two</p>
+<p>3. three</p>
+<cite>
+<p>Blockquote
+is
+for
+citatons.</p>
+</cite>
+<empty-line />
+<p>
+<code>Code</code>
+</p>
+<p>
+<code>block</code>
+</p>
+<p>
+<code>is</code>
+</p>
+<p>
+<code>for</code>
+</p>
+<p>
+<code>code.</code>
+</p>
+<empty-line />
+<p>
+<strikethrough>Strikeout</strikethrough> is Pandoc’s extension.
+Superscript and subscripts too: H<sub>2</sub>O is a liquid<a l:href="#n1" type="note">
+<sup>[1]</sup>
+</a>.
+2<sup>10</sup> is 1024.</p>
+<p>Math is another Pandoc extension: <code>E = m c^2</code>.</p>
+</section>
+</section>
+</section>
+</body>
+<body name="notes">
+<section id="n1">
+<title>
+<p>1</p>
+</title>
+<p>Sometimes.</p>
+</section>
+</body>
+</FictionBook>
diff --git a/test/fb2/meta.fb2 b/test/fb2/meta.fb2
new file mode 100644
index 000000000..04bd5f3c5
--- /dev/null
+++ b/test/fb2/meta.fb2
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink"><description><title-info><genre>unrecognised</genre><book-title>Book title</book-title><annotation><p>This is the abstract.</p>It consists of two paragraphs.</annotation></title-info><document-info><program-used>pandoc</program-used></document-info></description><body><title><p>Book title</p></title></body></FictionBook>
+
diff --git a/test/fb2/meta.markdown b/test/fb2/meta.markdown
new file mode 100644
index 000000000..5edad2981
--- /dev/null
+++ b/test/fb2/meta.markdown
@@ -0,0 +1,7 @@
+---
+title: Book title
+abstract: |
+  This is the abstract.
+
+  It consists of two paragraphs.
+---
diff --git a/test/fb2/reader/emphasis.fb2 b/test/fb2/reader/emphasis.fb2
new file mode 100644
index 000000000..1a936a9d0
--- /dev/null
+++ b/test/fb2/reader/emphasis.fb2
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink">
+	<body>
+		<section>
+			<p>Plain, <strong>strong</strong>, <emphasis>emphasis</emphasis>, <strong><emphasis>strong emphasis</emphasis></strong>, <emphasis><strong>emphasized strong</strong></emphasis>.</p>
+			<p>Strikethrough: <strikethrough>deleted</strikethrough></p>
+			<p><sub>Subscript</sub> and <sup>superscript</sup></p>
+			<p>Some <code>code</code></p>
+		</section>
+	</body>
+</FictionBook>
diff --git a/test/fb2/reader/emphasis.native b/test/fb2/reader/emphasis.native
new file mode 100644
index 000000000..422e7bb15
--- /dev/null
+++ b/test/fb2/reader/emphasis.native
@@ -0,0 +1,6 @@
+Pandoc (Meta {unMeta = fromList []})
+[Div ("",["section"],[])
+ [Para [Str "Plain,",Space,Strong [Str "strong"],Str ",",Space,Emph [Str "emphasis"],Str ",",Space,Strong [Emph [Str "strong",Space,Str "emphasis"]],Str ",",Space,Emph [Strong [Str "emphasized",Space,Str "strong"]],Str "."]
+ ,Para [Str "Strikethrough:",Space,Strikeout [Str "deleted"]]
+ ,Para [Subscript [Str "Subscript"],Space,Str "and",Space,Superscript [Str "superscript"]]
+ ,Para [Str "Some",Space,Code ("",[],[]) "code"]]]
diff --git a/test/fb2/reader/epigraph.fb2 b/test/fb2/reader/epigraph.fb2
new file mode 100644
index 000000000..5bb5cd2ef
--- /dev/null
+++ b/test/fb2/reader/epigraph.fb2
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink">
+	<body>
+		<epigraph>
+			<p>Body epigraph</p>
+		</epigraph>
+		<section>
+			<epigraph>
+				<p>Section epigraph</p>
+			</epigraph>
+			<section>
+				<epigraph>
+					<p>Subsection epigraph</p>
+				</epigraph>
+			</section>
+		</section>
+	</body>
+</FictionBook>
diff --git a/test/fb2/reader/epigraph.native b/test/fb2/reader/epigraph.native
new file mode 100644
index 000000000..a58a3e05b
--- /dev/null
+++ b/test/fb2/reader/epigraph.native
@@ -0,0 +1,9 @@
+Pandoc (Meta {unMeta = fromList []})
+[Div ("",["epigraph"],[])
+ [Para [Str "Body",Space,Str "epigraph"]]
+,Div ("",["section"],[])
+ [Div ("",["epigraph"],[])
+  [Para [Str "Section",Space,Str "epigraph"]]
+ ,Div ("",["section"],[])
+  [Div ("",["epigraph"],[])
+   [Para [Str "Subsection",Space,Str "epigraph"]]]]]
diff --git a/test/fb2/reader/meta.fb2 b/test/fb2/reader/meta.fb2
new file mode 100644
index 000000000..7e1736d64
--- /dev/null
+++ b/test/fb2/reader/meta.fb2
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink">
+	<description>
+		<title-info>
+			<author>
+				<first-name>First</first-name>
+				<middle-name>Middle</middle-name>
+				<last-name>Last</last-name>
+			</author>
+			<author>
+				<first-name>Another</first-name>
+				<last-name>Author</last-name>
+			</author>
+			<book-title>Book title</book-title>
+			<annotation>
+				<p>Book annotation</p>
+				<p>Second paragraph of book annotation</p>
+			</annotation>
+			<keywords>foo, bar, baz</keywords>
+			<date>2018</date>
+		</title-info>
+	</description>
+	<body>
+		<title><p>Body title</p></title>
+	</body>
+</FictionBook>
diff --git a/test/fb2/reader/meta.native b/test/fb2/reader/meta.native
new file mode 100644
index 000000000..71a8795b6
--- /dev/null
+++ b/test/fb2/reader/meta.native
@@ -0,0 +1,2 @@
+Pandoc (Meta {unMeta = fromList [("abstract",MetaBlocks [Para [Str "Book",Space,Str "annotation"],Para [Str "Second",Space,Str "paragraph",Space,Str "of",Space,Str "book",Space,Str "annotation"]]),("author",MetaList [MetaInlines [Str "First",Space,Str "Middle",Space,Str "Last"],MetaInlines [Str "Another",Space,Str "Author"]]),("date",MetaInlines [Str "2018"]),("keywords",MetaList [MetaString "foo",MetaString "bar",MetaString "baz"]),("title",MetaInlines [Str "Book",Space,Str "title"])]})
+[Header 1 ("",[],[]) [Str "Body",Space,Str "title"]]
diff --git a/test/fb2/reader/poem.fb2 b/test/fb2/reader/poem.fb2
new file mode 100644
index 000000000..fcf4a0c02
--- /dev/null
+++ b/test/fb2/reader/poem.fb2
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink">
+	<body>
+		<section>
+			<poem>
+				<title>
+					<p>Poem title</p>
+				</title>
+				<epigraph>
+					<p>Poem epigraph</p>
+				</epigraph>
+				<stanza>
+					<subtitle>Subtitle</subtitle>
+					<title>
+						<p>First stanza title</p>
+					</title>
+					<v>Verse</v>
+					<v><emphasis>More</emphasis> verse</v>
+				</stanza>
+				<stanza>
+					<v>One more stanza</v>
+				</stanza>
+				<text-author>Author</text-author>
+				<date>April 2018</date>
+			</poem>
+		</section>
+	</body>
+</FictionBook>
diff --git a/test/fb2/reader/poem.native b/test/fb2/reader/poem.native
new file mode 100644
index 000000000..67be6a672
--- /dev/null
+++ b/test/fb2/reader/poem.native
@@ -0,0 +1,14 @@
+Pandoc (Meta {unMeta = fromList []})
+[Div ("",["section"],[])
+ [Header 2 ("",[],[]) [Str "Poem",Space,Str "title"]
+ ,Div ("",["epigraph"],[])
+  [Para [Str "Poem",Space,Str "epigraph"]]
+ ,Header 2 ("",["unnumbered"],[]) [Str "Subtitle"]
+ ,Header 2 ("",[],[]) [Str "First",Space,Str "stanza",Space,Str "title"]
+ ,LineBlock
+  [[Str "Verse"]
+  ,[Emph [Str "More"],Space,Str "verse"]]
+ ,LineBlock
+  [[Str "One",Space,Str "more",Space,Str "stanza"]]
+ ,Para [Str "Author"]
+ ,Para [Str "April",Space,Str "2018"]]]
diff --git a/test/fb2/reader/titles.fb2 b/test/fb2/reader/titles.fb2
new file mode 100644
index 000000000..cfe9588d8
--- /dev/null
+++ b/test/fb2/reader/titles.fb2
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink">
+	<body>
+		<title><p>Body title</p></title>
+		<section>
+			<title><p>Section title</p></title>
+			<section>
+				<title>
+					<p>Subsection title</p>
+					<p>with multiple paragraphs</p>
+				</title>
+			</section>
+			<section>
+				<title><p>Another subsection title</p></title>
+			</section>
+		</section>
+	</body>
+</FictionBook>
diff --git a/test/fb2/reader/titles.native b/test/fb2/reader/titles.native
new file mode 100644
index 000000000..a6c34f5ea
--- /dev/null
+++ b/test/fb2/reader/titles.native
@@ -0,0 +1,8 @@
+Pandoc (Meta {unMeta = fromList []})
+[Header 1 ("",[],[]) [Str "Body",Space,Str "title"]
+,Div ("",["section"],[])
+ [Header 2 ("",[],[]) [Str "Section",Space,Str "title"]
+ ,Div ("",["section"],[])
+  [Header 3 ("",[],[]) [Str "Subsection",Space,Str "title",LineBreak,Str "with",Space,Str "multiple",Space,Str "paragraphs"]]
+ ,Div ("",["section"],[])
+  [Header 3 ("",[],[]) [Str "Another",Space,Str "subsection",Space,Str "title"]]]]
diff --git a/test/fb2/titles.fb2 b/test/fb2/titles.fb2
index 49a741b57..4e56fb3e6 100644
--- a/test/fb2/titles.fb2
+++ b/test/fb2/titles.fb2
@@ -1,3 +1,3 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink"><description><title-info><genre>unrecognised</genre></title-info><document-info><program-used>pandoc</program-used></document-info></description><body><title><p /></title><section><title><p>Simple title</p></title><p>This example tests if Pandoc doesn’t insert forbidden elements in FictionBook titles.</p></section><section><title><p>Emphasized Strong Title</p></title></section></body></FictionBook>
+<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink"><description><title-info><genre>unrecognised</genre></title-info><document-info><program-used>pandoc</program-used></document-info></description><body><title><p /></title><section><title><p>Simple title</p></title><p>This example tests FictionBook titles.</p></section><section><title><p><emphasis>Emphasized</emphasis> <strong>Strong</strong> Title</p></title></section></body></FictionBook>
 
diff --git a/test/fb2/titles.markdown b/test/fb2/titles.markdown
index 1eaf2ccd5..1d405a3c1 100644
--- a/test/fb2/titles.markdown
+++ b/test/fb2/titles.markdown
@@ -1,6 +1,6 @@
 # Simple title
 
-This example tests if Pandoc doesn't insert forbidden elements in FictionBook titles.
+This example tests FictionBook titles.
 
 # *Emphasized* **Strong** Title
 
diff --git a/test/jats-reader.native b/test/jats-reader.native
index a7c349149..83feeeffd 100644
--- a/test/jats-reader.native
+++ b/test/jats-reader.native
@@ -1,5 +1,5 @@
 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."]
+[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",Space,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"]]
@@ -13,7 +13,7 @@ Pandoc (Meta {unMeta = fromList [("author",MetaList [MetaInlines [Str "John",Spa
 ,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 "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",Space,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",Space,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"]
diff --git a/test/jats-reader.xml b/test/jats-reader.xml
index f98caa46e..bfbfdc6a0 100644
--- a/test/jats-reader.xml
+++ b/test/jats-reader.xml
@@ -29,10 +29,7 @@
 </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>
+<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">
@@ -56,91 +53,53 @@
     <title>Level 2 with <italic>emphasis</italic></title>
     <sec id="level-3">
       <title>Level 3</title>
-      <p>
-        with no blank line
-      </p>
+      <p>with no blank line</p>
     </sec>
   </sec>
   <sec id="level-2">
     <title>Level 2</title>
-    <p>
-      with no blank line
-    </p>
+    <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>
+  <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>
+  <p>E-mail style:</p>
   <disp-quote>
-    <p>
-      This is a block quote. It is pretty short.
-    </p>
+    <p>This is a block quote. It is pretty short.</p>
   </disp-quote>
   <disp-quote>
-    <p>
-      Code in a block quote:
-    </p>
+    <p>Code in a block quote:</p>
     <preformat>sub status {
     print &quot;working&quot;;
 }</preformat>
-    <p>
-      A list:
-    </p>
+    <p>A list:</p>
     <list list-type="order">
       <list-item>
-        <p>
-          item one
-        </p>
+        <p>item one</p>
       </list-item>
       <list-item>
-        <p>
-          item two
-        </p>
+        <p>item two</p>
       </list-item>
     </list>
-    <p>
-      Nested block quotes:
-    </p>
+    <p>Nested block quotes:</p>
     <disp-quote>
-      <p>
-        nested
-      </p>
+      <p>nested</p>
     </disp-quote>
     <disp-quote>
-      <p>
-        nested
-      </p>
+      <p>nested</p>
     </disp-quote>
   </disp-quote>
-  <p>
-    This should not be a block quote: 2 &gt; 1.
-  </p>
-  <p>
-    Box-style:
-  </p>
+  <p>This should not be a block quote: 2 &gt; 1.</p>
+  <p>Box-style:</p>
   <disp-quote>
-    <p>
-      Example:
-    </p>
+    <p>Example:</p>
     <preformat>sub status {
     print &quot;working&quot;;
 }</preformat>
@@ -148,39 +107,25 @@
   <disp-quote>
     <list list-type="order">
       <list-item>
-        <p>
-          do laundry
-        </p>
+        <p>do laundry</p>
       </list-item>
       <list-item>
-        <p>
-          take out the trash
-        </p>
+        <p>take out the trash</p>
       </list-item>
     </list>
   </disp-quote>
-  <p>
-    Here's a nested one:
-  </p>
+  <p>Here's a nested one:</p>
   <disp-quote>
-    <p>
-      Joe said:
-    </p>
+    <p>Joe said:</p>
     <disp-quote>
-      <p>
-        Don't quote me.
-      </p>
+      <p>Don't quote me.</p>
     </disp-quote>
   </disp-quote>
-  <p>
-    And a following paragraph.
-  </p>
+  <p>And a following paragraph.</p>
 </sec>
 <sec id="code-blocks">
   <title>Code Blocks</title>
-  <p>
-    Code:
-  </p>
+  <p>Code:</p>
   <preformat>---- (should be four hyphens)
 
 sub status {
@@ -188,9 +133,7 @@ sub status {
 }
 
 this code block is indented by one tab</preformat>
-  <p>
-    And:
-  </p>
+  <p>And:</p>
   <preformat>    this code block is indented by two tabs
 
 These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
@@ -199,236 +142,144 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
   <title>Lists</title>
   <sec id="unordered">
     <title>Unordered</title>
-    <p>
-      Asterisks tight:
-    </p>
+    <p>Asterisks tight:</p>
     <list list-type="bullet">
       <list-item>
-        <p>
-          asterisk 1
-        </p>
+        <p>asterisk 1</p>
       </list-item>
       <list-item>
-        <p>
-          asterisk 2
-        </p>
+        <p>asterisk 2</p>
       </list-item>
       <list-item>
-        <p>
-          asterisk 3
-        </p>
+        <p>asterisk 3</p>
       </list-item>
     </list>
-    <p>
-      Asterisks loose:
-    </p>
+    <p>Asterisks loose:</p>
     <list list-type="bullet">
       <list-item>
-        <p>
-          asterisk 1
-        </p>
+        <p>asterisk 1</p>
       </list-item>
       <list-item>
-        <p>
-          asterisk 2
-        </p>
+        <p>asterisk 2</p>
       </list-item>
       <list-item>
-        <p>
-          asterisk 3
-        </p>
+        <p>asterisk 3</p>
       </list-item>
     </list>
-    <p>
-      Pluses tight:
-    </p>
+    <p>Pluses tight:</p>
     <list list-type="bullet">
       <list-item>
-        <p>
-          Plus 1
-        </p>
+        <p>Plus 1</p>
       </list-item>
       <list-item>
-        <p>
-          Plus 2
-        </p>
+        <p>Plus 2</p>
       </list-item>
       <list-item>
-        <p>
-          Plus 3
-        </p>
+        <p>Plus 3</p>
       </list-item>
     </list>
-    <p>
-      Pluses loose:
-    </p>
+    <p>Pluses loose:</p>
     <list list-type="bullet">
       <list-item>
-        <p>
-          Plus 1
-        </p>
+        <p>Plus 1</p>
       </list-item>
       <list-item>
-        <p>
-          Plus 2
-        </p>
+        <p>Plus 2</p>
       </list-item>
       <list-item>
-        <p>
-          Plus 3
-        </p>
+        <p>Plus 3</p>
       </list-item>
     </list>
-    <p>
-      Minuses tight:
-    </p>
+    <p>Minuses tight:</p>
     <list list-type="bullet">
       <list-item>
-        <p>
-          Minus 1
-        </p>
+        <p>Minus 1</p>
       </list-item>
       <list-item>
-        <p>
-          Minus 2
-        </p>
+        <p>Minus 2</p>
       </list-item>
       <list-item>
-        <p>
-          Minus 3
-        </p>
+        <p>Minus 3</p>
       </list-item>
     </list>
-    <p>
-      Minuses loose:
-    </p>
+    <p>Minuses loose:</p>
     <list list-type="bullet">
       <list-item>
-        <p>
-          Minus 1
-        </p>
+        <p>Minus 1</p>
       </list-item>
       <list-item>
-        <p>
-          Minus 2
-        </p>
+        <p>Minus 2</p>
       </list-item>
       <list-item>
-        <p>
-          Minus 3
-        </p>
+        <p>Minus 3</p>
       </list-item>
     </list>
   </sec>
   <sec id="ordered">
     <title>Ordered</title>
-    <p>
-      Tight:
-    </p>
+    <p>Tight:</p>
     <list list-type="order">
       <list-item>
-        <p>
-          First
-        </p>
+        <p>First</p>
       </list-item>
       <list-item>
-        <p>
-          Second
-        </p>
+        <p>Second</p>
       </list-item>
       <list-item>
-        <p>
-          Third
-        </p>
+        <p>Third</p>
       </list-item>
     </list>
-    <p>
-      and:
-    </p>
+    <p>and:</p>
     <list list-type="order">
       <list-item>
-        <p>
-          One
-        </p>
+        <p>One</p>
       </list-item>
       <list-item>
-        <p>
-          Two
-        </p>
+        <p>Two</p>
       </list-item>
       <list-item>
-        <p>
-          Three
-        </p>
+        <p>Three</p>
       </list-item>
     </list>
-    <p>
-      Loose using tabs:
-    </p>
+    <p>Loose using tabs:</p>
     <list list-type="order">
       <list-item>
-        <p>
-          First
-        </p>
+        <p>First</p>
       </list-item>
       <list-item>
-        <p>
-          Second
-        </p>
+        <p>Second</p>
       </list-item>
       <list-item>
-        <p>
-          Third
-        </p>
+        <p>Third</p>
       </list-item>
     </list>
-    <p>
-      and using spaces:
-    </p>
+    <p>and using spaces:</p>
     <list list-type="order">
       <list-item>
-        <p>
-          One
-        </p>
+        <p>One</p>
       </list-item>
       <list-item>
-        <p>
-          Two
-        </p>
+        <p>Two</p>
       </list-item>
       <list-item>
-        <p>
-          Three
-        </p>
+        <p>Three</p>
       </list-item>
     </list>
-    <p>
-      Multiple paragraphs:
-    </p>
+    <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>
+        <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>
+        <p>Item 2.</p>
       </list-item>
       <list-item>
-        <p>
-          Item 3.
-        </p>
+        <p>Item 3.</p>
       </list-item>
     </list>
-    <p>
-      List styles:
-    </p>
+    <p>List styles:</p>
     <list list-type="order"></list>
     <list list-type="roman-lower"></list>
   </sec>
@@ -436,97 +287,63 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
     <title>Nested</title>
     <list list-type="bullet">
       <list-item>
-        <p>
-          Tab
-        </p>
+        <p>Tab</p>
         <list list-type="bullet">
           <list-item>
-            <p>
-              Tab
-            </p>
+            <p>Tab</p>
             <list list-type="bullet">
               <list-item>
-                <p>
-                  Tab
-                </p>
+                <p>Tab</p>
               </list-item>
             </list>
           </list-item>
         </list>
       </list-item>
     </list>
-    <p>
-      Here's another:
-    </p>
+    <p>Here's another:</p>
     <list list-type="order">
       <list-item>
-        <p>
-          First
-        </p>
+        <p>First</p>
       </list-item>
       <list-item>
-        <p>
-          Second:
-        </p>
+        <p>Second:</p>
         <list list-type="bullet">
           <list-item>
-            <p>
-              Fee
-            </p>
+            <p>Fee</p>
           </list-item>
           <list-item>
-            <p>
-              Fie
-            </p>
+            <p>Fie</p>
           </list-item>
           <list-item>
-            <p>
-              Foe
-            </p>
+            <p>Foe</p>
           </list-item>
         </list>
       </list-item>
       <list-item>
-        <p>
-          Third
-        </p>
+        <p>Third</p>
       </list-item>
     </list>
-    <p>
-      Same thing but with paragraphs:
-    </p>
+    <p>Same thing but with paragraphs:</p>
     <list list-type="order">
       <list-item>
-        <p>
-          First
-        </p>
+        <p>First</p>
       </list-item>
       <list-item>
-        <p>
-          Second:
-        </p>
+        <p>Second:</p>
         <list list-type="bullet">
           <list-item>
-            <p>
-              Fee
-            </p>
+            <p>Fee</p>
           </list-item>
           <list-item>
-            <p>
-              Fie
-            </p>
+            <p>Fie</p>
           </list-item>
           <list-item>
-            <p>
-              Foe
-            </p>
+            <p>Foe</p>
           </list-item>
         </list>
       </list-item>
       <list-item>
-        <p>
-          Third
-        </p>
+        <p>Third</p>
       </list-item>
     </list>
   </sec>
@@ -534,24 +351,16 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
     <title>Tabs and spaces</title>
     <list list-type="bullet">
       <list-item>
-        <p>
-          this is a list item indented with tabs
-        </p>
+        <p>this is a list item indented with tabs</p>
       </list-item>
       <list-item>
-        <p>
-          this is a list item indented with spaces
-        </p>
+        <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>
+            <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>
+            <p>this is an example list item indented with spaces</p>
           </list-item>
         </list>
       </list-item>
@@ -559,24 +368,16 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
   </sec>
   <sec id="fancy-list-markers">
     <title>Fancy list markers</title>
-    <p>
-      Autonumbering:
-    </p>
+    <p>Autonumbering:</p>
     <list list-type="order">
       <list-item>
-        <p>
-          Autonumber.
-        </p>
+        <p>Autonumber.</p>
       </list-item>
       <list-item>
-        <p>
-          More.
-        </p>
+        <p>More.</p>
         <list list-type="order">
           <list-item>
-            <p>
-              Nested.
-            </p>
+            <p>Nested.</p>
           </list-item>
         </list>
       </list-item>
@@ -590,12 +391,8 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
           Violin
         </term>
         <def>
-          <p>
-            Stringed musical instrument.
-          </p>
-          <p>
-            Torture device.
-          </p>
+          <p>Stringed musical instrument.</p>
+          <p>Torture device.</p>
         </def>
       </def-item>
       <def-item>
@@ -603,9 +400,7 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
           Cello<break />Violoncello
         </term>
         <def>
-          <p>
-            Low-voiced stringed instrument.
-          </p>
+          <p>Low-voiced stringed instrument.</p>
         </def>
       </def-item>
     </def-list>
@@ -613,452 +408,244 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
 </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
+  <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>,
+    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>
+    <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
+  <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>
+    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>
+      <p>\cite[22-23]{smith.1899}</p>
     </list-item>
     <list-item>
-      <p>
-        \doublespacing
-      </p>
+      <p>\doublespacing</p>
     </list-item>
     <list-item>
-      <p>
-        $2+2=4$
-      </p>
+      <p>$2+2=4$</p>
     </list-item>
     <list-item>
-      <p>
-        $x \in y$
-      </p>
+      <p>$x \in y$</p>
     </list-item>
     <list-item>
-      <p>
-        $\alpha \wedge \omega$
-      </p>
+      <p>$\alpha \wedge \omega$</p>
     </list-item>
     <list-item>
-      <p>
-        $223$
-      </p>
+      <p>$223$</p>
     </list-item>
     <list-item>
-      <p>
-        $p$-Tree
-      </p>
+      <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>
+      <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>
+      <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>
+  <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>
+      <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>
+      <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>
+      <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>
+  <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>
+  <p>Here is some unicode:</p>
   <list list-type="bullet">
     <list-item>
-      <p>
-        I hat: Î
-      </p>
+      <p>I hat: Î</p>
     </list-item>
     <list-item>
-      <p>
-        o umlaut: ö
-      </p>
+      <p>o umlaut: ö</p>
     </list-item>
     <list-item>
-      <p>
-        section: §
-      </p>
+      <p>section: §</p>
     </list-item>
     <list-item>
-      <p>
-        set membership: elem
-      </p>
+      <p>set membership: elem</p>
     </list-item>
     <list-item>
-      <p>
-        copyright: ©
-      </p>
+      <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>
+  <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>
+    <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>
+    <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>
+    <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
+    <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
+      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
+      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>
+      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>
+    <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>
+        <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>
+        <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>
+        <p>It should.</p>
       </list-item>
     </list>
-    <p>
-      An e-mail address: nobody [at] nowhere.net
-    </p>
+    <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>
+      <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>
+    <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
+  <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>
+    icon.</p>
 </sec>
 <sec id="footnotes">
   <title>Footnotes</title>
-  <p>
-    Here is a footnote reference<xref alt="(1)" rid="note_1">(1)</xref>,
+  <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>
+    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
+  <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>
+    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>
@@ -1071,55 +658,37 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
       <thead>
         <tr>
           <th>
-            <p>
-              X
-            </p>
+            <p>X</p>
           </th>
           <th>
-            <p>
-              Y
-            </p>
+            <p>Y</p>
           </th>
           <th>
-            <p>
-              Z
-            </p>
+            <p>Z</p>
           </th>
         </tr>
       </thead>
       <tbody>
         <tr>
           <td>
-            <p>
-              1
-            </p>
+            <p>1</p>
           </td>
           <td>
-            <p>
-              2
-            </p>
+            <p>2</p>
           </td>
           <td>
-            <p>
-              3
-            </p>
+            <p>3</p>
           </td>
         </tr>
         <tr>
           <td>
-            <p>
-              4
-            </p>
+            <p>4</p>
           </td>
           <td>
-            <p>
-              5
-            </p>
+            <p>5</p>
           </td>
           <td>
-            <p>
-              6
-            </p>
+            <p>6</p>
           </td>
         </tr>
       </tbody>
@@ -1131,55 +700,37 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
       <thead>
         <tr>
           <th>
-            <p>
-              X
-            </p>
+            <p>X</p>
           </th>
           <th>
-            <p>
-              Y
-            </p>
+            <p>Y</p>
           </th>
           <th>
-            <p>
-              Z
-            </p>
+            <p>Z</p>
           </th>
         </tr>
       </thead>
       <tbody>
         <tr>
           <td>
-            <p>
-              1
-            </p>
+            <p>1</p>
           </td>
           <td>
-            <p>
-              2
-            </p>
+            <p>2</p>
           </td>
           <td>
-            <p>
-              3
-            </p>
+            <p>3</p>
           </td>
         </tr>
         <tr>
           <td>
-            <p>
-              4
-            </p>
+            <p>4</p>
           </td>
           <td>
-            <p>
-              5
-            </p>
+            <p>5</p>
           </td>
           <td>
-            <p>
-              6
-            </p>
+            <p>6</p>
           </td>
         </tr>
       </tbody>
@@ -1191,55 +742,37 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
       <thead>
         <tr>
           <th>
-            <p>
-              X
-            </p>
+            <p>X</p>
           </th>
           <th>
-            <p>
-              Y
-            </p>
+            <p>Y</p>
           </th>
           <th>
-            <p>
-              Z
-            </p>
+            <p>Z</p>
           </th>
         </tr>
       </thead>
       <tbody>
         <tr>
           <td>
-            <p>
-              1
-            </p>
+            <p>1</p>
           </td>
           <td>
-            <p>
-              2
-            </p>
+            <p>2</p>
           </td>
           <td>
-            <p>
-              3
-            </p>
+            <p>3</p>
           </td>
         </tr>
         <tr>
           <td>
-            <p>
-              4
-            </p>
+            <p>4</p>
           </td>
           <td>
-            <p>
-              5
-            </p>
+            <p>5</p>
           </td>
           <td>
-            <p>
-              6
-            </p>
+            <p>6</p>
           </td>
         </tr>
       </tbody>
@@ -1251,55 +784,37 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
       <thead>
         <tr>
           <th>
-            <p>
-              X
-            </p>
+            <p>X</p>
           </th>
           <th>
-            <p>
-              Y
-            </p>
+            <p>Y</p>
           </th>
           <th>
-            <p>
-              Z
-            </p>
+            <p>Z</p>
           </th>
         </tr>
       </thead>
       <tbody>
         <tr>
           <td>
-            <p>
-              1
-            </p>
+            <p>1</p>
           </td>
           <td>
-            <p>
-              2
-            </p>
+            <p>2</p>
           </td>
           <td>
-            <p>
-              3
-            </p>
+            <p>3</p>
           </td>
         </tr>
         <tr>
           <td>
-            <p>
-              4
-            </p>
+            <p>4</p>
           </td>
           <td>
-            <p>
-              5
-            </p>
+            <p>5</p>
           </td>
           <td>
-            <p>
-              6
-            </p>
+            <p>6</p>
           </td>
         </tr>
       </tbody>
@@ -1311,55 +826,37 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
       <thead>
         <tr>
           <th>
-            <p>
-              X
-            </p>
+            <p>X</p>
           </th>
           <th>
-            <p>
-              Y
-            </p>
+            <p>Y</p>
           </th>
           <th>
-            <p>
-              Z
-            </p>
+            <p>Z</p>
           </th>
         </tr>
       </thead>
       <tbody>
         <tr>
           <td>
-            <p>
-              1
-            </p>
+            <p>1</p>
           </td>
           <td>
-            <p>
-              2
-            </p>
+            <p>2</p>
           </td>
           <td>
-            <p>
-              3
-            </p>
+            <p>3</p>
           </td>
         </tr>
         <tr>
           <td>
-            <p>
-              4
-            </p>
+            <p>4</p>
           </td>
           <td>
-            <p>
-              5
-            </p>
+            <p>5</p>
           </td>
           <td>
-            <p>
-              6
-            </p>
+            <p>6</p>
           </td>
         </tr>
       </tbody>
@@ -1371,55 +868,37 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
       <thead>
         <tr>
           <th>
-            <p>
-              X
-            </p>
+            <p>X</p>
           </th>
           <th>
-            <p>
-              Y
-            </p>
+            <p>Y</p>
           </th>
           <th>
-            <p>
-              Z
-            </p>
+            <p>Z</p>
           </th>
         </tr>
       </thead>
       <tbody>
         <tr>
           <td>
-            <p>
-              1
-            </p>
+            <p>1</p>
           </td>
           <td>
-            <p>
-              2
-            </p>
+            <p>2</p>
           </td>
           <td>
-            <p>
-              3
-            </p>
+            <p>3</p>
           </td>
         </tr>
         <tr>
           <td>
-            <p>
-              4
-            </p>
+            <p>4</p>
           </td>
           <td>
-            <p>
-              5
-            </p>
+            <p>5</p>
           </td>
           <td>
-            <p>
-              6
-            </p>
+            <p>6</p>
           </td>
         </tr>
       </tbody>
@@ -1431,55 +910,37 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
       <thead>
         <tr>
           <th>
-            <p>
-              X
-            </p>
+            <p>X</p>
           </th>
           <th>
-            <p>
-              Y
-            </p>
+            <p>Y</p>
           </th>
           <th>
-            <p>
-              Z
-            </p>
+            <p>Z</p>
           </th>
         </tr>
       </thead>
       <tbody>
         <tr>
           <td>
-            <p>
-              1
-            </p>
+            <p>1</p>
           </td>
           <td>
-            <p>
-              2
-            </p>
+            <p>2</p>
           </td>
           <td>
-            <p>
-              3
-            </p>
+            <p>3</p>
           </td>
         </tr>
         <tr>
           <td>
-            <p>
-              4
-            </p>
+            <p>4</p>
           </td>
           <td>
-            <p>
-              5
-            </p>
+            <p>5</p>
           </td>
           <td>
-            <p>
-              6
-            </p>
+            <p>6</p>
           </td>
         </tr>
       </tbody>
@@ -1491,55 +952,37 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
       <thead>
         <tr>
           <th>
-            <p>
-              X
-            </p>
+            <p>X</p>
           </th>
           <th>
-            <p>
-              Y
-            </p>
+            <p>Y</p>
           </th>
           <th>
-            <p>
-              Z
-            </p>
+            <p>Z</p>
           </th>
         </tr>
       </thead>
       <tbody>
         <tr>
           <td>
-            <p>
-              1
-            </p>
+            <p>1</p>
           </td>
           <td>
-            <p>
-              2
-            </p>
+            <p>2</p>
           </td>
           <td>
-            <p>
-              3
-            </p>
+            <p>3</p>
           </td>
         </tr>
         <tr>
           <td>
-            <p>
-              4
-            </p>
+            <p>4</p>
           </td>
           <td>
-            <p>
-              5
-            </p>
+            <p>5</p>
           </td>
           <td>
-            <p>
-              6
-            </p>
+            <p>6</p>
           </td>
         </tr>
       </tbody>
@@ -1551,55 +994,37 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
       <thead>
         <tr>
           <th>
-            <p>
-              X
-            </p>
+            <p>X</p>
           </th>
           <th>
-            <p>
-              Y
-            </p>
+            <p>Y</p>
           </th>
           <th>
-            <p>
-              Z
-            </p>
+            <p>Z</p>
           </th>
         </tr>
       </thead>
       <tbody>
         <tr>
           <td>
-            <p>
-              1
-            </p>
+            <p>1</p>
           </td>
           <td>
-            <p>
-              2
-            </p>
+            <p>2</p>
           </td>
           <td>
-            <p>
-              3
-            </p>
+            <p>3</p>
           </td>
         </tr>
         <tr>
           <td>
-            <p>
-              4
-            </p>
+            <p>4</p>
           </td>
           <td>
-            <p>
-              5
-            </p>
+            <p>5</p>
           </td>
           <td>
-            <p>
-              6
-            </p>
+            <p>6</p>
           </td>
         </tr>
       </tbody>
@@ -1614,36 +1039,24 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
       <tbody>
         <tr>
           <td>
-            <p>
-              1
-            </p>
+            <p>1</p>
           </td>
           <td>
-            <p>
-              2
-            </p>
+            <p>2</p>
           </td>
           <td>
-            <p>
-              3
-            </p>
+            <p>3</p>
           </td>
         </tr>
         <tr>
           <td>
-            <p>
-              4
-            </p>
+            <p>4</p>
           </td>
           <td>
-            <p>
-              5
-            </p>
+            <p>5</p>
           </td>
           <td>
-            <p>
-              6
-            </p>
+            <p>6</p>
           </td>
         </tr>
       </tbody>
@@ -1655,36 +1068,24 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
       <tbody>
         <tr>
           <td>
-            <p>
-              1
-            </p>
+            <p>1</p>
           </td>
           <td>
-            <p>
-              2
-            </p>
+            <p>2</p>
           </td>
           <td>
-            <p>
-              3
-            </p>
+            <p>3</p>
           </td>
         </tr>
         <tr>
           <td>
-            <p>
-              4
-            </p>
+            <p>4</p>
           </td>
           <td>
-            <p>
-              5
-            </p>
+            <p>5</p>
           </td>
           <td>
-            <p>
-              6
-            </p>
+            <p>6</p>
           </td>
         </tr>
       </tbody>
@@ -1696,36 +1097,24 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
       <tbody>
         <tr>
           <td>
-            <p>
-              1
-            </p>
+            <p>1</p>
           </td>
           <td>
-            <p>
-              2
-            </p>
+            <p>2</p>
           </td>
           <td>
-            <p>
-              3
-            </p>
+            <p>3</p>
           </td>
         </tr>
         <tr>
           <td>
-            <p>
-              4
-            </p>
+            <p>4</p>
           </td>
           <td>
-            <p>
-              5
-            </p>
+            <p>5</p>
           </td>
           <td>
-            <p>
-              6
-            </p>
+            <p>6</p>
           </td>
         </tr>
       </tbody>
@@ -1737,36 +1126,24 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
       <tbody>
         <tr>
           <td>
-            <p>
-              1
-            </p>
+            <p>1</p>
           </td>
           <td>
-            <p>
-              2
-            </p>
+            <p>2</p>
           </td>
           <td>
-            <p>
-              3
-            </p>
+            <p>3</p>
           </td>
         </tr>
         <tr>
           <td>
-            <p>
-              4
-            </p>
+            <p>4</p>
           </td>
           <td>
-            <p>
-              5
-            </p>
+            <p>5</p>
           </td>
           <td>
-            <p>
-              6
-            </p>
+            <p>6</p>
           </td>
         </tr>
       </tbody>
@@ -1774,9 +1151,7 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
   </sec>
   <sec id="empty-tables">
     <title>Empty Tables</title>
-    <p>
-      This section should be empty.
-    </p>
+    <p>This section should be empty.</p>
   </sec>
 </sec>
 </body>
diff --git a/test/lhs-test.rst b/test/lhs-test.rst
index 3de2d9ff6..4d012a9f9 100644
--- a/test/lhs-test.rst
+++ b/test/lhs-test.rst
@@ -6,9 +6,9 @@ return a single value:
 
 .. code:: haskell
 
-    unsplit :: (Arrow a) => (b -> c -> d) -> a (b, c) d
-    unsplit = arr . uncurry
-              -- arr (\op (x,y) -> x `op` y)
+   unsplit :: (Arrow a) => (b -> c -> d) -> a (b, c) d
+   unsplit = arr . uncurry
+             -- arr (\op (x,y) -> x `op` y)
 
 ``(***)`` combines two arrows into a new arrow by running the two arrows on a
 pair of values (one arrow on the first item of the pair and one arrow on the
@@ -16,8 +16,8 @@ second item of the pair).
 
 ::
 
-    f *** g = first f >>> second g
+   f *** g = first f >>> second g
 
 Block quote:
 
-    foo bar
+   foo bar
diff --git a/test/lhs-test.rst+lhs b/test/lhs-test.rst+lhs
index eec79c546..6196c39ab 100644
--- a/test/lhs-test.rst+lhs
+++ b/test/lhs-test.rst+lhs
@@ -14,8 +14,8 @@ second item of the pair).
 
 ::
 
-    f *** g = first f >>> second g
+   f *** g = first f >>> second g
 
 Block quote:
 
-    foo bar
+   foo bar
diff --git a/test/lua/math.lua b/test/lua/math.lua
new file mode 100644
index 000000000..34307dd9e
--- /dev/null
+++ b/test/lua/math.lua
@@ -0,0 +1,10 @@
+return {
+  {
+    Math = function (elem)
+      if elem.mathtype == "DisplayMath" then
+        elem.mathtype = "InlineMath"
+      end
+      return elem
+    end,
+  }
+}
diff --git a/test/lua/script-name.lua b/test/lua/script-name.lua
new file mode 100644
index 000000000..4b5a223f0
--- /dev/null
+++ b/test/lua/script-name.lua
@@ -0,0 +1,3 @@
+function Para (_)
+  return pandoc.Para{pandoc.Str(PANDOC_SCRIPT_FILE)}
+end
diff --git a/test/lua/test-pandoc-utils.lua b/test/lua/test-pandoc-utils.lua
index c732d2f85..21f937edb 100644
--- a/test/lua/test-pandoc-utils.lua
+++ b/test/lua/test-pandoc-utils.lua
@@ -32,25 +32,33 @@ end
 
 function warn (...) io.stderr:write(...) end
 
+function os_is_windows ()
+  return package.config:sub(1,1) == '\\'
+end
+
 function test_pipe ()
-  if not file_exists('/bin/sed') then
-    warn 'Did not find /bin/sed, skipping test'
-    return true
+  if os_is_windows() then
+    local pipe_result = pandoc.pipe('find', {'hi'}, 'hi')
+    return pipe_result:match("%a+") == 'hi'
+  else
+    local pipe_result = pandoc.pipe('tr', {'a', 'b'}, 'abc')
+    return pipe_result:match("%a+") == 'bbc'
   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
+  if os_is_windows() then
+    local res, err = pcall(pandoc.pipe, 'find', {'/a'}, 'hi')
+    return not res and
+      err.command == 'find' and
+      err.error_code ~= 0
+  else
+    local res, err = pcall(pandoc.pipe, 'false', {}, 'abc')
+    return not res and
+      err.command == 'false' and
+      err.error_code == 1 and
+      err.output == ''
   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
diff --git a/test/pandoc-test14632-86 b/test/pandoc-test14632-86
new file mode 100644
index 000000000..507e9f672
--- /dev/null
+++ b/test/pandoc-test14632-86
@@ -0,0 +1,1448 @@
+<?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>
+<string-name>John MacFarlane</string-name>
+</name>
+</contrib>
+<contrib contrib-type="author">
+<name>
+<string-name>Anonymous</string-name>
+</name>
+</contrib>
+</contrib-group>
+<pub-date pub-type="epub">
+<string-date>July 17, 2006</string-date>
+</pub-date>
+</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>
+    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>
+  </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>
+    <list list-type="order">
+      <list-item>
+        <label>
+          (2)
+        </label>
+        <p>
+          begins with 2
+        </p>
+      </list-item>
+      <list-item>
+        <label>
+          (3)
+        </label>
+        <p>
+          and now 3
+        </p>
+        <p>
+          with a continuation
+        </p>
+        <list list-type="roman-lower">
+          <list-item>
+            <label>
+              iv.
+            </label>
+            <p>
+              sublist with roman numerals, starting with 4
+            </p>
+          </list-item>
+          <list-item>
+            <label>
+              v.
+            </label>
+            <p>
+              more items
+            </p>
+            <list list-type="alpha-upper">
+              <list-item>
+                <label>
+                  (A)
+                </label>
+                <p>
+                  a subsublist
+                </p>
+              </list-item>
+              <list-item>
+                <label>
+                  (B)
+                </label>
+                <p>
+                  a subsublist
+                </p>
+              </list-item>
+            </list>
+          </list-item>
+        </list>
+      </list-item>
+    </list>
+    <p>
+      Nesting:
+    </p>
+    <list list-type="alpha-upper">
+      <list-item>
+        <p>
+          Upper Alpha
+        </p>
+        <list list-type="roman-upper">
+          <list-item>
+            <p>
+              Upper Roman.
+            </p>
+            <list list-type="order">
+              <list-item>
+                <label>
+                  (6)
+                </label>
+                <p>
+                  Decimal start with 6
+                </p>
+                <list list-type="alpha-lower">
+                  <list-item>
+                    <label>
+                      c)
+                    </label>
+                    <p>
+                      Lower alpha with paren
+                    </p>
+                  </list-item>
+                </list>
+              </list-item>
+            </list>
+          </list-item>
+        </list>
+      </list-item>
+    </list>
+    <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>
+    <p>
+      Should not be a list item:
+    </p>
+    <p>
+      M.A. 2007
+    </p>
+    <p>
+      B. Williams
+    </p>
+  </sec>
+</sec>
+<sec id="definition-lists">
+  <title>Definition Lists</title>
+  <p>
+    Tight using spaces:
+  </p>
+  <def-list>
+    <def-item>
+      <term>
+        apple
+      </term>
+      <def>
+        <p>
+          red fruit
+        </p>
+      </def>
+    </def-item>
+    <def-item>
+      <term>
+        orange
+      </term>
+      <def>
+        <p>
+          orange fruit
+        </p>
+      </def>
+    </def-item>
+    <def-item>
+      <term>
+        banana
+      </term>
+      <def>
+        <p>
+          yellow fruit
+        </p>
+      </def>
+    </def-item>
+  </def-list>
+  <p>
+    Tight using tabs:
+  </p>
+  <def-list>
+    <def-item>
+      <term>
+        apple
+      </term>
+      <def>
+        <p>
+          red fruit
+        </p>
+      </def>
+    </def-item>
+    <def-item>
+      <term>
+        orange
+      </term>
+      <def>
+        <p>
+          orange fruit
+        </p>
+      </def>
+    </def-item>
+    <def-item>
+      <term>
+        banana
+      </term>
+      <def>
+        <p>
+          yellow fruit
+        </p>
+      </def>
+    </def-item>
+  </def-list>
+  <p>
+    Loose:
+  </p>
+  <def-list>
+    <def-item>
+      <term>
+        apple
+      </term>
+      <def>
+        <p>
+          red fruit
+        </p>
+      </def>
+    </def-item>
+    <def-item>
+      <term>
+        orange
+      </term>
+      <def>
+        <p>
+          orange fruit
+        </p>
+      </def>
+    </def-item>
+    <def-item>
+      <term>
+        banana
+      </term>
+      <def>
+        <p>
+          yellow fruit
+        </p>
+      </def>
+    </def-item>
+  </def-list>
+  <p>
+    Multiple blocks with italics:
+  </p>
+  <def-list>
+    <def-item>
+      <term>
+        <italic>apple</italic>
+      </term>
+      <def>
+        <p>
+          red fruit
+        </p>
+        <p>
+          contains seeds, crisp, pleasant to taste
+        </p>
+      </def>
+    </def-item>
+    <def-item>
+      <term>
+        <italic>orange</italic>
+      </term>
+      <def>
+        <p>
+          orange fruit
+        </p>
+        <preformat>{ orange code block }</preformat>
+        <disp-quote>
+          <p>
+            orange block quote
+          </p>
+        </disp-quote>
+      </def>
+    </def-item>
+  </def-list>
+  <p>
+    Multiple definitions, tight:
+  </p>
+  <def-list>
+    <def-item>
+      <term>
+        apple
+      </term>
+      <def>
+        <p>
+          red fruit
+        </p>
+        <p>
+          computer
+        </p>
+      </def>
+    </def-item>
+    <def-item>
+      <term>
+        orange
+      </term>
+      <def>
+        <p>
+          orange fruit
+        </p>
+        <p>
+          bank
+        </p>
+      </def>
+    </def-item>
+  </def-list>
+  <p>
+    Multiple definitions, loose:
+  </p>
+  <def-list>
+    <def-item>
+      <term>
+        apple
+      </term>
+      <def>
+        <p>
+          red fruit
+        </p>
+        <p>
+          computer
+        </p>
+      </def>
+    </def-item>
+    <def-item>
+      <term>
+        orange
+      </term>
+      <def>
+        <p>
+          orange fruit
+        </p>
+        <p>
+          bank
+        </p>
+      </def>
+    </def-item>
+  </def-list>
+  <p>
+    Blank line after term, indented marker, alternate markers:
+  </p>
+  <def-list>
+    <def-item>
+      <term>
+        apple
+      </term>
+      <def>
+        <p>
+          red fruit
+        </p>
+        <p>
+          computer
+        </p>
+      </def>
+    </def-item>
+    <def-item>
+      <term>
+        orange
+      </term>
+      <def>
+        <p>
+          orange fruit
+        </p>
+        <list list-type="order">
+          <list-item>
+            <p>
+              sublist
+            </p>
+          </list-item>
+          <list-item>
+            <p>
+              sublist
+            </p>
+          </list-item>
+        </list>
+      </def>
+    </def-item>
+  </def-list>
+</sec>
+<sec id="html-blocks">
+  <title>HTML Blocks</title>
+  <p>
+    Simple block on one line:
+  </p>
+  <boxed-text>
+    <p>
+      foo
+    </p>
+  </boxed-text>
+  <p>
+    And nested without indentation:
+  </p>
+  <boxed-text>
+    <boxed-text>
+      <boxed-text>
+        <p>
+          foo
+        </p>
+      </boxed-text>
+    </boxed-text>
+    <boxed-text>
+      <p>
+        bar
+      </p>
+    </boxed-text>
+  </boxed-text>
+  <p>
+    Interpreted markdown in a table:
+  </p>
+  <p>
+    This is <italic>emphasized</italic>
+  </p>
+  <p>
+    And this is <bold role="strong">strong</bold>
+  </p>
+  <p>
+    Here’s a simple block:
+  </p>
+  <boxed-text>
+    <p>
+      foo
+    </p>
+  </boxed-text>
+  <p>
+    This should be a code block, though:
+  </p>
+  <preformat>&lt;div&gt;
+    foo
+&lt;/div&gt;</preformat>
+  <p>
+    As should this:
+  </p>
+  <preformat>&lt;div&gt;foo&lt;/div&gt;</preformat>
+  <p>
+    Now, nested:
+  </p>
+  <boxed-text>
+    <boxed-text>
+      <boxed-text>
+        <p>
+          foo
+        </p>
+      </boxed-text>
+    </boxed-text>
+  </boxed-text>
+  <p>
+    This should just be an HTML comment:
+  </p>
+  <p>
+    Multiline:
+  </p>
+  <p>
+    Code block:
+  </p>
+  <preformat>&lt;!-- Comment --&gt;</preformat>
+  <p>
+    Just plain comment, with trailing spaces on the line:
+  </p>
+  <p>
+    Code:
+  </p>
+  <preformat>&lt;hr /&gt;</preformat>
+  <p>
+    Hr’s:
+  </p>
+</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>
+    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>
+    <strike>This is <italic>strikeout</italic>.</strike>
+  </p>
+  <p>
+    Superscripts: a<sup>bc</sup>d a<sup><italic>hello</italic></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>
+</sec>
+<sec id="smart-quotes-ellipses-dashes">
+  <title>Smart quotes, ellipses, dashes</title>
+  <p>
+    “Hello,” said the spider. “‘Shelob’ is my name.”
+  </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, “I want to go.”’ Were you alive in the 70’s?
+  </p>
+  <p>
+    Here is some quoted ‘<monospace>code</monospace>’ and a
+    “<ext-link ext-link-type="uri" xlink:href="http://example.com/?foo=1&amp;bar=2">quoted
+    link</ext-link>”.
+  </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>
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        <inline-formula><alternatives>
+        <tex-math><![CDATA[2+2=4]]></tex-math>
+        <mml:math display="inline" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mn>2</mml:mn><mml:mo>+</mml:mo><mml:mn>2</mml:mn><mml:mo>=</mml:mo><mml:mn>4</mml:mn></mml:mrow></mml:math></alternatives></inline-formula>
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        <inline-formula><alternatives>
+        <tex-math><![CDATA[x \in y]]></tex-math>
+        <mml:math display="inline" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mi>x</mml:mi><mml:mo>∈</mml:mo><mml:mi>y</mml:mi></mml:mrow></mml:math></alternatives></inline-formula>
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        <inline-formula><alternatives>
+        <tex-math><![CDATA[\alpha \wedge \omega]]></tex-math>
+        <mml:math display="inline" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mi>α</mml:mi><mml:mo>∧</mml:mo><mml:mi>ω</mml:mi></mml:mrow></mml:math></alternatives></inline-formula>
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        <inline-formula><alternatives>
+        <tex-math><![CDATA[223]]></tex-math>
+        <mml:math display="inline" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mn>223</mml:mn></mml:math></alternatives></inline-formula>
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        <inline-formula><alternatives>
+        <tex-math><![CDATA[p]]></tex-math>
+        <mml:math display="inline" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mi>p</mml:mi></mml:math></alternatives></inline-formula>-Tree
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        Here’s some display math: <disp-formula><alternatives>
+        <tex-math><![CDATA[\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}]]></tex-math>
+        <mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mfrac><mml:mi>d</mml:mi><mml:mrow><mml:mi>d</mml:mi><mml:mi>x</mml:mi></mml:mrow></mml:mfrac><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>=</mml:mo><mml:munder><mml:mo>lim</mml:mo><mml:mrow><mml:mi>h</mml:mi><mml:mo>→</mml:mo><mml:mn>0</mml:mn></mml:mrow></mml:munder><mml:mfrac><mml:mrow><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo>+</mml:mo><mml:mi>h</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>−</mml:mo><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo></mml:mrow><mml:mi>h</mml:mi></mml:mfrac></mml:mrow></mml:math></alternatives></disp-formula>
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        Here’s one that has a line break in it: <inline-formula><alternatives>
+        <tex-math><![CDATA[\alpha + \omega \times x^2]]></tex-math>
+        <mml:math display="inline" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mi>α</mml:mi><mml:mo>+</mml:mo><mml:mi>ω</mml:mi><mml:mo>×</mml:mo><mml:msup><mml:mi>x</mml:mi><mml:mn>2</mml:mn></mml:msup></mml:mrow></mml:math></alternatives></inline-formula>.
+      </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 “lot” is emphasized.)
+      </p>
+    </list-item>
+    <list-item>
+      <p>
+        Shoes ($20) and socks ($5).
+      </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>
+</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: ∈
+      </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>
+      <ext-link ext-link-type="uri" xlink:href="/url/with_underscore">with_underscore</ext-link>
+    </p>
+    <p>
+      <ext-link ext-link-type="uri" xlink:href="mailto:nobody@nowhere.net">Email
+      link</ext-link>
+    </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>
+      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: <email>nobody@nowhere.net</email>
+    </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 “Voyage dans la Lune” by Georges Melies (1902):
+  </p>
+  <fig>
+    <caption>lalune</caption>
+    <graphic mimetype="image" mime-subtype="jpeg" xlink:href="lalune.jpg" xlink:title="Voyage dans la Lune" />
+  </fig>
+  <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,<fn>
+      <p>
+        Here is the footnote. It can go anywhere after the footnote reference.
+        It need not be placed at the end of the document.
+      </p>
+    </fn> and another.<fn>
+      <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>
+      <preformat>  { &lt;code&gt; }</preformat>
+      <p>
+        If you want, you can indent every line, but you can also be lazy and
+        just indent the first line of each block.
+      </p>
+    </fn> This should <italic>not</italic> be a footnote reference, because it
+    contains a space.[^my note] Here is an inline note.<fn>
+      <p>
+        This is <italic>easier</italic> to type. Inline notes may contain
+        <ext-link ext-link-type="uri" xlink:href="http://google.com">links</ext-link>
+        and <monospace>]</monospace> verbatim characters, as well as
+        [bracketed text].
+      </p>
+    </fn>
+  </p>
+  <disp-quote>
+    <p>
+      Notes can go in quotes.<fn>
+        <p>
+          In quote.
+        </p>
+      </fn>
+    </p>
+  </disp-quote>
+  <list list-type="order">
+    <list-item>
+      <p>
+        And in list items.<fn>
+          <p>
+            In list.
+          </p>
+        </fn>
+      </p>
+    </list-item>
+  </list>
+  <p>
+    This paragraph should not be part of the note, as it is not indented.
+  </p>
+</sec>
+</body>
+<back>
+</back>
+</article>
diff --git a/test/pandoc-test14632-89 b/test/pandoc-test14632-89
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test14632-90 b/test/pandoc-test14632-90
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test14632-91 b/test/pandoc-test14632-91
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test14632-94 b/test/pandoc-test14632-94
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test14632-95 b/test/pandoc-test14632-95
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test14632-96 b/test/pandoc-test14632-96
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test14632-97 b/test/pandoc-test14632-97
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test77993-78 b/test/pandoc-test77993-78
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test77993-79 b/test/pandoc-test77993-79
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test77993-82 b/test/pandoc-test77993-82
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test77993-83 b/test/pandoc-test77993-83
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test77993-86 b/test/pandoc-test77993-86
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test77993-87 b/test/pandoc-test77993-87
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test77993-90 b/test/pandoc-test77993-90
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test77993-91 b/test/pandoc-test77993-91
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test88473-110 b/test/pandoc-test88473-110
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test88473-111 b/test/pandoc-test88473-111
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test88473-112 b/test/pandoc-test88473-112
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test88473-113 b/test/pandoc-test88473-113
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test88473-116 b/test/pandoc-test88473-116
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test88473-117 b/test/pandoc-test88473-117
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test88473-118 b/test/pandoc-test88473-118
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test88473-119 b/test/pandoc-test88473-119
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test94017-86 b/test/pandoc-test94017-86
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test94017-87 b/test/pandoc-test94017-87
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test94017-90 b/test/pandoc-test94017-90
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test94017-91 b/test/pandoc-test94017-91
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test94017-92 b/test/pandoc-test94017-92
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pandoc-test94017-93 b/test/pandoc-test94017-93
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/pptx/endnotes_templated.pptx b/test/pptx/endnotes_templated.pptx
index 51501ec8c..4e99c22e1 100644
Binary files a/test/pptx/endnotes_templated.pptx and b/test/pptx/endnotes_templated.pptx differ
diff --git a/test/pptx/endnotes_toc_templated.pptx b/test/pptx/endnotes_toc_templated.pptx
index 77cd3ba58..e6896a7d5 100644
Binary files a/test/pptx/endnotes_toc_templated.pptx and b/test/pptx/endnotes_toc_templated.pptx differ
diff --git a/test/pptx/images_templated.pptx b/test/pptx/images_templated.pptx
index 76825e891..d9c93731c 100644
Binary files a/test/pptx/images_templated.pptx and b/test/pptx/images_templated.pptx differ
diff --git a/test/pptx/lists.native b/test/pptx/lists.native
new file mode 100644
index 000000000..e08580cd5
--- /dev/null
+++ b/test/pptx/lists.native
@@ -0,0 +1,18 @@
+[Header 1 ("lists",[],[]) [Str "Lists"]
+,BulletList
+ [[Para [Str "Bulleted",Space,Str "bulleted",Space,Str "lists."]]
+ ,[Para [Str "And",Space,Str "go",Space,Str "to",Space,Str "aribtrary",Space,Str "depth."]
+  ,BulletList
+   [[Para [Str "Like",Space,Str "this"]
+    ,BulletList
+     [[Plain [Str "Or",Space,Str "this"]]]]
+   ,[Para [Str "Back",Space,Str "to",Space,Str "here."]]]]]
+,Header 1 ("lists-continued",[],[]) [Str "Lists",Space,Str "(continued)"]
+,Para [Str "Lists",Space,Str "can",Space,Str "also",Space,Str "be",Space,Str "numbered:"]
+,OrderedList (1,Decimal,Period)
+ [[Para [Str "Tomatoes"]]
+ ,[Para [Str "Potatoes",Space,Str "of",Space,Str "various",Space,Str "sorts"]
+  ,OrderedList (1,LowerAlpha,Period)
+   [[Para [Str "sweet",Space,Str "potatoes"]]
+   ,[Para [Str "russet",Space,Str "potates"]]]]
+ ,[Para [Str "Tornadoes,",Space,Str "for",Space,Str "the",Space,Str "rhyme."]]]]
diff --git a/test/pptx/lists.pptx b/test/pptx/lists.pptx
new file mode 100644
index 000000000..acb0841ce
Binary files /dev/null and b/test/pptx/lists.pptx differ
diff --git a/test/pptx/lists_templated.pptx b/test/pptx/lists_templated.pptx
new file mode 100644
index 000000000..a25feaff1
Binary files /dev/null and b/test/pptx/lists_templated.pptx differ
diff --git a/test/pptx/remove_empty_slides.native b/test/pptx/remove_empty_slides.native
new file mode 100644
index 000000000..51c042281
--- /dev/null
+++ b/test/pptx/remove_empty_slides.native
@@ -0,0 +1,5 @@
+[Para [Str "Content"]
+,Para [Image ("",[],[]) [] ("lalune.jpg",""),Space,RawInline (Format "html") "<!--  -->"]
+,HorizontalRule
+,HorizontalRule
+,Para [Str "More",Space,Str "content"]]
diff --git a/test/pptx/remove_empty_slides.pptx b/test/pptx/remove_empty_slides.pptx
new file mode 100644
index 000000000..3b4843aa6
Binary files /dev/null and b/test/pptx/remove_empty_slides.pptx differ
diff --git a/test/pptx/remove_empty_slides_templated.pptx b/test/pptx/remove_empty_slides_templated.pptx
new file mode 100644
index 000000000..1efe33212
Binary files /dev/null and b/test/pptx/remove_empty_slides_templated.pptx differ
diff --git a/test/pptx/slide_breaks_slide_level_1_templated.pptx b/test/pptx/slide_breaks_slide_level_1_templated.pptx
index 3e0009c76..9770a5da0 100644
Binary files a/test/pptx/slide_breaks_slide_level_1_templated.pptx and b/test/pptx/slide_breaks_slide_level_1_templated.pptx differ
diff --git a/test/pptx/slide_breaks_templated.pptx b/test/pptx/slide_breaks_templated.pptx
index 6df99735d..25d199d3b 100644
Binary files a/test/pptx/slide_breaks_templated.pptx and b/test/pptx/slide_breaks_templated.pptx differ
diff --git a/test/pptx/slide_breaks_toc_templated.pptx b/test/pptx/slide_breaks_toc_templated.pptx
index 472f41cf4..3d65242bb 100644
Binary files a/test/pptx/slide_breaks_toc_templated.pptx and b/test/pptx/slide_breaks_toc_templated.pptx differ
diff --git a/test/pptx/speaker_notes_afterseps.native b/test/pptx/speaker_notes_afterseps.native
new file mode 100644
index 000000000..30910708c
--- /dev/null
+++ b/test/pptx/speaker_notes_afterseps.native
@@ -0,0 +1,33 @@
+[Para [Image ("",[],[]) [Str "The",Space,Str "moon"] ("lalune.jpg","fig:")]
+,Div ("",["notes"],[])
+ [Para [Str "chicken",Space,Str "and",Space,Str "dumplings"]]
+,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax,",Space,Str "with",Space,Str "alignment"] [AlignRight,AlignLeft,AlignCenter,AlignDefault] [0.0,0.0,0.0,0.0]
+ [[Plain [Str "Right"]]
+ ,[Plain [Str "Left"]]
+ ,[Plain [Str "Center"]]
+ ,[Plain [Str "Default"]]]
+ [[[Plain [Str "12"]]
+  ,[Plain [Str "12"]]
+  ,[Plain [Str "12"]]
+  ,[Plain [Str "12"]]]
+ ,[[Plain [Str "123"]]
+  ,[Plain [Str "123"]]
+  ,[Plain [Str "123"]]
+  ,[Plain [Str "123"]]]
+ ,[[Plain [Str "1"]]
+  ,[Plain [Str "1"]]
+  ,[Plain [Str "1"]]
+  ,[Plain [Str "1"]]]]
+,Div ("",["notes"],[])
+ [Para [Str "foo",Space,Str "bar"]]
+,Div ("",["columns"],[])
+ [Div ("",["column"],[])
+  [BulletList
+   [[Para [Str "some",Space,Str "stuff"]]
+   ,[Para [Str "some",Space,Str "more",Space,Str "stuff"]]]
+  ,Div ("",["notes"],[])
+   [Para [Str "Some",Space,Str "notes",Space,Str "inside",Space,Str "a",Space,Str "column"]]]
+ ,Div ("",["column"],[])
+  [Para [Str "Some",Space,Str "other",Space,Emph [Str "stuff"]]]]
+,Div ("",["notes"],[])
+ [Para [Str "Some",Space,Str "notes",Space,Str "outside",Space,Str "the",Space,Str "column"]]]
diff --git a/test/pptx/speaker_notes_afterseps.pptx b/test/pptx/speaker_notes_afterseps.pptx
new file mode 100644
index 000000000..a7ba1c0d4
Binary files /dev/null and b/test/pptx/speaker_notes_afterseps.pptx differ
diff --git a/test/pptx/speaker_notes_afterseps_templated.pptx b/test/pptx/speaker_notes_afterseps_templated.pptx
new file mode 100644
index 000000000..73a142d1c
Binary files /dev/null and b/test/pptx/speaker_notes_afterseps_templated.pptx differ
diff --git a/test/pptx/tables.native b/test/pptx/tables.native
new file mode 100644
index 000000000..e41b7bc8d
--- /dev/null
+++ b/test/pptx/tables.native
@@ -0,0 +1,35 @@
+[Header 2 ("a-table-with-a-caption",[],[]) [Str "A",Space,Str "Table,",Space,Str "with",Space,Str "a",Space,Str "caption"]
+,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax,",Space,Str "with",Space,Str "alignment"] [AlignRight,AlignLeft,AlignCenter,AlignDefault] [0.0,0.0,0.0,0.0]
+ [[Plain [Str "Right"]]
+ ,[Plain [Str "Left"]]
+ ,[Plain [Str "Center"]]
+ ,[Plain [Str "Default"]]]
+ [[[Plain [Str "12"]]
+  ,[Plain [Str "12"]]
+  ,[Plain [Str "12"]]
+  ,[Plain [Str "12"]]]
+ ,[[Plain [Str "123"]]
+  ,[Plain [Str "123"]]
+  ,[Plain [Str "123"]]
+  ,[Plain [Str "123"]]]
+ ,[[Plain [Str "1"]]
+  ,[Plain [Str "1"]]
+  ,[Plain [Str "1"]]
+  ,[Plain [Str "1"]]]]
+,Table [] [AlignRight,AlignLeft,AlignCenter,AlignDefault] [0.0,0.0,0.0,0.0]
+ [[Plain [Str "Right"]]
+ ,[Plain [Str "Left"]]
+ ,[Plain [Str "Center"]]
+ ,[Plain [Str "Default"]]]
+ [[[Plain [Str "12"]]
+  ,[Plain [Str "12"]]
+  ,[Plain [Str "12"]]
+  ,[Plain [Str "12"]]]
+ ,[[Plain [Str "123"]]
+  ,[Plain [Str "123"]]
+  ,[Plain [Str "123"]]
+  ,[Plain [Str "123"]]]
+ ,[[Plain [Str "1"]]
+  ,[Plain [Str "1"]]
+  ,[Plain [Str "1"]]
+  ,[Plain [Str "1"]]]]]
diff --git a/test/pptx/tables.pptx b/test/pptx/tables.pptx
new file mode 100644
index 000000000..c3e215a30
Binary files /dev/null and b/test/pptx/tables.pptx differ
diff --git a/test/pptx/tables_templated.pptx b/test/pptx/tables_templated.pptx
new file mode 100644
index 000000000..53de9b886
Binary files /dev/null and b/test/pptx/tables_templated.pptx differ
diff --git a/test/s5-fancy.html b/test/s5-fancy.html
index 9f724af96..b326f9872 100644
--- a/test/s5-fancy.html
+++ b/test/s5-fancy.html
@@ -26,207 +26,7 @@
   <link rel="stylesheet" href="s5/default/opera.css" type="text/css" media="projection" id="operaFix" />
   <!-- S5 JS -->
   <script src="s5/default/slides.js" type="text/javascript"></script>
-  <script type="text/javascript">/*<![CDATA[*/
-  /*
-  LaTeXMathML.js from http://math.etsu.edu/LaTeXMathML/
-  Adapted by Jeff Knisely and Douglas Woodall from ASCIIMathML.js v. 1.4.7,
-  (c) 2005 Peter Jipsen http://www.chapman.edu/~jipsen.
-  Released under the GNU General Public License version 2 or later.
-  See the GNU General Public License (at http://www.gnu.org/copyleft/gpl.html)
-  for more details.
-  */
-  var checkForMathML=true;var notifyIfNoMathML=true;var alertIfNoMathML=false;var mathcolor="";var mathfontfamily="";var showasciiformulaonhover=true;var isIE=document.createElementNS==null;if(document.getElementById==null)
-  alert("This webpage requires a recent browser such as \nMozilla/Netscape 7+ or Internet Explorer 6+MathPlayer")
-  function AMcreateElementXHTML(t){if(isIE)return document.createElement(t);else return document.createElementNS("http://www.w3.org/1999/xhtml",t);}
-  function AMnoMathMLNote(){var nd=AMcreateElementXHTML("h3");nd.setAttribute("align","center")
-  nd.appendChild(AMcreateElementXHTML("p"));nd.appendChild(document.createTextNode("To view the "));var an=AMcreateElementXHTML("a");an.appendChild(document.createTextNode("LaTeXMathML"));an.setAttribute("href","http://www.maths.nott.ac.uk/personal/drw/lm.html");nd.appendChild(an);nd.appendChild(document.createTextNode(" notation use Internet Explorer 6+"));an=AMcreateElementXHTML("a");an.appendChild(document.createTextNode("MathPlayer"));an.setAttribute("href","http://www.dessci.com/en/products/mathplayer/download.htm");nd.appendChild(an);nd.appendChild(document.createTextNode(" or Netscape/Mozilla/Firefox"));nd.appendChild(AMcreateElementXHTML("p"));return nd;}
-  function AMisMathMLavailable(){if(navigator.appName.slice(0,8)=="Netscape")
-  if(navigator.appVersion.slice(0,1)>="5")return null;else return AMnoMathMLNote();else if(navigator.appName.slice(0,9)=="Microsoft")
-  try{var ActiveX=new ActiveXObject("MathPlayer.Factory.1");return null;}catch(e){return AMnoMathMLNote();}
-  else return AMnoMathMLNote();}
-  var AMcal=[0xEF35,0x212C,0xEF36,0xEF37,0x2130,0x2131,0xEF38,0x210B,0x2110,0xEF39,0xEF3A,0x2112,0x2133,0xEF3B,0xEF3C,0xEF3D,0xEF3E,0x211B,0xEF3F,0xEF40,0xEF41,0xEF42,0xEF43,0xEF44,0xEF45,0xEF46];var AMfrk=[0xEF5D,0xEF5E,0x212D,0xEF5F,0xEF60,0xEF61,0xEF62,0x210C,0x2111,0xEF63,0xEF64,0xEF65,0xEF66,0xEF67,0xEF68,0xEF69,0xEF6A,0x211C,0xEF6B,0xEF6C,0xEF6D,0xEF6E,0xEF6F,0xEF70,0xEF71,0x2128];var AMbbb=[0xEF8C,0xEF8D,0x2102,0xEF8E,0xEF8F,0xEF90,0xEF91,0x210D,0xEF92,0xEF93,0xEF94,0xEF95,0xEF96,0x2115,0xEF97,0x2119,0x211A,0x211D,0xEF98,0xEF99,0xEF9A,0xEF9B,0xEF9C,0xEF9D,0xEF9E,0x2124];var CONST=0,UNARY=1,BINARY=2,INFIX=3,LEFTBRACKET=4,RIGHTBRACKET=5,SPACE=6,UNDEROVER=7,DEFINITION=8,TEXT=9,BIG=10,LONG=11,STRETCHY=12,MATRIX=13;var AMsqrt={input:"\\sqrt",tag:"msqrt",output:"sqrt",ttype:UNARY},AMroot={input:"\\root",tag:"mroot",output:"root",ttype:BINARY},AMfrac={input:"\\frac",tag:"mfrac",output:"/",ttype:BINARY},AMover={input:"\\stackrel",tag:"mover",output:"stackrel",ttype:BINARY},AMatop={input:"\\atop",tag:"mfrac",output:"",ttype:INFIX},AMchoose={input:"\\choose",tag:"mfrac",output:"",ttype:INFIX},AMsub={input:"_",tag:"msub",output:"_",ttype:INFIX},AMsup={input:"^",tag:"msup",output:"^",ttype:INFIX},AMtext={input:"\\mathrm",tag:"mtext",output:"text",ttype:TEXT},AMmbox={input:"\\mbox",tag:"mtext",output:"mbox",ttype:TEXT};var AMsymbols=[{input:"\\alpha",tag:"mi",output:"\u03B1",ttype:CONST},{input:"\\beta",tag:"mi",output:"\u03B2",ttype:CONST},{input:"\\gamma",tag:"mi",output:"\u03B3",ttype:CONST},{input:"\\delta",tag:"mi",output:"\u03B4",ttype:CONST},{input:"\\epsilon",tag:"mi",output:"\u03B5",ttype:CONST},{input:"\\varepsilon",tag:"mi",output:"\u025B",ttype:CONST},{input:"\\zeta",tag:"mi",output:"\u03B6",ttype:CONST},{input:"\\eta",tag:"mi",output:"\u03B7",ttype:CONST},{input:"\\theta",tag:"mi",output:"\u03B8",ttype:CONST},{input:"\\vartheta",tag:"mi",output:"\u03D1",ttype:CONST},{input:"\\iota",tag:"mi",output:"\u03B9",ttype:CONST},{input:"\\kappa",tag:"mi",output:"\u03BA",ttype:CONST},{input:"\\lambda",tag:"mi",output:"\u03BB",ttype:CONST},{input:"\\mu",tag:"mi",output:"\u03BC",ttype:CONST},{input:"\\nu",tag:"mi",output:"\u03BD",ttype:CONST},{input:"\\xi",tag:"mi",output:"\u03BE",ttype:CONST},{input:"\\pi",tag:"mi",output:"\u03C0",ttype:CONST},{input:"\\varpi",tag:"mi",output:"\u03D6",ttype:CONST},{input:"\\rho",tag:"mi",output:"\u03C1",ttype:CONST},{input:"\\varrho",tag:"mi",output:"\u03F1",ttype:CONST},{input:"\\varsigma",tag:"mi",output:"\u03C2",ttype:CONST},{input:"\\sigma",tag:"mi",output:"\u03C3",ttype:CONST},{input:"\\tau",tag:"mi",output:"\u03C4",ttype:CONST},{input:"\\upsilon",tag:"mi",output:"\u03C5",ttype:CONST},{input:"\\phi",tag:"mi",output:"\u03C6",ttype:CONST},{input:"\\varphi",tag:"mi",output:"\u03D5",ttype:CONST},{input:"\\chi",tag:"mi",output:"\u03C7",ttype:CONST},{input:"\\psi",tag:"mi",output:"\u03C8",ttype:CONST},{input:"\\omega",tag:"mi",output:"\u03C9",ttype:CONST},{input:"\\Gamma",tag:"mo",output:"\u0393",ttype:CONST},{input:"\\Delta",tag:"mo",output:"\u0394",ttype:CONST},{input:"\\Theta",tag:"mo",output:"\u0398",ttype:CONST},{input:"\\Lambda",tag:"mo",output:"\u039B",ttype:CONST},{input:"\\Xi",tag:"mo",output:"\u039E",ttype:CONST},{input:"\\Pi",tag:"mo",output:"\u03A0",ttype:CONST},{input:"\\Sigma",tag:"mo",output:"\u03A3",ttype:CONST},{input:"\\Upsilon",tag:"mo",output:"\u03A5",ttype:CONST},{input:"\\Phi",tag:"mo",output:"\u03A6",ttype:CONST},{input:"\\Psi",tag:"mo",output:"\u03A8",ttype:CONST},{input:"\\Omega",tag:"mo",output:"\u03A9",ttype:CONST},{input:"\\frac12",tag:"mo",output:"\u00BD",ttype:CONST},{input:"\\frac14",tag:"mo",output:"\u00BC",ttype:CONST},{input:"\\frac34",tag:"mo",output:"\u00BE",ttype:CONST},{input:"\\frac13",tag:"mo",output:"\u2153",ttype:CONST},{input:"\\frac23",tag:"mo",output:"\u2154",ttype:CONST},{input:"\\frac15",tag:"mo",output:"\u2155",ttype:CONST},{input:"\\frac25",tag:"mo",output:"\u2156",ttype:CONST},{input:"\\frac35",tag:"mo",output:"\u2157",ttype:CONST},{input:"\\frac45",tag:"mo",output:"\u2158",ttype:CONST},{input:"\\frac16",tag:"mo",output:"\u2159",ttype:CONST},{input:"\\frac56",tag:"mo",output:"\u215A",ttype:CONST},{input:"\\frac18",tag:"mo",output:"\u215B",ttype:CONST},{input:"\\frac38",tag:"mo",output:"\u215C",ttype:CONST},{input:"\\frac58",tag:"mo",output:"\u215D",ttype:CONST},{input:"\\frac78",tag:"mo",output:"\u215E",ttype:CONST},{input:"\\pm",tag:"mo",output:"\u00B1",ttype:CONST},{input:"\\mp",tag:"mo",output:"\u2213",ttype:CONST},{input:"\\triangleleft",tag:"mo",output:"\u22B2",ttype:CONST},{input:"\\triangleright",tag:"mo",output:"\u22B3",ttype:CONST},{input:"\\cdot",tag:"mo",output:"\u22C5",ttype:CONST},{input:"\\star",tag:"mo",output:"\u22C6",ttype:CONST},{input:"\\ast",tag:"mo",output:"\u002A",ttype:CONST},{input:"\\times",tag:"mo",output:"\u00D7",ttype:CONST},{input:"\\div",tag:"mo",output:"\u00F7",ttype:CONST},{input:"\\circ",tag:"mo",output:"\u2218",ttype:CONST},{input:"\\bullet",tag:"mo",output:"\u2022",ttype:CONST},{input:"\\oplus",tag:"mo",output:"\u2295",ttype:CONST},{input:"\\ominus",tag:"mo",output:"\u2296",ttype:CONST},{input:"\\otimes",tag:"mo",output:"\u2297",ttype:CONST},{input:"\\bigcirc",tag:"mo",output:"\u25CB",ttype:CONST},{input:"\\oslash",tag:"mo",output:"\u2298",ttype:CONST},{input:"\\odot",tag:"mo",output:"\u2299",ttype:CONST},{input:"\\land",tag:"mo",output:"\u2227",ttype:CONST},{input:"\\wedge",tag:"mo",output:"\u2227",ttype:CONST},{input:"\\lor",tag:"mo",output:"\u2228",ttype:CONST},{input:"\\vee",tag:"mo",output:"\u2228",ttype:CONST},{input:"\\cap",tag:"mo",output:"\u2229",ttype:CONST},{input:"\\cup",tag:"mo",output:"\u222A",ttype:CONST},{input:"\\sqcap",tag:"mo",output:"\u2293",ttype:CONST},{input:"\\sqcup",tag:"mo",output:"\u2294",ttype:CONST},{input:"\\uplus",tag:"mo",output:"\u228E",ttype:CONST},{input:"\\amalg",tag:"mo",output:"\u2210",ttype:CONST},{input:"\\bigtriangleup",tag:"mo",output:"\u25B3",ttype:CONST},{input:"\\bigtriangledown",tag:"mo",output:"\u25BD",ttype:CONST},{input:"\\dag",tag:"mo",output:"\u2020",ttype:CONST},{input:"\\dagger",tag:"mo",output:"\u2020",ttype:CONST},{input:"\\ddag",tag:"mo",output:"\u2021",ttype:CONST},{input:"\\ddagger",tag:"mo",output:"\u2021",ttype:CONST},{input:"\\lhd",tag:"mo",output:"\u22B2",ttype:CONST},{input:"\\rhd",tag:"mo",output:"\u22B3",ttype:CONST},{input:"\\unlhd",tag:"mo",output:"\u22B4",ttype:CONST},{input:"\\unrhd",tag:"mo",output:"\u22B5",ttype:CONST},{input:"\\sum",tag:"mo",output:"\u2211",ttype:UNDEROVER},{input:"\\prod",tag:"mo",output:"\u220F",ttype:UNDEROVER},{input:"\\bigcap",tag:"mo",output:"\u22C2",ttype:UNDEROVER},{input:"\\bigcup",tag:"mo",output:"\u22C3",ttype:UNDEROVER},{input:"\\bigwedge",tag:"mo",output:"\u22C0",ttype:UNDEROVER},{input:"\\bigvee",tag:"mo",output:"\u22C1",ttype:UNDEROVER},{input:"\\bigsqcap",tag:"mo",output:"\u2A05",ttype:UNDEROVER},{input:"\\bigsqcup",tag:"mo",output:"\u2A06",ttype:UNDEROVER},{input:"\\coprod",tag:"mo",output:"\u2210",ttype:UNDEROVER},{input:"\\bigoplus",tag:"mo",output:"\u2A01",ttype:UNDEROVER},{input:"\\bigotimes",tag:"mo",output:"\u2A02",ttype:UNDEROVER},{input:"\\bigodot",tag:"mo",output:"\u2A00",ttype:UNDEROVER},{input:"\\biguplus",tag:"mo",output:"\u2A04",ttype:UNDEROVER},{input:"\\int",tag:"mo",output:"\u222B",ttype:CONST},{input:"\\oint",tag:"mo",output:"\u222E",ttype:CONST},{input:":=",tag:"mo",output:":=",ttype:CONST},{input:"\\lt",tag:"mo",output:"<",ttype:CONST},{input:"\\gt",tag:"mo",output:">",ttype:CONST},{input:"\\ne",tag:"mo",output:"\u2260",ttype:CONST},{input:"\\neq",tag:"mo",output:"\u2260",ttype:CONST},{input:"\\le",tag:"mo",output:"\u2264",ttype:CONST},{input:"\\leq",tag:"mo",output:"\u2264",ttype:CONST},{input:"\\leqslant",tag:"mo",output:"\u2264",ttype:CONST},{input:"\\ge",tag:"mo",output:"\u2265",ttype:CONST},{input:"\\geq",tag:"mo",output:"\u2265",ttype:CONST},{input:"\\geqslant",tag:"mo",output:"\u2265",ttype:CONST},{input:"\\equiv",tag:"mo",output:"\u2261",ttype:CONST},{input:"\\ll",tag:"mo",output:"\u226A",ttype:CONST},{input:"\\gg",tag:"mo",output:"\u226B",ttype:CONST},{input:"\\doteq",tag:"mo",output:"\u2250",ttype:CONST},{input:"\\prec",tag:"mo",output:"\u227A",ttype:CONST},{input:"\\succ",tag:"mo",output:"\u227B",ttype:CONST},{input:"\\preceq",tag:"mo",output:"\u227C",ttype:CONST},{input:"\\succeq",tag:"mo",output:"\u227D",ttype:CONST},{input:"\\subset",tag:"mo",output:"\u2282",ttype:CONST},{input:"\\supset",tag:"mo",output:"\u2283",ttype:CONST},{input:"\\subseteq",tag:"mo",output:"\u2286",ttype:CONST},{input:"\\supseteq",tag:"mo",output:"\u2287",ttype:CONST},{input:"\\sqsubset",tag:"mo",output:"\u228F",ttype:CONST},{input:"\\sqsupset",tag:"mo",output:"\u2290",ttype:CONST},{input:"\\sqsubseteq",tag:"mo",output:"\u2291",ttype:CONST},{input:"\\sqsupseteq",tag:"mo",output:"\u2292",ttype:CONST},{input:"\\sim",tag:"mo",output:"\u223C",ttype:CONST},{input:"\\simeq",tag:"mo",output:"\u2243",ttype:CONST},{input:"\\approx",tag:"mo",output:"\u2248",ttype:CONST},{input:"\\cong",tag:"mo",output:"\u2245",ttype:CONST},{input:"\\Join",tag:"mo",output:"\u22C8",ttype:CONST},{input:"\\bowtie",tag:"mo",output:"\u22C8",ttype:CONST},{input:"\\in",tag:"mo",output:"\u2208",ttype:CONST},{input:"\\ni",tag:"mo",output:"\u220B",ttype:CONST},{input:"\\owns",tag:"mo",output:"\u220B",ttype:CONST},{input:"\\propto",tag:"mo",output:"\u221D",ttype:CONST},{input:"\\vdash",tag:"mo",output:"\u22A2",ttype:CONST},{input:"\\dashv",tag:"mo",output:"\u22A3",ttype:CONST},{input:"\\models",tag:"mo",output:"\u22A8",ttype:CONST},{input:"\\perp",tag:"mo",output:"\u22A5",ttype:CONST},{input:"\\smile",tag:"mo",output:"\u2323",ttype:CONST},{input:"\\frown",tag:"mo",output:"\u2322",ttype:CONST},{input:"\\asymp",tag:"mo",output:"\u224D",ttype:CONST},{input:"\\notin",tag:"mo",output:"\u2209",ttype:CONST},{input:"\\begin{eqnarray}",output:"X",ttype:MATRIX,invisible:true},{input:"\\begin{array}",output:"X",ttype:MATRIX,invisible:true},{input:"\\\\",output:"}&{",ttype:DEFINITION},{input:"\\end{eqnarray}",output:"}}",ttype:DEFINITION},{input:"\\end{array}",output:"}}",ttype:DEFINITION},{input:"\\big",tag:"mo",output:"X",atval:"1.2",ieval:"2.2",ttype:BIG},{input:"\\Big",tag:"mo",output:"X",atval:"1.6",ieval:"2.6",ttype:BIG},{input:"\\bigg",tag:"mo",output:"X",atval:"2.2",ieval:"3.2",ttype:BIG},{input:"\\Bigg",tag:"mo",output:"X",atval:"2.9",ieval:"3.9",ttype:BIG},{input:"\\left",tag:"mo",output:"X",ttype:LEFTBRACKET},{input:"\\right",tag:"mo",output:"X",ttype:RIGHTBRACKET},{input:"{",output:"{",ttype:LEFTBRACKET,invisible:true},{input:"}",output:"}",ttype:RIGHTBRACKET,invisible:true},{input:"(",tag:"mo",output:"(",atval:"1",ttype:STRETCHY},{input:"[",tag:"mo",output:"[",atval:"1",ttype:STRETCHY},{input:"\\lbrack",tag:"mo",output:"[",atval:"1",ttype:STRETCHY},{input:"\\{",tag:"mo",output:"{",atval:"1",ttype:STRETCHY},{input:"\\lbrace",tag:"mo",output:"{",atval:"1",ttype:STRETCHY},{input:"\\langle",tag:"mo",output:"\u2329",atval:"1",ttype:STRETCHY},{input:"\\lfloor",tag:"mo",output:"\u230A",atval:"1",ttype:STRETCHY},{input:"\\lceil",tag:"mo",output:"\u2308",atval:"1",ttype:STRETCHY},{input:")",tag:"mo",output:")",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"]",tag:"mo",output:"]",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"\\rbrack",tag:"mo",output:"]",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"\\}",tag:"mo",output:"}",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"\\rbrace",tag:"mo",output:"}",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"\\rangle",tag:"mo",output:"\u232A",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"\\rfloor",tag:"mo",output:"\u230B",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"\\rceil",tag:"mo",output:"\u2309",rtag:"mi",atval:"1",ttype:STRETCHY},{input:"|",tag:"mo",output:"\u2223",atval:"1",ttype:STRETCHY},{input:"\\|",tag:"mo",output:"\u2225",atval:"1",ttype:STRETCHY},{input:"\\vert",tag:"mo",output:"\u2223",atval:"1",ttype:STRETCHY},{input:"\\Vert",tag:"mo",output:"\u2225",atval:"1",ttype:STRETCHY},{input:"\\mid",tag:"mo",output:"\u2223",atval:"1",ttype:STRETCHY},{input:"\\parallel",tag:"mo",output:"\u2225",atval:"1",ttype:STRETCHY},{input:"/",tag:"mo",output:"/",atval:"1.01",ttype:STRETCHY},{input:"\\backslash",tag:"mo",output:"\u2216",atval:"1",ttype:STRETCHY},{input:"\\setminus",tag:"mo",output:"\\",ttype:CONST},{input:"\\!",tag:"mspace",atname:"width",atval:"-0.167em",ttype:SPACE},{input:"\\,",tag:"mspace",atname:"width",atval:"0.167em",ttype:SPACE},{input:"\\>",tag:"mspace",atname:"width",atval:"0.222em",ttype:SPACE},{input:"\\:",tag:"mspace",atname:"width",atval:"0.222em",ttype:SPACE},{input:"\\;",tag:"mspace",atname:"width",atval:"0.278em",ttype:SPACE},{input:"~",tag:"mspace",atname:"width",atval:"0.333em",ttype:SPACE},{input:"\\quad",tag:"mspace",atname:"width",atval:"1em",ttype:SPACE},{input:"\\qquad",tag:"mspace",atname:"width",atval:"2em",ttype:SPACE},{input:"\\prime",tag:"mo",output:"\u2032",ttype:CONST},{input:"'",tag:"mo",output:"\u02B9",ttype:CONST},{input:"''",tag:"mo",output:"\u02BA",ttype:CONST},{input:"'''",tag:"mo",output:"\u2034",ttype:CONST},{input:"''''",tag:"mo",output:"\u2057",ttype:CONST},{input:"\\ldots",tag:"mo",output:"\u2026",ttype:CONST},{input:"\\cdots",tag:"mo",output:"\u22EF",ttype:CONST},{input:"\\vdots",tag:"mo",output:"\u22EE",ttype:CONST},{input:"\\ddots",tag:"mo",output:"\u22F1",ttype:CONST},{input:"\\forall",tag:"mo",output:"\u2200",ttype:CONST},{input:"\\exists",tag:"mo",output:"\u2203",ttype:CONST},{input:"\\Re",tag:"mo",output:"\u211C",ttype:CONST},{input:"\\Im",tag:"mo",output:"\u2111",ttype:CONST},{input:"\\aleph",tag:"mo",output:"\u2135",ttype:CONST},{input:"\\hbar",tag:"mo",output:"\u210F",ttype:CONST},{input:"\\ell",tag:"mo",output:"\u2113",ttype:CONST},{input:"\\wp",tag:"mo",output:"\u2118",ttype:CONST},{input:"\\emptyset",tag:"mo",output:"\u2205",ttype:CONST},{input:"\\infty",tag:"mo",output:"\u221E",ttype:CONST},{input:"\\surd",tag:"mo",output:"\\sqrt{}",ttype:DEFINITION},{input:"\\partial",tag:"mo",output:"\u2202",ttype:CONST},{input:"\\nabla",tag:"mo",output:"\u2207",ttype:CONST},{input:"\\triangle",tag:"mo",output:"\u25B3",ttype:CONST},{input:"\\therefore",tag:"mo",output:"\u2234",ttype:CONST},{input:"\\angle",tag:"mo",output:"\u2220",ttype:CONST},{input:"\\diamond",tag:"mo",output:"\u22C4",ttype:CONST},{input:"\\Diamond",tag:"mo",output:"\u25C7",ttype:CONST},{input:"\\neg",tag:"mo",output:"\u00AC",ttype:CONST},{input:"\\lnot",tag:"mo",output:"\u00AC",ttype:CONST},{input:"\\bot",tag:"mo",output:"\u22A5",ttype:CONST},{input:"\\top",tag:"mo",output:"\u22A4",ttype:CONST},{input:"\\square",tag:"mo",output:"\u25AB",ttype:CONST},{input:"\\Box",tag:"mo",output:"\u25A1",ttype:CONST},{input:"\\wr",tag:"mo",output:"\u2240",ttype:CONST},{input:"\\arccos",tag:"mi",output:"arccos",ttype:UNARY,func:true},{input:"\\arcsin",tag:"mi",output:"arcsin",ttype:UNARY,func:true},{input:"\\arctan",tag:"mi",output:"arctan",ttype:UNARY,func:true},{input:"\\arg",tag:"mi",output:"arg",ttype:UNARY,func:true},{input:"\\cos",tag:"mi",output:"cos",ttype:UNARY,func:true},{input:"\\cosh",tag:"mi",output:"cosh",ttype:UNARY,func:true},{input:"\\cot",tag:"mi",output:"cot",ttype:UNARY,func:true},{input:"\\coth",tag:"mi",output:"coth",ttype:UNARY,func:true},{input:"\\csc",tag:"mi",output:"csc",ttype:UNARY,func:true},{input:"\\deg",tag:"mi",output:"deg",ttype:UNARY,func:true},{input:"\\det",tag:"mi",output:"det",ttype:UNARY,func:true},{input:"\\dim",tag:"mi",output:"dim",ttype:UNARY,func:true},{input:"\\exp",tag:"mi",output:"exp",ttype:UNARY,func:true},{input:"\\gcd",tag:"mi",output:"gcd",ttype:UNARY,func:true},{input:"\\hom",tag:"mi",output:"hom",ttype:UNARY,func:true},{input:"\\inf",tag:"mo",output:"inf",ttype:UNDEROVER},{input:"\\ker",tag:"mi",output:"ker",ttype:UNARY,func:true},{input:"\\lg",tag:"mi",output:"lg",ttype:UNARY,func:true},{input:"\\lim",tag:"mo",output:"lim",ttype:UNDEROVER},{input:"\\liminf",tag:"mo",output:"liminf",ttype:UNDEROVER},{input:"\\limsup",tag:"mo",output:"limsup",ttype:UNDEROVER},{input:"\\ln",tag:"mi",output:"ln",ttype:UNARY,func:true},{input:"\\log",tag:"mi",output:"log",ttype:UNARY,func:true},{input:"\\max",tag:"mo",output:"max",ttype:UNDEROVER},{input:"\\min",tag:"mo",output:"min",ttype:UNDEROVER},{input:"\\Pr",tag:"mi",output:"Pr",ttype:UNARY,func:true},{input:"\\sec",tag:"mi",output:"sec",ttype:UNARY,func:true},{input:"\\sin",tag:"mi",output:"sin",ttype:UNARY,func:true},{input:"\\sinh",tag:"mi",output:"sinh",ttype:UNARY,func:true},{input:"\\sup",tag:"mo",output:"sup",ttype:UNDEROVER},{input:"\\tan",tag:"mi",output:"tan",ttype:UNARY,func:true},{input:"\\tanh",tag:"mi",output:"tanh",ttype:UNARY,func:true},{input:"\\gets",tag:"mo",output:"\u2190",ttype:CONST},{input:"\\leftarrow",tag:"mo",output:"\u2190",ttype:CONST},{input:"\\to",tag:"mo",output:"\u2192",ttype:CONST},{input:"\\rightarrow",tag:"mo",output:"\u2192",ttype:CONST},{input:"\\leftrightarrow",tag:"mo",output:"\u2194",ttype:CONST},{input:"\\uparrow",tag:"mo",output:"\u2191",ttype:CONST},{input:"\\downarrow",tag:"mo",output:"\u2193",ttype:CONST},{input:"\\updownarrow",tag:"mo",output:"\u2195",ttype:CONST},{input:"\\Leftarrow",tag:"mo",output:"\u21D0",ttype:CONST},{input:"\\Rightarrow",tag:"mo",output:"\u21D2",ttype:CONST},{input:"\\Leftrightarrow",tag:"mo",output:"\u21D4",ttype:CONST},{input:"\\iff",tag:"mo",output:"~\\Longleftrightarrow~",ttype:DEFINITION},{input:"\\Uparrow",tag:"mo",output:"\u21D1",ttype:CONST},{input:"\\Downarrow",tag:"mo",output:"\u21D3",ttype:CONST},{input:"\\Updownarrow",tag:"mo",output:"\u21D5",ttype:CONST},{input:"\\mapsto",tag:"mo",output:"\u21A6",ttype:CONST},{input:"\\longleftarrow",tag:"mo",output:"\u2190",ttype:LONG},{input:"\\longrightarrow",tag:"mo",output:"\u2192",ttype:LONG},{input:"\\longleftrightarrow",tag:"mo",output:"\u2194",ttype:LONG},{input:"\\Longleftarrow",tag:"mo",output:"\u21D0",ttype:LONG},{input:"\\Longrightarrow",tag:"mo",output:"\u21D2",ttype:LONG},{input:"\\Longleftrightarrow",tag:"mo",output:"\u21D4",ttype:LONG},{input:"\\longmapsto",tag:"mo",output:"\u21A6",ttype:CONST},AMsqrt,AMroot,AMfrac,AMover,AMsub,AMsup,AMtext,AMmbox,AMatop,AMchoose,{input:"\\acute",tag:"mover",output:"\u00B4",ttype:UNARY,acc:true},{input:"\\grave",tag:"mover",output:"\u0060",ttype:UNARY,acc:true},{input:"\\breve",tag:"mover",output:"\u02D8",ttype:UNARY,acc:true},{input:"\\check",tag:"mover",output:"\u02C7",ttype:UNARY,acc:true},{input:"\\dot",tag:"mover",output:".",ttype:UNARY,acc:true},{input:"\\ddot",tag:"mover",output:"..",ttype:UNARY,acc:true},{input:"\\mathring",tag:"mover",output:"\u00B0",ttype:UNARY,acc:true},{input:"\\vec",tag:"mover",output:"\u20D7",ttype:UNARY,acc:true},{input:"\\overrightarrow",tag:"mover",output:"\u20D7",ttype:UNARY,acc:true},{input:"\\overleftarrow",tag:"mover",output:"\u20D6",ttype:UNARY,acc:true},{input:"\\hat",tag:"mover",output:"\u005E",ttype:UNARY,acc:true},{input:"\\widehat",tag:"mover",output:"\u0302",ttype:UNARY,acc:true},{input:"\\tilde",tag:"mover",output:"~",ttype:UNARY,acc:true},{input:"\\widetilde",tag:"mover",output:"\u02DC",ttype:UNARY,acc:true},{input:"\\bar",tag:"mover",output:"\u203E",ttype:UNARY,acc:true},{input:"\\overbrace",tag:"mover",output:"\uFE37",ttype:UNARY,acc:true},{input:"\\overbracket",tag:"mover",output:"\u23B4",ttype:UNARY,acc:true},{input:"\\overline",tag:"mover",output:"\u00AF",ttype:UNARY,acc:true},{input:"\\underbrace",tag:"munder",output:"\uFE38",ttype:UNARY,acc:true},{input:"\\underbracket",tag:"munder",output:"\u23B5",ttype:UNARY,acc:true},{input:"\\underline",tag:"munder",output:"\u00AF",ttype:UNARY,acc:true},{input:"\\displaystyle",tag:"mstyle",atname:"displaystyle",atval:"true",ttype:UNARY},{input:"\\textstyle",tag:"mstyle",atname:"displaystyle",atval:"false",ttype:UNARY},{input:"\\scriptstyle",tag:"mstyle",atname:"scriptlevel",atval:"1",ttype:UNARY},{input:"\\scriptscriptstyle",tag:"mstyle",atname:"scriptlevel",atval:"2",ttype:UNARY},{input:"\\textrm",tag:"mstyle",output:"\\mathrm",ttype:DEFINITION},{input:"\\mathbf",tag:"mstyle",atname:"mathvariant",atval:"bold",ttype:UNARY},{input:"\\textbf",tag:"mstyle",atname:"mathvariant",atval:"bold",ttype:UNARY},{input:"\\mathit",tag:"mstyle",atname:"mathvariant",atval:"italic",ttype:UNARY},{input:"\\textit",tag:"mstyle",atname:"mathvariant",atval:"italic",ttype:UNARY},{input:"\\mathtt",tag:"mstyle",atname:"mathvariant",atval:"monospace",ttype:UNARY},{input:"\\texttt",tag:"mstyle",atname:"mathvariant",atval:"monospace",ttype:UNARY},{input:"\\mathsf",tag:"mstyle",atname:"mathvariant",atval:"sans-serif",ttype:UNARY},{input:"\\mathbb",tag:"mstyle",atname:"mathvariant",atval:"double-struck",ttype:UNARY,codes:AMbbb},{input:"\\mathcal",tag:"mstyle",atname:"mathvariant",atval:"script",ttype:UNARY,codes:AMcal},{input:"\\mathfrak",tag:"mstyle",atname:"mathvariant",atval:"fraktur",ttype:UNARY,codes:AMfrk},{input:"\\textcolor",tag:"mstyle",atname:"mathvariant",atval:"mathcolor",ttype:BINARY},{input:"\\colorbox",tag:"mstyle",atname:"mathvariant",atval:"background",ttype:BINARY}];function compareNames(s1,s2){if(s1.input>s2.input)return 1
-  else return-1;}
-  var AMnames=[];function AMinitSymbols(){AMsymbols.sort(compareNames);for(i=0;i<AMsymbols.length;i++)AMnames[i]=AMsymbols[i].input;}
-  var AMmathml="http://www.w3.org/1998/Math/MathML";function AMcreateElementMathML(t){if(isIE)return document.createElement("m:"+t);else return document.createElementNS(AMmathml,t);}
-  function AMcreateMmlNode(t,frag){if(isIE)var node=document.createElement("m:"+t);else var node=document.createElementNS(AMmathml,t);node.appendChild(frag);return node;}
-  function newcommand(oldstr,newstr){AMsymbols=AMsymbols.concat([{input:oldstr,tag:"mo",output:newstr,ttype:DEFINITION}]);}
-  function AMremoveCharsAndBlanks(str,n){var st;st=str.slice(n);for(var i=0;i<st.length&&st.charCodeAt(i)<=32;i=i+1);return st.slice(i);}
-  function AMposition(arr,str,n){if(n==0){var h,m;n=-1;h=arr.length;while(n+1<h){m=(n+h)>>1;if(arr[m]<str)n=m;else h=m;}
-  return h;}else
-  for(var i=n;i<arr.length&&arr[i]<str;i++);return i;}
-  function AMgetSymbol(str){var k=0;var j=0;var mk;var st;var tagst;var match="";var more=true;for(var i=1;i<=str.length&&more;i++){st=str.slice(0,i);j=k;k=AMposition(AMnames,st,j);if(k<AMnames.length&&str.slice(0,AMnames[k].length)==AMnames[k]){match=AMnames[k];mk=k;i=match.length;}
-  more=k<AMnames.length&&str.slice(0,AMnames[k].length)>=AMnames[k];}
-  AMpreviousSymbol=AMcurrentSymbol;if(match!=""){AMcurrentSymbol=AMsymbols[mk].ttype;return AMsymbols[mk];}
-  AMcurrentSymbol=CONST;k=1;st=str.slice(0,1);if("0"<=st&&st<="9")tagst="mn";else tagst=(("A">st||st>"Z")&&("a">st||st>"z")?"mo":"mi");return{input:st,tag:tagst,output:st,ttype:CONST};}
-  var AMpreviousSymbol,AMcurrentSymbol;function AMparseSexpr(str){var symbol,node,result,result2,i,st,newFrag=document.createDocumentFragment();str=AMremoveCharsAndBlanks(str,0);symbol=AMgetSymbol(str);if(symbol==null||symbol.ttype==RIGHTBRACKET)
-  return[null,str,null];if(symbol.ttype==DEFINITION){str=symbol.output+AMremoveCharsAndBlanks(str,symbol.input.length);symbol=AMgetSymbol(str);if(symbol==null||symbol.ttype==RIGHTBRACKET)
-  return[null,str,null];}
-  str=AMremoveCharsAndBlanks(str,symbol.input.length);switch(symbol.ttype){case SPACE:node=AMcreateElementMathML(symbol.tag);node.setAttribute(symbol.atname,symbol.atval);return[node,str,symbol.tag];case UNDEROVER:if(isIE){if(symbol.input.substr(0,4)=="\\big"){str="\\"+symbol.input.substr(4)+str;symbol=AMgetSymbol(str);symbol.ttype=UNDEROVER;str=AMremoveCharsAndBlanks(str,symbol.input.length);}}
-  return[AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)),str,symbol.tag];case CONST:var output=symbol.output;if(isIE){if(symbol.input=="'")
-  output="\u2032";else if(symbol.input=="''")
-  output="\u2033";else if(symbol.input=="'''")
-  output="\u2033\u2032";else if(symbol.input=="''''")
-  output="\u2033\u2033";else if(symbol.input=="\\square")
-  output="\u25A1";else if(symbol.input.substr(0,5)=="\\frac"){var denom=symbol.input.substr(6,1);if(denom=="5"||denom=="6"){str=symbol.input.replace(/\\frac/,"\\frac ")+str;return[node,str,symbol.tag];}}}
-  node=AMcreateMmlNode(symbol.tag,document.createTextNode(output));return[node,str,symbol.tag];case LONG:node=AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output));node.setAttribute("minsize","1.5");node.setAttribute("maxsize","1.5");node=AMcreateMmlNode("mover",node);node.appendChild(AMcreateElementMathML("mspace"));return[node,str,symbol.tag];case STRETCHY:if(isIE&&symbol.input=="\\backslash")
-  symbol.output="\\";node=AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output));if(symbol.input=="|"||symbol.input=="\\vert"||symbol.input=="\\|"||symbol.input=="\\Vert"){node.setAttribute("lspace","0em");node.setAttribute("rspace","0em");}
-  node.setAttribute("maxsize",symbol.atval);if(symbol.rtag!=null)
-  return[node,str,symbol.rtag];else
-  return[node,str,symbol.tag];case BIG:var atval=symbol.atval;if(isIE)
-  atval=symbol.ieval;symbol=AMgetSymbol(str);if(symbol==null)
-  return[null,str,null];str=AMremoveCharsAndBlanks(str,symbol.input.length);node=AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output));if(isIE){var space=AMcreateElementMathML("mspace");space.setAttribute("height",atval+"ex");node=AMcreateMmlNode("mrow",node);node.appendChild(space);}else{node.setAttribute("minsize",atval);node.setAttribute("maxsize",atval);}
-  return[node,str,symbol.tag];case LEFTBRACKET:if(symbol.input=="\\left"){symbol=AMgetSymbol(str);if(symbol!=null){if(symbol.input==".")
-  symbol.invisible=true;str=AMremoveCharsAndBlanks(str,symbol.input.length);}}
-  result=AMparseExpr(str,true,false);if(symbol==null||(typeof symbol.invisible=="boolean"&&symbol.invisible))
-  node=AMcreateMmlNode("mrow",result[0]);else{node=AMcreateMmlNode("mo",document.createTextNode(symbol.output));node=AMcreateMmlNode("mrow",node);node.appendChild(result[0]);}
-  return[node,result[1],result[2]];case MATRIX:if(symbol.input=="\\begin{array}"){var mask="";symbol=AMgetSymbol(str);str=AMremoveCharsAndBlanks(str,0);if(symbol==null)
-  mask="l";else{str=AMremoveCharsAndBlanks(str,symbol.input.length);if(symbol.input!="{")
-  mask="l";else do{symbol=AMgetSymbol(str);if(symbol!=null){str=AMremoveCharsAndBlanks(str,symbol.input.length);if(symbol.input!="}")
-  mask=mask+symbol.input;}}while(symbol!=null&&symbol.input!=""&&symbol.input!="}");}
-  result=AMparseExpr("{"+str,true,true);node=AMcreateMmlNode("mtable",result[0]);mask=mask.replace(/l/g,"left ");mask=mask.replace(/r/g,"right ");mask=mask.replace(/c/g,"center ");node.setAttribute("columnalign",mask);node.setAttribute("displaystyle","false");if(isIE)
-  return[node,result[1],null];var lspace=AMcreateElementMathML("mspace");lspace.setAttribute("width","0.167em");var rspace=AMcreateElementMathML("mspace");rspace.setAttribute("width","0.167em");var node1=AMcreateMmlNode("mrow",lspace);node1.appendChild(node);node1.appendChild(rspace);return[node1,result[1],null];}else{result=AMparseExpr("{"+str,true,true);node=AMcreateMmlNode("mtable",result[0]);if(isIE)
-  node.setAttribute("columnspacing","0.25em");else
-  node.setAttribute("columnspacing","0.167em");node.setAttribute("columnalign","right center left");node.setAttribute("displaystyle","true");node=AMcreateMmlNode("mrow",node);return[node,result[1],null];}
-  case TEXT:if(str.charAt(0)=="{")i=str.indexOf("}");else i=0;if(i==-1)
-  i=str.length;st=str.slice(1,i);if(st.charAt(0)==" "){node=AMcreateElementMathML("mspace");node.setAttribute("width","0.33em");newFrag.appendChild(node);}
-  newFrag.appendChild(AMcreateMmlNode(symbol.tag,document.createTextNode(st)));if(st.charAt(st.length-1)==" "){node=AMcreateElementMathML("mspace");node.setAttribute("width","0.33em");newFrag.appendChild(node);}
-  str=AMremoveCharsAndBlanks(str,i+1);return[AMcreateMmlNode("mrow",newFrag),str,null];case UNARY:result=AMparseSexpr(str);if(result[0]==null)return[AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)),str];if(typeof symbol.func=="boolean"&&symbol.func){st=str.charAt(0);if(st=="^"||st=="_"||st==","){return[AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)),str,symbol.tag];}else{node=AMcreateMmlNode("mrow",AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)));if(isIE){var space=AMcreateElementMathML("mspace");space.setAttribute("width","0.167em");node.appendChild(space);}
-  node.appendChild(result[0]);return[node,result[1],symbol.tag];}}
-  if(symbol.input=="\\sqrt"){if(isIE){var space=AMcreateElementMathML("mspace");space.setAttribute("height","1.2ex");space.setAttribute("width","0em");node=AMcreateMmlNode(symbol.tag,result[0])
-  node.appendChild(space);return[node,result[1],symbol.tag];}else
-  return[AMcreateMmlNode(symbol.tag,result[0]),result[1],symbol.tag];}else if(typeof symbol.acc=="boolean"&&symbol.acc){node=AMcreateMmlNode(symbol.tag,result[0]);var output=symbol.output;if(isIE){if(symbol.input=="\\hat")
-  output="\u0302";else if(symbol.input=="\\widehat")
-  output="\u005E";else if(symbol.input=="\\bar")
-  output="\u00AF";else if(symbol.input=="\\grave")
-  output="\u0300";else if(symbol.input=="\\tilde")
-  output="\u0303";}
-  var node1=AMcreateMmlNode("mo",document.createTextNode(output));if(symbol.input=="\\vec"||symbol.input=="\\check")
-  node1.setAttribute("maxsize","1.2");if(isIE&&symbol.input=="\\bar")
-  node1.setAttribute("maxsize","0.5");if(symbol.input=="\\underbrace"||symbol.input=="\\underline")
-  node1.setAttribute("accentunder","true");else
-  node1.setAttribute("accent","true");node.appendChild(node1);if(symbol.input=="\\overbrace"||symbol.input=="\\underbrace")
-  node.ttype=UNDEROVER;return[node,result[1],symbol.tag];}else{if(!isIE&&typeof symbol.codes!="undefined"){for(i=0;i<result[0].childNodes.length;i++)
-  if(result[0].childNodes[i].nodeName=="mi"||result[0].nodeName=="mi"){st=(result[0].nodeName=="mi"?result[0].firstChild.nodeValue:result[0].childNodes[i].firstChild.nodeValue);var newst=[];for(var j=0;j<st.length;j++)
-  if(st.charCodeAt(j)>64&&st.charCodeAt(j)<91)newst=newst+
-  String.fromCharCode(symbol.codes[st.charCodeAt(j)-65]);else newst=newst+st.charAt(j);if(result[0].nodeName=="mi")
-  result[0]=AMcreateElementMathML("mo").appendChild(document.createTextNode(newst));else result[0].replaceChild(AMcreateElementMathML("mo").appendChild(document.createTextNode(newst)),result[0].childNodes[i]);}}
-  node=AMcreateMmlNode(symbol.tag,result[0]);node.setAttribute(symbol.atname,symbol.atval);if(symbol.input=="\\scriptstyle"||symbol.input=="\\scriptscriptstyle")
-  node.setAttribute("displaystyle","false");return[node,result[1],symbol.tag];}
-  case BINARY:result=AMparseSexpr(str);if(result[0]==null)return[AMcreateMmlNode("mo",document.createTextNode(symbol.input)),str,null];result2=AMparseSexpr(result[1]);if(result2[0]==null)return[AMcreateMmlNode("mo",document.createTextNode(symbol.input)),str,null];if(symbol.input=="\\textcolor"||symbol.input=="\\colorbox"){var tclr=str.match(/\{\s*([#\w]+)\s*\}/);str=str.replace(/\{\s*[#\w]+\s*\}/,"");if(tclr!=null){if(IsColorName.test(tclr[1].toLowerCase())){tclr=LaTeXColor[tclr[1].toLowerCase()];}else{tclr=tclr[1];}
-  node=AMcreateElementMathML("mstyle");node.setAttribute(symbol.atval,tclr);node.appendChild(result2[0]);return[node,result2[1],symbol.tag];}}
-  if(symbol.input=="\\root"||symbol.input=="\\stackrel")newFrag.appendChild(result2[0]);newFrag.appendChild(result[0]);if(symbol.input=="\\frac")newFrag.appendChild(result2[0]);return[AMcreateMmlNode(symbol.tag,newFrag),result2[1],symbol.tag];case INFIX:str=AMremoveCharsAndBlanks(str,symbol.input.length);return[AMcreateMmlNode("mo",document.createTextNode(symbol.output)),str,symbol.tag];default:return[AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)),str,symbol.tag];}}
-  function AMparseIexpr(str){var symbol,sym1,sym2,node,result,tag,underover;str=AMremoveCharsAndBlanks(str,0);sym1=AMgetSymbol(str);result=AMparseSexpr(str);node=result[0];str=result[1];tag=result[2];symbol=AMgetSymbol(str);if(symbol.ttype==INFIX){str=AMremoveCharsAndBlanks(str,symbol.input.length);result=AMparseSexpr(str);if(result[0]==null)
-  result[0]=AMcreateMmlNode("mo",document.createTextNode("\u25A1"));str=result[1];tag=result[2];if(symbol.input=="_"||symbol.input=="^"){sym2=AMgetSymbol(str);tag=null;underover=((sym1.ttype==UNDEROVER)||(node.ttype==UNDEROVER));if(symbol.input=="_"&&sym2.input=="^"){str=AMremoveCharsAndBlanks(str,sym2.input.length);var res2=AMparseSexpr(str);str=res2[1];tag=res2[2];node=AMcreateMmlNode((underover?"munderover":"msubsup"),node);node.appendChild(result[0]);node.appendChild(res2[0]);}else if(symbol.input=="_"){node=AMcreateMmlNode((underover?"munder":"msub"),node);node.appendChild(result[0]);}else{node=AMcreateMmlNode((underover?"mover":"msup"),node);node.appendChild(result[0]);}
-  node=AMcreateMmlNode("mrow",node);}else{node=AMcreateMmlNode(symbol.tag,node);if(symbol.input=="\\atop"||symbol.input=="\\choose")
-  node.setAttribute("linethickness","0ex");node.appendChild(result[0]);if(symbol.input=="\\choose")
-  node=AMcreateMmlNode("mfenced",node);}}
-  return[node,str,tag];}
-  function AMparseExpr(str,rightbracket,matrix){var symbol,node,result,i,tag,newFrag=document.createDocumentFragment();do{str=AMremoveCharsAndBlanks(str,0);result=AMparseIexpr(str);node=result[0];str=result[1];tag=result[2];symbol=AMgetSymbol(str);if(node!=undefined){if((tag=="mn"||tag=="mi")&&symbol!=null&&typeof symbol.func=="boolean"&&symbol.func){var space=AMcreateElementMathML("mspace");space.setAttribute("width","0.167em");node=AMcreateMmlNode("mrow",node);node.appendChild(space);}
-  newFrag.appendChild(node);}}while((symbol.ttype!=RIGHTBRACKET)&&symbol!=null&&symbol.output!="");tag=null;if(symbol.ttype==RIGHTBRACKET){if(symbol.input=="\\right"){str=AMremoveCharsAndBlanks(str,symbol.input.length);symbol=AMgetSymbol(str);if(symbol!=null&&symbol.input==".")
-  symbol.invisible=true;if(symbol!=null)
-  tag=symbol.rtag;}
-  if(symbol!=null)
-  str=AMremoveCharsAndBlanks(str,symbol.input.length);var len=newFrag.childNodes.length;if(matrix&&len>0&&newFrag.childNodes[len-1].nodeName=="mrow"&&len>1&&newFrag.childNodes[len-2].nodeName=="mo"&&newFrag.childNodes[len-2].firstChild.nodeValue=="&"){var pos=[];var m=newFrag.childNodes.length;for(i=0;matrix&&i<m;i=i+2){pos[i]=[];node=newFrag.childNodes[i];for(var j=0;j<node.childNodes.length;j++)
-  if(node.childNodes[j].firstChild.nodeValue=="&")
-  pos[i][pos[i].length]=j;}
-  var row,frag,n,k,table=document.createDocumentFragment();for(i=0;i<m;i=i+2){row=document.createDocumentFragment();frag=document.createDocumentFragment();node=newFrag.firstChild;n=node.childNodes.length;k=0;for(j=0;j<n;j++){if(typeof pos[i][k]!="undefined"&&j==pos[i][k]){node.removeChild(node.firstChild);row.appendChild(AMcreateMmlNode("mtd",frag));k++;}else frag.appendChild(node.firstChild);}
-  row.appendChild(AMcreateMmlNode("mtd",frag));if(newFrag.childNodes.length>2){newFrag.removeChild(newFrag.firstChild);newFrag.removeChild(newFrag.firstChild);}
-  table.appendChild(AMcreateMmlNode("mtr",row));}
-  return[table,str];}
-  if(typeof symbol.invisible!="boolean"||!symbol.invisible){node=AMcreateMmlNode("mo",document.createTextNode(symbol.output));newFrag.appendChild(node);}}
-  return[newFrag,str,tag];}
-  function AMparseMath(str){var result,node=AMcreateElementMathML("mstyle");var cclr=str.match(/\\color\s*\{\s*([#\w]+)\s*\}/);str=str.replace(/\\color\s*\{\s*[#\w]+\s*\}/g,"");if(cclr!=null){if(IsColorName.test(cclr[1].toLowerCase())){cclr=LaTeXColor[cclr[1].toLowerCase()];}else{cclr=cclr[1];}
-  node.setAttribute("mathcolor",cclr);}else{if(mathcolor!="")node.setAttribute("mathcolor",mathcolor);};if(mathfontfamily!="")node.setAttribute("fontfamily",mathfontfamily);node.appendChild(AMparseExpr(str.replace(/^\s+/g,""),false,false)[0]);node=AMcreateMmlNode("math",node);if(showasciiformulaonhover)
-  node.setAttribute("title",str.replace(/\s+/g," "));if(false){var fnode=AMcreateElementXHTML("font");fnode.setAttribute("face",mathfontfamily);fnode.appendChild(node);return fnode;}
-  return node;}
-  function AMstrarr2docFrag(arr,linebreaks){var newFrag=document.createDocumentFragment();var expr=false;for(var i=0;i<arr.length;i++){if(expr)newFrag.appendChild(AMparseMath(arr[i]));else{var arri=(linebreaks?arr[i].split("\n\n"):[arr[i]]);newFrag.appendChild(AMcreateElementXHTML("span").appendChild(document.createTextNode(arri[0])));for(var j=1;j<arri.length;j++){newFrag.appendChild(AMcreateElementXHTML("p"));newFrag.appendChild(AMcreateElementXHTML("span").appendChild(document.createTextNode(arri[j])));}}
-  expr=!expr;}
-  return newFrag;}
-  function AMprocessNodeR(n,linebreaks){var mtch,str,arr,frg,i;if(n.childNodes.length==0){if((n.nodeType!=8||linebreaks)&&n.parentNode.nodeName!="form"&&n.parentNode.nodeName!="FORM"&&n.parentNode.nodeName!="textarea"&&n.parentNode.nodeName!="TEXTAREA"&&n.parentNode.nodeName!="pre"&&n.parentNode.nodeName!="PRE"){str=n.nodeValue;if(!(str==null)){str=str.replace(/\r\n\r\n/g,"\n\n");str=str.replace(/\x20+/g," ");str=str.replace(/\s*\r\n/g," ");mtch=(str.indexOf("\$")==-1?false:true);str=str.replace(/([^\\])\$/g,"$1 \$");str=str.replace(/^\$/," \$");arr=str.split(" \$");for(i=0;i<arr.length;i++)
-  arr[i]=arr[i].replace(/\\\$/g,"\$");if(arr.length>1||mtch){if(checkForMathML){checkForMathML=false;var nd=AMisMathMLavailable();AMnoMathML=nd!=null;if(AMnoMathML&&notifyIfNoMathML)
-  if(alertIfNoMathML)
-  alert("To view the ASCIIMathML notation use Internet Explorer 6 +\nMathPlayer (free from www.dessci.com)\nor Firefox/Mozilla/Netscape");else AMbody.insertBefore(nd,AMbody.childNodes[0]);}
-  if(!AMnoMathML){frg=AMstrarr2docFrag(arr,n.nodeType==8);var len=frg.childNodes.length;n.parentNode.replaceChild(frg,n);return len-1;}else return 0;}}}else return 0;}else if(n.nodeName!="math"){for(i=0;i<n.childNodes.length;i++)
-  i+=AMprocessNodeR(n.childNodes[i],linebreaks);}
-  return 0;}
-  function AMprocessNode(n,linebreaks,spanclassAM){var frag,st;if(spanclassAM!=null){frag=document.getElementsByTagName("span")
-  for(var i=0;i<frag.length;i++)
-  if(frag[i].className=="AM")
-  AMprocessNodeR(frag[i],linebreaks);}else{try{st=n.innerHTML;}catch(err){}
-  if(st==null||st.indexOf("\$")!=-1)
-  AMprocessNodeR(n,linebreaks);}
-  if(isIE){frag=document.getElementsByTagName('math');for(var i=0;i<frag.length;i++)frag[i].update()}}
-  var inAppendix=false;var sectionCntr=0;var IEcommentWarning=true;var biblist=[];var bibcntr=0;var LaTeXCounter=[];LaTeXCounter["definition"]=0;LaTeXCounter["proposition"]=0;LaTeXCounter["lemma"]=0;LaTeXCounter["theorem"]=0;LaTeXCounter["corollary"]=0;LaTeXCounter["example"]=0;LaTeXCounter["exercise"]=0;LaTeXCounter["subsection"]=0;LaTeXCounter["subsubsection"]=0;LaTeXCounter["figure"]=0;LaTeXCounter["equation"]=0;LaTeXCounter["table"]=0;var LaTeXColor=[];LaTeXColor["greenyellow"]="#D9FF4F";LaTeXColor["yellow"]="#FFFF00";LaTeXColor["goldenrod"]="#FFE529";LaTeXColor["dandelion"]="#FFB529";LaTeXColor["apricot"]="#FFAD7A";LaTeXColor["peach"]="#FF804D";LaTeXColor["melon"]="#FF8A80";LaTeXColor["yelloworange"]="#FF9400";LaTeXColor["orange"]="#FF6321";LaTeXColor["burntorange"]="#FF7D00";LaTeXColor["bittersweet"]="#C20300";LaTeXColor["redorange"]="#FF3B21";LaTeXColor["mahogany"]="#A60000";LaTeXColor["maroon"]="#AD0000";LaTeXColor["brickred"]="#B80000";LaTeXColor["red"]="#FF0000";LaTeXColor["orangered"]="#FF0080";LaTeXColor["rubinered"]="#FF00DE";LaTeXColor["wildstrawberry"]="#FF0A9C";LaTeXColor["salmon"]="#FF789E";LaTeXColor["carnationpink"]="#FF5EFF";LaTeXColor["magenta"]="#FF00FF";LaTeXColor["violetred"]="#FF30FF";LaTeXColor["rhodamine"]="#FF2EFF";LaTeXColor["mulberry"]="#A314FA";LaTeXColor["redviolet"]="#9600A8";LaTeXColor["fuchsia"]="#7303EB";LaTeXColor["lavender"]="#FF85FF";LaTeXColor["thistle"]="#E069FF";LaTeXColor["orchid"]="#AD5CFF";LaTeXColor["darkorchid"]="#9933CC";LaTeXColor["purple"]="#8C24FF";LaTeXColor["plum"]="#8000FF";LaTeXColor["violet"]="#361FFF";LaTeXColor["royalpurple"]="#401AFF";LaTeXColor["blueviolet"]="#1A0DF5";LaTeXColor["periwinkle"]="#6E73FF";LaTeXColor["cadetblue"]="#616EC4";LaTeXColor["cornflowerblue"]="#59DEFF";LaTeXColor["midnightblue"]="#007091";LaTeXColor["navyblue"]="#0F75FF";LaTeXColor["royalblue"]="#0080FF";LaTeXColor["blue"]="#0000FF";LaTeXColor["cerulean"]="#0FE3FF";LaTeXColor["cyan"]="#00FFFF";LaTeXColor["processblue"]="#0AFFFF";LaTeXColor["skyblue"]="#61FFE0";LaTeXColor["turquoise"]="#26FFCC";LaTeXColor["tealblue"]="#1FFAA3";LaTeXColor["aquamarine"]="#2EFFB2";LaTeXColor["bluegreen"]="#26FFAB";LaTeXColor["emerald"]="#00FF80";LaTeXColor["junglegreen"]="#03FF7A";LaTeXColor["seagreen"]="#4FFF80";LaTeXColor["green"]="#00FF00";LaTeXColor["forestgreen"]="#00E000";LaTeXColor["pinegreen"]="#00BF29";LaTeXColor["limegreen"]="#80FF00";LaTeXColor["yellowgreen"]="#8FFF42";LaTeXColor["springgreen"]="#BDFF3D";LaTeXColor["olivegreen"]="#009900";LaTeXColor["rawsienna"]="#8C0000";LaTeXColor["sepia"]="#4D0000";LaTeXColor["brown"]="#660000";LaTeXColor["tan"]="#DB9470";LaTeXColor["gray"]="#808080";LaTeXColor["grey"]="#808080";LaTeXColor["black"]="#000000";LaTeXColor["white"]="#FFFFFF";var IsColorName=/^(?:greenyellow|yellow|goldenrod|dandelion|apricot|peach|melon|yelloworange|orange|burntorange|bittersweet|redorange|mahogany|maroon|brickred|red|orangered|rubinered|wildstrawberry|salmon|carnationpink|magenta|violetred|rhodamine|mulberry|redviolet|fuchsia|lavender|thistle|orchid|darkorchid|purple|plum|violet|royalpurple|blueviolet|periwinkle|cadetblue|cornflowerblue|midnightblue|navyblue|royalblue|blue|cerulean|cyan|processblue|skyblue|turquoise|tealblue|aquamarine|bluegreen|emerald|junglegreen|seagreen|green|forestgreen|pinegreen|limegreen|yellowgreen|springgreen|olivegreen|rawsienna|sepia|brown|tan|gray|grey|black|white)$/;var IsCounter=/^(?:definition|proposition|lemma|theorem|corollary|example|exercise|subsection|subsubsection|figure|equation|table)$/;var IsLaTeXElement=/^(?:displayequation|title|author|address|date|abstract|keyword|section|subsection|subsubsection|ref|cite|thebibliography|definition|proposition|lemma|theorem|corollary|example|exercise|itemize|enumerate|enddefinition|endproposition|endlemma|endtheorem|endcorollary|endexample|endexercise|enditemize|endenumerate|LaTeXMathMLlabel|LaTeXMathML|smallskip|medskip|bigskip|quote|quotation|endquote|endquotation|center|endcenter|description|enddescription|inlinemath)$/;var IsTextOnlyArea=/^(?:form|textarea|pre)$/i;var tableid=0;function makeNumberString(cntr){if(sectionCntr>0){if(inAppendix){return"A"+sectionCntr+"."+cntr;}else{return sectionCntr+"."+cntr;}}else{return""+cntr;}};function LaTeXpreProcess(thebody){var TheBody=thebody;if(TheBody.hasChildNodes()){if(!(IsLaTeXElement.test(TheBody.className)))
-  {for(var i=0;i<TheBody.childNodes.length;i++){LaTeXpreProcess(TheBody.childNodes[i])}}}
-  else{if(TheBody.nodeType==3&&!(IsTextOnlyArea.test(TheBody.parentNode.nodeName)))
-  {var str=TheBody.nodeValue;if(!(str==null)){str=str.replace(/\\%/g,"<per>");str=str.replace(/%[^\n]*(?=\n)/g,"");str=str.replace(/%[^\r]*(?=\r)/g,"");str=str.replace(/%[^\n]*$/,"")
-  if(isIE&&str.match(/%/g)!=null&&IEcommentWarning){alert("Comments may not have parsed properly.  Try putting in <pre class='LaTeX><div>..</div></pre> structure.");IEcommentWarning=false;}
-  str=str.replace(/<per>/g,"%");if(str.match(/XXX[\s\S]*/)!=null){var tmp=str.match(/XXX[\s\S]*/)[0];var tmpstr=tmp.charCodeAt(7)+"::"+tmp.charCodeAt(8)+"::"+tmp.charCodeAt(9)+"::"+tmp.charCodeAt(10)+"::"+tmp.charCodeAt(11)+"::"+tmp.charCodeAt(12)+"::"+tmp.charCodeAt(13);alert(tmpstr);}
-  str=str.replace(/([^\\])\\(\s)/g,"$1\u00A0$2");str=str.replace(/\\quad/g,"\u2001");str=str.replace(/\\qquad/g,"\u2001\u2001");str=str.replace(/\\enspace/g,"\u2002");str=str.replace(/\\;/g,"\u2004");str=str.replace(/\\:/g,"\u2005");str=str.replace(/\\,/g,"\u2006");str=str.replace(/\\thinspace/g,"\u200A");str=str.replace(/([^\\])~/g,"$1\u00A0");str=str.replace(/\\~/g,"~");str=str.replace(/\\\[/g," <DEQ> $\\displaystyle{");str=str.replace(/\\\]/g,"}$ <DEQ> ");str=str.replace(/\$\$/g,"${$<DEQ>$}$");str=str.replace(/\\begin\s*\{\s*array\s*\}/g,"\\begin{array}");str=str.replace(/\\end\s*\{\s*array\s*\}/g,"\\end{array}");str=str.replace(/\\begin\s*\{\s*eqnarray\s*\}/g,"  <DEQ>eqno$\\begin{eqnarray}");str=str.replace(/\\end\s*\{\s*eqnarray\s*\}/g,"\\end{eqnarray}$<DEQ>  ");str=str.replace(/\\begin\s*\{\s*eqnarray\*\s*\}/g,"  <DEQ>$\\begin{eqnarray}");str=str.replace(/\\end\s*\{\s*eqnarray\*\s*\}/g,"\\end{eqnarray}$<DEQ>  ");str=str.replace(/\\begin\s*\{\s*displaymath\s*\}/g," <DEQ> $\\displaystyle{");str=str.replace(/\\end\s*\{\s*displaymath\s*\}/g,"}$ <DEQ> ");str=str.replace(/\\begin\s*\{\s*equation\s*\*\s*\}/g," <DEQ> $\\displaystyle{");str=str.replace(/\\end\s*\{\s*equation\s*\*\s*\}/g,"}$ <DEQ> ");str=str.replace(/\\begin\s*\{\s*equation\s*\}/g," <DEQ>eqno$\\displaystyle{");str=str.replace(/\\end\s*\{\s*equation\s*\}/g,"}$ <DEQ> ");str=str.split("<DEQ>");var newFrag=document.createDocumentFragment();for(var i=0;i<str.length;i++){if(i%2){var DEQtable=document.createElement("table");DEQtable.className='displayequation';var DEQtbody=document.createElement("tbody");var DEQtr=document.createElement("tr");var DEQtdeq=document.createElement("td");DEQtdeq.className='eq';str[i]=str[i].replace(/\$\}\$/g,"$\\displaystyle{");str[i]=str[i].replace(/\$\{\$/g,"}");var lbl=str[i].match(/\\label\s*\{\s*(\w+)\s*\}/);var ISeqno=str[i].match(/^eqno/);str[i]=str[i].replace(/^eqno/," ");str[i]=str[i].replace(/\\label\s*\{\s*\w+\s*\}/," ");DEQtdeq.appendChild(document.createTextNode(str[i]));DEQtr.appendChild(DEQtdeq);str[i]=str[i].replace(/\\nonumber/g,"");if(ISeqno!=null||lbl!=null){var DEQtdno=document.createElement("td");DEQtdno.className='eqno';LaTeXCounter["equation"]++;var eqnoString=makeNumberString(LaTeXCounter["equation"]);var DEQanchor=document.createElement("a");if(lbl!=null){DEQanchor.id=lbl[1]};DEQanchor.className="eqno";var anchorSpan=document.createElement("span");anchorSpan.className="eqno";anchorSpan.style.display="none";anchorSpan.appendChild(document.createTextNode(eqnoString));DEQanchor.appendChild(anchorSpan);DEQtdno.appendChild(DEQanchor);var DEQspan=document.createElement("span");DEQspan.className="eqno";DEQspan.appendChild(document.createTextNode("("+eqnoString+")"));DEQtdno.appendChild(DEQspan);DEQtr.appendChild(DEQtdno);}
-  DEQtbody.appendChild(DEQtr);DEQtable.appendChild(DEQtbody);newFrag.appendChild(DEQtable);}
-  else{str[i]=str[i].replace(/\$\}\$/g,"");str[i]=str[i].replace(/\$\{\$/g,"");str[i]=str[i].replace(/\\maketitle/g,"");str[i]=str[i].replace(/\\begin\s*\{\s*document\s*\}/g,"");str[i]=str[i].replace(/\\end\s*\{\s*document\s*\}/g,"");str[i]=str[i].replace(/\\documentclass[^\}]*?\}/g,"");str[i]=str[i].replace(/\\usepackage[^\}]*?\}/g,"");str[i]=str[i].replace(/\\noindent/g,"");str[i]=str[i].replace(/\\notag/g,"");str[i]=str[i].replace(/\\ref\s*\{\s*(\w+)\}/g," \\[ref\\]$1\\[ ");str[i]=str[i].replace(/\\url\s*\{\s*([^\}\n]+)\}/g," \\[url\\]$1\\[ ");str[i]=str[i].replace(/\\href\s*\{\s*([^\}]+)\}\s*\{\s*([^\}]+)\}/g," \\[href\\]$1\\]$2\\[ ");str[i]=str[i].replace(/\\cite\s*\{\s*(\w+)\}/g," \\[cite\\]$1\\[ ");str[i]=str[i].replace(/\\qed/g,"\u220E");str[i]=str[i].replace(/\\endproof/g,"\u220E");str[i]=str[i].replace(/\\proof/g,"\\textbf{Proof: }");str[i]=str[i].replace(/\\n(?=\s)/g," \\[br\\] \\[ ");str[i]=str[i].replace(/\\newline/g," \\[br\\] \\[ ");str[i]=str[i].replace(/\\linebreak/g," \\[br\\] \\[ ");str[i]=str[i].replace(/\\smallskip/g," \\[logicalbreak\\]smallskip\\[ ");str[i]=str[i].replace(/\\medskip/g," \\[logicalbreak\\]medskip\\[ ");str[i]=str[i].replace(/\\bigskip/g," \\[logicalbreak\\]bigskip\\[ ");str[i]=str[i].replace(/[\n\r]+[ \f\n\r\t\v\u2028\u2029]*[\n\r]+/g," \\[logicalbreak\\]LaTeXMathML\\[ ");if(isIE){str[i]=str[i].replace(/\r/g," ");}
-  str[i]=str[i].replace(/\\bibitem\s*([^\{]*\{\s*\w*\s*\})/g," \\[bibitem\\]$1\\[ ");str[i]=str[i].replace(/\\bibitem\s*/g," \\[bibitem\\] \\[ ");str[i]=str[i].replace(/\\item\s*\[\s*(\w+)\s*\]/g," \\[alistitem\\]$1\\[ ");str[i]=str[i].replace(/\\item\s*/g," \\[alistitem\\] \\[ ");str[i]=str[i].replace(/\\appendix/g," \\[appendix\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*figure\s*\}([\s\S]+?)\\end\s*\{\s*figure\s*\}/g," \\[figure\\]$1\\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*table\s*\}([\s\S]+?)\\end\s*\{\s*table\s*\}/g," \\[table\\]$1\\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*theorem\s*\}/g," \\[theorem\\]Theorem \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*theorem\s*\}/g," \\[endtheorem\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*definition\s*\}/g," \\[definition\\]Definition \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*definition\s*\}/g," \\[enddefinition\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*lemma\s*\}/g," \\[lemma\\]Lemma \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*lemma\s*\}/g," \\[endlemma\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*corollary\s*\}/g," \\[corollary\\]Corollary \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*corollary\s*\}/g," \\[endcorollary\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*proposition\s*\}/g," \\[proposition\\]Proposition \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*proposition\s*\}/g," \\[endproposition\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*example\s*\}/g," \\[example\\]Example \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*example\s*\}/g," \\[endexample\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*exercise\s*\}/g," \\[exercise\\]Exercise \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*exercise\s*\}/g," \\[endexercise\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*thebibliography\s*\}\s*\{\s*\w+\s*\}/g," \\[thebibliography\\]References \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*thebibliography\s*\}/g," \\[thebibliography\\]References \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*thebibliography\s*\}/g," \\[endthebibliography\\]References \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*proof\s*\}/g," \\[proof\\]Proof: \\[ ");if(isIE){str[i]=str[i].replace(/\\end\s*\{\s*proof\s*\}/g,"\u220E \\[endproof\\] \\[ ");}else{str[i]=str[i].replace(/\\end\s*\{\s*proof\s*\}/g," \\[endproof\\] \\[ ");}
-  str[i]=str[i].replace(/\\title\s*\{\s*([^\}]+)\}/g," \\[title\\] \\[$1 \\[endtitle\\] \\[ ");str[i]=str[i].replace(/\\author\s*\{\s*([^\}]+)\}/g," \\[author\\] \\[$1 \\[endauthor\\] \\[ ");str[i]=str[i].replace(/\\address\s*\{\s*([^\}]+)\}/g," \\[address\\] \\[$1 \\[endaddress\\] \\[ ");str[i]=str[i].replace(/\\date\s*\{\s*([^\}]+)\}/g," \\[date\\] \\[$1 \\[enddate\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*keyword\s*\}/g," \\[keyword\\] \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*keyword\s*\}/g," \\[endkeyword\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*abstract\s*\}/g," \\[abstract\\] \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*abstract\s*\}/g," \\[endabstract\\] \\[ ");str[i]=str[i].replace(/\\begin\s*\{\s*(?!array|tabular)(\w+)\s*\}/g," \\[$1\\] \\[ ");str[i]=str[i].replace(/\\end\s*\{\s*(?!array|tabular)(\w+)\s*\}/g," \\[end$1\\] \\[ ");var sectionIndex=str[i].search(/\\section\s*\{\s*[\s\S]+\}/);while(sectionIndex>=0){str[i]=str[i].replace(/\\section\s*\{/," \\[section\\]");var delimcnt=1;for(var ii=sectionIndex;ii<str[i].length;ii++){if(str[i].charAt(ii)=="{"){delimcnt++};if(str[i].charAt(ii)=="}"){delimcnt--};if(delimcnt==0){str[i]=str[i].substring(0,ii)+"\\[ "+str[i].substring(ii+1,str[i].length);break;}};sectionIndex=str[i].search(/\\section\s*\{\s*[\s\S]+\}/);}
-  sectionIndex=str[i].search(/\\subsection\s*\{\s*[\s\S]+\}/);while(sectionIndex>=0){str[i]=str[i].replace(/\\subsection\s*\{/," \\[subsection\\]");var delimcnt=1;for(var ii=sectionIndex;ii<str[i].length;ii++){if(str[i].charAt(ii)=="{"){delimcnt++};if(str[i].charAt(ii)=="}"){delimcnt--};if(delimcnt==0){str[i]=str[i].substring(0,ii)+"\\[ "+str[i].substring(ii+1,str[i].length);break;}};sectionIndex=str[i].search(/\\subsection\s*\{\s*[\s\S]+\}/);}
-  sectionIndex=str[i].search(/\\subsubsection\s*\{\s*[\s\S]+\}/);while(sectionIndex>=0){str[i]=str[i].replace(/\\subsubsection\s*\{/," \\[subsubsection\\]");var delimcnt=1;for(var ii=sectionIndex;ii<str[i].length;ii++){if(str[i].charAt(ii)=="{"){delimcnt++};if(str[i].charAt(ii)=="}"){delimcnt--};if(delimcnt==0){str[i]=str[i].substring(0,ii)+"\\[ "+str[i].substring(ii+1,str[i].length);break;}};sectionIndex=str[i].search(/\\subsubsection\s*\{\s*[\s\S]+\}/);}
-  var CatToNextEven="";var strtmp=str[i].split("\\[");for(var j=0;j<strtmp.length;j++){if(j%2){var strtmparray=strtmp[j].split("\\]");switch(strtmparray[0]){case"section":var nodeTmp=document.createElement("H2");nodeTmp.className='section';sectionCntr++;for(var div in LaTeXCounter){LaTeXCounter[div]=0};var nodeAnchor=document.createElement("a");if(inAppendix){nodeAnchor.className='appendixsection';}else{nodeAnchor.className='section';}
-  var nodeNumString=makeNumberString("");var anchorSpan=document.createElement("span");anchorSpan.className="section";anchorSpan.style.display="none";anchorSpan.appendChild(document.createTextNode(nodeNumString));nodeAnchor.appendChild(anchorSpan);nodeTmp.appendChild(nodeAnchor);var nodeSpan=document.createElement("span");nodeSpan.className='section';nodeSpan.appendChild(document.createTextNode(nodeNumString+" "));nodeTmp.appendChild(nodeSpan);nodeTmp.appendChild(document.createTextNode(strtmparray[1]));newFrag.appendChild(nodeTmp);break;case"subsection":var nodeTmp=document.createElement("H3");nodeTmp.className='subsection';LaTeXCounter["subsection"]++;LaTeXCounter["subsubsection"]=0;var nodeAnchor=document.createElement("a");nodeAnchor.className='subsection';var nodeNumString=makeNumberString(LaTeXCounter["subsection"]);var anchorSpan=document.createElement("span");anchorSpan.className="subsection";anchorSpan.style.display="none";anchorSpan.appendChild(document.createTextNode(nodeNumString));nodeAnchor.appendChild(anchorSpan);nodeTmp.appendChild(nodeAnchor);var nodeSpan=document.createElement("span");nodeSpan.className='subsection';nodeSpan.appendChild(document.createTextNode(nodeNumString+". "));nodeTmp.appendChild(nodeSpan);nodeTmp.appendChild(document.createTextNode(strtmparray[1]));newFrag.appendChild(nodeTmp);break;case"subsubsection":var nodeTmp=document.createElement("H4");nodeTmp.className='subsubsection';LaTeXCounter["subsubsection"]++;var nodeAnchor=document.createElement("a");nodeAnchor.className='subsubsection';var nodeNumString=makeNumberString(LaTeXCounter["subsection"]+"."+LaTeXCounter["subsubsection"]);var anchorSpan=document.createElement("span");anchorSpan.className="subsubsection";anchorSpan.style.display="none";anchorSpan.appendChild(document.createTextNode(nodeNumString));nodeAnchor.appendChild(anchorSpan);nodeTmp.appendChild(nodeAnchor);var nodeSpan=document.createElement("span");nodeSpan.className='subsubsection';nodeSpan.appendChild(document.createTextNode(nodeNumString+". "));nodeTmp.appendChild(nodeSpan);nodeTmp.appendChild(document.createTextNode(strtmparray[1]));newFrag.appendChild(nodeTmp);break;case"href":var nodeTmp=document.createElement("a");nodeTmp.className='LaTeXMathML';nodeTmp.href=strtmparray[1];nodeTmp.appendChild(document.createTextNode(strtmparray[2]));newFrag.appendChild(nodeTmp);break;case"url":var nodeTmp=document.createElement("a");nodeTmp.className='LaTeXMathML';nodeTmp.href=strtmparray[1];nodeTmp.appendChild(document.createTextNode(strtmparray[1]));newFrag.appendChild(nodeTmp);break;case"figure":var nodeTmp=document.createElement("table");nodeTmp.className='figure';var FIGtbody=document.createElement("tbody");var FIGlbl=strtmparray[1].match(/\\label\s*\{\s*(\w+)\s*\}/);strtmparray[1]=strtmparray[1].replace(/\\label\s*\{\w+\}/g,"");var capIndex=strtmparray[1].search(/\\caption\s*\{[\s\S]+\}/);var FIGcap="";if(capIndex>=0){var tmp=strtmparray[1];var delimcnt=0;var capstart=-1;for(var pos=capIndex;pos<tmp.length;pos++){if(tmp.charAt(pos)=="{"){delimcnt++};if(tmp.charAt(pos)=="}"){delimcnt--};if(delimcnt==1&&capstart<0){capstart=pos+1};if(delimcnt==0&&capstart>0){capend=pos-1;FIGcap=tmp.substring(capstart,pos);break}}}
-  var FIGtr2=document.createElement("tr");var FIGtd2=document.createElement("td");FIGtd2.className="caption";var FIGanchor=document.createElement("a");FIGanchor.className="figure";if(FIGlbl!=null){FIGanchor.id=FIGlbl[1];}
-  LaTeXCounter["figure"]++;var fignmbr=makeNumberString(LaTeXCounter["figure"]);var anchorSpan=document.createElement("span");anchorSpan.className="figure";anchorSpan.style.display="none";anchorSpan.appendChild(document.createTextNode(fignmbr));FIGanchor.appendChild(anchorSpan);FIGtd2.appendChild(FIGanchor);var FIGspan=document.createElement("span");FIGspan.className="figure";FIGspan.appendChild(document.createTextNode("Figure "+fignmbr+". "));FIGtd2.appendChild(FIGspan);FIGtd2.appendChild(document.createTextNode(""+FIGcap));FIGtr2.appendChild(FIGtd2);FIGtbody.appendChild(FIGtr2);var IsSpecial=false;var FIGinfo=strtmparray[1].match(/\\includegraphics\s*\{([^\}]+)\}/);if(FIGinfo==null){FIGinfo=strtmparray[1].match(/\\includegraphics\s*\[[^\]]*\]\s*\{\s*([^\}]+)\s*\}/);}
-  if(FIGinfo==null){FIGinfo=strtmparray[1].match(/\\special\s*\{\s*([^\}]+)\}/);IsSpecial=true};if(FIGinfo!=null){var FIGtr1=document.createElement("tr");var FIGtd1=document.createElement("td");FIGtd1.className="image";var FIGimg=document.createElement("img");var FIGsrc=FIGinfo[1];FIGimg.src=FIGsrc;FIGimg.alt="Figure "+FIGsrc+" did not load";FIGimg.title="Figure "+fignmbr+". "+FIGcap;FIGimg.id="figure"+fignmbr;FIGtd1.appendChild(FIGimg);FIGtr1.appendChild(FIGtd1);FIGtbody.appendChild(FIGtr1);}
-  nodeTmp.appendChild(FIGtbody);newFrag.appendChild(nodeTmp);break;case"table":var nodeTmp=document.createElement("table");if(strtmparray[1].search(/\\centering/)>=0){nodeTmp.className='LaTeXtable centered';nodeTmp.align="center";}else{nodeTmp.className='LaTeXtable';};tableid++;nodeTmp.id="LaTeXtable"+tableid;var TABlbl=strtmparray[1].match(/\\label\s*\{\s*(\w+)\s*\}/);strtmparray[1]=strtmparray[1].replace(/\\label\s*\{\w+\}/g,"");var capIndex=strtmparray[1].search(/\\caption\s*\{[\s\S]+\}/);var TABcap="";if(capIndex>=0){var tmp=strtmparray[1];var delimcnt=0;var capstart=-1;for(var pos=capIndex;pos<tmp.length;pos++){if(tmp.charAt(pos)=="{"){delimcnt++};if(tmp.charAt(pos)=="}"){delimcnt--};if(delimcnt==1&&capstart<0){capstart=pos+1};if(delimcnt==0&&capstart>0){capend=pos-1;TABcap=tmp.substring(capstart,pos);break}}}
-  if(TABcap!=""){var TABtbody=document.createElement("tbody");var TABcaption=document.createElement("caption");TABcaption.className="LaTeXtable centered";var TABanchor=document.createElement("a");TABanchor.className="LaTeXtable";if(TABlbl!=null){TABanchor.id=TABlbl[1];}
-  LaTeXCounter["table"]++;var tabnmbr=makeNumberString(LaTeXCounter["table"]);var anchorSpan=document.createElement("span");anchorSpan.className="LaTeXtable";anchorSpan.style.display="none";anchorSpan.appendChild(document.createTextNode(tabnmbr));TABanchor.appendChild(anchorSpan);TABcaption.appendChild(TABanchor);var TABspan=document.createElement("span");TABspan.className="LaTeXtable";TABspan.appendChild(document.createTextNode("Table "+tabnmbr+". "));TABcaption.appendChild(TABspan);TABcaption.appendChild(document.createTextNode(""+TABcap));nodeTmp.appendChild(TABcaption);}
-  var TABinfo=strtmparray[1].match(/\\begin\s*\{\s*tabular\s*\}([\s\S]+)\\end\s*\{\s*tabular\s*\}/);if(TABinfo!=null){var TABtbody=document.createElement('tbody');var TABrow=null;var TABcell=null;var row=0;var col=0;var TABalign=TABinfo[1].match(/^\s*\{([^\}]+)\}/);TABinfo=TABinfo[1].replace(/^\s*\{[^\}]+\}/,"");TABinfo=TABinfo.replace(/\\hline/g,"");TABalign[1]=TABalign[1].replace(/\|/g,"");TABalign[1]=TABalign[1].replace(/\s/g,"");TABinfo=TABinfo.split("\\\\");for(row=0;row<TABinfo.length;row++){TABrow=document.createElement("tr");TABinfo[row]=TABinfo[row].split("&");for(col=0;col<TABinfo[row].length;col++){TABcell=document.createElement("td");switch(TABalign[1].charAt(col)){case"l":TABcell.align="left";break;case"c":TABcell.align="center";break;case"r":TABcell.align="right";break;default:TABcell.align="left";};TABcell.appendChild(document.createTextNode(TABinfo[row][col]));TABrow.appendChild(TABcell);}
-  TABtbody.appendChild(TABrow);}
-  nodeTmp.appendChild(TABtbody);}
-  newFrag.appendChild(nodeTmp);break;case"logicalbreak":var nodeTmp=document.createElement("p");nodeTmp.className=strtmparray[1];nodeTmp.appendChild(document.createTextNode("\u00A0"));newFrag.appendChild(nodeTmp);break;case"appendix":inAppendix=true;sectionCntr=0;break;case"alistitem":var EndDiv=document.createElement("div");EndDiv.className="endlistitem";newFrag.appendChild(EndDiv);var BegDiv=document.createElement("div");BegDiv.className="listitem";if(strtmparray[1]!=" "){var BegSpan=document.createElement("span");BegSpan.className="listitemmarker";var boldBegSpan=document.createElement("b");boldBegSpan.appendChild(document.createTextNode(strtmparray[1]+" "));BegSpan.appendChild(boldBegSpan);BegDiv.appendChild(BegSpan);}
-  newFrag.appendChild(BegDiv);break;case"br":newFrag.appendChild(document.createElement("br"));break;case"bibitem":newFrag.appendChild(document.createElement("br"));var nodeTmp=document.createElement("a");nodeTmp.className='bibitem';var nodeSpan=document.createElement("span");nodeSpan.className='bibitem';bibcntr++;var lbl=strtmparray[1].match(/\{\s*(\w+)\s*\}/);strtmparray[1]=strtmparray[1].replace(/\s*\{\s*\w+\s*\}/g,"");strtmparray[1]=strtmparray[1].replace(/^\s*\[/,"");strtmparray[1]=strtmparray[1].replace(/\s*\]$/,"");strtmparray[1]=strtmparray[1].replace(/^\s+|\s+$/g,"");if(lbl==null){biblist[bibcntr]="bibitem"+bibcntr}else{biblist[bibcntr]=lbl[1];};nodeTmp.name=biblist[bibcntr];nodeTmp.id=biblist[bibcntr];if(strtmparray[1]!=""){nodeSpan.appendChild(document.createTextNode(strtmparray[1]));}else{nodeSpan.appendChild(document.createTextNode("["+bibcntr+"]"));}
-  nodeTmp.appendChild(nodeSpan);newFrag.appendChild(nodeTmp);break;case"cite":var nodeTmp=document.createElement("a");nodeTmp.className='cite';nodeTmp.name='cite';nodeTmp.href="#"+strtmparray[1];newFrag.appendChild(nodeTmp);break;case"ref":var nodeTmp=document.createElement("a");nodeTmp.className='ref';nodeTmp.name='ref';nodeTmp.href="#"+strtmparray[1];newFrag.appendChild(nodeTmp);break;default:var nodeTmp=document.createElement("div");nodeTmp.className=strtmparray[0];if(IsCounter.test(strtmparray[0])){LaTeXCounter[strtmparray[0]]++;var nodeAnchor=document.createElement("a");nodeAnchor.className=strtmparray[0];var divnum=makeNumberString(LaTeXCounter[strtmparray[0]]);var anchorSpan=document.createElement("span");anchorSpan.className=strtmparray[0];anchorSpan.appendChild(document.createTextNode(divnum));anchorSpan.style.display="none";nodeAnchor.appendChild(anchorSpan);nodeTmp.appendChild(nodeAnchor);var nodeSpan=document.createElement("span");nodeSpan.className=strtmparray[0];nodeSpan.appendChild(document.createTextNode(strtmparray[1]+" "+divnum+". "));nodeTmp.appendChild(nodeSpan);}
-  if(isIE){if(strtmparray[0]==("thebibliography"||"abstract"||"keyword"||"proof")){var nodeSpan=document.createElement("span");nodeSpan.className=strtmparray[0];nodeSpan.appendChild(document.createTextNode(strtmparray[1]));nodeTmp.appendChild(nodeSpan);}}
-  if(strtmparray[0]=="endenumerate"||strtmparray[0]=="enditemize"||strtmparray[0]=="enddescription"){var endDiv=document.createElement("div");endDiv.className="endlistitem";newFrag.appendChild(endDiv);}
-  newFrag.appendChild(nodeTmp);if(strtmparray[0]=="enumerate"||strtmparray[0]=="itemize"||strtmparray[0]=="description"){var endDiv=document.createElement("div");endDiv.className="listitem";newFrag.appendChild(endDiv);}}}else{strtmp[j]=strtmp[j].replace(/\\\$/g,"<per>");strtmp[j]=strtmp[j].replace(/\$([^\$]+)\$/g," \\[$1\\[ ");strtmp[j]=strtmp[j].replace(/<per>/g,"\\$");strtmp[j]=strtmp[j].replace(/\\begin\s*\{\s*math\s*\}([\s\S]+?)\\end\s*\{\s*math\s*\}/g," \\[$1\\[ ");var strtmptmp=strtmp[j].split("\\[");for(var jjj=0;jjj<strtmptmp.length;jjj++){if(jjj%2){var nodeTmp=document.createElement("span");nodeTmp.className='inlinemath';nodeTmp.appendChild(document.createTextNode("$"+strtmptmp[jjj]+"$"));newFrag.appendChild(nodeTmp);}else{var TagIndex=strtmptmp[jjj].search(/\\\w+/);var tmpIndex=TagIndex;while(tmpIndex>-1){if(/^\\textcolor/.test(strtmptmp[jjj].substring(TagIndex,strtmptmp[jjj].length))){strtmptmp[jjj]=strtmptmp[jjj].replace(/\\textcolor\s*\{\s*(\w+)\s*\}\s*/," \\[textcolor\\]$1\\]|");}else{if(/^\\colorbox/.test(strtmptmp[jjj].substring(TagIndex,strtmptmp[jjj].length))){strtmptmp[jjj]=strtmptmp[jjj].replace(/\\colorbox\s*\{\s*(\w+)\s*\}\s*/," \\[colorbox\\]$1\\]|");}else{strtmptmp[jjj]=strtmptmp[jjj].substring(0,TagIndex)+strtmptmp[jjj].substring(TagIndex,strtmptmp[jjj].length).replace(/\\\s*(\w+)\s*/," \\[$1\\]|");}}
-  TagIndex+=strtmptmp[jjj].substring(TagIndex,strtmptmp[jjj].length).search(/\|/);TagIndex++;strtmptmp[jjj]=strtmptmp[jjj].replace(/\\\]\|/,"\\] ");if(strtmptmp[jjj].charAt(TagIndex)=="{"){strtmptmp[jjj]=strtmptmp[jjj].substring(0,TagIndex)+strtmptmp[jjj].substring(TagIndex+1,strtmptmp[jjj].length);var delimcnt=1;for(var kk=TagIndex;kk<strtmptmp[jjj].length;kk++){if(strtmptmp[jjj].charAt(kk)=="{"){delimcnt++};if(strtmptmp[jjj].charAt(kk)=="}"){delimcnt--};if(delimcnt==0){break;}}
-  strtmptmp[jjj]=strtmptmp[jjj].substring(0,kk)+"\\[ "+strtmptmp[jjj].substring(kk+1,strtmptmp[jjj].length);TagIndex=kk+3;}else{strtmptmp[jjj]=strtmptmp[jjj].substring(0,TagIndex)+"\\[ "+strtmptmp[jjj].substring(TagIndex+1,strtmptmp[jjj].length);TagIndex=TagIndex+3;}
-  if(TagIndex<strtmptmp[jjj].length){tmpIndex=strtmptmp[jjj].substring(TagIndex,strtmptmp[jjj].length).search(/\\\w+/);}
-  else{tmpIndex=-1};TagIndex+=tmpIndex;}
-  strtmptmp[jjj]=strtmptmp[jjj].replace(/\\\\\s*\\\\/g,"\\\\");strtmptmp[jjj]=strtmptmp[jjj].replace(/\\\\/g," \\[br\\] \\[ ");strtmptmp[jjj]=strtmptmp[jjj].replace(/\\label\s*\{\s*(\w+)\s*\}/g," \\[a\\]$1\\[ ");var strlbls=strtmptmp[jjj].split("\\[");for(var jj=0;jj<strlbls.length;jj++){if(jj%2){var strtmparray=strlbls[jj].split("\\]");switch(strtmparray[0]){case"textcolor":var nodeTmp=document.createElement("span");nodeTmp.className='LaTeXColor';if(IsColorName.test(strtmparray[1].toLowerCase())){nodeTmp.style.color=LaTeXColor[strtmparray[1].toLowerCase()];}else{nodeTmp.style.color=strtmparray[1];};nodeTmp.appendChild(document.createTextNode(strtmparray[2]));newFrag.appendChild(nodeTmp);break;case"colorbox":var nodeTmp=document.createElement("span");nodeTmp.className='LaTeXColor';if(IsColorName.test(strtmparray[1].toLowerCase())){nodeTmp.style.background=LaTeXColor[strtmparray[1].toLowerCase()];}else{nodeTmp.style.background=strtmparray[1];};nodeTmp.appendChild(document.createTextNode(strtmparray[2]));newFrag.appendChild(nodeTmp);break;case"br":newFrag.appendChild(document.createElement("br"));break;case"a":var nodeTmp=document.createElement("a");nodeTmp.className='LaTeXMathMLlabel';nodeTmp.id=strtmparray[1];nodeTmp.style.display="none";newFrag.appendChild(nodeTmp);break;default:var nodeTmp=document.createElement("span");nodeTmp.className=strtmparray[0];nodeTmp.appendChild(document.createTextNode(strtmparray[1]))
-  newFrag.appendChild(nodeTmp);}}else{newFrag.appendChild(document.createTextNode(strlbls[jj]));}}}}}}}};TheBody.parentNode.replaceChild(newFrag,TheBody);}}}
-  return TheBody;}
-  function LaTeXDivsAndRefs(thebody){var TheBody=thebody;var EndDivClass=null;var AllDivs=TheBody.getElementsByTagName("div");var lbl2id="";var lblnode=null;for(var i=AllDivs.length-1;i>=0;i--){EndDivClass=AllDivs[i].className.match(/end\w+/);if(EndDivClass!=null){EndDivClass=EndDivClass[0];var DivClass=EndDivClass.substring(3,EndDivClass.length);var EndDivNode=AllDivs[i];break;}}
-  while(EndDivClass!=null){var newFrag=document.createDocumentFragment();var RootNode=EndDivNode.parentNode;var ClassCount=1;while(EndDivNode.previousSibling!=null&&ClassCount>0){switch(EndDivNode.previousSibling.className){case EndDivClass:ClassCount++;newFrag.insertBefore(EndDivNode.previousSibling,newFrag.firstChild);break;case DivClass:if(EndDivNode.previousSibling.nodeName=="DIV"){ClassCount--;if(lbl2id!=""){EndDivNode.previousSibling.id=lbl2id;lbl2id=""}
-  if(ClassCount==0){RootNode=EndDivNode.previousSibling;}else{newFrag.insertBefore(EndDivNode.previousSibling,newFrag.firstChild);}};break;case'LaTeXMathMLlabel':lbl2id=EndDivNode.previousSibling.id;EndDivNode.parentNode.removeChild(EndDivNode.previousSibling);break;default:newFrag.insertBefore(EndDivNode.previousSibling,newFrag.firstChild);}}
-  RootNode.appendChild(newFrag);EndDivNode.parentNode.removeChild(EndDivNode);AllDivs=TheBody.getElementsByTagName("DIV");for(i=AllDivs.length-1;i>=0;i--){EndDivClass=AllDivs[i].className.match(/end\w+/);if(EndDivClass!=null){ClassCount=0;EndDivClass=EndDivClass[0];DivClass=EndDivClass.substring(3,EndDivClass.length);EndDivNode=AllDivs[i];RootNode=EndDivNode.parentNode;break;}}}
-  var AllDivs=TheBody.getElementsByTagName("div");var DIV2LI=null;for(var i=0;i<AllDivs.length;i++){if(AllDivs[i].className=="itemize"||AllDivs[i].className=="enumerate"||AllDivs[i].className=="description"){if(AllDivs[i].className=="itemize"){RootNode=document.createElement("UL");}else{RootNode=document.createElement("OL");}
-  RootNode.className='LaTeXMathML';if(AllDivs[i].hasChildNodes()){AllDivs[i].removeChild(AllDivs[i].firstChild)};while(AllDivs[i].hasChildNodes()){if(AllDivs[i].firstChild.hasChildNodes()){DIV2LI=document.createElement("LI");while(AllDivs[i].firstChild.hasChildNodes()){DIV2LI.appendChild(AllDivs[i].firstChild.firstChild);}
-  if(DIV2LI.firstChild.className=="listitemmarker"){DIV2LI.style.listStyleType="none";}
-  RootNode.appendChild(DIV2LI)}
-  AllDivs[i].removeChild(AllDivs[i].firstChild);}
-  AllDivs[i].appendChild(RootNode);}}
-  var AllAnchors=TheBody.getElementsByTagName("a");for(var i=0;i<AllAnchors.length;i++){if(AllAnchors[i].className=="ref"||AllAnchors[i].className=="cite"){var label=AllAnchors[i].href.match(/\#(\w+)/);if(label!=null){var labelNode=document.getElementById(label[1]);if(labelNode!=null){var TheSpans=labelNode.getElementsByTagName("SPAN");if(TheSpans!=null){var refNode=TheSpans[0].cloneNode(true);refNode.style.display="inline"
-  refNode.className=AllAnchors[i].className;AllAnchors[i].appendChild(refNode);}}}}}
-  return TheBody;}
-  var AMbody;var AMnoMathML=false,AMtranslated=false;function translate(spanclassAM){if(!AMtranslated){AMtranslated=true;AMinitSymbols();var LaTeXContainers=[];var AllContainers=document.getElementsByTagName('*');var ExtendName="";for(var k=0,l=0;k<AllContainers.length;k++){ExtendName=" "+AllContainers[k].className+" ";if(ExtendName.match(/\sLaTeX\s/)!=null){LaTeXContainers[l]=AllContainers[k];l++;}};if(LaTeXContainers.length>0){for(var m=0;m<LaTeXContainers.length;m++){AMbody=LaTeXContainers[m];try{AMbody=LaTeXDivsAndRefs(LaTeXpreProcess(AMbody));}catch(err){alert("Unknown Error: Defaulting to Original LaTeXMathML");}
-  if(AMbody.tagName=="PRE"){var PreChilds=document.createDocumentFragment();var DivChilds=document.createElement("DIV");while(AMbody.hasChildNodes()){DivChilds.appendChild(AMbody.firstChild);}
-  PreChilds.appendChild(DivChilds);AMbody.parentNode.replaceChild(PreChilds,AMbody);AMbody=DivChilds;}
-  AMprocessNode(AMbody,false,spanclassAM);}}else{AMbody=document.getElementsByTagName("body")[0];try{AMbody=LaTeXDivsAndRefs(LaTeXpreProcess(AMbody));}catch(err){alert("Unknown Error: Defaulting to Original LaTeXMathML");}
-  AMprocessNode(AMbody,false,spanclassAM);}}}
-  if(isIE){document.write("<object id=\"mathplayer\" classid=\"clsid:32F66A20-7614-11D4-BD11-00104BD3F987\"></object>");document.write("<?import namespace=\"m\" implementation=\"#mathplayer\"?>");}
-  function generic()
-  {translate();};if(typeof window.addEventListener!='undefined')
-  {window.addEventListener('load',generic,false);}
-  else if(typeof document.addEventListener!='undefined')
-  {document.addEventListener('load',generic,false);}
-  else if(typeof window.attachEvent!='undefined')
-  {window.attachEvent('onload',generic);}
-  else
-  {if(typeof window.onload=='function')
-  {var existing=onload;window.onload=function()
-  {existing();generic();};}
-  else
-  {window.onload=generic;}}
-  /*]]>*/
-  </script>
+  <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-AMS_CHTML-full" type="text/javascript"></script>
 </head>
 <body>
 <div class="layout">
@@ -254,7 +54,7 @@
 <div id="math" class="slide section level1">
 <h1>Math</h1>
 <ul class="incremental">
-<li><span class="LaTeX">$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$</span></li>
+<li><span class="math inline">\(\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}\)</span></li>
 </ul>
 </div>
 </div>
diff --git a/test/tables-rstsubset.native b/test/tables-rstsubset.native
index 8b7ccdf76..5ea520d7c 100644
--- a/test/tables-rstsubset.native
+++ b/test/tables-rstsubset.native
@@ -53,7 +53,7 @@
   ,[Plain [Str "1"]]
   ,[Plain [Str "1"]]]]
 ,Para [Str "Multiline",Space,Str "table",Space,Str "with",Space,Str "caption:"]
-,Table [Str "Here\8217s",Space,Str "the",Space,Str "caption.",Space,Str "It",Space,Str "may",Space,Str "span",Space,Str "multiple",Space,Str "lines."] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.1375,0.125,0.15,0.325]
+,Table [Str "Here\8217s",Space,Str "the",Space,Str "caption.",Space,Str "It",Space,Str "may",Space,Str "span",Space,Str "multiple",Space,Str "lines."] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.1375,0.125,0.15,0.3375]
  [[Plain [Str "Centered",SoftBreak,Str "Header"]]
  ,[Plain [Str "Left",SoftBreak,Str "Aligned"]]
  ,[Plain [Str "Right",SoftBreak,Str "Aligned"]]
@@ -65,9 +65,9 @@
  ,[[Plain [Str "Second"]]
   ,[Plain [Str "row"]]
   ,[Plain [Str "5.0"]]
-  ,[Plain [Str "Here\8217s",Space,Str "another",Space,Str "one.",SoftBreak,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",SoftBreak,Str "between",Space,Str "rows."]]]]
+  ,[Plain [Str "Here\8217s",Space,Str "another",Space,Str "one.",Space,Str "Note",SoftBreak,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",SoftBreak,Str "rows."]]]]
 ,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "caption:"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.1375,0.125,0.15,0.325]
+,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.1375,0.125,0.15,0.3375]
  [[Plain [Str "Centered",SoftBreak,Str "Header"]]
  ,[Plain [Str "Left",SoftBreak,Str "Aligned"]]
  ,[Plain [Str "Right",SoftBreak,Str "Aligned"]]
@@ -79,7 +79,7 @@
  ,[[Plain [Str "Second"]]
   ,[Plain [Str "row"]]
   ,[Plain [Str "5.0"]]
-  ,[Plain [Str "Here\8217s",Space,Str "another",Space,Str "one.",SoftBreak,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",SoftBreak,Str "between",Space,Str "rows."]]]]
+  ,[Plain [Str "Here\8217s",Space,Str "another",Space,Str "one.",Space,Str "Note",SoftBreak,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",SoftBreak,Str "rows."]]]]
 ,Para [Str "Table",Space,Str "without",Space,Str "column",Space,Str "headers:"]
 ,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [7.5e-2,7.5e-2,7.5e-2,7.5e-2]
  [[]
@@ -99,7 +99,7 @@
   ,[Plain [Str "1"]]
   ,[Plain [Str "1"]]]]
 ,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "column",Space,Str "headers:"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.1375,0.125,0.15,0.325]
+,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.1375,0.125,0.15,0.3375]
  [[]
  ,[]
  ,[]
@@ -111,4 +111,4 @@
  ,[[Plain [Str "Second"]]
   ,[Plain [Str "row"]]
   ,[Plain [Str "5.0"]]
-  ,[Plain [Str "Here\8217s",Space,Str "another",Space,Str "one.",SoftBreak,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",SoftBreak,Str "between",Space,Str "rows."]]]]]
+  ,[Plain [Str "Here\8217s",Space,Str "another",Space,Str "one.",Space,Str "Note",SoftBreak,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",SoftBreak,Str "rows."]]]]]
diff --git a/test/tables.asciidoc b/test/tables.asciidoc
index 91490a27a..75632157e 100644
--- a/test/tables.asciidoc
+++ b/test/tables.asciidoc
@@ -33,7 +33,7 @@ Simple table indented two spaces:
 Multiline table with caption:
 
 .Here’s the caption. It may span multiple lines.
-[width="78%",cols="^21%,<17%,>20%,<42%",options="header",]
+[width="80%",cols="^20%,<17%,>20%,<43%",options="header",]
 |=======================================================================
 |Centered Header |Left Aligned |Right Aligned |Default aligned
 |First |row |12.0 |Example of a row that spans multiple lines.
@@ -42,7 +42,7 @@ Multiline table with caption:
 
 Multiline table without caption:
 
-[width="78%",cols="^21%,<17%,>20%,<42%",options="header",]
+[width="80%",cols="^20%,<17%,>20%,<43%",options="header",]
 |=======================================================================
 |Centered Header |Left Aligned |Right Aligned |Default aligned
 |First |row |12.0 |Example of a row that spans multiple lines.
@@ -60,7 +60,7 @@ Table without column headers:
 
 Multiline table without column headers:
 
-[width="78%",cols="^21%,<17%,>20%,42%",]
+[width="80%",cols="^20%,<17%,>20%,43%",]
 |=======================================================================
 |First |row |12.0 |Example of a row that spans multiple lines.
 |Second |row |5.0 |Here’s another one. Note the blank line between rows.
diff --git a/test/tables.context b/test/tables.context
index 11dffc065..556d2c216 100644
--- a/test/tables.context
+++ b/test/tables.context
@@ -118,7 +118,7 @@ Multiline table with caption:
 \startxcell[align=middle,width={0.15\textwidth}] Centered Header \stopxcell
 \startxcell[align=right,width={0.14\textwidth}] Left Aligned \stopxcell
 \startxcell[align=left,width={0.16\textwidth}] Right Aligned \stopxcell
-\startxcell[align=right,width={0.34\textwidth}] Default aligned \stopxcell
+\startxcell[align=right,width={0.35\textwidth}] Default aligned \stopxcell
 \stopxrow
 \stopxtablehead
 \startxtablebody[body]
@@ -126,7 +126,7 @@ Multiline table with caption:
 \startxcell[align=middle,width={0.15\textwidth}] First \stopxcell
 \startxcell[align=right,width={0.14\textwidth}] row \stopxcell
 \startxcell[align=left,width={0.16\textwidth}] 12.0 \stopxcell
-\startxcell[align=right,width={0.34\textwidth}] Example of a row that spans
+\startxcell[align=right,width={0.35\textwidth}] Example of a row that spans
 multiple lines. \stopxcell
 \stopxrow
 \stopxtablebody
@@ -135,7 +135,7 @@ multiple lines. \stopxcell
 \startxcell[align=middle,width={0.15\textwidth}] Second \stopxcell
 \startxcell[align=right,width={0.14\textwidth}] row \stopxcell
 \startxcell[align=left,width={0.16\textwidth}] 5.0 \stopxcell
-\startxcell[align=right,width={0.34\textwidth}] Here's another one. Note the
+\startxcell[align=right,width={0.35\textwidth}] Here's another one. Note the
 blank line between rows. \stopxcell
 \stopxrow
 \stopxtablefoot
@@ -151,7 +151,7 @@ Multiline table without caption:
 \startxcell[align=middle,width={0.15\textwidth}] Centered Header \stopxcell
 \startxcell[align=right,width={0.14\textwidth}] Left Aligned \stopxcell
 \startxcell[align=left,width={0.16\textwidth}] Right Aligned \stopxcell
-\startxcell[align=right,width={0.34\textwidth}] Default aligned \stopxcell
+\startxcell[align=right,width={0.35\textwidth}] Default aligned \stopxcell
 \stopxrow
 \stopxtablehead
 \startxtablebody[body]
@@ -159,7 +159,7 @@ Multiline table without caption:
 \startxcell[align=middle,width={0.15\textwidth}] First \stopxcell
 \startxcell[align=right,width={0.14\textwidth}] row \stopxcell
 \startxcell[align=left,width={0.16\textwidth}] 12.0 \stopxcell
-\startxcell[align=right,width={0.34\textwidth}] Example of a row that spans
+\startxcell[align=right,width={0.35\textwidth}] Example of a row that spans
 multiple lines. \stopxcell
 \stopxrow
 \stopxtablebody
@@ -168,7 +168,7 @@ multiple lines. \stopxcell
 \startxcell[align=middle,width={0.15\textwidth}] Second \stopxcell
 \startxcell[align=right,width={0.14\textwidth}] row \stopxcell
 \startxcell[align=left,width={0.16\textwidth}] 5.0 \stopxcell
-\startxcell[align=right,width={0.34\textwidth}] Here's another one. Note the
+\startxcell[align=right,width={0.35\textwidth}] Here's another one. Note the
 blank line between rows. \stopxcell
 \stopxrow
 \stopxtablefoot
@@ -213,7 +213,7 @@ Multiline table without column headers:
 \startxcell[align=middle,width={0.15\textwidth}] First \stopxcell
 \startxcell[align=right,width={0.14\textwidth}] row \stopxcell
 \startxcell[align=left,width={0.16\textwidth}] 12.0 \stopxcell
-\startxcell[width={0.34\textwidth}] Example of a row that spans multiple
+\startxcell[width={0.35\textwidth}] Example of a row that spans multiple
 lines. \stopxcell
 \stopxrow
 \stopxtablebody
@@ -222,7 +222,7 @@ lines. \stopxcell
 \startxcell[align=middle,width={0.15\textwidth}] Second \stopxcell
 \startxcell[align=right,width={0.14\textwidth}] row \stopxcell
 \startxcell[align=left,width={0.16\textwidth}] 5.0 \stopxcell
-\startxcell[width={0.34\textwidth}] Here's another one. Note the blank line
+\startxcell[width={0.35\textwidth}] Here's another one. Note the blank line
 between rows. \stopxcell
 \stopxrow
 \stopxtablefoot
diff --git a/test/tables.custom b/test/tables.custom
index 410b68d3f..b78b3a4e9 100644
--- a/test/tables.custom
+++ b/test/tables.custom
@@ -95,7 +95,7 @@ It may span multiple lines.</caption>
 <col width="15%" />
 <col width="14%" />
 <col width="16%" />
-<col width="34%" />
+<col width="35%" />
 <tr class="header">
 <th align="center">Centered
 Header</th>
@@ -127,7 +127,7 @@ the blank line between rows.</td>
 <col width="15%" />
 <col width="14%" />
 <col width="16%" />
-<col width="34%" />
+<col width="35%" />
 <tr class="header">
 <th align="center">Centered
 Header</th>
@@ -182,7 +182,7 @@ the blank line between rows.</td>
 <col width="15%" />
 <col width="14%" />
 <col width="16%" />
-<col width="34%" />
+<col width="35%" />
 <tr class="odd">
 <td align="center">First</td>
 <td align="left">row</td>
diff --git a/test/tables.docbook4 b/test/tables.docbook4
index f86b1c390..a661805e5 100644
--- a/test/tables.docbook4
+++ b/test/tables.docbook4
@@ -228,7 +228,7 @@
     <colspec colwidth="15*" align="center" />
     <colspec colwidth="13*" align="left" />
     <colspec colwidth="16*" align="right" />
-    <colspec colwidth="33*" align="left" />
+    <colspec colwidth="35*" align="left" />
     <thead>
       <row>
         <entry>
@@ -285,7 +285,7 @@
     <colspec colwidth="15*" align="center" />
     <colspec colwidth="13*" align="left" />
     <colspec colwidth="16*" align="right" />
-    <colspec colwidth="33*" align="left" />
+    <colspec colwidth="35*" align="left" />
     <thead>
       <row>
         <entry>
@@ -397,7 +397,7 @@
     <colspec colwidth="15*" align="center" />
     <colspec colwidth="13*" align="left" />
     <colspec colwidth="16*" align="right" />
-    <colspec colwidth="33*" align="left" />
+    <colspec colwidth="35*" align="left" />
     <tbody>
       <row>
         <entry>
diff --git a/test/tables.docbook5 b/test/tables.docbook5
index f86b1c390..a661805e5 100644
--- a/test/tables.docbook5
+++ b/test/tables.docbook5
@@ -228,7 +228,7 @@
     <colspec colwidth="15*" align="center" />
     <colspec colwidth="13*" align="left" />
     <colspec colwidth="16*" align="right" />
-    <colspec colwidth="33*" align="left" />
+    <colspec colwidth="35*" align="left" />
     <thead>
       <row>
         <entry>
@@ -285,7 +285,7 @@
     <colspec colwidth="15*" align="center" />
     <colspec colwidth="13*" align="left" />
     <colspec colwidth="16*" align="right" />
-    <colspec colwidth="33*" align="left" />
+    <colspec colwidth="35*" align="left" />
     <thead>
       <row>
         <entry>
@@ -397,7 +397,7 @@
     <colspec colwidth="15*" align="center" />
     <colspec colwidth="13*" align="left" />
     <colspec colwidth="16*" align="right" />
-    <colspec colwidth="33*" align="left" />
+    <colspec colwidth="35*" align="left" />
     <tbody>
       <row>
         <entry>
diff --git a/test/tables.fb2 b/test/tables.fb2
index 56ed5316b..6be553df9 100644
--- a/test/tables.fb2
+++ b/test/tables.fb2
@@ -1,3 +1,16 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink"><description><title-info><genre>unrecognised</genre></title-info><document-info><program-used>pandoc</program-used></document-info></description><body><title><p /></title><section><p>Simple table with caption:</p><table><tr><th align="right">Right</th><th align="left">Left</th><th align="center">Center</th><th align="left">Default</th></tr><tr><td align="right">12</td><td align="left">12</td><td align="center">12</td><td align="left">12</td></tr><tr><td align="right">123</td><td align="left">123</td><td align="center">123</td><td align="left">123</td></tr><tr><td align="right">1</td><td align="left">1</td><td align="center">1</td><td align="left">1</td></tr></table><p><emphasis>Demonstration of simple table syntax.</emphasis></p><p>Simple table without caption:</p><table><tr><th align="right">Right</th><th align="left">Left</th><th align="center">Center</th><th align="left">Default</th></tr><tr><td align="right">12</td><td align="left">12</td><td align="center">12</td><td align="left">12</td></tr><tr><td align="right">123</td><td align="left">123</td><td align="center">123</td><td align="left">123</td></tr><tr><td align="right">1</td><td align="left">1</td><td align="center">1</td><td align="left">1</td></tr></table><p><emphasis /></p><p>Simple table indented two spaces:</p><table><tr><th align="right">Right</th><th align="left">Left</th><th align="center">Center</th><th align="left">Default</th></tr><tr><td align="right">12</td><td align="left">12</td><td align="center">12</td><td align="left">12</td></tr><tr><td align="right">123</td><td align="left">123</td><td align="center">123</td><td align="left">123</td></tr><tr><td align="right">1</td><td align="left">1</td><td align="center">1</td><td align="left">1</td></tr></table><p><emphasis>Demonstration of simple table syntax.</emphasis></p><p>Multiline table with caption:</p><table><tr><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><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><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><emphasis>Here’s the caption. It may span multiple lines.</emphasis></p><p>Multiline table without caption:</p><table><tr><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><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><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><emphasis /></p><p>Table without column headers:</p><table><tr><th align="right" /><th align="left" /><th align="center" /><th align="right" /></tr><tr><td align="right">12</td><td align="left">12</td><td align="center">12</td><td align="right">12</td></tr><tr><td align="right">123</td><td align="left">123</td><td align="center">123</td><td align="right">123</td></tr><tr><td align="right">1</td><td align="left">1</td><td align="center">1</td><td align="right">1</td></tr></table><p><emphasis /></p><p>Multiline table without column headers:</p><table><tr><th align="center" /><th align="left" /><th align="right" /><th align="left" /></tr><tr><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><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><emphasis /></p></section></body></FictionBook>
+<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink"><description><title-info><genre>unrecognised</genre></title-info><document-info><program-used>pandoc</program-used></document-info></description><body><title><p /></title><section><p>Simple table with caption:</p><table><tr><th align="right">Right</th><th align="left">Left</th><th align="center">Center</th><th align="left">Default</th></tr><tr><td align="right">12</td><td align="left">12</td><td align="center">12</td><td align="left">12</td></tr><tr><td align="right">123</td><td align="left">123</td><td align="center">123</td><td align="left">123</td></tr><tr><td align="right">1</td><td align="left">1</td><td align="center">1</td><td align="left">1</td></tr></table><p><emphasis>Demonstration of simple table syntax.</emphasis></p><p>Simple table without caption:</p><table><tr><th align="right">Right</th><th align="left">Left</th><th align="center">Center</th><th align="left">Default</th></tr><tr><td align="right">12</td><td align="left">12</td><td align="center">12</td><td align="left">12</td></tr><tr><td align="right">123</td><td align="left">123</td><td align="center">123</td><td align="left">123</td></tr><tr><td align="right">1</td><td align="left">1</td><td align="center">1</td><td align="left">1</td></tr></table><p><emphasis /></p><p>Simple table indented two spaces:</p><table><tr><th align="right">Right</th><th align="left">Left</th><th align="center">Center</th><th align="left">Default</th></tr><tr><td align="right">12</td><td align="left">12</td><td align="center">12</td><td align="left">12</td></tr><tr><td align="right">123</td><td align="left">123</td><td align="center">123</td><td align="left">123</td></tr><tr><td align="right">1</td><td align="left">1</td><td align="center">1</td><td align="left">1</td></tr></table><p><emphasis>Demonstration of simple table syntax.</emphasis></p><p>Multiline table with caption:</p><table><tr><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><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><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><emphasis>Here’s the caption.
+It may span multiple lines.</emphasis></p><p>Multiline table without caption:</p><table><tr><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><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><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><emphasis /></p><p>Table without column headers:</p><table><tr><th align="right" /><th align="left" /><th align="center" /><th align="right" /></tr><tr><td align="right">12</td><td align="left">12</td><td align="center">12</td><td align="right">12</td></tr><tr><td align="right">123</td><td align="left">123</td><td align="center">123</td><td align="right">123</td></tr><tr><td align="right">1</td><td align="left">1</td><td align="center">1</td><td align="right">1</td></tr></table><p><emphasis /></p><p>Multiline table without column headers:</p><table><tr><th align="center" /><th align="left" /><th align="right" /><th align="left" /></tr><tr><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><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><emphasis /></p></section></body></FictionBook>
 
diff --git a/test/tables.haddock b/test/tables.haddock
index 84a15cce8..dcfc0f7ad 100644
--- a/test/tables.haddock
+++ b/test/tables.haddock
@@ -1,76 +1,90 @@
 Simple table with caption:
 
->     Right Left    Center  Default
->   ------- ------ -------- ---------
->        12 12        12    12
->       123 123      123    123
->         1 1         1     1
+> +-------+------+--------+---------+
+> | Right | Left | Center | Default |
+> +=======+======+========+=========+
+> | 12    | 12   | 12     | 12      |
+> +-------+------+--------+---------+
+> | 123   | 123  | 123    | 123     |
+> +-------+------+--------+---------+
+> | 1     | 1    | 1      | 1       |
+> +-------+------+--------+---------+
 >
->   Demonstration of simple table syntax.
+> Demonstration of simple table syntax.
 
 Simple table without caption:
 
->     Right Left    Center  Default
->   ------- ------ -------- ---------
->        12 12        12    12
->       123 123      123    123
->         1 1         1     1
+> +-------+------+--------+---------+
+> | Right | Left | Center | Default |
+> +=======+======+========+=========+
+> | 12    | 12   | 12     | 12      |
+> +-------+------+--------+---------+
+> | 123   | 123  | 123    | 123     |
+> +-------+------+--------+---------+
+> | 1     | 1    | 1      | 1       |
+> +-------+------+--------+---------+
 
 Simple table indented two spaces:
 
->     Right Left    Center  Default
->   ------- ------ -------- ---------
->        12 12        12    12
->       123 123      123    123
->         1 1         1     1
+> +-------+------+--------+---------+
+> | Right | Left | Center | Default |
+> +=======+======+========+=========+
+> | 12    | 12   | 12     | 12      |
+> +-------+------+--------+---------+
+> | 123   | 123  | 123    | 123     |
+> +-------+------+--------+---------+
+> | 1     | 1    | 1      | 1       |
+> +-------+------+--------+---------+
 >
->   Demonstration of simple table syntax.
+> Demonstration of simple table syntax.
 
 Multiline table with caption:
 
->   --------------------------------------------------------------
->    Centered   Left              Right Default aligned
->     Header    Aligned         Aligned 
->   ----------- ---------- ------------ --------------------------
->      First    row                12.0 Example of a row that
->                                       spans multiple lines.
+> +----------+---------+-----------+--------------------------+
+> | Centered | Left    | Right     | Default aligned          |
+> | Header   | Aligned | Aligned   |                          |
+> +==========+=========+===========+==========================+
+> | First    | row     | 12.0      | Example of a row that    |
+> |          |         |           | spans multiple lines.    |
+> +----------+---------+-----------+--------------------------+
+> | Second   | row     | 5.0       | Here’s another one. Note |
+> |          |         |           | the blank line between   |
+> |          |         |           | rows.                    |
+> +----------+---------+-----------+--------------------------+
 >
->     Second    row                 5.0 Here’s another one. Note
->                                       the blank line between
->                                       rows.
->   --------------------------------------------------------------
->
->   Here’s the caption. It may span multiple lines.
+> Here’s the caption. It may span multiple lines.
 
 Multiline table without caption:
 
->   --------------------------------------------------------------
->    Centered   Left              Right Default aligned
->     Header    Aligned         Aligned 
->   ----------- ---------- ------------ --------------------------
->      First    row                12.0 Example of a row that
->                                       spans multiple lines.
->
->     Second    row                 5.0 Here’s another one. Note
->                                       the blank line between
->                                       rows.
->   --------------------------------------------------------------
+> +----------+---------+-----------+--------------------------+
+> | Centered | Left    | Right     | Default aligned          |
+> | Header   | Aligned | Aligned   |                          |
+> +==========+=========+===========+==========================+
+> | First    | row     | 12.0      | Example of a row that    |
+> |          |         |           | spans multiple lines.    |
+> +----------+---------+-----------+--------------------------+
+> | Second   | row     | 5.0       | Here’s another one. Note |
+> |          |         |           | the blank line between   |
+> |          |         |           | rows.                    |
+> +----------+---------+-----------+--------------------------+
 
 Table without column headers:
 
->   ----- ----- ----- -----
->      12 12     12      12
->     123 123    123    123
->       1 1       1       1
->   ----- ----- ----- -----
+> +-----+-----+-----+-----+
+> | 12  | 12  | 12  | 12  |
+> +-----+-----+-----+-----+
+> | 123 | 123 | 123 | 123 |
+> +-----+-----+-----+-----+
+> | 1   | 1   | 1   | 1   |
+> +-----+-----+-----+-----+
 
 Multiline table without column headers:
 
->   ----------- ---------- ------------ --------------------------
->      First    row                12.0 Example of a row that
->                                       spans multiple lines.
->
->     Second    row                 5.0 Here’s another one. Note
->                                       the blank line between
->                                       rows.
->   ----------- ---------- ------------ --------------------------
+> +----------+---------+-----------+--------------------------+
+> | First    | row     | 12.0      | Example of a row that    |
+> |          |         |           | spans multiple lines.    |
+> +----------+---------+-----------+--------------------------+
+> | Second   | row     | 5.0       | Here’s another one. Note |
+> |          |         |           | the blank line between   |
+> |          |         |           | rows.                    |
+> +----------+---------+-----------+--------------------------+
diff --git a/test/tables.html4 b/test/tables.html4
index 5bb7a7de2..0f699133b 100644
--- a/test/tables.html4
+++ b/test/tables.html4
@@ -94,13 +94,13 @@
 </tbody>
 </table>
 <p>Multiline table with caption:</p>
-<table style="width:79%;">
+<table style="width:80%;">
 <caption>Here’s the caption. It may span multiple lines.</caption>
 <colgroup>
 <col width="15%" />
 <col width="13%" />
 <col width="16%" />
-<col width="33%" />
+<col width="35%" />
 </colgroup>
 <thead>
 <tr class="header">
@@ -126,12 +126,12 @@
 </tbody>
 </table>
 <p>Multiline table without caption:</p>
-<table style="width:79%;">
+<table style="width:80%;">
 <colgroup>
 <col width="15%" />
 <col width="13%" />
 <col width="16%" />
-<col width="33%" />
+<col width="35%" />
 </colgroup>
 <thead>
 <tr class="header">
@@ -180,12 +180,12 @@
 </tbody>
 </table>
 <p>Multiline table without column headers:</p>
-<table style="width:79%;">
+<table style="width:80%;">
 <colgroup>
 <col width="15%" />
 <col width="13%" />
 <col width="16%" />
-<col width="33%" />
+<col width="35%" />
 </colgroup>
 <tbody>
 <tr class="odd">
diff --git a/test/tables.html5 b/test/tables.html5
index 17a82110f..533d2fd25 100644
--- a/test/tables.html5
+++ b/test/tables.html5
@@ -94,13 +94,13 @@
 </tbody>
 </table>
 <p>Multiline table with caption:</p>
-<table style="width:79%;">
+<table style="width:80%;">
 <caption>Here’s the caption. It may span multiple lines.</caption>
 <colgroup>
 <col style="width: 15%" />
 <col style="width: 13%" />
 <col style="width: 16%" />
-<col style="width: 33%" />
+<col style="width: 35%" />
 </colgroup>
 <thead>
 <tr class="header">
@@ -126,12 +126,12 @@
 </tbody>
 </table>
 <p>Multiline table without caption:</p>
-<table style="width:79%;">
+<table style="width:80%;">
 <colgroup>
 <col style="width: 15%" />
 <col style="width: 13%" />
 <col style="width: 16%" />
-<col style="width: 33%" />
+<col style="width: 35%" />
 </colgroup>
 <thead>
 <tr class="header">
@@ -180,12 +180,12 @@
 </tbody>
 </table>
 <p>Multiline table without column headers:</p>
-<table style="width:79%;">
+<table style="width:80%;">
 <colgroup>
 <col style="width: 15%" />
 <col style="width: 13%" />
 <col style="width: 16%" />
-<col style="width: 33%" />
+<col style="width: 35%" />
 </colgroup>
 <tbody>
 <tr class="odd">
diff --git a/test/tables.icml b/test/tables.icml
index 0280cafed..10945ef46 100644
--- a/test/tables.icml
+++ b/test/tables.icml
@@ -395,7 +395,7 @@
   <Column Name="0" SingleColumnWidth="75.0" />
   <Column Name="1" SingleColumnWidth="68.75" />
   <Column Name="2" SingleColumnWidth="81.25" />
-  <Column Name="3" SingleColumnWidth="168.75" />
+  <Column Name="3" SingleColumnWidth="175.0" />
   <Cell Name="0:0" AppliedCellStyle="CellStyle/Cell">
     <ParagraphStyleRange AppliedParagraphStyle="ParagraphStyle/TablePar &gt; TableHeader &gt; CenterAlign">
       <CharacterStyleRange AppliedCharacterStyle="$ID/NormalCharacterStyle">
@@ -497,7 +497,7 @@
   <Column Name="0" SingleColumnWidth="75.0" />
   <Column Name="1" SingleColumnWidth="68.75" />
   <Column Name="2" SingleColumnWidth="81.25" />
-  <Column Name="3" SingleColumnWidth="168.75" />
+  <Column Name="3" SingleColumnWidth="175.0" />
   <Cell Name="0:0" AppliedCellStyle="CellStyle/Cell">
     <ParagraphStyleRange AppliedParagraphStyle="ParagraphStyle/TablePar &gt; TableHeader &gt; CenterAlign">
       <CharacterStyleRange AppliedCharacterStyle="$ID/NormalCharacterStyle">
@@ -695,7 +695,7 @@
   <Column Name="0" SingleColumnWidth="75.0" />
   <Column Name="1" SingleColumnWidth="68.75" />
   <Column Name="2" SingleColumnWidth="81.25" />
-  <Column Name="3" SingleColumnWidth="168.75" />
+  <Column Name="3" SingleColumnWidth="175.0" />
   <Cell Name="0:0" AppliedCellStyle="CellStyle/Cell">
     <ParagraphStyleRange AppliedParagraphStyle="ParagraphStyle/TablePar &gt; CenterAlign">
       <CharacterStyleRange AppliedCharacterStyle="$ID/NormalCharacterStyle">
diff --git a/test/tables.jats b/test/tables.jats
index 46af61635..70f71e384 100644
--- a/test/tables.jats
+++ b/test/tables.jats
@@ -1,11 +1,7 @@
-<p>
-  Simple table with caption:
-</p>
+<p>Simple table with caption:</p>
 <table-wrap>
   <caption>
-    <p>
-      Demonstration of simple table syntax.
-    </p>
+    <p>Demonstration of simple table syntax.</p>
   </caption>
   <table>
     <col align="right" />
@@ -14,69 +10,35 @@
     <col align="left" />
     <thead>
       <tr>
-        <th>
-          Right
-        </th>
-        <th>
-          Left
-        </th>
-        <th>
-          Center
-        </th>
-        <th>
-          Default
-        </th>
+        <th>Right</th>
+        <th>Left</th>
+        <th>Center</th>
+        <th>Default</th>
       </tr>
     </thead>
     <tbody>
       <tr>
-        <td>
-          12
-        </td>
-        <td>
-          12
-        </td>
-        <td>
-          12
-        </td>
-        <td>
-          12
-        </td>
+        <td>12</td>
+        <td>12</td>
+        <td>12</td>
+        <td>12</td>
       </tr>
       <tr>
-        <td>
-          123
-        </td>
-        <td>
-          123
-        </td>
-        <td>
-          123
-        </td>
-        <td>
-          123
-        </td>
+        <td>123</td>
+        <td>123</td>
+        <td>123</td>
+        <td>123</td>
       </tr>
       <tr>
-        <td>
-          1
-        </td>
-        <td>
-          1
-        </td>
-        <td>
-          1
-        </td>
-        <td>
-          1
-        </td>
+        <td>1</td>
+        <td>1</td>
+        <td>1</td>
+        <td>1</td>
       </tr>
     </tbody>
   </table>
 </table-wrap>
-<p>
-  Simple table without caption:
-</p>
+<p>Simple table without caption:</p>
 <table>
   <col align="right" />
   <col align="left" />
@@ -84,73 +46,37 @@
   <col align="left" />
   <thead>
     <tr>
-      <th>
-        Right
-      </th>
-      <th>
-        Left
-      </th>
-      <th>
-        Center
-      </th>
-      <th>
-        Default
-      </th>
+      <th>Right</th>
+      <th>Left</th>
+      <th>Center</th>
+      <th>Default</th>
     </tr>
   </thead>
   <tbody>
     <tr>
-      <td>
-        12
-      </td>
-      <td>
-        12
-      </td>
-      <td>
-        12
-      </td>
-      <td>
-        12
-      </td>
+      <td>12</td>
+      <td>12</td>
+      <td>12</td>
+      <td>12</td>
     </tr>
     <tr>
-      <td>
-        123
-      </td>
-      <td>
-        123
-      </td>
-      <td>
-        123
-      </td>
-      <td>
-        123
-      </td>
+      <td>123</td>
+      <td>123</td>
+      <td>123</td>
+      <td>123</td>
     </tr>
     <tr>
-      <td>
-        1
-      </td>
-      <td>
-        1
-      </td>
-      <td>
-        1
-      </td>
-      <td>
-        1
-      </td>
+      <td>1</td>
+      <td>1</td>
+      <td>1</td>
+      <td>1</td>
     </tr>
   </tbody>
 </table>
-<p>
-  Simple table indented two spaces:
-</p>
+<p>Simple table indented two spaces:</p>
 <table-wrap>
   <caption>
-    <p>
-      Demonstration of simple table syntax.
-    </p>
+    <p>Demonstration of simple table syntax.</p>
   </caption>
   <table>
     <col align="right" />
@@ -159,186 +85,98 @@
     <col align="left" />
     <thead>
       <tr>
-        <th>
-          Right
-        </th>
-        <th>
-          Left
-        </th>
-        <th>
-          Center
-        </th>
-        <th>
-          Default
-        </th>
+        <th>Right</th>
+        <th>Left</th>
+        <th>Center</th>
+        <th>Default</th>
       </tr>
     </thead>
     <tbody>
       <tr>
-        <td>
-          12
-        </td>
-        <td>
-          12
-        </td>
-        <td>
-          12
-        </td>
-        <td>
-          12
-        </td>
+        <td>12</td>
+        <td>12</td>
+        <td>12</td>
+        <td>12</td>
       </tr>
       <tr>
-        <td>
-          123
-        </td>
-        <td>
-          123
-        </td>
-        <td>
-          123
-        </td>
-        <td>
-          123
-        </td>
+        <td>123</td>
+        <td>123</td>
+        <td>123</td>
+        <td>123</td>
       </tr>
       <tr>
-        <td>
-          1
-        </td>
-        <td>
-          1
-        </td>
-        <td>
-          1
-        </td>
-        <td>
-          1
-        </td>
+        <td>1</td>
+        <td>1</td>
+        <td>1</td>
+        <td>1</td>
       </tr>
     </tbody>
   </table>
 </table-wrap>
-<p>
-  Multiline table with caption:
-</p>
+<p>Multiline table with caption:</p>
 <table-wrap>
   <caption>
-    <p>
-      Here’s the caption. It may span multiple lines.
-    </p>
+    <p>Here’s the caption. It may span multiple lines.</p>
   </caption>
   <table>
     <col width="15*" align="center" />
     <col width="13*" align="left" />
     <col width="16*" align="right" />
-    <col width="33*" align="left" />
+    <col width="35*" align="left" />
     <thead>
       <tr>
-        <th>
-          Centered Header
-        </th>
-        <th>
-          Left Aligned
-        </th>
-        <th>
-          Right Aligned
-        </th>
-        <th>
-          Default aligned
-        </th>
+        <th>Centered Header</th>
+        <th>Left Aligned</th>
+        <th>Right Aligned</th>
+        <th>Default aligned</th>
       </tr>
     </thead>
     <tbody>
       <tr>
-        <td>
-          First
-        </td>
-        <td>
-          row
-        </td>
-        <td>
-          12.0
-        </td>
-        <td>
-          Example of a row that spans multiple lines.
-        </td>
+        <td>First</td>
+        <td>row</td>
+        <td>12.0</td>
+        <td>Example of a row that spans multiple lines.</td>
       </tr>
       <tr>
-        <td>
-          Second
-        </td>
-        <td>
-          row
-        </td>
-        <td>
-          5.0
-        </td>
-        <td>
-          Here’s another one. Note the blank line between rows.
-        </td>
+        <td>Second</td>
+        <td>row</td>
+        <td>5.0</td>
+        <td>Here’s another one. Note the blank line between rows.</td>
       </tr>
     </tbody>
   </table>
 </table-wrap>
-<p>
-  Multiline table without caption:
-</p>
+<p>Multiline table without caption:</p>
 <table>
   <col width="15*" align="center" />
   <col width="13*" align="left" />
   <col width="16*" align="right" />
-  <col width="33*" align="left" />
+  <col width="35*" align="left" />
   <thead>
     <tr>
-      <th>
-        Centered Header
-      </th>
-      <th>
-        Left Aligned
-      </th>
-      <th>
-        Right Aligned
-      </th>
-      <th>
-        Default aligned
-      </th>
+      <th>Centered Header</th>
+      <th>Left Aligned</th>
+      <th>Right Aligned</th>
+      <th>Default aligned</th>
     </tr>
   </thead>
   <tbody>
     <tr>
-      <td>
-        First
-      </td>
-      <td>
-        row
-      </td>
-      <td>
-        12.0
-      </td>
-      <td>
-        Example of a row that spans multiple lines.
-      </td>
+      <td>First</td>
+      <td>row</td>
+      <td>12.0</td>
+      <td>Example of a row that spans multiple lines.</td>
     </tr>
     <tr>
-      <td>
-        Second
-      </td>
-      <td>
-        row
-      </td>
-      <td>
-        5.0
-      </td>
-      <td>
-        Here’s another one. Note the blank line between rows.
-      </td>
+      <td>Second</td>
+      <td>row</td>
+      <td>5.0</td>
+      <td>Here’s another one. Note the blank line between rows.</td>
     </tr>
   </tbody>
 </table>
-<p>
-  Table without column headers:
-</p>
+<p>Table without column headers:</p>
 <table>
   <col align="right" />
   <col align="left" />
@@ -346,85 +184,43 @@
   <col align="right" />
   <tbody>
     <tr>
-      <td>
-        12
-      </td>
-      <td>
-        12
-      </td>
-      <td>
-        12
-      </td>
-      <td>
-        12
-      </td>
+      <td>12</td>
+      <td>12</td>
+      <td>12</td>
+      <td>12</td>
     </tr>
     <tr>
-      <td>
-        123
-      </td>
-      <td>
-        123
-      </td>
-      <td>
-        123
-      </td>
-      <td>
-        123
-      </td>
+      <td>123</td>
+      <td>123</td>
+      <td>123</td>
+      <td>123</td>
     </tr>
     <tr>
-      <td>
-        1
-      </td>
-      <td>
-        1
-      </td>
-      <td>
-        1
-      </td>
-      <td>
-        1
-      </td>
+      <td>1</td>
+      <td>1</td>
+      <td>1</td>
+      <td>1</td>
     </tr>
   </tbody>
 </table>
-<p>
-  Multiline table without column headers:
-</p>
+<p>Multiline table without column headers:</p>
 <table>
   <col width="15*" align="center" />
   <col width="13*" align="left" />
   <col width="16*" align="right" />
-  <col width="33*" align="left" />
+  <col width="35*" align="left" />
   <tbody>
     <tr>
-      <td>
-        First
-      </td>
-      <td>
-        row
-      </td>
-      <td>
-        12.0
-      </td>
-      <td>
-        Example of a row that spans multiple lines.
-      </td>
+      <td>First</td>
+      <td>row</td>
+      <td>12.0</td>
+      <td>Example of a row that spans multiple lines.</td>
     </tr>
     <tr>
-      <td>
-        Second
-      </td>
-      <td>
-        row
-      </td>
-      <td>
-        5.0
-      </td>
-      <td>
-        Here’s another one. Note the blank line between rows.
-      </td>
+      <td>Second</td>
+      <td>row</td>
+      <td>5.0</td>
+      <td>Here’s another one. Note the blank line between rows.</td>
     </tr>
   </tbody>
 </table>
diff --git a/test/tables.latex b/test/tables.latex
index 759b35dfa..4616448a9 100644
--- a/test/tables.latex
+++ b/test/tables.latex
@@ -58,7 +58,7 @@ Centered Header\strut
 Left Aligned\strut
 \end{minipage} & \begin{minipage}[b]{0.14\columnwidth}\raggedleft
 Right Aligned\strut
-\end{minipage} & \begin{minipage}[b]{0.30\columnwidth}\raggedright
+\end{minipage} & \begin{minipage}[b]{0.31\columnwidth}\raggedright
 Default aligned\strut
 \end{minipage}\tabularnewline
 \midrule
@@ -70,7 +70,7 @@ Centered Header\strut
 Left Aligned\strut
 \end{minipage} & \begin{minipage}[b]{0.14\columnwidth}\raggedleft
 Right Aligned\strut
-\end{minipage} & \begin{minipage}[b]{0.30\columnwidth}\raggedright
+\end{minipage} & \begin{minipage}[b]{0.31\columnwidth}\raggedright
 Default aligned\strut
 \end{minipage}\tabularnewline
 \midrule
@@ -81,7 +81,7 @@ First\strut
 row\strut
 \end{minipage} & \begin{minipage}[t]{0.14\columnwidth}\raggedleft
 12.0\strut
-\end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright
+\end{minipage} & \begin{minipage}[t]{0.31\columnwidth}\raggedright
 Example of a row that spans multiple lines.\strut
 \end{minipage}\tabularnewline
 \begin{minipage}[t]{0.13\columnwidth}\centering
@@ -90,7 +90,7 @@ Second\strut
 row\strut
 \end{minipage} & \begin{minipage}[t]{0.14\columnwidth}\raggedleft
 5.0\strut
-\end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright
+\end{minipage} & \begin{minipage}[t]{0.31\columnwidth}\raggedright
 Here's another one. Note the blank line between rows.\strut
 \end{minipage}\tabularnewline
 \bottomrule
@@ -106,7 +106,7 @@ Centered Header\strut
 Left Aligned\strut
 \end{minipage} & \begin{minipage}[b]{0.14\columnwidth}\raggedleft
 Right Aligned\strut
-\end{minipage} & \begin{minipage}[b]{0.30\columnwidth}\raggedright
+\end{minipage} & \begin{minipage}[b]{0.31\columnwidth}\raggedright
 Default aligned\strut
 \end{minipage}\tabularnewline
 \midrule
@@ -117,7 +117,7 @@ First\strut
 row\strut
 \end{minipage} & \begin{minipage}[t]{0.14\columnwidth}\raggedleft
 12.0\strut
-\end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright
+\end{minipage} & \begin{minipage}[t]{0.31\columnwidth}\raggedright
 Example of a row that spans multiple lines.\strut
 \end{minipage}\tabularnewline
 \begin{minipage}[t]{0.13\columnwidth}\centering
@@ -126,7 +126,7 @@ Second\strut
 row\strut
 \end{minipage} & \begin{minipage}[t]{0.14\columnwidth}\raggedleft
 5.0\strut
-\end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright
+\end{minipage} & \begin{minipage}[t]{0.31\columnwidth}\raggedright
 Here's another one. Note the blank line between rows.\strut
 \end{minipage}\tabularnewline
 \bottomrule
@@ -154,7 +154,7 @@ First\strut
 row\strut
 \end{minipage} & \begin{minipage}[t]{0.14\columnwidth}\raggedleft
 12.0\strut
-\end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright
+\end{minipage} & \begin{minipage}[t]{0.31\columnwidth}\raggedright
 Example of a row that spans multiple lines.\strut
 \end{minipage}\tabularnewline
 \begin{minipage}[t]{0.13\columnwidth}\centering
@@ -163,7 +163,7 @@ Second\strut
 row\strut
 \end{minipage} & \begin{minipage}[t]{0.14\columnwidth}\raggedleft
 5.0\strut
-\end{minipage} & \begin{minipage}[t]{0.30\columnwidth}\raggedright
+\end{minipage} & \begin{minipage}[t]{0.31\columnwidth}\raggedright
 Here's another one. Note the blank line between rows.\strut
 \end{minipage}\tabularnewline
 \bottomrule
diff --git a/test/tables.man b/test/tables.man
index dd6a3cce9..8c9385b4f 100644
--- a/test/tables.man
+++ b/test/tables.man
@@ -138,7 +138,7 @@ Multiline table with caption:
 Here's the caption. It may span multiple lines.
 .TS
 tab(@);
-cw(10.5n) lw(9.6n) rw(11.4n) lw(23.6n).
+cw(10.5n) lw(9.6n) rw(11.4n) lw(24.5n).
 T{
 Centered Header
 T}@T{
@@ -174,7 +174,7 @@ Multiline table without caption:
 .PP
 .TS
 tab(@);
-cw(10.5n) lw(9.6n) rw(11.4n) lw(23.6n).
+cw(10.5n) lw(9.6n) rw(11.4n) lw(24.5n).
 T{
 Centered Header
 T}@T{
@@ -244,7 +244,7 @@ Multiline table without column headers:
 .PP
 .TS
 tab(@);
-cw(10.5n) lw(9.6n) rw(11.4n) lw(23.6n).
+cw(10.5n) lw(9.6n) rw(11.4n) lw(24.5n).
 T{
 First
 T}@T{
diff --git a/test/tables.markdown b/test/tables.markdown
index f5ee776fa..7f89bfc08 100644
--- a/test/tables.markdown
+++ b/test/tables.markdown
@@ -28,33 +28,33 @@ Simple table indented two spaces:
 
 Multiline table with caption:
 
-  -------------------------------------------------------------
+  --------------------------------------------------------------
    Centered   Left              Right Default aligned
     Header    Aligned         Aligned 
-  ----------- ---------- ------------ -------------------------
+  ----------- ---------- ------------ --------------------------
      First    row                12.0 Example of a row that
                                       spans multiple lines.
 
     Second    row                 5.0 Here's another one. Note
                                       the blank line between
                                       rows.
-  -------------------------------------------------------------
+  --------------------------------------------------------------
 
   : Here's the caption. It may span multiple lines.
 
 Multiline table without caption:
 
-  -------------------------------------------------------------
+  --------------------------------------------------------------
    Centered   Left              Right Default aligned
     Header    Aligned         Aligned 
-  ----------- ---------- ------------ -------------------------
+  ----------- ---------- ------------ --------------------------
      First    row                12.0 Example of a row that
                                       spans multiple lines.
 
     Second    row                 5.0 Here's another one. Note
                                       the blank line between
                                       rows.
-  -------------------------------------------------------------
+  --------------------------------------------------------------
 
 Table without column headers:
 
@@ -66,11 +66,11 @@ Table without column headers:
 
 Multiline table without column headers:
 
-  ----------- ---------- ------------ -------------------------
+  ----------- ---------- ------------ --------------------------
      First    row                12.0 Example of a row that
                                       spans multiple lines.
 
     Second    row                 5.0 Here's another one. Note
                                       the blank line between
                                       rows.
-  ----------- ---------- ------------ -------------------------
+  ----------- ---------- ------------ --------------------------
diff --git a/test/tables.mediawiki b/test/tables.mediawiki
index ce7c17887..5402b286b 100644
--- a/test/tables.mediawiki
+++ b/test/tables.mediawiki
@@ -79,7 +79,7 @@ Multiline table with caption:
 !align="center" width="15%"| Centered Header
 !width="13%"| Left Aligned
 !align="right" width="16%"| Right Aligned
-!width="33%"| Default aligned
+!width="35%"| Default aligned
 |-
 |align="center"| First
 | row
@@ -98,7 +98,7 @@ Multiline table without caption:
 !align="center" width="15%"| Centered Header
 !width="13%"| Left Aligned
 !align="right" width="16%"| Right Aligned
-!width="33%"| Default aligned
+!width="35%"| Default aligned
 |-
 |align="center"| First
 | row
@@ -136,7 +136,7 @@ Multiline table without column headers:
 |align="center" width="15%"| First
 |width="13%"| row
 |align="right" width="16%"| 12.0
-|width="33%"| Example of a row that spans multiple lines.
+|width="35%"| Example of a row that spans multiple lines.
 |-
 |align="center"| Second
 | row
diff --git a/test/tables.ms b/test/tables.ms
index 21b3bd4e2..6d9138c64 100644
--- a/test/tables.ms
+++ b/test/tables.ms
@@ -135,10 +135,10 @@ T}
 .LP
 Multiline table with caption:
 .PP
-Here's the caption. It may span multiple lines.
+Here’s the caption. It may span multiple lines.
 .TS
 delim(@@) tab(	);
-cw(10.5n) lw(9.6n) rw(11.4n) lw(23.6n).
+cw(10.5n) lw(9.6n) rw(11.4n) lw(24.5n).
 T{
 Centered Header
 T}	T{
@@ -165,7 +165,7 @@ row
 T}	T{
 5.0
 T}	T{
-Here's another one.
+Here’s another one.
 Note the blank line between rows.
 T}
 .TE
@@ -174,7 +174,7 @@ Multiline table without caption:
 .PP
 .TS
 delim(@@) tab(	);
-cw(10.5n) lw(9.6n) rw(11.4n) lw(23.6n).
+cw(10.5n) lw(9.6n) rw(11.4n) lw(24.5n).
 T{
 Centered Header
 T}	T{
@@ -201,7 +201,7 @@ row
 T}	T{
 5.0
 T}	T{
-Here's another one.
+Here’s another one.
 Note the blank line between rows.
 T}
 .TE
@@ -244,7 +244,7 @@ Multiline table without column headers:
 .PP
 .TS
 delim(@@) tab(	);
-cw(10.5n) lw(9.6n) rw(11.4n) lw(23.6n).
+cw(10.5n) lw(9.6n) rw(11.4n) lw(24.5n).
 T{
 First
 T}	T{
@@ -261,7 +261,7 @@ row
 T}	T{
 5.0
 T}	T{
-Here's another one.
+Here’s another one.
 Note the blank line between rows.
 T}
 .TE
diff --git a/test/tables.native b/test/tables.native
index a60f9b586..62ed56bb4 100644
--- a/test/tables.native
+++ b/test/tables.native
@@ -53,7 +53,7 @@
   ,[Plain [Str "1"]]
   ,[Plain [Str "1"]]]]
 ,Para [Str "Multiline",Space,Str "table",Space,Str "with",Space,Str "caption:"]
-,Table [Str "Here\8217s",Space,Str "the",Space,Str "caption.",SoftBreak,Str "It",Space,Str "may",Space,Str "span",Space,Str "multiple",Space,Str "lines."] [AlignCenter,AlignLeft,AlignRight,AlignLeft] [0.15,0.1375,0.1625,0.3375]
+,Table [Str "Here\8217s",Space,Str "the",Space,Str "caption.",SoftBreak,Str "It",Space,Str "may",Space,Str "span",Space,Str "multiple",Space,Str "lines."] [AlignCenter,AlignLeft,AlignRight,AlignLeft] [0.15,0.1375,0.1625,0.35]
  [[Plain [Str "Centered",SoftBreak,Str "Header"]]
  ,[Plain [Str "Left",SoftBreak,Str "Aligned"]]
  ,[Plain [Str "Right",SoftBreak,Str "Aligned"]]
@@ -67,7 +67,7 @@
   ,[Plain [Str "5.0"]]
   ,[Plain [Str "Here\8217s",Space,Str "another",Space,Str "one.",Space,Str "Note",SoftBreak,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]]
 ,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "caption:"]
-,Table [] [AlignCenter,AlignLeft,AlignRight,AlignLeft] [0.15,0.1375,0.1625,0.3375]
+,Table [] [AlignCenter,AlignLeft,AlignRight,AlignLeft] [0.15,0.1375,0.1625,0.35]
  [[Plain [Str "Centered",SoftBreak,Str "Header"]]
  ,[Plain [Str "Left",SoftBreak,Str "Aligned"]]
  ,[Plain [Str "Right",SoftBreak,Str "Aligned"]]
@@ -99,7 +99,7 @@
   ,[Plain [Str "1"]]
   ,[Plain [Str "1"]]]]
 ,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "column",Space,Str "headers:"]
-,Table [] [AlignCenter,AlignLeft,AlignRight,AlignDefault] [0.15,0.1375,0.1625,0.3375]
+,Table [] [AlignCenter,AlignLeft,AlignRight,AlignDefault] [0.15,0.1375,0.1625,0.35]
  [[]
  ,[]
  ,[]
diff --git a/test/tables.plain b/test/tables.plain
index 7013d0caa..e46317a6f 100644
--- a/test/tables.plain
+++ b/test/tables.plain
@@ -28,33 +28,33 @@ Simple table indented two spaces:
 
 Multiline table with caption:
 
-  -------------------------------------------------------------
+  --------------------------------------------------------------
    Centered   Left              Right Default aligned
     Header    Aligned         Aligned 
-  ----------- ---------- ------------ -------------------------
+  ----------- ---------- ------------ --------------------------
      First    row                12.0 Example of a row that
                                       spans multiple lines.
 
     Second    row                 5.0 Here’s another one. Note
                                       the blank line between
                                       rows.
-  -------------------------------------------------------------
+  --------------------------------------------------------------
 
   : Here’s the caption. It may span multiple lines.
 
 Multiline table without caption:
 
-  -------------------------------------------------------------
+  --------------------------------------------------------------
    Centered   Left              Right Default aligned
     Header    Aligned         Aligned 
-  ----------- ---------- ------------ -------------------------
+  ----------- ---------- ------------ --------------------------
      First    row                12.0 Example of a row that
                                       spans multiple lines.
 
     Second    row                 5.0 Here’s another one. Note
                                       the blank line between
                                       rows.
-  -------------------------------------------------------------
+  --------------------------------------------------------------
 
 Table without column headers:
 
@@ -66,11 +66,11 @@ Table without column headers:
 
 Multiline table without column headers:
 
-  ----------- ---------- ------------ -------------------------
+  ----------- ---------- ------------ --------------------------
      First    row                12.0 Example of a row that
                                       spans multiple lines.
 
     Second    row                 5.0 Here’s another one. Note
                                       the blank line between
                                       rows.
-  ----------- ---------- ------------ -------------------------
+  ----------- ---------- ------------ --------------------------
diff --git a/test/tables.rst b/test/tables.rst
index e76c505aa..4559883cd 100644
--- a/test/tables.rst
+++ b/test/tables.rst
@@ -42,31 +42,31 @@ Multiline table with caption:
 
 .. table:: Here’s the caption. It may span multiple lines.
 
-   +----------+---------+-----------+-------------------------+
-   | Centered | Left    | Right     | Default aligned         |
-   | Header   | Aligned | Aligned   |                         |
-   +==========+=========+===========+=========================+
-   | First    | row     | 12.0      | Example of a row that   |
-   |          |         |           | spans multiple lines.   |
-   +----------+---------+-----------+-------------------------+
-   | Second   | row     | 5.0       | Here’s another one.     |
-   |          |         |           | Note the blank line     |
-   |          |         |           | between rows.           |
-   +----------+---------+-----------+-------------------------+
+   +----------+---------+-----------+--------------------------+
+   | Centered | Left    | Right     | Default aligned          |
+   | Header   | Aligned | Aligned   |                          |
+   +==========+=========+===========+==========================+
+   | First    | row     | 12.0      | Example of a row that    |
+   |          |         |           | spans multiple lines.    |
+   +----------+---------+-----------+--------------------------+
+   | Second   | row     | 5.0       | Here’s another one. Note |
+   |          |         |           | the blank line between   |
+   |          |         |           | rows.                    |
+   +----------+---------+-----------+--------------------------+
 
 Multiline table without caption:
 
-+----------+---------+-----------+-------------------------+
-| Centered | Left    | Right     | Default aligned         |
-| Header   | Aligned | Aligned   |                         |
-+==========+=========+===========+=========================+
-| First    | row     | 12.0      | Example of a row that   |
-|          |         |           | spans multiple lines.   |
-+----------+---------+-----------+-------------------------+
-| Second   | row     | 5.0       | Here’s another one.     |
-|          |         |           | Note the blank line     |
-|          |         |           | between rows.           |
-+----------+---------+-----------+-------------------------+
++----------+---------+-----------+--------------------------+
+| Centered | Left    | Right     | Default aligned          |
+| Header   | Aligned | Aligned   |                          |
++==========+=========+===========+==========================+
+| First    | row     | 12.0      | Example of a row that    |
+|          |         |           | spans multiple lines.    |
++----------+---------+-----------+--------------------------+
+| Second   | row     | 5.0       | Here’s another one. Note |
+|          |         |           | the blank line between   |
+|          |         |           | rows.                    |
++----------+---------+-----------+--------------------------+
 
 Table without column headers:
 
@@ -80,11 +80,11 @@ Table without column headers:
 
 Multiline table without column headers:
 
-+----------+---------+-----------+-------------------------+
-| First    | row     | 12.0      | Example of a row that   |
-|          |         |           | spans multiple lines.   |
-+----------+---------+-----------+-------------------------+
-| Second   | row     | 5.0       | Here’s another one.     |
-|          |         |           | Note the blank line     |
-|          |         |           | between rows.           |
-+----------+---------+-----------+-------------------------+
++----------+---------+-----------+--------------------------+
+| First    | row     | 12.0      | Example of a row that    |
+|          |         |           | spans multiple lines.    |
++----------+---------+-----------+--------------------------+
+| Second   | row     | 5.0       | Here’s another one. Note |
+|          |         |           | the blank line between   |
+|          |         |           | rows.                    |
++----------+---------+-----------+--------------------------+
diff --git a/test/tables.rtf b/test/tables.rtf
index 57030b114..97ea46bad 100644
--- a/test/tables.rtf
+++ b/test/tables.rtf
@@ -187,7 +187,7 @@
 {\pard \ql \f0 \sa180 \li0 \fi0 Multiline table with caption:\par}
 {
 \trowd \trgaph120
-\clbrdrb\brdrs\cellx1296\clbrdrb\brdrs\cellx2484\clbrdrb\brdrs\cellx3888\clbrdrb\brdrs\cellx6804
+\clbrdrb\brdrs\cellx1296\clbrdrb\brdrs\cellx2484\clbrdrb\brdrs\cellx3888\clbrdrb\brdrs\cellx6912
 \trkeep\intbl
 {
 {{\pard\intbl \qc \f0 \sa0 \li0 \fi0 Centered Header\par}
@@ -202,7 +202,7 @@
 \intbl\row}
 {
 \trowd \trgaph120
-\cellx1296\cellx2484\cellx3888\cellx6804
+\cellx1296\cellx2484\cellx3888\cellx6912
 \trkeep\intbl
 {
 {{\pard\intbl \qc \f0 \sa0 \li0 \fi0 First\par}
@@ -217,7 +217,7 @@
 \intbl\row}
 {
 \trowd \trgaph120
-\cellx1296\cellx2484\cellx3888\cellx6804
+\cellx1296\cellx2484\cellx3888\cellx6912
 \trkeep\intbl
 {
 {{\pard\intbl \qc \f0 \sa0 \li0 \fi0 Second\par}
@@ -234,7 +234,7 @@
 {\pard \ql \f0 \sa180 \li0 \fi0 Multiline table without caption:\par}
 {
 \trowd \trgaph120
-\clbrdrb\brdrs\cellx1296\clbrdrb\brdrs\cellx2484\clbrdrb\brdrs\cellx3888\clbrdrb\brdrs\cellx6804
+\clbrdrb\brdrs\cellx1296\clbrdrb\brdrs\cellx2484\clbrdrb\brdrs\cellx3888\clbrdrb\brdrs\cellx6912
 \trkeep\intbl
 {
 {{\pard\intbl \qc \f0 \sa0 \li0 \fi0 Centered Header\par}
@@ -249,7 +249,7 @@
 \intbl\row}
 {
 \trowd \trgaph120
-\cellx1296\cellx2484\cellx3888\cellx6804
+\cellx1296\cellx2484\cellx3888\cellx6912
 \trkeep\intbl
 {
 {{\pard\intbl \qc \f0 \sa0 \li0 \fi0 First\par}
@@ -264,7 +264,7 @@
 \intbl\row}
 {
 \trowd \trgaph120
-\cellx1296\cellx2484\cellx3888\cellx6804
+\cellx1296\cellx2484\cellx3888\cellx6912
 \trkeep\intbl
 {
 {{\pard\intbl \qc \f0 \sa0 \li0 \fi0 Second\par}
@@ -328,7 +328,7 @@
 {\pard \ql \f0 \sa180 \li0 \fi0 Multiline table without column headers:\par}
 {
 \trowd \trgaph120
-\cellx1296\cellx2484\cellx3888\cellx6804
+\cellx1296\cellx2484\cellx3888\cellx6912
 \trkeep\intbl
 {
 {{\pard\intbl \qc \f0 \sa0 \li0 \fi0 First\par}
@@ -343,7 +343,7 @@
 \intbl\row}
 {
 \trowd \trgaph120
-\cellx1296\cellx2484\cellx3888\cellx6804
+\cellx1296\cellx2484\cellx3888\cellx6912
 \trkeep\intbl
 {
 {{\pard\intbl \qc \f0 \sa0 \li0 \fi0 Second\par}
diff --git a/test/tables.texinfo b/test/tables.texinfo
index b82006f1a..4f09246af 100644
--- a/test/tables.texinfo
+++ b/test/tables.texinfo
@@ -83,7 +83,7 @@ Right
 Multiline table with caption:
 
 @float
-@multitable @columnfractions 0.15 0.14 0.16 0.34 
+@multitable @columnfractions 0.15 0.14 0.16 0.35 
 @headitem 
 Centered Header
  @tab Left Aligned
@@ -104,7 +104,7 @@ Second
 @end float
 Multiline table without caption:
 
-@multitable @columnfractions 0.15 0.14 0.16 0.34 
+@multitable @columnfractions 0.15 0.14 0.16 0.35 
 @headitem 
 Centered Header
  @tab Left Aligned
@@ -144,7 +144,7 @@ Table without column headers:
 
 Multiline table without column headers:
 
-@multitable @columnfractions 0.15 0.14 0.16 0.34 
+@multitable @columnfractions 0.15 0.14 0.16 0.35 
 @item 
 First
  @tab row
diff --git a/test/tables.textile b/test/tables.textile
index 6c6b234e6..9c71ec383 100644
--- a/test/tables.textile
+++ b/test/tables.textile
@@ -80,7 +80,7 @@ Multiline table with caption:
 <col width="15%" />
 <col width="13%" />
 <col width="16%" />
-<col width="33%" />
+<col width="35%" />
 <thead>
 <tr class="header">
 <th align="center">Centered Header</th>
@@ -111,7 +111,7 @@ Multiline table without caption:
 <col width="15%" />
 <col width="13%" />
 <col width="16%" />
-<col width="33%" />
+<col width="35%" />
 <thead>
 <tr class="header">
 <th align="center">Centered Header</th>
@@ -148,7 +148,7 @@ Multiline table without column headers:
 <col width="15%" />
 <col width="13%" />
 <col width="16%" />
-<col width="33%" />
+<col width="35%" />
 <tbody>
 <tr class="odd">
 <td align="center">First</td>
diff --git a/test/test-pandoc.hs b/test/test-pandoc.hs
index 9d4632f35..dc51b73cc 100644
--- a/test/test-pandoc.hs
+++ b/test/test-pandoc.hs
@@ -1,7 +1,9 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# OPTIONS_GHC -Wall #-}
 
 module Main where
 
+import Prelude
 import GHC.IO.Encoding
 import Test.Tasty
 import qualified Tests.Command
@@ -10,6 +12,7 @@ import qualified Tests.Old
 import qualified Tests.Readers.Creole
 import qualified Tests.Readers.Docx
 import qualified Tests.Readers.EPUB
+import qualified Tests.Readers.FB2
 import qualified Tests.Readers.HTML
 import qualified Tests.Readers.JATS
 import qualified Tests.Readers.LaTeX
@@ -75,6 +78,7 @@ tests = testGroup "pandoc tests" [ Tests.Command.tests
           , testGroup "Muse" Tests.Readers.Muse.tests
           , testGroup "Creole" Tests.Readers.Creole.tests
           , testGroup "Man" Tests.Readers.Man.tests
+          , testGroup "FB2" Tests.Readers.FB2.tests
           ]
         , testGroup "Lua filters" Tests.Lua.tests
         ]
diff --git a/test/test-pandoc.hs.orig b/test/test-pandoc.hs.orig
new file mode 100644
index 000000000..4cf1a952d
--- /dev/null
+++ b/test/test-pandoc.hs.orig
@@ -0,0 +1,83 @@
+{-# OPTIONS_GHC -Wall #-}
+
+module Main where
+
+import GHC.IO.Encoding
+import Test.Tasty
+import qualified Tests.Command
+import qualified Tests.Lua
+import qualified Tests.Old
+import qualified Tests.Readers.Creole
+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
+import qualified Tests.Readers.Odt
+import qualified Tests.Readers.Org
+import qualified Tests.Readers.RST
+import qualified Tests.Readers.Txt2Tags
+import qualified Tests.Shared
+import qualified Tests.Writers.AsciiDoc
+import qualified Tests.Writers.ConTeXt
+import qualified Tests.Writers.Docbook
+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)
+
+tests :: TestTree
+tests = testGroup "pandoc tests" [ Tests.Command.tests
+        , testGroup "Old" Tests.Old.tests
+        , testGroup "Shared" Tests.Shared.tests
+        , testGroup "Writers"
+          [ testGroup "Native" Tests.Writers.Native.tests
+          , 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
+          , testGroup "Plain" Tests.Writers.Plain.tests
+          , testGroup "AsciiDoc" Tests.Writers.AsciiDoc.tests
+          , testGroup "Docx" Tests.Writers.Docx.tests
+          , testGroup "RST" Tests.Writers.RST.tests
+          , 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
+          , testGroup "Odt" Tests.Readers.Odt.tests
+          , testGroup "Txt2Tags" Tests.Readers.Txt2Tags.tests
+          , testGroup "EPUB" Tests.Readers.EPUB.tests
+          , testGroup "Muse" Tests.Readers.Muse.tests
+          , testGroup "Creole" Tests.Readers.Creole.tests
+          ]
+        , testGroup "Lua filters" Tests.Lua.tests
+        ]
+
+main :: IO ()
+main = do
+  setLocaleEncoding utf8
+  inDirectory "test" $ defaultMain tests
diff --git a/test/writer.context b/test/writer.context
index 0cbbc7df4..bb69f4e43 100644
--- a/test/writer.context
+++ b/test/writer.context
@@ -21,7 +21,7 @@
 
 \setupbodyfontenvironment[default][em=italic] % use italic as em, not slanted
 
-\definefallbackfamily[mainface][rm][DejaVu Serif][preset=range:greek, force=yes]
+\definefallbackfamily[mainface][rm][CMU Serif][preset=range:greek, force=yes]
 \definefontfamily[mainface][rm][Latin Modern Roman]
 \definefontfamily[mainface][mm][Latin Modern Math]
 \definefontfamily[mainface][ss][Latin Modern Sans]
diff --git a/test/writer.fb2 b/test/writer.fb2
index 20f566334..b2d002230 100644
--- a/test/writer.fb2
+++ b/test/writer.fb2
@@ -22,9 +22,8 @@
 <p>Pandoc Test Suite</p>
 </title>
 <section>
-<p>This is a set of tests for pandoc. Most of them are adapted from John Gruber’s markdown test suite.</p>
-<empty-line />
-<p>——————————</p>
+<p>This is a set of tests for pandoc. Most of them are adapted from
+John Gruber’s markdown test suite.</p>
 <empty-line />
 </section>
 <section>
@@ -33,11 +32,13 @@
 </title>
 <section>
 <title>
-<p>Level 2 with an embedded link &lt;/url&gt;</p>
+<p>Level 2 with an <a l:href="/url">embedded link</a>
+</p>
 </title>
 <section>
 <title>
-<p>Level 3 with emphasis</p>
+<p>Level 3 with <emphasis>emphasis</emphasis>
+</p>
 </title>
 <section>
 <title>
@@ -58,7 +59,8 @@
 </title>
 <section>
 <title>
-<p>Level 2 with emphasis</p>
+<p>Level 2 with <emphasis>emphasis</emphasis>
+</p>
 </title>
 <section>
 <title>
@@ -73,8 +75,6 @@
 </title>
 <p>with no blank line</p>
 <empty-line />
-<p>——————————</p>
-<empty-line />
 </section>
 </section>
 <section>
@@ -82,11 +82,15 @@
 <p>Paragraphs</p>
 </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<empty-line />here.</p>
-<empty-line />
-<p>——————————</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
+here.</p>
 <empty-line />
 </section>
 <section>
@@ -95,7 +99,8 @@
 </title>
 <p>E-mail style:</p>
 <cite>
-<p>This is a block quote. It is pretty short.</p>
+<p>This is a block quote.
+It is pretty short.</p>
 </cite>
 <cite>
 <p>Code in a block quote:</p>
@@ -121,11 +126,10 @@
 <p>nested</p>
 </cite>
 </cite>
-<p>This should not be a block quote: 2 &gt; 1.</p>
+<p>This should not be a block quote: 2
+&gt; 1.</p>
 <p>And a following paragraph.</p>
 <empty-line />
-<p>——————————</p>
-<empty-line />
 </section>
 <section>
 <title>
@@ -171,8 +175,6 @@
 </p>
 <empty-line />
 <empty-line />
-<p>——————————</p>
-<empty-line />
 </section>
 <section>
 <title>
@@ -245,7 +247,8 @@
 <p>Multiple paragraphs:</p>
 <p>1. Item 1, graf one.</p>
 <empty-line />
-<p>   Item 1. graf two. The quick brown fox jumped over the lazy dog’s back.</p>
+<p>   Item 1. graf two. The quick brown fox jumped over the lazy dog’s
+back.</p>
 <empty-line />
 <p>2. Item 2.</p>
 <empty-line />
@@ -281,13 +284,17 @@
 <title>
 <p>Tabs and spaces</p>
 </title>
-<p>• this is a list item indented with tabs</p>
+<p>• this is a list item
+indented with tabs</p>
 <empty-line />
-<p>• this is a list item indented with spaces</p>
+<p>• this is a list item
+indented with spaces</p>
 <empty-line />
-<p>• • this is an example list item indented with tabs</p>
+<p>• • this is an example list item
+indented with tabs</p>
 <empty-line />
-<p>• • this is an example list item indented with spaces</p>
+<p>• • this is an example list item
+indented with spaces</p>
 <empty-line />
 </section>
 <section>
@@ -299,7 +306,8 @@
 <empty-line />
 <p>    with a continuation</p>
 <empty-line />
-<p>(3) iv. sublist with roman numerals, starting with 4</p>
+<p>(3) iv. sublist with roman numerals,
+starting with 4</p>
 <p>(3) v. more items</p>
 <p>(3) v. (A) a subsublist</p>
 <p>(3) v. (B) a subsublist</p>
@@ -316,8 +324,6 @@
 <p>M.A. 2007</p>
 <p>B. Williams</p>
 <empty-line />
-<p>——————————</p>
-<empty-line />
 </section>
 </section>
 <section>
@@ -374,7 +380,8 @@
 </p>
 <p>    red fruit</p>
 <empty-line />
-<p>    contains seeds, crisp, pleasant to taste</p>
+<p>    contains seeds,
+crisp, pleasant to taste</p>
 <empty-line />
 <p>
 <strong>
@@ -476,8 +483,6 @@
 <empty-line />
 <p>Hr’s:</p>
 <empty-line />
-<p>——————————</p>
-<empty-line />
 </section>
 <section>
 <title>
@@ -485,9 +490,8 @@
 </title>
 <p>This is <emphasis>emphasized</emphasis>, and so <emphasis>is this</emphasis>.</p>
 <p>This is <strong>strong</strong>, and so <strong>is this</strong>.</p>
-<p>An <emphasis>emphasized link<a l:href="#l1" type="note">
-<sup>[1]</sup>
-</a>
+<p>An <emphasis>
+<a l:href="/url">emphasized link</a>
 </emphasis>.</p>
 <p>
 <strong>
@@ -513,9 +517,8 @@
 <emphasis>hello</emphasis>
 </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>
-<empty-line />
-<p>——————————</p>
+<p>These should not be superscripts or subscripts,
+because of the unescaped spaces: a^b c^d, a~b c~d.</p>
 <empty-line />
 </section>
 <section>
@@ -524,17 +527,15 @@
 </title>
 <p>“Hello,” said the spider. “‘Shelob’ is my name.”</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, “I want to go.”’ Were you alive in the 70’s?</p>
-<p>Here is some quoted ‘<code>code</code>’ and a “quoted link<a l:href="#l2" type="note">
-<sup>[2]</sup>
-</a>”.</p>
+<p>‘Oak,’ ‘elm,’ and ‘beech’ are names of trees.
+So is ‘pine.’</p>
+<p>‘He said, “I want to go.”’ Were you alive in the
+70’s?</p>
+<p>Here is some quoted ‘<code>code</code>’ and a “<a l:href="http://example.com/?foo=1&amp;bar=2">quoted link</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>
 <empty-line />
-<p>——————————</p>
-<empty-line />
 </section>
 <section>
 <title>
@@ -550,18 +551,18 @@
 <p>• <code>223</code>
 </p>
 <p>• <code>p</code>-Tree</p>
-<p>• Here’s some display math: <code>\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}</code>
+<p>• Here’s some display math:
+<code>\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}</code>
 </p>
 <p>• Here’s one that has a line break in it: <code>\alpha + \omega \times x^2</code>.</p>
 <p>These shouldn’t be math:</p>
 <p>• To get the famous equation, write <code>$e = mc^2$</code>.</p>
-<p>• $22,000 is a <emphasis>lot</emphasis> of money. So is $34,000. (It worked if “lot” is emphasized.)</p>
+<p>• $22,000 is a <emphasis>lot</emphasis> of money. So is $34,000.
+(It worked if “lot” is emphasized.)</p>
 <p>• Shoes ($20) and socks ($5).</p>
 <p>• Escaped <code>$</code>: $73 <emphasis>this should be emphasized</emphasis> 23$.</p>
 <p>Here’s a LaTeX table:</p>
 <empty-line />
-<p>——————————</p>
-<empty-line />
 </section>
 <section>
 <title>
@@ -595,8 +596,6 @@
 <p>Plus: +</p>
 <p>Minus: -</p>
 <empty-line />
-<p>——————————</p>
-<empty-line />
 </section>
 <section>
 <title>
@@ -606,112 +605,71 @@
 <title>
 <p>Explicit</p>
 </title>
-<p>Just a URL<a l:href="#l3" type="note">
-<sup>[3]</sup>
-</a>.</p>
-<p>URL and title<a l:href="#l4" type="note">
-<sup>[4]</sup>
-</a>.</p>
-<p>URL and title<a l:href="#l5" type="note">
-<sup>[5]</sup>
-</a>.</p>
-<p>URL and title<a l:href="#l6" type="note">
-<sup>[6]</sup>
-</a>.</p>
-<p>URL and title<a l:href="#l7" type="note">
-<sup>[7]</sup>
-</a>
+<p>Just a <a l:href="/url/">URL</a>.</p>
+<p>
+<a l:href="/url/">URL and title</a>.</p>
+<p>
+<a l:href="/url/">URL and title</a>.</p>
+<p>
+<a l:href="/url/">URL and title</a>.</p>
+<p>
+<a l:href="/url/">URL and title</a>
 </p>
-<p>URL and title<a l:href="#l8" type="note">
-<sup>[8]</sup>
-</a>
+<p>
+<a l:href="/url/">URL and title</a>
 </p>
-<p>with_underscore<a l:href="#l9" type="note">
-<sup>[9]</sup>
-</a>
+<p>
+<a l:href="/url/with_underscore">with_underscore</a>
 </p>
-<p>Email link<a l:href="#l10" type="note">
-<sup>[10]</sup>
-</a>
+<p>
+<a l:href="mailto:nobody@nowhere.net">Email link</a>
 </p>
-<p>Empty<a l:href="#l11" type="note">
-<sup>[11]</sup>
-</a>.</p>
+<p>
+<a l:href="">Empty</a>.</p>
 </section>
 <section>
 <title>
 <p>Reference</p>
 </title>
-<p>Foo bar<a l:href="#l12" type="note">
-<sup>[12]</sup>
-</a>.</p>
-<p>With embedded [brackets]<a l:href="#l13" type="note">
-<sup>[13]</sup>
-</a>.</p>
-<p>b<a l:href="#l14" type="note">
-<sup>[14]</sup>
-</a> by itself should be a link.</p>
-<p>Indented once<a l:href="#l15" type="note">
-<sup>[15]</sup>
-</a>.</p>
-<p>Indented twice<a l:href="#l16" type="note">
-<sup>[16]</sup>
-</a>.</p>
-<p>Indented thrice<a l:href="#l17" type="note">
-<sup>[17]</sup>
-</a>.</p>
+<p>Foo <a l:href="/url/">bar</a>.</p>
+<p>With <a l:href="/url/">embedded [brackets]</a>.</p>
+<p>
+<a l:href="/url/">b</a> by itself should be a link.</p>
+<p>Indented <a l:href="/url">once</a>.</p>
+<p>Indented <a l:href="/url">twice</a>.</p>
+<p>Indented <a l:href="/url">thrice</a>.</p>
 <p>This should [not][] be a link.</p>
 <empty-line />
 <p>
 <code>[not]: /url</code>
 </p>
 <empty-line />
-<p>Foo bar<a l:href="#l18" type="note">
-<sup>[18]</sup>
-</a>.</p>
-<p>Foo biz<a l:href="#l19" type="note">
-<sup>[19]</sup>
-</a>.</p>
+<p>Foo <a l:href="/url/">bar</a>.</p>
+<p>Foo <a l:href="/url/">biz</a>.</p>
 </section>
 <section>
 <title>
 <p>With ampersands</p>
 </title>
-<p>Here’s a link with an ampersand in the URL<a l:href="#l20" type="note">
-<sup>[20]</sup>
-</a>.</p>
-<p>Here’s a link with an amersand in the link text: AT&amp;T<a l:href="#l21" type="note">
-<sup>[21]</sup>
-</a>.</p>
-<p>Here’s an inline link<a l:href="#l22" type="note">
-<sup>[22]</sup>
-</a>.</p>
-<p>Here’s an inline link in pointy braces<a l:href="#l23" type="note">
-<sup>[23]</sup>
-</a>.</p>
+<p>Here’s a <a l:href="http://example.com/?foo=1&amp;bar=2">link with an ampersand in the URL</a>.</p>
+<p>Here’s a link with an amersand in the link text: <a l:href="http://att.com/">AT&amp;T</a>.</p>
+<p>Here’s an <a l:href="/script?foo=1&amp;bar=2">inline link</a>.</p>
+<p>Here’s an <a l:href="/script?foo=1&amp;bar=2">inline link in pointy braces</a>.</p>
 </section>
 <section>
 <title>
 <p>Autolinks</p>
 </title>
-<p>With an ampersand: http://example.com/?foo=1&amp;bar=2<a l:href="#l24" type="note">
-<sup>[24]</sup>
-</a>
+<p>With an ampersand: <a l:href="http://example.com/?foo=1&amp;bar=2">http://example.com/?foo=1&amp;bar=2</a>
 </p>
 <p>• In a list?</p>
-<p>• http://example.com/<a l:href="#l25" type="note">
-<sup>[25]</sup>
-</a>
+<p>• <a l:href="http://example.com/">http://example.com/</a>
 </p>
 <p>• It should.</p>
-<p>An e-mail address: nobody@nowhere.net<a l:href="#l26" type="note">
-<sup>[26]</sup>
-</a>
+<p>An e-mail address: <a l:href="mailto:nobody@nowhere.net">nobody@nowhere.net</a>
 </p>
 <cite>
-<p>Blockquoted: http://example.com/<a l:href="#l27" type="note">
-<sup>[27]</sup>
-</a>
+<p>Blockquoted: <a l:href="http://example.com/">http://example.com/</a>
 </p>
 </cite>
 <p>Auto-links should not occur here: <code>&lt;http://example.com/&gt;</code>
@@ -722,8 +680,6 @@
 </p>
 <empty-line />
 <empty-line />
-<p>——————————</p>
-<empty-line />
 </section>
 </section>
 <section>
@@ -734,280 +690,76 @@
 <image l:href="#image1" l:type="imageType" alt="lalune" title="Voyage dans la Lune" />
 <p>Here is a movie <image l:href="#image2" l:type="inlineImageType" alt="movie" /> icon.</p>
 <empty-line />
-<p>——————————</p>
-<empty-line />
 </section>
 <section>
 <title>
 <p>Footnotes</p>
 </title>
-<p>Here is a footnote reference,<a l:href="#n28" type="note">
-<sup>[28]</sup>
-</a> and another.<a l:href="#n29" type="note">
-<sup>[29]</sup>
-</a> This should <emphasis>not</emphasis> be a footnote reference, because it contains a space.[^my note] Here is an inline note.<a l:href="#n30" type="note">
-<sup>[30]</sup>
+<p>Here is a footnote reference,<a l:href="#n1" type="note">
+<sup>[1]</sup>
+</a> and another.<a l:href="#n2" type="note">
+<sup>[2]</sup>
+</a>
+This should <emphasis>not</emphasis> be a footnote reference, because it
+contains a space.[^my note] Here is an inline note.<a l:href="#n3" type="note">
+<sup>[3]</sup>
 </a>
 </p>
 <cite>
-<p>Notes can go in quotes.<a l:href="#n31" type="note">
-<sup>[31]</sup>
+<p>Notes can go in quotes.<a l:href="#n4" type="note">
+<sup>[4]</sup>
 </a>
 </p>
 </cite>
-<p>1. And in list items.<a l:href="#n32" type="note">
-<sup>[32]</sup>
+<p>1. And in list items.<a l:href="#n5" type="note">
+<sup>[5]</sup>
 </a>
 </p>
 <p>This paragraph should not be part of the note, as it is not indented.</p>
 </section>
 </body>
 <body name="notes">
-<section id="l1">
+<section id="n1">
 <title>
 <p>1</p>
 </title>
-<p>
-<code>/url</code>
-</p>
+<p>Here is the footnote. It can go anywhere after the footnote
+reference. It need not be placed at the end of the document.</p>
 </section>
-<section id="l2">
+<section id="n2">
 <title>
 <p>2</p>
 </title>
-<p>
-<code>http://example.com/?foo=1&amp;bar=2</code>
-</p>
-</section>
-<section id="l3">
-<title>
-<p>3</p>
-</title>
-<p>
-<code>/url/</code>
-</p>
-</section>
-<section id="l4">
-<title>
-<p>4</p>
-</title>
-<p>title: <code>/url/</code>
-</p>
-</section>
-<section id="l5">
-<title>
-<p>5</p>
-</title>
-<p>title preceded by two spaces: <code>/url/</code>
-</p>
-</section>
-<section id="l6">
-<title>
-<p>6</p>
-</title>
-<p>title preceded by a tab: <code>/url/</code>
-</p>
-</section>
-<section id="l7">
-<title>
-<p>7</p>
-</title>
-<p>title with &quot;quotes&quot; in it: <code>/url/</code>
-</p>
-</section>
-<section id="l8">
-<title>
-<p>8</p>
-</title>
-<p>title with single quotes: <code>/url/</code>
-</p>
-</section>
-<section id="l9">
-<title>
-<p>9</p>
-</title>
-<p>
-<code>/url/with_underscore</code>
-</p>
-</section>
-<section id="l10">
-<title>
-<p>10</p>
-</title>
-<p>
-<code>mailto:nobody@nowhere.net</code>
-</p>
-</section>
-<section id="l11">
-<title>
-<p>11</p>
-</title>
-<p>
-<code>
-</code>
-</p>
-</section>
-<section id="l12">
-<title>
-<p>12</p>
-</title>
-<p>
-<code>/url/</code>
-</p>
-</section>
-<section id="l13">
-<title>
-<p>13</p>
-</title>
-<p>
-<code>/url/</code>
-</p>
-</section>
-<section id="l14">
-<title>
-<p>14</p>
-</title>
-<p>
-<code>/url/</code>
-</p>
-</section>
-<section id="l15">
-<title>
-<p>15</p>
-</title>
-<p>
-<code>/url</code>
-</p>
-</section>
-<section id="l16">
-<title>
-<p>16</p>
-</title>
-<p>
-<code>/url</code>
-</p>
-</section>
-<section id="l17">
-<title>
-<p>17</p>
-</title>
-<p>
-<code>/url</code>
-</p>
-</section>
-<section id="l18">
-<title>
-<p>18</p>
-</title>
-<p>Title with &quot;quotes&quot; inside: <code>/url/</code>
-</p>
-</section>
-<section id="l19">
-<title>
-<p>19</p>
-</title>
-<p>Title with &quot;quote&quot; inside: <code>/url/</code>
-</p>
-</section>
-<section id="l20">
-<title>
-<p>20</p>
-</title>
-<p>
-<code>http://example.com/?foo=1&amp;bar=2</code>
-</p>
-</section>
-<section id="l21">
-<title>
-<p>21</p>
-</title>
-<p>AT&amp;T: <code>http://att.com/</code>
-</p>
-</section>
-<section id="l22">
-<title>
-<p>22</p>
-</title>
-<p>
-<code>/script?foo=1&amp;bar=2</code>
-</p>
-</section>
-<section id="l23">
-<title>
-<p>23</p>
-</title>
-<p>
-<code>/script?foo=1&amp;bar=2</code>
-</p>
-</section>
-<section id="l24">
-<title>
-<p>24</p>
-</title>
-<p>
-<code>http://example.com/?foo=1&amp;bar=2</code>
-</p>
-</section>
-<section id="l25">
-<title>
-<p>25</p>
-</title>
-<p>
-<code>http://example.com/</code>
-</p>
-</section>
-<section id="l26">
-<title>
-<p>26</p>
-</title>
-<p>
-<code>mailto:nobody@nowhere.net</code>
-</p>
-</section>
-<section id="l27">
-<title>
-<p>27</p>
-</title>
-<p>
-<code>http://example.com/</code>
-</p>
-</section>
-<section id="n28">
-<title>
-<p>28</p>
-</title>
-<p>Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.</p>
-</section>
-<section id="n29">
-<title>
-<p>29</p>
-</title>
-<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>
+<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>
 <empty-line />
 <p>
 <code>  { &lt;code&gt; }</code>
 </p>
 <empty-line />
-<p>If you want, you can indent every line, but you can also be lazy and just indent the first line of each block.</p>
+<p>If you want, you can indent every line, but you can also be
+lazy and just indent the first line of each block.</p>
 </section>
-<section id="n30">
+<section id="n3">
 <title>
-<p>30</p>
+<p>3</p>
 </title>
-<p>This is <emphasis>easier</emphasis> to type. Inline notes may contain links<a l:href="#l30" type="note">
-<sup>[30]</sup>
-</a> and <code>]</code> verbatim characters, as well as [bracketed text].</p>
+<p>This
+is <emphasis>easier</emphasis> to type. Inline notes may contain
+<a l:href="http://google.com">links</a> and <code>]</code> verbatim characters,
+as well as [bracketed text].</p>
 </section>
-<section id="n31">
+<section id="n4">
 <title>
-<p>31</p>
+<p>4</p>
 </title>
 <p>In quote.</p>
 </section>
-<section id="n32">
+<section id="n5">
 <title>
-<p>32</p>
+<p>5</p>
 </title>
 <p>In list.</p>
 </section>
diff --git a/test/writer.jats b/test/writer.jats
index 507e9f672..b51addf3b 100644
--- a/test/writer.jats
+++ b/test/writer.jats
@@ -32,10 +32,8 @@
 </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>
+<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">
@@ -59,93 +57,57 @@
     <title>Level 2 with <italic>emphasis</italic></title>
     <sec id="level-3">
       <title>Level 3</title>
-      <p>
-        with no blank line
-      </p>
+      <p>with no blank line</p>
     </sec>
   </sec>
   <sec id="level-2">
     <title>Level 2</title>
-    <p>
-      with no blank line
-    </p>
+    <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>
+  <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>
+  <p>E-mail style:</p>
   <disp-quote>
-    <p>
-      This is a block quote. It is pretty short.
-    </p>
+    <p>This is a block quote. It is pretty short.</p>
   </disp-quote>
   <disp-quote>
-    <p>
-      Code in a block quote:
-    </p>
+    <p>Code in a block quote:</p>
     <preformat>sub status {
     print &quot;working&quot;;
 }</preformat>
-    <p>
-      A list:
-    </p>
+    <p>A list:</p>
     <list list-type="order">
       <list-item>
-        <p>
-          item one
-        </p>
+        <p>item one</p>
       </list-item>
       <list-item>
-        <p>
-          item two
-        </p>
+        <p>item two</p>
       </list-item>
     </list>
-    <p>
-      Nested block quotes:
-    </p>
+    <p>Nested block quotes:</p>
     <disp-quote>
-      <p>
-        nested
-      </p>
+      <p>nested</p>
     </disp-quote>
     <disp-quote>
-      <p>
-        nested
-      </p>
+      <p>nested</p>
     </disp-quote>
   </disp-quote>
-  <p>
-    This should not be a block quote: 2 &gt; 1.
-  </p>
-  <p>
-    And a following paragraph.
-  </p>
+  <p>This should not be a block quote: 2 &gt; 1.</p>
+  <p>And a following paragraph.</p>
 </sec>
 <sec id="code-blocks">
   <title>Code Blocks</title>
-  <p>
-    Code:
-  </p>
+  <p>Code:</p>
   <preformat>---- (should be four hyphens)
 
 sub status {
@@ -153,9 +115,7 @@ sub status {
 }
 
 this code block is indented by one tab</preformat>
-  <p>
-    And:
-  </p>
+  <p>And:</p>
   <preformat>    this code block is indented by two tabs
 
 These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
@@ -164,231 +124,141 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
   <title>Lists</title>
   <sec id="unordered">
     <title>Unordered</title>
-    <p>
-      Asterisks tight:
-    </p>
+    <p>Asterisks tight:</p>
     <list list-type="bullet">
       <list-item>
-        <p>
-          asterisk 1
-        </p>
+        <p>asterisk 1</p>
       </list-item>
       <list-item>
-        <p>
-          asterisk 2
-        </p>
+        <p>asterisk 2</p>
       </list-item>
       <list-item>
-        <p>
-          asterisk 3
-        </p>
+        <p>asterisk 3</p>
       </list-item>
     </list>
-    <p>
-      Asterisks loose:
-    </p>
+    <p>Asterisks loose:</p>
     <list list-type="bullet">
       <list-item>
-        <p>
-          asterisk 1
-        </p>
+        <p>asterisk 1</p>
       </list-item>
       <list-item>
-        <p>
-          asterisk 2
-        </p>
+        <p>asterisk 2</p>
       </list-item>
       <list-item>
-        <p>
-          asterisk 3
-        </p>
+        <p>asterisk 3</p>
       </list-item>
     </list>
-    <p>
-      Pluses tight:
-    </p>
+    <p>Pluses tight:</p>
     <list list-type="bullet">
       <list-item>
-        <p>
-          Plus 1
-        </p>
+        <p>Plus 1</p>
       </list-item>
       <list-item>
-        <p>
-          Plus 2
-        </p>
+        <p>Plus 2</p>
       </list-item>
       <list-item>
-        <p>
-          Plus 3
-        </p>
+        <p>Plus 3</p>
       </list-item>
     </list>
-    <p>
-      Pluses loose:
-    </p>
+    <p>Pluses loose:</p>
     <list list-type="bullet">
       <list-item>
-        <p>
-          Plus 1
-        </p>
+        <p>Plus 1</p>
       </list-item>
       <list-item>
-        <p>
-          Plus 2
-        </p>
+        <p>Plus 2</p>
       </list-item>
       <list-item>
-        <p>
-          Plus 3
-        </p>
+        <p>Plus 3</p>
       </list-item>
     </list>
-    <p>
-      Minuses tight:
-    </p>
+    <p>Minuses tight:</p>
     <list list-type="bullet">
       <list-item>
-        <p>
-          Minus 1
-        </p>
+        <p>Minus 1</p>
       </list-item>
       <list-item>
-        <p>
-          Minus 2
-        </p>
+        <p>Minus 2</p>
       </list-item>
       <list-item>
-        <p>
-          Minus 3
-        </p>
+        <p>Minus 3</p>
       </list-item>
     </list>
-    <p>
-      Minuses loose:
-    </p>
+    <p>Minuses loose:</p>
     <list list-type="bullet">
       <list-item>
-        <p>
-          Minus 1
-        </p>
+        <p>Minus 1</p>
       </list-item>
       <list-item>
-        <p>
-          Minus 2
-        </p>
+        <p>Minus 2</p>
       </list-item>
       <list-item>
-        <p>
-          Minus 3
-        </p>
+        <p>Minus 3</p>
       </list-item>
     </list>
   </sec>
   <sec id="ordered">
     <title>Ordered</title>
-    <p>
-      Tight:
-    </p>
+    <p>Tight:</p>
     <list list-type="order">
       <list-item>
-        <p>
-          First
-        </p>
+        <p>First</p>
       </list-item>
       <list-item>
-        <p>
-          Second
-        </p>
+        <p>Second</p>
       </list-item>
       <list-item>
-        <p>
-          Third
-        </p>
+        <p>Third</p>
       </list-item>
     </list>
-    <p>
-      and:
-    </p>
+    <p>and:</p>
     <list list-type="order">
       <list-item>
-        <p>
-          One
-        </p>
+        <p>One</p>
       </list-item>
       <list-item>
-        <p>
-          Two
-        </p>
+        <p>Two</p>
       </list-item>
       <list-item>
-        <p>
-          Three
-        </p>
+        <p>Three</p>
       </list-item>
     </list>
-    <p>
-      Loose using tabs:
-    </p>
+    <p>Loose using tabs:</p>
     <list list-type="order">
       <list-item>
-        <p>
-          First
-        </p>
+        <p>First</p>
       </list-item>
       <list-item>
-        <p>
-          Second
-        </p>
+        <p>Second</p>
       </list-item>
       <list-item>
-        <p>
-          Third
-        </p>
+        <p>Third</p>
       </list-item>
     </list>
-    <p>
-      and using spaces:
-    </p>
+    <p>and using spaces:</p>
     <list list-type="order">
       <list-item>
-        <p>
-          One
-        </p>
+        <p>One</p>
       </list-item>
       <list-item>
-        <p>
-          Two
-        </p>
+        <p>Two</p>
       </list-item>
       <list-item>
-        <p>
-          Three
-        </p>
+        <p>Three</p>
       </list-item>
     </list>
-    <p>
-      Multiple paragraphs:
-    </p>
+    <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>
+        <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>
+        <p>Item 2.</p>
       </list-item>
       <list-item>
-        <p>
-          Item 3.
-        </p>
+        <p>Item 3.</p>
       </list-item>
     </list>
   </sec>
@@ -396,97 +266,63 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
     <title>Nested</title>
     <list list-type="bullet">
       <list-item>
-        <p>
-          Tab
-        </p>
+        <p>Tab</p>
         <list list-type="bullet">
           <list-item>
-            <p>
-              Tab
-            </p>
+            <p>Tab</p>
             <list list-type="bullet">
               <list-item>
-                <p>
-                  Tab
-                </p>
+                <p>Tab</p>
               </list-item>
             </list>
           </list-item>
         </list>
       </list-item>
     </list>
-    <p>
-      Here’s another:
-    </p>
+    <p>Here’s another:</p>
     <list list-type="order">
       <list-item>
-        <p>
-          First
-        </p>
+        <p>First</p>
       </list-item>
       <list-item>
-        <p>
-          Second:
-        </p>
+        <p>Second:</p>
         <list list-type="bullet">
           <list-item>
-            <p>
-              Fee
-            </p>
+            <p>Fee</p>
           </list-item>
           <list-item>
-            <p>
-              Fie
-            </p>
+            <p>Fie</p>
           </list-item>
           <list-item>
-            <p>
-              Foe
-            </p>
+            <p>Foe</p>
           </list-item>
         </list>
       </list-item>
       <list-item>
-        <p>
-          Third
-        </p>
+        <p>Third</p>
       </list-item>
     </list>
-    <p>
-      Same thing but with paragraphs:
-    </p>
+    <p>Same thing but with paragraphs:</p>
     <list list-type="order">
       <list-item>
-        <p>
-          First
-        </p>
+        <p>First</p>
       </list-item>
       <list-item>
-        <p>
-          Second:
-        </p>
+        <p>Second:</p>
         <list list-type="bullet">
           <list-item>
-            <p>
-              Fee
-            </p>
+            <p>Fee</p>
           </list-item>
           <list-item>
-            <p>
-              Fie
-            </p>
+            <p>Fie</p>
           </list-item>
           <list-item>
-            <p>
-              Foe
-            </p>
+            <p>Foe</p>
           </list-item>
         </list>
       </list-item>
       <list-item>
-        <p>
-          Third
-        </p>
+        <p>Third</p>
       </list-item>
     </list>
   </sec>
@@ -494,24 +330,16 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
     <title>Tabs and spaces</title>
     <list list-type="bullet">
       <list-item>
-        <p>
-          this is a list item indented with tabs
-        </p>
+        <p>this is a list item indented with tabs</p>
       </list-item>
       <list-item>
-        <p>
-          this is a list item indented with spaces
-        </p>
+        <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>
+            <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>
+            <p>this is an example list item indented with spaces</p>
           </list-item>
         </list>
       </list-item>
@@ -521,90 +349,50 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
     <title>Fancy list markers</title>
     <list list-type="order">
       <list-item>
-        <label>
-          (2)
-        </label>
-        <p>
-          begins with 2
-        </p>
+        <label>(2)</label>
+        <p>begins with 2</p>
       </list-item>
       <list-item>
-        <label>
-          (3)
-        </label>
-        <p>
-          and now 3
-        </p>
-        <p>
-          with a continuation
-        </p>
+        <label>(3)</label>
+        <p>and now 3</p>
+        <p>with a continuation</p>
         <list list-type="roman-lower">
           <list-item>
-            <label>
-              iv.
-            </label>
-            <p>
-              sublist with roman numerals, starting with 4
-            </p>
+            <label>iv.</label>
+            <p>sublist with roman numerals, starting with 4</p>
           </list-item>
           <list-item>
-            <label>
-              v.
-            </label>
-            <p>
-              more items
-            </p>
+            <label>v.</label>
+            <p>more items</p>
             <list list-type="alpha-upper">
               <list-item>
-                <label>
-                  (A)
-                </label>
-                <p>
-                  a subsublist
-                </p>
+                <label>(A)</label>
+                <p>a subsublist</p>
               </list-item>
               <list-item>
-                <label>
-                  (B)
-                </label>
-                <p>
-                  a subsublist
-                </p>
+                <label>(B)</label>
+                <p>a subsublist</p>
               </list-item>
             </list>
           </list-item>
         </list>
       </list-item>
     </list>
-    <p>
-      Nesting:
-    </p>
+    <p>Nesting:</p>
     <list list-type="alpha-upper">
       <list-item>
-        <p>
-          Upper Alpha
-        </p>
+        <p>Upper Alpha</p>
         <list list-type="roman-upper">
           <list-item>
-            <p>
-              Upper Roman.
-            </p>
+            <p>Upper Roman.</p>
             <list list-type="order">
               <list-item>
-                <label>
-                  (6)
-                </label>
-                <p>
-                  Decimal start with 6
-                </p>
+                <label>(6)</label>
+                <p>Decimal start with 6</p>
                 <list list-type="alpha-lower">
                   <list-item>
-                    <label>
-                      c)
-                    </label>
-                    <p>
-                      Lower alpha with paren
-                    </p>
+                    <label>c)</label>
+                    <p>Lower alpha with paren</p>
                   </list-item>
                 </list>
               </list-item>
@@ -613,277 +401,163 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
         </list>
       </list-item>
     </list>
-    <p>
-      Autonumbering:
-    </p>
+    <p>Autonumbering:</p>
     <list list-type="order">
       <list-item>
-        <p>
-          Autonumber.
-        </p>
+        <p>Autonumber.</p>
       </list-item>
       <list-item>
-        <p>
-          More.
-        </p>
+        <p>More.</p>
         <list list-type="order">
           <list-item>
-            <p>
-              Nested.
-            </p>
+            <p>Nested.</p>
           </list-item>
         </list>
       </list-item>
     </list>
-    <p>
-      Should not be a list item:
-    </p>
-    <p>
-      M.A. 2007
-    </p>
-    <p>
-      B. Williams
-    </p>
+    <p>Should not be a list item:</p>
+    <p>M.A. 2007</p>
+    <p>B. Williams</p>
   </sec>
 </sec>
 <sec id="definition-lists">
   <title>Definition Lists</title>
-  <p>
-    Tight using spaces:
-  </p>
+  <p>Tight using spaces:</p>
   <def-list>
     <def-item>
-      <term>
-        apple
-      </term>
+      <term>apple</term>
       <def>
-        <p>
-          red fruit
-        </p>
+        <p>red fruit</p>
       </def>
     </def-item>
     <def-item>
-      <term>
-        orange
-      </term>
+      <term>orange</term>
       <def>
-        <p>
-          orange fruit
-        </p>
+        <p>orange fruit</p>
       </def>
     </def-item>
     <def-item>
-      <term>
-        banana
-      </term>
+      <term>banana</term>
       <def>
-        <p>
-          yellow fruit
-        </p>
+        <p>yellow fruit</p>
       </def>
     </def-item>
   </def-list>
-  <p>
-    Tight using tabs:
-  </p>
+  <p>Tight using tabs:</p>
   <def-list>
     <def-item>
-      <term>
-        apple
-      </term>
+      <term>apple</term>
       <def>
-        <p>
-          red fruit
-        </p>
+        <p>red fruit</p>
       </def>
     </def-item>
     <def-item>
-      <term>
-        orange
-      </term>
+      <term>orange</term>
       <def>
-        <p>
-          orange fruit
-        </p>
+        <p>orange fruit</p>
       </def>
     </def-item>
     <def-item>
-      <term>
-        banana
-      </term>
+      <term>banana</term>
       <def>
-        <p>
-          yellow fruit
-        </p>
+        <p>yellow fruit</p>
       </def>
     </def-item>
   </def-list>
-  <p>
-    Loose:
-  </p>
+  <p>Loose:</p>
   <def-list>
     <def-item>
-      <term>
-        apple
-      </term>
+      <term>apple</term>
       <def>
-        <p>
-          red fruit
-        </p>
+        <p>red fruit</p>
       </def>
     </def-item>
     <def-item>
-      <term>
-        orange
-      </term>
+      <term>orange</term>
       <def>
-        <p>
-          orange fruit
-        </p>
+        <p>orange fruit</p>
       </def>
     </def-item>
     <def-item>
-      <term>
-        banana
-      </term>
+      <term>banana</term>
       <def>
-        <p>
-          yellow fruit
-        </p>
+        <p>yellow fruit</p>
       </def>
     </def-item>
   </def-list>
-  <p>
-    Multiple blocks with italics:
-  </p>
+  <p>Multiple blocks with italics:</p>
   <def-list>
     <def-item>
-      <term>
-        <italic>apple</italic>
-      </term>
+      <term><italic>apple</italic></term>
       <def>
-        <p>
-          red fruit
-        </p>
-        <p>
-          contains seeds, crisp, pleasant to taste
-        </p>
+        <p>red fruit</p>
+        <p>contains seeds, crisp, pleasant to taste</p>
       </def>
     </def-item>
     <def-item>
-      <term>
-        <italic>orange</italic>
-      </term>
+      <term><italic>orange</italic></term>
       <def>
-        <p>
-          orange fruit
-        </p>
+        <p>orange fruit</p>
         <preformat>{ orange code block }</preformat>
         <disp-quote>
-          <p>
-            orange block quote
-          </p>
+          <p>orange block quote</p>
         </disp-quote>
       </def>
     </def-item>
   </def-list>
-  <p>
-    Multiple definitions, tight:
-  </p>
+  <p>Multiple definitions, tight:</p>
   <def-list>
     <def-item>
-      <term>
-        apple
-      </term>
+      <term>apple</term>
       <def>
-        <p>
-          red fruit
-        </p>
-        <p>
-          computer
-        </p>
+        <p>red fruit</p>
+        <p>computer</p>
       </def>
     </def-item>
     <def-item>
-      <term>
-        orange
-      </term>
+      <term>orange</term>
       <def>
-        <p>
-          orange fruit
-        </p>
-        <p>
-          bank
-        </p>
+        <p>orange fruit</p>
+        <p>bank</p>
       </def>
     </def-item>
   </def-list>
-  <p>
-    Multiple definitions, loose:
-  </p>
+  <p>Multiple definitions, loose:</p>
   <def-list>
     <def-item>
-      <term>
-        apple
-      </term>
+      <term>apple</term>
       <def>
-        <p>
-          red fruit
-        </p>
-        <p>
-          computer
-        </p>
+        <p>red fruit</p>
+        <p>computer</p>
       </def>
     </def-item>
     <def-item>
-      <term>
-        orange
-      </term>
+      <term>orange</term>
       <def>
-        <p>
-          orange fruit
-        </p>
-        <p>
-          bank
-        </p>
+        <p>orange fruit</p>
+        <p>bank</p>
       </def>
     </def-item>
   </def-list>
-  <p>
-    Blank line after term, indented marker, alternate markers:
-  </p>
+  <p>Blank line after term, indented marker, alternate markers:</p>
   <def-list>
     <def-item>
-      <term>
-        apple
-      </term>
+      <term>apple</term>
       <def>
-        <p>
-          red fruit
-        </p>
-        <p>
-          computer
-        </p>
+        <p>red fruit</p>
+        <p>computer</p>
       </def>
     </def-item>
     <def-item>
-      <term>
-        orange
-      </term>
+      <term>orange</term>
       <def>
-        <p>
-          orange fruit
-        </p>
+        <p>orange fruit</p>
         <list list-type="order">
           <list-item>
-            <p>
-              sublist
-            </p>
+            <p>sublist</p>
           </list-item>
           <list-item>
-            <p>
-              sublist
-            </p>
+            <p>sublist</p>
           </list-item>
         </list>
       </def>
@@ -892,555 +566,315 @@ These should not be escaped:  \$ \\ \&gt; \[ \{</preformat>
 </sec>
 <sec id="html-blocks">
   <title>HTML Blocks</title>
-  <p>
-    Simple block on one line:
-  </p>
+  <p>Simple block on one line:</p>
   <boxed-text>
-    <p>
-      foo
-    </p>
+    <p>foo</p>
   </boxed-text>
-  <p>
-    And nested without indentation:
-  </p>
+  <p>And nested without indentation:</p>
   <boxed-text>
     <boxed-text>
       <boxed-text>
-        <p>
-          foo
-        </p>
+        <p>foo</p>
       </boxed-text>
     </boxed-text>
     <boxed-text>
-      <p>
-        bar
-      </p>
+      <p>bar</p>
     </boxed-text>
   </boxed-text>
-  <p>
-    Interpreted markdown in a table:
-  </p>
-  <p>
-    This is <italic>emphasized</italic>
-  </p>
-  <p>
-    And this is <bold role="strong">strong</bold>
-  </p>
-  <p>
-    Here’s a simple block:
-  </p>
+  <p>Interpreted markdown in a table:</p>
+  <p>This is <italic>emphasized</italic></p>
+  <p>And this is <bold role="strong">strong</bold></p>
+  <p>Here’s a simple block:</p>
   <boxed-text>
-    <p>
-      foo
-    </p>
+    <p>foo</p>
   </boxed-text>
-  <p>
-    This should be a code block, though:
-  </p>
+  <p>This should be a code block, though:</p>
   <preformat>&lt;div&gt;
     foo
 &lt;/div&gt;</preformat>
-  <p>
-    As should this:
-  </p>
+  <p>As should this:</p>
   <preformat>&lt;div&gt;foo&lt;/div&gt;</preformat>
-  <p>
-    Now, nested:
-  </p>
+  <p>Now, nested:</p>
   <boxed-text>
     <boxed-text>
       <boxed-text>
-        <p>
-          foo
-        </p>
+        <p>foo</p>
       </boxed-text>
     </boxed-text>
   </boxed-text>
-  <p>
-    This should just be an HTML comment:
-  </p>
-  <p>
-    Multiline:
-  </p>
-  <p>
-    Code block:
-  </p>
+  <p>This should just be an HTML comment:</p>
+  <p>Multiline:</p>
+  <p>Code block:</p>
   <preformat>&lt;!-- Comment --&gt;</preformat>
-  <p>
-    Just plain comment, with trailing spaces on the line:
-  </p>
-  <p>
-    Code:
-  </p>
+  <p>Just plain comment, with trailing spaces on the line:</p>
+  <p>Code:</p>
   <preformat>&lt;hr /&gt;</preformat>
-  <p>
-    Hr’s:
-  </p>
+  <p>Hr’s:</p>
 </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>
-    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>
-    <strike>This is <italic>strikeout</italic>.</strike>
-  </p>
-  <p>
-    Superscripts: a<sup>bc</sup>d a<sup><italic>hello</italic></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>
+  <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>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><strike>This is <italic>strikeout</italic>.</strike></p>
+  <p>Superscripts: a<sup>bc</sup>d a<sup><italic>hello</italic></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>
 </sec>
 <sec id="smart-quotes-ellipses-dashes">
   <title>Smart quotes, ellipses, dashes</title>
-  <p>
-    “Hello,” said the spider. “‘Shelob’ is my name.”
-  </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, “I want to go.”’ Were you alive in the 70’s?
-  </p>
-  <p>
-    Here is some quoted ‘<monospace>code</monospace>’ and a
-    “<ext-link ext-link-type="uri" xlink:href="http://example.com/?foo=1&amp;bar=2">quoted
-    link</ext-link>”.
-  </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>
+  <p>“Hello,” said the spider. “‘Shelob’ is my name.”</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, “I want to go.”’ Were you alive in the 70’s?</p>
+  <p>Here is some quoted ‘<monospace>code</monospace>’ and a
+  “<ext-link ext-link-type="uri" xlink:href="http://example.com/?foo=1&amp;bar=2">quoted
+  link</ext-link>”.</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>
-      </p>
+      <p></p>
     </list-item>
     <list-item>
-      <p>
-        <inline-formula><alternatives>
-        <tex-math><![CDATA[2+2=4]]></tex-math>
-        <mml:math display="inline" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mn>2</mml:mn><mml:mo>+</mml:mo><mml:mn>2</mml:mn><mml:mo>=</mml:mo><mml:mn>4</mml:mn></mml:mrow></mml:math></alternatives></inline-formula>
-      </p>
+      <p><inline-formula><alternatives>
+      <tex-math><![CDATA[2+2=4]]></tex-math>
+      <mml:math display="inline" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mn>2</mml:mn><mml:mo>+</mml:mo><mml:mn>2</mml:mn><mml:mo>=</mml:mo><mml:mn>4</mml:mn></mml:mrow></mml:math></alternatives></inline-formula></p>
     </list-item>
     <list-item>
-      <p>
-        <inline-formula><alternatives>
-        <tex-math><![CDATA[x \in y]]></tex-math>
-        <mml:math display="inline" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mi>x</mml:mi><mml:mo>∈</mml:mo><mml:mi>y</mml:mi></mml:mrow></mml:math></alternatives></inline-formula>
-      </p>
+      <p><inline-formula><alternatives>
+      <tex-math><![CDATA[x \in y]]></tex-math>
+      <mml:math display="inline" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mi>x</mml:mi><mml:mo>∈</mml:mo><mml:mi>y</mml:mi></mml:mrow></mml:math></alternatives></inline-formula></p>
     </list-item>
     <list-item>
-      <p>
-        <inline-formula><alternatives>
-        <tex-math><![CDATA[\alpha \wedge \omega]]></tex-math>
-        <mml:math display="inline" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mi>α</mml:mi><mml:mo>∧</mml:mo><mml:mi>ω</mml:mi></mml:mrow></mml:math></alternatives></inline-formula>
-      </p>
+      <p><inline-formula><alternatives>
+      <tex-math><![CDATA[\alpha \wedge \omega]]></tex-math>
+      <mml:math display="inline" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mi>α</mml:mi><mml:mo>∧</mml:mo><mml:mi>ω</mml:mi></mml:mrow></mml:math></alternatives></inline-formula></p>
     </list-item>
     <list-item>
-      <p>
-        <inline-formula><alternatives>
-        <tex-math><![CDATA[223]]></tex-math>
-        <mml:math display="inline" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mn>223</mml:mn></mml:math></alternatives></inline-formula>
-      </p>
+      <p><inline-formula><alternatives>
+      <tex-math><![CDATA[223]]></tex-math>
+      <mml:math display="inline" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mn>223</mml:mn></mml:math></alternatives></inline-formula></p>
     </list-item>
     <list-item>
-      <p>
-        <inline-formula><alternatives>
-        <tex-math><![CDATA[p]]></tex-math>
-        <mml:math display="inline" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mi>p</mml:mi></mml:math></alternatives></inline-formula>-Tree
-      </p>
+      <p><inline-formula><alternatives>
+      <tex-math><![CDATA[p]]></tex-math>
+      <mml:math display="inline" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mi>p</mml:mi></mml:math></alternatives></inline-formula>-Tree</p>
     </list-item>
     <list-item>
-      <p>
-        Here’s some display math: <disp-formula><alternatives>
-        <tex-math><![CDATA[\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}]]></tex-math>
-        <mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mfrac><mml:mi>d</mml:mi><mml:mrow><mml:mi>d</mml:mi><mml:mi>x</mml:mi></mml:mrow></mml:mfrac><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>=</mml:mo><mml:munder><mml:mo>lim</mml:mo><mml:mrow><mml:mi>h</mml:mi><mml:mo>→</mml:mo><mml:mn>0</mml:mn></mml:mrow></mml:munder><mml:mfrac><mml:mrow><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo>+</mml:mo><mml:mi>h</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>−</mml:mo><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo></mml:mrow><mml:mi>h</mml:mi></mml:mfrac></mml:mrow></mml:math></alternatives></disp-formula>
-      </p>
+      <p>Here’s some display math: <disp-formula><alternatives>
+      <tex-math><![CDATA[\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}]]></tex-math>
+      <mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mfrac><mml:mi>d</mml:mi><mml:mrow><mml:mi>d</mml:mi><mml:mi>x</mml:mi></mml:mrow></mml:mfrac><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>=</mml:mo><mml:munder><mml:mo>lim</mml:mo><mml:mrow><mml:mi>h</mml:mi><mml:mo>→</mml:mo><mml:mn>0</mml:mn></mml:mrow></mml:munder><mml:mfrac><mml:mrow><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo>+</mml:mo><mml:mi>h</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo><mml:mo>−</mml:mo><mml:mi>f</mml:mi><mml:mo stretchy="false" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="false" form="postfix">)</mml:mo></mml:mrow><mml:mi>h</mml:mi></mml:mfrac></mml:mrow></mml:math></alternatives></disp-formula></p>
     </list-item>
     <list-item>
-      <p>
-        Here’s one that has a line break in it: <inline-formula><alternatives>
-        <tex-math><![CDATA[\alpha + \omega \times x^2]]></tex-math>
-        <mml:math display="inline" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mi>α</mml:mi><mml:mo>+</mml:mo><mml:mi>ω</mml:mi><mml:mo>×</mml:mo><mml:msup><mml:mi>x</mml:mi><mml:mn>2</mml:mn></mml:msup></mml:mrow></mml:math></alternatives></inline-formula>.
-      </p>
+      <p>Here’s one that has a line break in it:
+      <inline-formula><alternatives>
+      <tex-math><![CDATA[\alpha + \omega \times x^2]]></tex-math>
+      <mml:math display="inline" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mi>α</mml:mi><mml:mo>+</mml:mo><mml:mi>ω</mml:mi><mml:mo>×</mml:mo><mml:msup><mml:mi>x</mml:mi><mml:mn>2</mml:mn></mml:msup></mml:mrow></mml:math></alternatives></inline-formula>.</p>
     </list-item>
   </list>
-  <p>
-    These shouldn’t be math:
-  </p>
+  <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>
+      <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 “lot” is emphasized.)
-      </p>
+      <p>$22,000 is a <italic>lot</italic> of money. So is $34,000. (It worked
+      if “lot” is emphasized.)</p>
     </list-item>
     <list-item>
-      <p>
-        Shoes ($20) and socks ($5).
-      </p>
+      <p>Shoes ($20) and socks ($5).</p>
     </list-item>
     <list-item>
-      <p>
-        Escaped <monospace>$</monospace>: $73 <italic>this should be
-        emphasized</italic> 23$.
-      </p>
+      <p>Escaped <monospace>$</monospace>: $73 <italic>this should be
+      emphasized</italic> 23$.</p>
     </list-item>
   </list>
-  <p>
-    Here’s a LaTeX table:
-  </p>
+  <p>Here’s a LaTeX table:</p>
 </sec>
 <sec id="special-characters">
   <title>Special Characters</title>
-  <p>
-    Here is some unicode:
-  </p>
+  <p>Here is some unicode:</p>
   <list list-type="bullet">
     <list-item>
-      <p>
-        I hat: Î
-      </p>
+      <p>I hat: Î</p>
     </list-item>
     <list-item>
-      <p>
-        o umlaut: ö
-      </p>
+      <p>o umlaut: ö</p>
     </list-item>
     <list-item>
-      <p>
-        section: §
-      </p>
+      <p>section: §</p>
     </list-item>
     <list-item>
-      <p>
-        set membership: ∈
-      </p>
+      <p>set membership: ∈</p>
     </list-item>
     <list-item>
-      <p>
-        copyright: ©
-      </p>
+      <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>
+  <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>
-      <ext-link ext-link-type="uri" xlink:href="/url/with_underscore">with_underscore</ext-link>
-    </p>
-    <p>
-      <ext-link ext-link-type="uri" xlink:href="mailto:nobody@nowhere.net">Email
-      link</ext-link>
-    </p>
-    <p>
-      <ext-link ext-link-type="uri" xlink:href="">Empty</ext-link>.
-    </p>
+    <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><ext-link ext-link-type="uri" xlink:href="/url/with_underscore">with_underscore</ext-link></p>
+    <p><ext-link ext-link-type="uri" xlink:href="mailto:nobody@nowhere.net">Email
+    link</ext-link></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>
-      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>
+    <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>
+    <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>
+    <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>
+    <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>
+        <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>
+        <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>
+        <p>It should.</p>
       </list-item>
     </list>
-    <p>
-      An e-mail address: <email>nobody@nowhere.net</email>
-    </p>
+    <p>An e-mail address: <email>nobody@nowhere.net</email></p>
     <disp-quote>
-      <p>
-        Blockquoted:
-        <ext-link ext-link-type="uri" xlink:href="http://example.com/">http://example.com/</ext-link>
-      </p>
+      <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>
+    <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 “Voyage dans la Lune” by Georges Melies (1902):
-  </p>
+  <p>From “Voyage dans la Lune” by Georges Melies (1902):</p>
   <fig>
     <caption>lalune</caption>
     <graphic mimetype="image" mime-subtype="jpeg" xlink:href="lalune.jpg" xlink:title="Voyage dans la Lune" />
   </fig>
-  <p>
-    Here is a movie
-    <inline-graphic mimetype="image" mime-subtype="jpeg" xlink:href="movie.jpg" />
-    icon.
-  </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,<fn>
-      <p>
-        Here is the footnote. It can go anywhere after the footnote reference.
-        It need not be placed at the end of the document.
-      </p>
-    </fn> and another.<fn>
-      <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>
-      <preformat>  { &lt;code&gt; }</preformat>
-      <p>
-        If you want, you can indent every line, but you can also be lazy and
-        just indent the first line of each block.
-      </p>
-    </fn> This should <italic>not</italic> be a footnote reference, because it
-    contains a space.[^my note] Here is an inline note.<fn>
-      <p>
-        This is <italic>easier</italic> to type. Inline notes may contain
-        <ext-link ext-link-type="uri" xlink:href="http://google.com">links</ext-link>
-        and <monospace>]</monospace> verbatim characters, as well as
-        [bracketed text].
-      </p>
-    </fn>
-  </p>
+  <p>Here is a footnote reference,<fn>
+    <p>Here is the footnote. It can go anywhere after the footnote reference.
+    It need not be placed at the end of the document.</p>
+  </fn> and another.<fn>
+    <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>
+    <preformat>  { &lt;code&gt; }</preformat>
+    <p>If you want, you can indent every line, but you can also be lazy and
+    just indent the first line of each block.</p>
+  </fn> This should <italic>not</italic> be a footnote reference, because it
+  contains a space.[^my note] Here is an inline note.<fn>
+    <p>This is <italic>easier</italic> to type. Inline notes may contain
+    <ext-link ext-link-type="uri" xlink:href="http://google.com">links</ext-link>
+    and <monospace>]</monospace> verbatim characters, as well as [bracketed
+    text].</p>
+  </fn></p>
   <disp-quote>
-    <p>
-      Notes can go in quotes.<fn>
-        <p>
-          In quote.
-        </p>
-      </fn>
-    </p>
+    <p>Notes can go in quotes.<fn>
+      <p>In quote.</p>
+    </fn></p>
   </disp-quote>
   <list list-type="order">
     <list-item>
-      <p>
-        And in list items.<fn>
-          <p>
-            In list.
-          </p>
-        </fn>
-      </p>
+      <p>And in list items.<fn>
+        <p>In list.</p>
+      </fn></p>
     </list-item>
   </list>
-  <p>
-    This paragraph should not be part of the note, as it is not indented.
-  </p>
+  <p>This paragraph should not be part of the note, as it is not indented.</p>
 </sec>
 </body>
 <back>
diff --git a/test/writer.ms b/test/writer.ms
index 7e079c55d..e7ac44bb9 100644
--- a/test/writer.ms
+++ b/test/writer.ms
@@ -67,12 +67,15 @@ Pandoc Test Suite
 John MacFarlane
 .AU
 Anonymous
-.ND "July 17, 2006"
+.AU
+.sp 0.5
+.ft R
+July 17, 2006
 .\" 1 column (use .2C for two column)
 .1C
 .LP
 This is a set of tests for pandoc.
-Most of them are adapted from John Gruber's markdown test suite.
+Most of them are adapted from John Gruber’s markdown test suite.
 .HLINE
 .SH 1
 Headers
@@ -86,7 +89,7 @@ Level 2 with an \c
 .pdfhref O 2 "Level 2 with an embedded link"
 .pdfhref M "level-2-with-an-embedded-link"
 .SH 3
-Level 3 with \f[I]emphasis\f[]
+Level 3 with \f[BI]emphasis\f[B]
 .pdfhref O 3 "Level 3 with emphasis"
 .pdfhref M "level-3-with-emphasis"
 .SH 4
@@ -102,7 +105,7 @@ Level 1
 .pdfhref O 1 "Level 1"
 .pdfhref M "level-1"
 .SH 2
-Level 2 with \f[I]emphasis\f[]
+Level 2 with \f[BI]emphasis\f[B]
 .pdfhref O 2 "Level 2 with emphasis"
 .pdfhref M "level-2-with-emphasis"
 .SH 3
@@ -123,15 +126,15 @@ Paragraphs
 .pdfhref O 1 "Paragraphs"
 .pdfhref M "paragraphs"
 .LP
-Here's a regular paragraph.
+Here’s a regular paragraph.
 .PP
 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
+Because a hard-wrapped line in the middle of a paragraph looked like a list
 item.
 .PP
-Here's one with a bullet.
+Here’s one with a bullet.
 * criminey.
 .PP
 There should be a hard line break
@@ -143,7 +146,7 @@ Block Quotes
 .pdfhref O 1 "Block Quotes"
 .pdfhref M "block-quotes"
 .LP
-E\-mail style:
+E-mail style:
 .RS
 .LP
 This is a block quote.
@@ -191,7 +194,7 @@ Code:
 .IP
 .nf
 \f[C]
-\-\-\-\-\ (should\ be\ four\ hyphens)
+----\ (should\ be\ four\ hyphens)
 
 sub\ status\ {
 \ \ \ \ print\ \[dq]working\[dq];
@@ -311,7 +314,7 @@ Item 1, graf one.
 .PP
 Item 1.
 graf two.
-The quick brown fox jumped over the lazy dog's back.
+The quick brown fox jumped over the lazy dog’s back.
 .RE
 .IP " 2." 4
 Item 2.
@@ -332,7 +335,7 @@ Tab
 .RE
 .RE
 .LP
-Here's another:
+Here’s another:
 .IP " 1." 4
 First
 .IP " 2." 4
@@ -481,13 +484,13 @@ yellow fruit
 .RE
 .LP
 Multiple blocks with italics:
-.IP "\f[I]apple\f[]"
+.IP "\f[I]apple\f[R]"
 red fruit
 .RS
 .PP
 contains seeds, crisp, pleasant to taste
 .RE
-.IP "\f[I]orange\f[]"
+.IP "\f[I]orange\f[R]"
 orange fruit
 .RS
 .IP
@@ -564,10 +567,10 @@ foo
 bar
 .LP
 Interpreted markdown in a table:
-This is \f[I]emphasized\f[]
-And this is \f[B]strong\f[]
+This is \f[I]emphasized\f[R]
+And this is \f[B]strong\f[R]
 .PP
-Here's a simple block:
+Here’s a simple block:
 .LP
 foo
 .LP
@@ -600,7 +603,7 @@ Code block:
 .IP
 .nf
 \f[C]
-<!\-\-\ Comment\ \-\->
+<!--\ Comment\ -->
 \f[]
 .fi
 .LP
@@ -614,36 +617,36 @@ Code:
 \f[]
 .fi
 .LP
-Hr's:
+Hr’s:
 .HLINE
 .SH 1
 Inline Markup
 .pdfhref O 1 "Inline Markup"
 .pdfhref M "inline-markup"
 .LP
-This is \f[I]emphasized\f[], and so \f[I]is this\f[].
+This is \f[I]emphasized\f[R], and so \f[I]is this\f[R].
 .PP
-This is \f[B]strong\f[], and so \f[B]is this\f[].
+This is \f[B]strong\f[R], and so \f[B]is this\f[R].
 .PP
 An \f[I]\c
 .pdfhref W -D "/url" -A "\c" \
  -- "emphasized link"
-\&\f[].
+\&\f[R].
 .PP
-\f[B]\f[BI]This is strong and em.\f[B]\f[]
+\f[B]\f[BI]This is strong and em.\f[B]\f[R]
 .PP
-So is \f[B]\f[BI]this\f[B]\f[] word.
+So is \f[B]\f[BI]this\f[B]\f[R] word.
 .PP
-\f[B]\f[BI]This is strong and em.\f[B]\f[]
+\f[B]\f[BI]This is strong and em.\f[B]\f[R]
 .PP
-So is \f[B]\f[BI]this\f[B]\f[] word.
+So is \f[B]\f[BI]this\f[B]\f[R] word.
 .PP
-This is code: \f[C]>\f[], \f[C]$\f[], \f[C]\\\f[], \f[C]\\$\f[],
-\f[C]<html>\f[].
+This is code: \f[C]>\f[R], \f[C]$\f[R], \f[C]\\\f[R], \f[C]\\$\f[R],
+\f[C]<html>\f[R].
 .PP
-\m[strikecolor]This is \f[I]strikeout\f[].\m[]
+\m[strikecolor]This is \f[I]strikeout\f[R].\m[]
 .PP
-Superscripts: a\*{bc\*}d a\*{\f[I]hello\f[]\*} a\*{hello\~there\*}.
+Superscripts: a\*{bc\*}d a\*{\f[I]hello\f[R]\*} a\*{hello\~there\*}.
 .PP
 Subscripts: H\*<2\*>O, H\*<23\*>O, H\*<many\~of\~them\*>O.
 .PP
@@ -663,9 +666,9 @@ Smart quotes, ellipses, dashes
 `Oak,' `elm,' and `beech' are names of trees.
 So is `pine.'
 .PP
-`He said, \[lq]I want to go.\[rq]' Were you alive in the 70's?
+`He said, \[lq]I want to go.\[rq]' Were you alive in the 70’s?
 .PP
-Here is some quoted `\f[C]code\f[]' and a \[lq]\c
+Here is some quoted `\f[C]code\f[R]' and a \[lq]\c
 .pdfhref W -D "http://example.com/?foo=1&bar=2" -A "\c" \
  -- "quoted link"
 \&\[rq].
@@ -690,28 +693,28 @@ LaTeX
 .IP \[bu] 3
 @223@
 .IP \[bu] 3
-@p@\-Tree
+@p@-Tree
 .IP \[bu] 3
-Here's some display math:
+Here’s some display math:
 .EQ
 d over {d x} f ( x ) = lim sub {h -> 0} {f ( x + h ) \[u2212] f ( x )} over h
 .EN
 .IP \[bu] 3
-Here's one that has a line break in it: @alpha + omega times x sup 2@.
+Here’s one that has a line break in it: @alpha + omega times x sup 2@.
 .LP
-These shouldn't be math:
+These shouldn’t be math:
 .IP \[bu] 3
-To get the famous equation, write \f[C]$e\ =\ mc\[ha]2$\f[].
+To get the famous equation, write \f[C]$e\ =\ mc\[ha]2$\f[R].
 .IP \[bu] 3
-$22,000 is a \f[I]lot\f[] of money.
+$22,000 is a \f[I]lot\f[R] of money.
 So is $34,000.
 (It worked if \[lq]lot\[rq] is emphasized.)
 .IP \[bu] 3
 Shoes ($20) and socks ($5).
 .IP \[bu] 3
-Escaped \f[C]$\f[]: $73 \f[I]this should be emphasized\f[] 23$.
+Escaped \f[C]$\f[R]: $73 \f[I]this should be emphasized\f[R] 23$.
 .LP
-Here's a LaTeX table:
+Here’s a LaTeX table:
 .HLINE
 .SH 1
 Special Characters
@@ -760,7 +763,7 @@ Left paren: (
 .PP
 Right paren: )
 .PP
-Greater\-than: >
+Greater-than: >
 .PP
 Hash: #
 .PP
@@ -770,7 +773,7 @@ Bang: !
 .PP
 Plus: +
 .PP
-Minus: \-
+Minus: -
 .HLINE
 .SH 1
 Links
@@ -882,22 +885,22 @@ With ampersands
 .pdfhref O 2 "With ampersands"
 .pdfhref M "with-ampersands"
 .LP
-Here's a \c
+Here’s a \c
 .pdfhref W -D "http://example.com/?foo=1&bar=2" -A "\c" \
  -- "link with an ampersand in the URL"
 \&.
 .PP
-Here's a link with an amersand in the link text: \c
+Here’s a link with an amersand in the link text: \c
 .pdfhref W -D "http://att.com/" -A "\c" \
  -- "AT&T"
 \&.
 .PP
-Here's an \c
+Here’s an \c
 .pdfhref W -D "/script?foo=1&bar=2" -A "\c" \
  -- "inline link"
 \&.
 .PP
-Here's an \c
+Here’s an \c
 .pdfhref W -D "/script?foo=1&bar=2" -A "\c" \
  -- "inline link in pointy braces"
 \&.
@@ -920,7 +923,7 @@ In a list?
 .IP \[bu] 3
 It should.
 .LP
-An e\-mail address: \c
+An e-mail address: \c
 .pdfhref W -D "mailto:nobody%40nowhere.net" -A "\c" \
  -- "nobody\@nowhere.net"
 \&
@@ -932,7 +935,7 @@ Blockquoted: \c
 \&
 .RE
 .LP
-Auto\-links should not occur here: \f[C]<http://example.com/>\f[]
+Auto-links should not occur here: \f[C]<http://example.com/>\f[R]
 .IP
 .nf
 \f[C]
@@ -964,7 +967,7 @@ It need not be placed at the end of the document.
 .FE
 and another.\**
 .FS
-Here's the long note.
+Here’s the long note.
 This one contains multiple blocks.
 .PP
 Subsequent blocks are indented to show that they belong to the footnote (as
@@ -979,14 +982,14 @@ with list items).
 If you want, you can indent every line, but you can also be lazy and just
 indent the first line of each block.
 .FE
-This should \f[I]not\f[] be a footnote reference, because it contains a
+This should \f[I]not\f[R] be a footnote reference, because it contains a
 space.[\[ha]my note] Here is an inline note.\**
 .FS
-This is \f[I]easier\f[] to type.
+This is \f[I]easier\f[R] to type.
 Inline notes may contain \c
 .pdfhref W -D "http://google.com" -A "\c" \
  -- "links"
-\& and \f[C]]\f[] verbatim characters, as well as [bracketed text].
+\& and \f[C]]\f[R] verbatim characters, as well as [bracketed text].
 .FE
 .RS
 .LP
diff --git a/test/writer.muse b/test/writer.muse
index cd6d05432..9492a5517 100644
--- a/test/writer.muse
+++ b/test/writer.muse
@@ -79,7 +79,7 @@ nested
 </quote>
 </quote>
 
-This should not be a block quote: 2 <verbatim>></verbatim> 1.
+This should not be a block quote: 2 > 1.
 
 And a following paragraph.
 
@@ -224,9 +224,9 @@ Same thing but with paragraphs:
     with a continuation
 
     iv. sublist with roman numerals, starting with 4
-    v.  more items
-        A. a subsublist
-        B. a subsublist
+    v. more items
+       A. a subsublist
+       B. a subsublist
 
 Nesting:
 
@@ -514,7 +514,7 @@ Ellipses…and…and….
 * LaTeX
 
  - <literal style="tex">\cite[22-23]{smith.1899}</literal>
- - 2 + 2 <verbatim>=</verbatim> 4
+ - <verbatim>2 + 2 = 4</verbatim>
  - <em>x</em> ∈ <em>y</em>
  - <em>α</em> ∧ <em>ω</em>
  - 223
@@ -562,7 +562,7 @@ This & that.
 
 4 <verbatim><</verbatim> 5.
 
-6 <verbatim>></verbatim> 5.
+6 > 5.
 
 Backslash: \
 
@@ -576,15 +576,15 @@ Left brace: {
 
 Right brace: }
 
-Left bracket: <verbatim>[</verbatim>
+Left bracket: [
 
-Right bracket: <verbatim>]</verbatim>
+Right bracket: ]
 
 Left paren: (
 
 Right paren: )
 
-Greater-than: <verbatim>></verbatim>
+Greater-than: >
 
 Hash: <verbatim>#</verbatim>
 
@@ -634,7 +634,7 @@ Indented [[/url][twice]].
 
 Indented [[/url][thrice]].
 
-This should <verbatim>[not][]</verbatim> be a link.
+This should [not][] be a link.
 
 <example>
 [not]: /url
@@ -690,8 +690,8 @@ Here is a movie [[movie.jpg][movie]] icon.
 * Footnotes
 
 Here is a footnote reference,[1] and another.[2] This should <em>not</em> be a
-footnote reference, because it contains a <verbatim>space.[^my</verbatim>
-<verbatim>note]</verbatim> Here is an inline note.[3]
+footnote reference, because it contains a space.[^my note] Here is an inline
+note.[3]
 
 <quote>
 Notes can go in quotes.[4]
@@ -718,7 +718,7 @@ This paragraph should not be part of the note, as it is not indented.
 
 [3] This is <em>easier</em> to type. Inline notes may contain
     [[http://google.com][links]] and <code>]</code> verbatim characters, as
-    well as <verbatim>[bracketed</verbatim> <verbatim>text].</verbatim>
+    well as [bracketed text].
 
 [4] In quote.
 
diff --git a/test/writer.rst b/test/writer.rst
index 93158f0c3..0c986b887 100644
--- a/test/writer.rst
+++ b/test/writer.rst
@@ -69,30 +69,30 @@ Block Quotes
 
 E-mail style:
 
-    This is a block quote. It is pretty short.
+   This is a block quote. It is pretty short.
 
 ..
 
-    Code in a block quote:
+   Code in a block quote:
 
-    ::
+   ::
 
-        sub status {
-            print "working";
-        }
+      sub status {
+          print "working";
+      }
 
-    A list:
+   A list:
 
-    1. item one
-    2. item two
+   1. item one
+   2. item two
 
-    Nested block quotes:
+   Nested block quotes:
 
-        nested
+      nested
 
-    ..
+   ..
 
-        nested
+      nested
 
 This should not be a block quote: 2 > 1.
 
@@ -107,21 +107,21 @@ Code:
 
 ::
 
-    ---- (should be four hyphens)
+   ---- (should be four hyphens)
 
-    sub status {
-        print "working";
-    }
+   sub status {
+       print "working";
+   }
 
-    this code block is indented by one tab
+   this code block is indented by one tab
 
 And:
 
 ::
 
-        this code block is indented by two tabs
+       this code block is indented by two tabs
 
-    These should not be escaped:  \$ \\ \> \[ \{
+   These should not be escaped:  \$ \\ \> \[ \{
 
 --------------
 
@@ -302,83 +302,83 @@ Definition Lists
 Tight using spaces:
 
 apple
-    red fruit
+   red fruit
 orange
-    orange fruit
+   orange fruit
 banana
-    yellow fruit
+   yellow fruit
 
 Tight using tabs:
 
 apple
-    red fruit
+   red fruit
 orange
-    orange fruit
+   orange fruit
 banana
-    yellow fruit
+   yellow fruit
 
 Loose:
 
 apple
-    red fruit
+   red fruit
 
 orange
-    orange fruit
+   orange fruit
 
 banana
-    yellow fruit
+   yellow fruit
 
 Multiple blocks with italics:
 
 *apple*
-    red fruit
+   red fruit
 
-    contains seeds, crisp, pleasant to taste
+   contains seeds, crisp, pleasant to taste
 
 *orange*
-    orange fruit
+   orange fruit
 
-    ::
+   ::
 
-        { orange code block }
+      { orange code block }
 
-    ..
+   ..
 
-        orange block quote
+      orange block quote
 
 Multiple definitions, tight:
 
 apple
-    red fruit
-    computer
+   red fruit
+   computer
 orange
-    orange fruit
-    bank
+   orange fruit
+   bank
 
 Multiple definitions, loose:
 
 apple
-    red fruit
+   red fruit
 
-    computer
+   computer
 
 orange
-    orange fruit
+   orange fruit
 
-    bank
+   bank
 
 Blank line after term, indented marker, alternate markers:
 
 apple
-    red fruit
+   red fruit
 
-    computer
+   computer
 
 orange
-    orange fruit
+   orange fruit
 
-    1. sublist
-    2. sublist
+   1. sublist
+   2. sublist
 
 HTML Blocks
 ===========
@@ -491,15 +491,15 @@ This should be a code block, though:
 
 ::
 
-    <div>
-        foo
-    </div>
+   <div>
+       foo
+   </div>
 
 As should this:
 
 ::
 
-    <div>foo</div>
+   <div>foo</div>
 
 Now, nested:
 
@@ -554,7 +554,7 @@ Code block:
 
 ::
 
-    <!-- Comment -->
+   <!-- Comment -->
 
 Just plain comment, with trailing spaces on the line:
 
@@ -566,7 +566,7 @@ Code:
 
 ::
 
-    <hr />
+   <hr />
 
 Hr’s:
 
@@ -615,21 +615,21 @@ This is *emphasized*, and so *is this*.
 
 This is **strong**, and so **is this**.
 
-An *`emphasized link </url>`__*.
+An `emphasized link </url>`__.
 
-***This is strong and em.***
+**This is strong and em.**
 
-So is ***this*** word.
+So is **this** word.
 
-***This is strong and em.***
+**This is strong and em.**
 
-So is ***this*** word.
+So is **this** word.
 
 This is code: ``>``, ``$``, ``\``, ``\$``, ``<html>``.
 
-[STRIKEOUT:This is *strikeout*.]
+[STRIKEOUT:This is strikeout.]
 
-Superscripts: a\ :sup:`bc`\ d a\ :sup:`*hello*` a\ :sup:`hello there`.
+Superscripts: a\ :sup:`bc`\ d a\ :sup:`hello` a\ :sup:`hello there`.
 
 Subscripts: H\ :sub:`2`\ O, H\ :sub:`23`\ O, H\ :sub:`many of them`\ O.
 
@@ -793,7 +793,7 @@ This should [not][] be a link.
 
 ::
 
-    [not]: /url
+   [not]: /url
 
 Foo `bar </url/>`__.
 
@@ -822,13 +822,13 @@ With an ampersand: http://example.com/?foo=1&bar=2
 
 An e-mail address: nobody@nowhere.net
 
-    Blockquoted: http://example.com/
+   Blockquoted: http://example.com/
 
 Auto-links should not occur here: ``<http://example.com/>``
 
 ::
 
-    or here: <http://example.com/>
+   or here: <http://example.com/>
 
 --------------
 
@@ -853,7 +853,7 @@ Here is a footnote reference, [1]_ and another. [2]_ This should *not* be a
 footnote reference, because it contains a space.[^my note] Here is an inline
 note. [3]_
 
-    Notes can go in quotes. [4]_
+   Notes can go in quotes. [4]_
 
 1. And in list items. [5]_
 
@@ -871,7 +871,7 @@ This paragraph should not be part of the note, as it is not indented.
 
    ::
 
-         { <code> }
+        { <code> }
 
    If you want, you can indent every line, but you can also be lazy and just
    indent the first line of each block.
diff --git a/test/writers-lang-and-dir.context b/test/writers-lang-and-dir.context
index a1c87bb27..3b29763d7 100644
--- a/test/writers-lang-and-dir.context
+++ b/test/writers-lang-and-dir.context
@@ -19,7 +19,7 @@
 
 \setupbodyfontenvironment[default][em=italic] % use italic as em, not slanted
 
-\definefallbackfamily[mainface][rm][DejaVu Serif][preset=range:greek, force=yes]
+\definefallbackfamily[mainface][rm][CMU Serif][preset=range:greek, force=yes]
 \definefontfamily[mainface][rm][Latin Modern Roman]
 \definefontfamily[mainface][mm][Latin Modern Math]
 \definefontfamily[mainface][ss][Latin Modern Sans]
diff --git a/test/writers-lang-and-dir.latex b/test/writers-lang-and-dir.latex
index 97c34010c..9a31a7df8 100644
--- a/test/writers-lang-and-dir.latex
+++ b/test/writers-lang-and-dir.latex
@@ -74,8 +74,8 @@
 \fi
 \ifxetex
   % load bidi as late as possible as it modifies e.g. graphicx
-    \usepackage{bidi}
-  \fi
+  \usepackage{bidi}
+\fi
 \ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex
   \TeXXeTstate=1
   \newcommand{\RL}[1]{\beginR #1\endR}
diff --git a/tools/update-readme.lua b/tools/update-readme.lua
index 4f77c59c2..eabaf2285 100644
--- a/tools/update-readme.lua
+++ b/tools/update-readme.lua
@@ -1,38 +1,22 @@
 -- update README.md based on MANUAL.txt
--- assumes that the README.md has a div with id 'description'.
--- this gets replaced by the contents of the 'description' section
--- of the manual.
+-- inserts contents of input-formats and output-formats
+
+local f = assert(io.open("MANUAL.txt", "r"))
+local manual = f:read("*all")
+mdoc = pandoc.read(manual, "markdown")
+f:close()
+result = {}
 
 function Div(elem)
-    if elem.classes[1] and elem.classes[1] == 'description' then
-        local f = assert(io.open("MANUAL.txt", "r"))
-        local manual = f:read("*all")
-        f:close()
-        local description = {}
-        local i = 1
-        local include = false
-        local mdoc = pandoc.read(manual, "markdown")
-        local blocks = mdoc.blocks
-        while blocks[i] do
-            if blocks[i].t == 'Header' then
-                include = false
-            end
-            if include then
-                table.insert(description, pandoc.walk_block(blocks[i],
-                             -- remove internal links
-                             { Link = function(el)
-                                 if el.target:match("^#") then
-                                     return el.content
-                                 end
-                               end }))
-            end
-            if blocks[i].t == 'Header' and
-                blocks[i].identifier == 'description' then
-                    include = true
-            end
-            i = i + 1
-        end
-        return pandoc.Div(description, pandoc.Attr("description",{},{}))
+    local ident = elem.identifier or ""
+    local get = function(el)
+                    if el.identifier == ident then
+                        result = el
+                    end
+                end
+    if ident == 'input-formats' or ident == 'output-formats' then
+      pandoc.walk_block(pandoc.Div(mdoc.blocks), { Div = get })
+      return result
     end
 end
 
diff --git a/trypandoc/trypandoc.hs b/trypandoc/trypandoc.hs
index 5a4828877..a4c21e1f6 100644
--- a/trypandoc/trypandoc.hs
+++ b/trypandoc/trypandoc.hs
@@ -1,5 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Main where
+import Prelude
 import Network.Wai.Handler.CGI
 import Network.Wai
 import Control.Applicative ((<$>))