diff --git a/AUTHORS.md b/AUTHORS.md
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -39,6 +39,8 @@
 - Caleb Mclennan
 - Calvin Beck
 - Carlos Sosa
+- Cécile Chemin
+- Cédric Couralet
 - Chris Black
 - Christian Conkle
 - Christian Despres
@@ -104,6 +106,7 @@
 - J. B. Rainsberger
 - J. Lewis Muir
 - Jaime Marquínez Ferrándiz
+- Jake Zimmerman
 - Jakob Voß
 - James Aspnes
 - Jamie F. Olson
@@ -131,6 +134,7 @@
 - Josef Svenningsson
 - Joseph C. Sible
 - Julien Cretel
+- Juliette Fourcot
 - Juliusz Gonera
 - Justin Bogner
 - Jérémy Bobbio
@@ -143,7 +147,10 @@
 - Krystof Beuermann
 - Herwig Stuetz
 - Lars-Dominik Braun
+- Laurent P. René de Cotret
 - Leif Metcalf
+- Lila
+- Lucas Escot
 - Luke Plant
 - Marc Schreiber
 - Mark Szepieniec
@@ -153,6 +160,7 @@
 - Matej Kollar
 - Mathias Schenner
 - Mathias Walter
+- Mathieu Boespflug
 - Mathieu Duponchelle
 - Matthew Doty
 - Matthew Eddey
@@ -165,8 +173,10 @@
 - Michael Beaumont
 - Michael Chladek
 - Michael Peyton Jones
+- Michael Reed
 - Michael Snoyman
 - Michael Thompson
+- Mike Tzou
 - MinRK
 - Morton Fox
 - Nathan Gass
@@ -201,6 +211,7 @@
 - Recai Oktaş
 - Roland Hieber
 - RyanGlScott
+- Salim B
 - Sascha Wilde
 - Scott Morrison
 - Sebastian Talmon
@@ -224,6 +235,7 @@
 - Tiziano Müller
 - Todd Sifleet
 - Tom Leese
+- Tristan de Cacqueray
 - Tristan Stenner
 - Uli Köhler
 - Urs Liska
@@ -233,6 +245,7 @@
 - Vasily Alferov
 - Viktor Kronvall
 - Vincent
+- Vlad Hanciuta
 - Wandmalfarbe
 - Waldir Pimenta
 - Wikiwide
@@ -242,11 +255,13 @@
 - Yoan Blanc
 - Yuchen Pei
 - Zihang Chen
+- andrebauer
 - blmage
 - bucklereed
 - bumper314
 - chinapedia
 - csforste
+- dbecher-ito
 - d-dorazio
 - ebiim
 - infinity0x
diff --git a/INSTALL.md b/INSTALL.md
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -71,7 +71,7 @@
 
 By default, Pandoc creates PDFs using LaTeX.  Because a full [MacTeX]
 installation uses four gigabytes of disk space, we recommend
-[BasicTeX] or [TinyTeX](https://yihui.name/tinytex/)
+[BasicTeX] or [TinyTeX](https://yihui.org/tinytex/)
 and using the `tlmgr` tool to install additional packages
 as needed.  If you receive errors warning of fonts not found:
 
@@ -400,7 +400,7 @@
 [Cabal User's Guide]: http://www.haskell.org/cabal/release/latest/doc/users-guide/builders.html#setup-configure-paths
 [Debian]: https://packages.debian.org/pandoc
 [Fedora]: https://apps.fedoraproject.org/packages/pandoc
-[FreeBSD ports]: http://www.freshports.org/textproc/pandoc/
+[FreeBSD ports]: http://www.freshports.org/textproc/hs-pandoc/
 [GHC]:  http://www.haskell.org/ghc/
 [GPL]:  http://www.gnu.org/copyleft/gpl.html
 [Haskell platform]: http://hackage.haskell.org/platform/
diff --git a/MANUAL.txt b/MANUAL.txt
--- a/MANUAL.txt
+++ b/MANUAL.txt
@@ -1,7 +1,7 @@
 ---
 title: Pandoc User's Guide
 author: John MacFarlane
-date: March 23, 2020
+date: June 29, 2020
 ---
 
 # Synopsis
@@ -241,7 +241,7 @@
     - `html` ([HTML])
     - `ipynb` ([Jupyter notebook])
     - `jats` ([JATS] XML)
-    - `jira` ([Jira] wiki markup)
+    - `jira` ([Jira]/Confluence wiki markup)
     - `json` (JSON version of native AST)
     - `latex` ([LaTeX])
     - `markdown` ([Pandoc's Markdown])
@@ -298,7 +298,7 @@
     - `jats_articleauthoring` ([JATS] XML, Article Authoring Tag Set)
     - `jats_publishing` ([JATS] XML, Journal Publishing Tag Set)
     - `jats` (alias for `jats_archiving`)
-    - `jira` ([Jira] wiki markup)
+    - `jira` ([Jira]/Confluence wiki markup)
     - `json` (JSON version of native AST)
     - `latex` ([LaTeX])
     - `man` ([roff man])
@@ -386,8 +386,7 @@
 
 `--verbose`
 
-:   Give verbose debugging output.  Currently this only has an effect
-    with PDF output.
+:   Give verbose debugging output.
 
 `--quiet`
 
@@ -903,6 +902,12 @@
     downloaded). If you're behind a proxy, you also need to set
     the environment variable `http_proxy` to `http://...`.
 
+`--no-check-certificate
+
+:   Disable the certificate verification to allow access to 
+    unsecure HTTP resources (for example when the certificate
+    is no longer valid or self signed).
+
 ## Options affecting specific writers {.options}
 
 `--self-contained`
@@ -1265,7 +1270,9 @@
     - `-t latex` or none: `pdflatex` (other options: `xelatex`, `lualatex`,
         `tectonic`, `latexmk`)
     - `-t context`: `context`
-    - `-t html`:  `wkhtmltopdf` (other options: `prince`, `weasyprint`)
+    - `-t html`:  `wkhtmltopdf` (other options: `prince`, `weasyprint`;
+        see [print-css.rocks](https://print-css.rocks) for a good
+        introduction to PDF generation from HTML/CSS.)
     - `-t ms`:  `pdfroff`
 
 `--pdf-engine-opt=`*STRING*
@@ -1808,17 +1815,25 @@
 ### Partials
 
 Partials (subtemplates stored in different files) may be
-included using the syntax
+included by using the name of the partial, followed
+by `()`, for example:
 
 ```
-${ boilerplate() }
+${ styles() }
 ```
 
 Partials will be sought in the directory containing
-the main template, and will be assumed to have the
-same extension as the main template if they lack
-an explicit extension.  (If the partials are not
-found here, they will also be sought in the `templates`
+the main template. The file name will be assumed to
+have the same extension as the main template if it
+lacks an extension. When calling the partial, the
+full name including file extension can also be used:
+
+```
+${ styles.html() }
+```
+
+(If a partial is not found in the directory of the
+template, it will also be sought in the `templates`
 subdirectory of the user data directory.)
 
 Partials may optionally be applied to variables using
@@ -1967,6 +1982,22 @@
 - `reverse`:  Reverses a textual value or array,
   and has no effect on other values.
 
+- `first`: Returns the first value of an array, if
+  applied to a non-empty array; otherwise returns
+  the original value.
+
+- `last`: Returns the last value of an array, if
+  applied to a non-empty array; otherwise returns
+  the original value.
+
+- `rest`: Returns all but the first value of an array, if
+  applied to a non-empty array; otherwise returns
+  the original value.
+
+- `allbutlast`: Returns all but the last value of an array, if
+  applied to a non-empty array; otherwise returns
+  the original value.
+
 - `chomp`:  Removes trailing newlines (and breakable space).
 
 - `nowrap`:  Disables line wrapping on breakable spaces.
@@ -2122,7 +2153,8 @@
 To turn off boolean flags that default to true in reveal.js, use `0`.
 
 `revealjs-url`
-:   base URL for reveal.js documents (defaults to `reveal.js`)
+:   base URL for reveal.js documents (defaults to
+    `https://unpkg.com/reveal.js@^4/`)
 
 `s5-url`
 :   base URL for S5 documents (defaults to `s5/default`)
@@ -2138,7 +2170,7 @@
 :   additional attributes for the title slide of reveal.js slide shows.
     See [background in reveal.js and beamer] for an example.
 
-[reveal.js configuration options]: https://github.com/hakimel/reveal.js#configuration
+[reveal.js configuration options]: https://revealjs.com/config/
 
 ### Variables for Beamer slides
 
@@ -2869,7 +2901,7 @@
 output formats
 :  `odt`, `opendocument`
 
-#### Extension: `styles` #### {#ext-styles}
+#### Extension: `styles` {#ext-styles} ####
 
 When converting from docx, read all docx styles as divs (for
 paragraph styles) and spans (for character styles) regardless
@@ -3793,7 +3825,7 @@
 
 The cells of pipe tables cannot contain block elements like paragraphs
 and lists, and cannot span multiple lines.  If a pipe table contains a
-row whose printable content is wider than the column width (see
+row whose Markdown content is wider than the column width (see
 `--columns`), then the table will take up the full text width and
 the cell contents will wrap, with the relative cell widths determined
 by the number of dashes in the line separating the table header from
@@ -3833,30 +3865,42 @@
 or all three elements. If you want to include an author but no
 title, or a title and a date but no author, you need a blank line:
 
-    %
-    % Author
+```
+%
+% Author
+```
 
-    % My title
-    %
-    % June 15, 2006
+```
+% My title
+%
+% June 15, 2006
+```
 
 The title may occupy multiple lines, but continuation lines must
 begin with leading space, thus:
 
-    % My title
-      on multiple lines
+```
+% My title
+  on multiple lines
+```
 
 If a document has multiple authors, the authors may be put on
 separate lines with leading space, or separated by semicolons, or
 both.  So, all of the following are equivalent:
 
-    % Author One
-      Author Two
+```
+% Author One
+  Author Two
+```
 
-    % Author One; Author Two
+```
+% Author One; Author Two
+```
 
-    % Author One;
-      Author Two
+```
+% Author One;
+  Author Two
+```
 
 The date must fit on one line.
 
@@ -4558,10 +4602,12 @@
 ![](file.jpg){ width=50% }
 ```
 
-- Dimensions are converted to inches for output in page-based formats like
-  LaTeX. Dimensions are converted to pixels for output in HTML-like
-  formats.  Use the `--dpi` option to specify the number of pixels per
-  inch.  The default is 96dpi.
+- Dimensions may be converted to a form that is compatible with
+  the output format (for example, dimensions given in pixels will
+  be converted to inches when converting HTML to LaTeX). Conversion
+  between pixels and physical measurements is affected by the
+  `--dpi` option (by default, 96 dpi is assumed, unless the image
+  itself contains dpi information).
 - The `%` unit is generally relative to some available space.
   For example the above example will render to the following.
   - HTML: `<img href="file.jpg" style="width: 50%;" />`
@@ -5343,6 +5389,41 @@
     :::
     ::::::::::::::
 
+### Additional columns attributes in beamer
+
+The div containers with classes `columns` and `column` can optionally have
+an `align` attribute.
+The class `columns` can optionally have a `totalwidth` attribute or an
+`onlytextwidth` class.
+
+    :::::::::::::: {.columns align=center totalwidth=8em}
+    ::: {.column width="40%"}
+    contents...
+    :::
+    ::: {.column width="60%" align=bottom}
+    contents...
+    :::
+    ::::::::::::::
+
+The `align` attributes on `columns` and `column` can be used with the
+values `top`, `top-baseline`, `center` and `bottom` to vertically align
+the columns. It defaults to `top` in `columns`.
+
+The `totalwidth` attribute limits the width of the columns to the given value.
+
+    :::::::::::::: {.columns align=top .onlytextwidth}
+    ::: {.column width="40%" align=center}
+    contents...
+    :::
+    ::: {.column width="60%"}
+    contents...
+    :::
+    ::::::::::::::
+
+The class `onlytextwidth` sets the `totalwidth` to `\textwidth`.
+
+See Section 12.7 of the [Beamer User's Guide] for more details.
+
 ## Frame attributes in beamer
 
 Sometimes it is necessary to add the LaTeX `[fragile]` option to
@@ -5387,9 +5468,8 @@
 `title-slide-attributes` variable in the YAML metadata block. It must contain
 a map of attribute names and values.
 
-See the [reveal.js
-documentation](https://github.com/hakimel/reveal.js#slide-backgrounds)
-for more details.
+See the [reveal.js documentation](https://revealjs.com/backgrounds/) for more
+details.
 
 For example in reveal.js:
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -50,7 +50,7 @@
     notebook](https://nbformat.readthedocs.io/en/latest/))
   - `jats` ([JATS](https://jats.nlm.nih.gov) XML)
   - `jira`
-    ([Jira](https://jira.atlassian.com/secure/WikiRendererHelpAction.jspa?section=all)
+    ([Jira](https://jira.atlassian.com/secure/WikiRendererHelpAction.jspa?section=all)/Confluence
     wiki markup)
   - `json` (JSON version of native AST)
   - `latex` ([LaTeX](https://www.latex-project.org/))
@@ -124,7 +124,7 @@
     Publishing Tag Set)
   - `jats` (alias for `jats_archiving`)
   - `jira`
-    ([Jira](https://jira.atlassian.com/secure/WikiRendererHelpAction.jspa?section=all)
+    ([Jira](https://jira.atlassian.com/secure/WikiRendererHelpAction.jspa?section=all)/Confluence
     wiki markup)
   - `json` (JSON version of native AST)
   - `latex` ([LaTeX](https://www.latex-project.org/))
diff --git a/cabal.project b/cabal.project
--- a/cabal.project
+++ b/cabal.project
@@ -11,4 +11,4 @@
 source-repository-package
     type: git
     location: https://github.com/jgm/pandoc-citeproc
-    tag: 0.17
+    tag: 0.17.0.1
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,417 @@
 # Revision history for pandoc
 
+## pandoc 2.10 (YYYY-MM-DD)
+
+  * Use pandoc-types 1.21.  This adds two things:
+
+    + A native Underline constructor for Inline (#6277, Vaibhav Sagar).
+    + More expressive types for tables (#1024, Christian Despres).
+      Tables can now take attributes; and rowspans and colspans,
+      column headers, multiple row headers, table head and foot
+      can all be represented.  (Note, however, that reader and
+      writer support for these features is still lacking, so
+      most users won't see any differences in table conversion
+      yet.  These changes just lay the foundation for further
+      improvements.)
+
+  * Support new Underline element in readers and writers (#6277,
+    Vaibhav Sagar).
+
+  * Support new Table type (Christian Despres).
+    The Builder.simpleTable now only adds a row to the TableHead
+    when the given header row is not null. This uncovered an
+    inconsistency in the readers: some would unconditionally
+    emit a header filled with empty cells, even if the header
+    was not present. Now every reader has the conditional
+    behaviour.  Only the XWiki writer depended on the header row
+    being always present; it now pads its head as necessary.
+
+  * Add an option to disable certificate validation (#6156, Cédric Couralet,
+    Cécile Chemin, Juliette Fourcot).  This commit adds the option
+    `--no-check-certificate`, which disables certificate checking when
+    resources are fetched by HTTP.
+
+  * Unify defaults and markdown metadata parsers (#6328, Nikolay
+    Yakimov). Clean up code in Text.Pandoc.Readers.Metadata and
+    properly handle errors in `yamlToMeta`.  This fixes parsing
+    of Boolean fields in metadata withinin defaults files and reduces
+    code duplication.
+
+  * Docbook reader:
+
+    + Implement `<procedure>` (#6442, Mathieu Boespflug).
+    + Implement `<phrase>` (#6438, Mathieu Boespflug).
+    + Treat envar and systemitem like code (#6435, Mathieu Boespflug).
+    + Implement `<replaceable>` (#6437, Mathieu Boespflug)
+    + Map `<simplesect>` to unnumbered section (#6436, Mathieu Boespflug).
+
+  * JATS reader:
+
+    + Handle "label" element in section title (#6288).
+    + Parse abstract element into metadata field of same name
+      (#6480, Albert Krewinkel).
+
+  * Jira reader (Albert Krewinkel):
+
+    + Resolve multiple parsing problems, including issues with empty
+      table cells, faulty recognition of closing emphasis characters, and
+      parsing of image attributes (#6212, #6219, #6220).
+    + Two consecutive markup chars are now parsed verbatim (#6343);
+      styled text must not be empty.
+    + Newlines are no longer allowed within styled text (#6325).
+    + Links to anchors are now parsed as links (#6407).
+    + Retain image attributes (#6234).  Jira images attributes as in
+      `!image.jpg|align=right!` are retained as key-value pairs. Thumbnail
+      images, such as `!example.gif|thumbnail!`, are marked by a
+      `thumbnail` class in their attributes.
+    + Use Underline for inserted text (#6237). Previously, the span was
+      marked with the non-standard class `inserted`.
+    + Improve icon conversion for `(/)`, `(x)`, `(!)`, `(?)`
+      `(+)`, `(-)`, `(off)`, `(*)`. (#6236, #6264).
+    + Support citations, attachment links, and user links (#6231, #6238,
+      #6239).
+    + Resolve parsing issues of blockquote, color (#6233, #6235).
+
+  * HTML reader:
+
+    + Parse attributes into table attributes.
+    + Support `<bdo>` (#5794, Tristan de Cacqueray).
+    + Add `summary` to list of block-level HTML tags (#6385).
+      This improves support for summary/details inside Markdown.
+      NOTE:  you need to include a blank line before the closing
+      `</details>`, if you want the last part of the content to
+      be parsed as a paragraph.
+    + Fix parsing unclosed th elements in a table (#6247).
+
+  * Commonmark reader: Implement `implicit_figures` extension (#6350).
+
+  * Markdown Reader:
+
+    + Fix inline code in lists (#6284, Nikolay Yakimov).
+      Previously inline code containing list markers was sometimes
+      parsed incorrectly.
+    + Don't require blank line after grid table (#6481).
+      This allows grid tables to be enclosed in fenced divs with no
+      intervening blank lines.
+
+  * LaTeX reader:
+
+    + Don't parse beyond `\end{document}` (#6380).
+      This required some internal changes to `\subfile` handling.
+    + Better handling of `\lettrine`.  SmallCaps instead of Span
+      for the part after the initial capital.  Ensure that both
+      arguments are parsed, so that in Markdown both
+      are treated as raw LateX. (Closes #6258.)
+
+  * Org reader (Albert Krewinkel):
+
+    + Recognize images with uppercase extensions (#6472).
+    + Keep unknown keyword lines as raw org.  The lines of unknown
+      keywords, like `#+SOMEWORD: value` are no longer read as metadata,
+      but kept as raw `org` blocks. This ensures that more information
+      is retained when round-tripping org-mode files; additionally,
+      this change makes it possible to support non-standard org
+      extensions via filters.
+    + Unify keyword handling.  Handling of export settings and other
+      keywords (like `#+LINK`) has been combined and unified.
+    + Support `LATEX_HEADER_EXTRA` and `HTML_HEAD_EXTRA`
+      settings.  These export settings are treated like their non-extra
+      counterparts, i.e., the values are added to the `header-includes`
+      metadata list.
+    + Allow multiple `#+SUBTITLE` export settings.  The values of all
+      lines are read as inlines and collected in the `subtitle`
+      metadata field.
+    + Read `#+INSTITUTE` values as text with markup.  The value is
+      stored in the `institute` metadata field and used in the
+      default beamer presentation template.
+    + The behavior of the `#+AUTHOR` and `#+KEYWORD` export
+      settings has changed: Org now allows multiple such lines
+      and adds a space between the contents of each line. Pandoc
+      now always parses these settings as meta inlines; setting
+      values are no longer treated as comma-separated lists.
+      Note that a Lua filter can be used to restore the previous
+      behavior.
+    + Read description lines as inlines (#6485). `#+DESCRIPTION` lines
+      are now treated as text with markup. If multiple such
+      lines are given, then all lines are read and separated by soft
+      linebreaks.
+    + Honor tex export option (#4070).  The `tex` export option can be set
+      with `#+OPTION: tex:nil` and allows three settings:
+      `t` (the default) causes LaTeX fragments to be parsed as TeX or added
+      as raw TeX.  `nil` removes all LaTeX fragments from the document.
+      `verbatim` treats LaTeX as text.
+
+
+  * RST reader:
+
+    + Pass arbitrary attributes through in code blocks (#6465).
+      Exceptions: name (which becomes the id), class (which becomes the
+      classes), and number-lines (which is treated specially to fit
+      with pandoc highlighting).
+    + Handle `date::` directive (#6276).
+
+  * Textile reader: support `pre.` for code blocks (#6454).
+
+  * Ipynb reader:
+
+    + Handle application/pdf output as image (#6430).
+    + Properly handle image/svg+xml as an image (#6430).
+
+  * Docx reader:
+
+    + Distinguish between docx parsing and docx container unpacking errors.
+
+  * MediaWiki reader:
+
+    + Fix `gfm_auto_identifiers` so that `-` is not replaced by `_` (#6335).
+
+  * Vimwiki reader:
+
+    + Add nested syntax highlighting (#6256, Vlad Hanciuta).
+      Nested syntaxes are specified like this:
+      ```
+      {{{sql
+      SELECT * FROM table
+      }}}
+      ```
+      The preformatted code block parser has been extended to check if the
+      first attribute of the block is not a `key=value` pair, and in that
+      case it will be considered as a class.
+
+
+  * Jira writer (Albert Krewinkel):
+
+    + Always escape braces (#6478).  Braces are now always escaped, even
+      within words or when surrounded by whitespace. Jira and
+      Confluence treat braces specially.
+    + Convert Underline to inserted text (`+inserted+`).
+    + Add image attributes (#6234).  Image attributes are added
+      to the output as image parameters. If the image has a
+      class "thumbnail", then a thumbnail image is generated;
+      all other attributes are discarded in this case.
+
+  * LaTeX writer:
+
+    + Ensure that `-M csquotes` works even in fragment mode (#6265).
+    + Escape `^` specially for listings (#6460).
+    + Create hypertarget for links with identifier (#6360).
+    + Distinguish between single and double quotes when using enquote
+      package (#6457, dbecher-ito).
+    + Add support for customizable alignment of columns in beamer (#6331,
+      andrebauer).
+    + Add support for customizable alignment of columns in beamer
+      (#4805, #4150, andrebauer).
+
+  * HTML writer:
+
+    + Use CSS in favor of `<br>` for display math (#6372)
+      Some CSS to ensure that display math is
+      displayed centered and on a new line is now included
+      in the default HTML-based templates; this may be
+      overridden if the user wants a different behavior.
+
+  * Org writer:
+
+    + Clean-up Div handling (Albert Krewinkel).
+
+  * Docx writer:
+
+    + Enable column and row bands for tables (#6371).
+      This change will not have any effect with the default style.
+      However, it enables users to use a style (via a reference.docx)
+      that turns on row and/or column bands.
+
+  * OpenDocument (and ODT) writer:
+
+    + Add custom-style "Abstract" in metadata abstract.
+      This ensures that the abstract is rendered with style Abstract.
+    + Enable custom-style attribute on a Div.
+      This allows you to apply a custom style to contained paragraphs.
+
+  * DocBook writer:
+
+    + Add id of figure to enclosed image.
+    + Add personname element to docbook author (#6244).
+
+  * FB2 writer:
+
+    + Properly handle cover-image containing spaces (#6391).
+
+  * Markdown writer:
+
+    + Ensure consistent padding for pipe tables (#6240).
+    + Avoid unnecessary escapes before intraword `_` when
+      `intraword_underscores` extension is enabled (#6296).
+
+  * RST writer:
+
+    + Properly handle images with same alt text (#6194).
+      Previously we created duplicate references for these in rendering RST.
+
+  * AsciiDoc writer:
+
+    + Add blank line after Div (#6308).
+
+  * Haddock Writer:
+
+    + Support Haddock tables (Joe Hermaszewski).
+      See this PR on Haddock for details on the table format:
+      <https://github.com/haskell/haddock/pull/718>.
+
+  * PowerPoint writer (Jesse Rosenthal):
+
+    + Write math input verbatim in speaker notes (#6301).
+      OMML in speaker notes would lead to corrupt PowerPoint output. We now
+      output the OMML verbatim as LaTeX in the speaker notes.
+
+  * LaTeX template: Make polyglossia package options list-aware
+    (#6444, Frederik Elwert).
+
+  * Reveal.js template:
+
+    + Update template for reveal.js 4.0.0 (#6390, Salim B).
+    + Update template with newly available options (#6347, Jake Zimmerman).
+    + Use CDN version of revealjs v4 by default (#6408).
+
+  * opendocument template: Add abstract and subtitle to opendocument
+    template (#6369).
+
+  * reference.odt: clean up styles.  Add Abstract.
+    Change Author, Date to centered paragraphs with no character
+    styling.
+
+  * epub.css: wrap overlong lines in highlighted code blocks (#6242).
+    This fixes a problem in iBooks v2.4 with our earlier
+    horizontally scrolling code blocks.  The problem seems to
+    be a bug in iBooks, not pandoc, but since iBooks is a major
+    target we're changing pandoc's default behavior so that
+    pandoc-produced epubs work on that platform.
+
+  * Text.Pandoc.PDF:
+
+    + Use `--enable-local-file-access` in invoking `wkhtmltopdf` (#6474).
+      `wkhtmltopdf` changed in recent versions to require this for
+      access to local files.  This fixes PDF via HTML5 with `--css`.
+    + Send verbose output to stderr, not stdout (#6483).
+
+  * Text.Pandoc.MIME: Fix MIME type for TrueType fonts in EPUBs
+    (#6464, Michael Reed).
+
+  * Text.Pandoc.Shared:
+
+    + `makeSections`: omit number attribute when unnumbered class
+      is present (#6339).  Previously the attribute was included but given
+      an empty value, and this caused the table of contents creation
+      functions in Text.Pandoc.Writers.Shared to think these items had
+      numbers, which meant that they were included in the TOC even if the
+      `unlisted` class was used.
+    + Deprecate `underlineSpan` in Shared in favor of
+      `Text.Pandoc.Builder.underline` (Vaibhav Sagar).
+    + `renderTags'`: use self-closing tag for col element (#6295).
+
+  * Text.Pandoc.UUID: Fix `getRandomUUID`, which previously would
+    return the same value twice in a row. Make `getRandomUUID`
+    polymorphic in PandocMonad.  Remove `getUUID` (#6228, Joseph C. Sible).
+
+  * Text.Pandoc.Class: Generalize `PandocIO` functions to `MonadIO`.
+
+  * Fixed Katex standalone script (#6399, Lucas Escot).
+    Global macros are now persistent when using the HTML Writer with the
+    `--katex` option.
+
+  * Lua subsystem (Albert Krewinkel):
+
+    + Use new type PandocLua for all pandoc Lua operations (API change).
+      The new type `PandocLua` is an instance of the `PandocMonad` typeclass
+      and can thus be used in a way similar to `PandocIO`.
+    + Use PandocError for exceptions in Lua subsystem (API change).
+      The PandocError type is used throughout the Lua subsystem. All Lua
+      functions throw an exception of this type if an error occurs. The
+      `LuaException` type is removed and no longer exported from
+      `Text.Pandoc.Lua`. In its place, a new constructor `PandocLuaError`
+      is added to PandocError.
+
+  * Lua filters: improve error messages for failing filters (#6332,
+    Albert Krewinkel).  Print the Lua error properly instead of
+    displaying their `show` string.
+
+  * Use latest skylighting.  This fixes a bug with lua multiline
+    comments (and may improve handling of other syntaxes as well).
+    IT also adds `aria-hidden="true"` to the empty a elements, which
+    helps people who use screen readers.
+
+  * Use latest texmath.
+
+  * Require latest doctemplates 0.8.2.
+    This adds support for template pipes `first`, `rest`,
+    `last`, `allbutlast`.
+
+  * Revert  0e48a02 and dependency on base-noprelude, which hasn't
+    been updated for ghc 8.10 (see #6187).
+
+  * Dependency adjustments:
+
+    + Allow haddock-library 1.9.x.
+    + Allow hslua 1.1 (#6243, Felix Yan).
+    + Allow base64-bytestring 1.1.
+    + Use latest jira-wiki-markup.
+    + Allow http-client 0.7.
+    + Allow tasty 1.3.x.
+    + Allow aeson 1.5 (#6400, Felix Yan).
+    + Remove unused dependency `vector` (#6462, Laurent P. René de Cotret).
+    + Bump QuickCheck upper bound.
+
+  * Significant code cleanup and simplification (Joseph C. Sible, #6223,
+    #6209, #6225, #6229, #6226, #6340).
+
+  * Remove unnecessary hlint ignores (#6341, Joseph C. Sible).
+
+  * Remove obsolete RelaxedPolyRec extension (#6487, Nikolay Yakimov).
+
+  * trypandoc improvements (Mike Tzou):
+
+    + Add standalone option to the command text (#6210).
+    + Update third party libraries.
+
+  * MANUAL.txt:
+
+    + Clarify template partial naming (#6476, Mauro Bieg).
+    + Describe `jira` as "Jira/Confluence wiki markup" (#6351, Albert
+      Krewinkel).  In the past, Jira's wiki markup was also used by -- and
+      could be imported into -- Atlassian Confluence.
+    + Add link to print-css.rocks (#6272, Mauro Bieg).
+    + Clarify pipe table column width adjustment (#6254).
+    + Fix ATX header syntax.
+    + Fix misleading note about image size conversions (#6353).
+    + Update links to reveal.js documentation (#6386, Salim B).
+    + Separate adjacent verbatim code blocks (#6307, tom-audm).
+
+  * org.md:
+
+    + Document behavior of `smart` extension (#4387, Albert Krewinkel).
+    + Describe all supported export options in detail.
+
+  * lua-filters.md:
+
+    + Fix description of BulletList Lua type (Levi Gruspe).
+    + Use pandoc.system module in TikZ example (Albert
+      Krewinkel).  Showcase temporary directory handling with
+      `with_temporary_directory` and `with_working_directory`.
+
+  * INSTALL.md: fix FreeBSD port link (#6422, Mo).
+    The FreeBSD port was renamed from pandoc to hs-pandoc in 2010.
+    The old pandoc port is still at version 1.5.1.1
+
+  * Propagate `(DY)LD_LIBRARY_PATH` in tests (#6376, Lila).
+
+  * Bump `cabal-version` to 2.2 (#6377).
+
+  * Make it possible to compile using Stack on NixOS (#6439, Mathieu
+    Boespflug).
+
+  * CI action to check for commit messsage length (Nikolay Yakimov, #6398).
+
+
 ## pandoc 2.9.2.1 (2020-03-23)
 
   * Markdown reader: Fix table alignment when heading begins with t (#6153).
diff --git a/data/epub.css b/data/epub.css
--- a/data/epub.css
+++ b/data/epub.css
@@ -23,3 +23,9 @@
 q { quotes: "“" "”" "‘" "’"; }
 div.column{ display: inline-block; vertical-align: top; width: 50%; }
 div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
+@media screen { /* Workaround for iBooks issue; see #6242 */
+  .sourceCode {
+    overflow: visible !important;
+    white-space: pre-wrap !important;
+  }
+}
diff --git a/data/odt/styles.xml b/data/odt/styles.xml
--- a/data/odt/styles.xml
+++ b/data/odt/styles.xml
@@ -73,6 +73,21 @@
       style:font-size-complex="12pt" style:language-complex="zxx"
       style:country-complex="none" />
     </style:default-style>
+    <style:style style:name="Author" style:family="paragraph"
+      style:parent-style-name="Standard" style:class="html">
+        <style:paragraph-properties fo:text-align="center" />
+    </style:style>
+    <style:style style:name="Date" style:family="paragraph"
+      style:parent-style-name="Standard" style:class="html">
+        <style:paragraph-properties fo:text-align="center" />
+    </style:style>
+    <style:style style:name="Abstract" style:family="paragraph"
+      style:parent-style-name="Standard" style:class="html">
+      <style:paragraph-properties fo:margin-left="0.3937in"
+      fo:margin-right="0.3937in" fo:margin-top="0.1in"
+      fo:margin-bottom="0.1in" style:contextual-spacing="false"
+      fo:text-indent="0in" style:auto-text-indent="false" />
+    </style:style>
     <style:default-style style:family="paragraph">
       <style:paragraph-properties fo:hyphenation-ladder-count="no-limit"
       style:text-autospace="ideograph-alpha"
@@ -318,17 +333,6 @@
       fo:margin-right="0in" fo:margin-top="0in"
       fo:margin-bottom="0in" style:contextual-spacing="false"
       fo:text-indent="0in" style:auto-text-indent="false" />
-    </style:style>
-    <style:style style:name="Date" style:family="paragraph"
-    style:parent-style-name="Standard"
-    style:next-style-name="Text_20_body">
-      <style:text-properties fo:font-style="italic" />
-    </style:style>
-    <style:style style:name="Author" style:family="paragraph"
-    style:parent-style-name="Standard" style:next-style-name="Date"
-    style:master-page-name="">
-      <style:paragraph-properties style:page-number="auto" />
-      <style:text-properties fo:font-style="italic" />
     </style:style>
     <style:style style:name="Horizontal_20_Line"
     style:display-name="Horizontal Line" style:family="paragraph"
diff --git a/data/pandoc.lua b/data/pandoc.lua
--- a/data/pandoc.lua
+++ b/data/pandoc.lua
@@ -556,26 +556,27 @@
 
 --- Creates a table element.
 -- @function Table
--- @tparam      {Inline,...} caption    table caption
--- @tparam      {AlignDefault|AlignLeft|AlignRight|AlignCenter,...} aligns alignments
--- @tparam      {int,...}    widths     column widths
--- @tparam      {Block,...}  headers    header row
--- @tparam      {{Block,...}} rows      table rows
--- @treturn     Block                   table element
+-- @tparam      Attr         attr       attributes
+-- @tparam      Caption      caption    table caption
+-- @tparam      {ColSpec,...} colspecs  column alignments and widths
+-- @tparam      TableHead    head       table head
+-- @tparam      {TableBody,..} bodies   table bodies
+-- @treturn     TableFoot    foot       table foot
 M.Table = M.Block:create_constructor(
   "Table",
-  function(caption, aligns, widths, headers, rows)
+  function(attr, caption, colspecs, head, bodies, foot)
     return {
       c = {
-        ensureInlineList(caption),
-        List:new(aligns),
-        List:new(widths),
-        List:new(headers),
-        List:new(rows)
+        attr,
+        caption,
+        List:new(colspecs),
+        head,
+        List:new(bodies),
+        foot
       }
     }
   end,
-  {"caption", "aligns", "widths", "headers", "rows"}
+  {"attr", "caption", "colspecs", "head", "bodies", "foot"}
 )
 
 
@@ -828,9 +829,19 @@
 --- Creates a Superscript inline element
 -- @function Superscript
 -- @tparam      {Inline,..} content     inline content
--- @treturn     Inline                  strong element
+-- @treturn     Inline                  superscript element
 M.Superscript = M.Inline:create_constructor(
   "Superscript",
+  function(content) return {c = ensureInlineList(content)} end,
+  "content"
+)
+
+--- Creates an Underline inline element
+-- @function Underline
+-- @tparam      {Inline,..} content     inline content
+-- @treturn     Inline                  underline element
+M.Underline = M.Inline:create_constructor(
+  "Underline",
   function(content) return {c = ensureInlineList(content)} end,
   "content"
 )
diff --git a/data/templates/default.latex b/data/templates/default.latex
--- a/data/templates/default.latex
+++ b/data/templates/default.latex
@@ -328,9 +328,9 @@
 \ifxetex
   % Load polyglossia as late as possible: uses bidi with RTL langages (e.g. Hebrew, Arabic)
   \usepackage{polyglossia}
-  \setmainlanguage[$polyglossia-lang.options$]{$polyglossia-lang.name$}
+  \setmainlanguage[$for(polyglossia-lang.options)$$polyglossia-lang.options$$sep$,$endfor$]{$polyglossia-lang.name$}
 $for(polyglossia-otherlangs)$
-  \setotherlanguage[$polyglossia-otherlangs.options$]{$polyglossia-otherlangs.name$}
+  \setotherlanguage[$for(polyglossia-otherlangs.options)$$polyglossia-otherlangs.options$$sep$,$endfor$]{$polyglossia-otherlangs.name$}
 $endfor$
 \else
   \usepackage[shorthands=off,$for(babel-otherlangs)$$babel-otherlangs$,$endfor$main=$babel-lang$]{babel}
diff --git a/data/templates/default.opendocument b/data/templates/default.opendocument
--- a/data/templates/default.opendocument
+++ b/data/templates/default.opendocument
@@ -14,11 +14,17 @@
 $if(title)$
 <text:p text:style-name="Title">$title$</text:p>
 $endif$
+$if(subtitle)$
+<text:p text:style-name="Subtitle">$subtitle$</text:p>
+$endif$
 $for(author)$
 <text:p text:style-name="Author">$author$</text:p>
 $endfor$
 $if(date)$
 <text:p text:style-name="Date">$date$</text:p>
+$endif$
+$if(abstract)$
+$abstract$
 $endif$
 $for(include-before)$
 $include-before$
diff --git a/data/templates/default.revealjs b/data/templates/default.revealjs
--- a/data/templates/default.revealjs
+++ b/data/templates/default.revealjs
@@ -16,30 +16,19 @@
   <meta name="apple-mobile-web-app-capable" content="yes">
   <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
   <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">
-  <link rel="stylesheet" href="$revealjs-url$/css/reset.css">
-  <link rel="stylesheet" href="$revealjs-url$/css/reveal.css">
+  <link rel="stylesheet" href="$revealjs-url$/dist/reset.css">
+  <link rel="stylesheet" href="$revealjs-url$/dist/reveal.css">
   <style>
     $styles.html()$
   </style>
 $if(theme)$
-  <link rel="stylesheet" href="$revealjs-url$/css/theme/$theme$.css" id="theme">
+  <link rel="stylesheet" href="$revealjs-url$/dist/theme/$theme$.css" id="theme">
 $else$
-  <link rel="stylesheet" href="$revealjs-url$/css/theme/black.css" id="theme">
+  <link rel="stylesheet" href="$revealjs-url$/dist/theme/black.css" id="theme">
 $endif$
 $for(css)$
   <link rel="stylesheet" href="$css$"/>
 $endfor$
-  <!-- Printing and PDF exports -->
-  <script>
-    var link = document.createElement( 'link' );
-    link.rel = 'stylesheet';
-    link.type = 'text/css';
-    link.href = window.location.search.match( /print-pdf/gi ) ? '$revealjs-url$/css/print/pdf.css' : '$revealjs-url$/css/print/paper.css';
-    document.getElementsByTagName( 'head' )[0].appendChild( link );
-  </script>
-  <!--[if lt IE 9]>
-  <script src="$revealjs-url$/lib/js/html5shiv.js"></script>
-  <![endif]-->
 $if(math)$
   $math$
 $endif$
@@ -78,17 +67,39 @@
     </div>
   </div>
 
-  <script src="$revealjs-url$/js/reveal.js"></script>
+  <script src="$revealjs-url$/dist/reveal.js"></script>
 
+  // reveal.js plugins
+  <script src="$revealjs-url$/plugin/notes/notes.js"></script>
+  <script src="$revealjs-url$/plugin/search/search.js"></script>
+  <script src="$revealjs-url$/plugin/zoom/zoom.js"></script>
+$if(mathjax)$
+  <script src="$revealjs-url$/plugin/math/math.js"></script>
+$endif$
+
   <script>
 
       // Full list of configuration options available at:
-      // https://github.com/hakimel/reveal.js#configuration
+      // https://revealjs.com/config/
       Reveal.initialize({
 $if(controls)$
         // Display controls in the bottom right corner
         controls: $controls$,
 $endif$
+$if(controlsTutorial)$
+        // Help the user learn the controls by providing hints, for example by
+        // bouncing the down arrow when they first encounter a vertical slide
+        controlsTutorial: $controlsTutorial$,
+$endif$
+$if(controlsLayout)$
+        // Determines where controls appear, "edges" or "bottom-right"
+        controlsLayout: $controlsLayout$,
+$endif$
+$if(controlsBackArrows)$
+        // Visibility rule for backwards navigation arrows; "faded", "hidden"
+        // or "visible"
+        controlsBackArrows: $controlsBackArrows$,
+$endif$
 $if(progress)$
         // Display a presentation progress bar
         progress: $progress$,
@@ -97,6 +108,11 @@
         // Display the page number of the current slide
         slideNumber: $slideNumber$,
 $endif$
+$if(hash)$
+        // Add the current slide number to the URL hash so that reloading the
+        // page/copying the URL will return you to the same slide
+        hash: $hash$,
+$endif$
         // Push each slide change to the browser history
 $if(history)$
         history: $history$,
@@ -128,13 +144,22 @@
         rtl: $rtl$,
 $endif$
 $if(navigationMode)$
-        // see https://github.com/hakimel/reveal.js/#navigation-mode
+        // see https://revealjs.com/vertical-slides/#navigation-mode
         navigationMode: '$navigationMode$',
 $endif$
+$if(shuffle)$
+        // Randomizes the order of slides each time the presentation loads
+        shuffle: $shuffle$,
+$endif$
 $if(fragments)$
         // Turns fragments on and off globally
         fragments: $fragments$,
 $endif$
+$if(fragmentInURL)$
+        // Flags whether to include the current fragment in the URL,
+        // so that reloading brings you to the same fragment position
+        fragmentInURL: $fragmentInURL$,
+$endif$
 $if(embedded)$
         // Flags if the presentation is running in an embedded mode,
         // i.e. contained within a limited portion of the screen
@@ -149,6 +174,21 @@
         // Flags if speaker notes should be visible to all viewers
         showNotes: $showNotes$,
 $endif$
+$if(autoPlayMedia)$
+        // Global override for autoplaying embedded media (video/audio/iframe)
+        // - null: Media will only autoplay if data-autoplay is present
+        // - true: All media will autoplay, regardless of individual setting
+        // - false: No media will autoplay, regardless of individual setting
+        autoPlayMedia: $autoPlayMedia$,
+$endif$
+$if(preloadIframes)$
+        // Global override for preloading lazy-loaded iframes
+        // - null: Iframes with data-src AND data-preload will be loaded when within
+        //   the viewDistance, iframes with only data-src will be loaded when visible
+        // - true: All iframes with data-src will be loaded when within the viewDistance
+        // - false: All iframes with data-src will be loaded only when visible
+        preloadIframes: $preloadIframes$,
+$endif$
 $if(autoSlide)$
         // Number of milliseconds between automatically proceeding to the
         // next slide, disabled when set to 0, this value can be overwritten
@@ -159,6 +199,31 @@
         // Stop auto-sliding after user input
         autoSlideStoppable: $autoSlideStoppable$,
 $endif$
+$if(autoSlideMethod)$
+        // Use this method for navigation when auto-sliding
+        autoSlideMethod: $autoSlideMethod$,
+$endif$
+$if(defaultTiming)$
+        // Specify the average time in seconds that you think you will spend
+        // presenting each slide. This is used to show a pacing timer in the
+        // speaker view
+        defaultTiming: $defaultTiming$,
+$endif$
+$if(totalTime)$
+        // Specify the total time in seconds that is available to
+        // present.  If this is set to a nonzero value, the pacing
+        // timer will work out the time available for each slide,
+        // instead of using the defaultTiming value
+        totalTime: $totalTime$,
+$endif$
+$if(minimumTimePerSlide)$
+        // Specify the minimum amount of time you want to allot to
+        // each slide, if using the totalTime calculation method.  If
+        // the automated time allocation causes slide pacing to fall
+        // below this threshold, then you will see an alert in the
+        // speaker notes window
+        minimumTimePerSlide: $minimumTimePerSlide$,
+$endif$
 $if(mouseWheel)$
         // Enable slide navigation via mouse wheel
         mouseWheel: $mouseWheel$,
@@ -167,6 +232,14 @@
         // Apply a 3D roll to links on hover
         rollingLinks: $rollingLinks$,
 $endif$
+$if(hideInactiveCursor)$
+        // Hide cursor if inactive
+        hideInactiveCursor: $hideInactiveCursor$,
+$endif$
+$if(hideCursorTime)$
+        // Time before the cursor is hidden (in ms)
+        hideCursorTime: $hideCursorTime$,
+$endif$
 $if(hideAddressBar)$
         // Hides the address bar on mobile devices
         hideAddressBar: $hideAddressBar$,
@@ -191,6 +264,12 @@
         // Number of slides away from the current that are visible
         viewDistance: $viewDistance$,
 $endif$
+$if(mobileViewDistance)$
+        // Number of slides away from the current that are visible on mobile
+        // devices. It is advisable to set this to a lower number than
+        // viewDistance in order to save resources.
+        mobileViewDistance: $mobileViewDistance$,
+$endif$
 $if(parallaxBackgroundImage)$
         // Parallax background image
         parallaxBackgroundImage: '$parallaxBackgroundImage$', // e.g. "'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg'"
@@ -236,6 +315,10 @@
         // Modifier key used to click-zoom to part of the slide
         zoomKey: '$zoomKey$',
 $endif$
+$if(display)$
+        // The display mode that will be used to show slides
+        display: $display$,
+$endif$
 $if(mathjax)$
         math: {
           mathjax: '$mathjaxurl$',
@@ -255,18 +338,14 @@
         },
 $endif$
 
-        // Optional reveal.js plugins
-        dependencies: [
-          { src: '$revealjs-url$/lib/js/classList.js', condition: function() { return !document.body.classList; } },
-          { src: '$revealjs-url$/plugin/zoom-js/zoom.js', async: true },
-$if(notes-server)$
-          { src: '$revealjs-url$/socket.io/socket.io.js', async: true },
-          { src: '$revealjs-url$/plugin/notes-server/client.js', async: true },
-$endif$
+        // reveal.js plugins
+        plugins: [
 $if(mathjax)$
-          { src: '$revealjs-url$/plugin/math/math.js', async: true },
+          RevealMath,
 $endif$
-          { src: '$revealjs-url$/plugin/notes/notes.js', async: true }
+          RevealNotes,
+          RevealSearch,
+          RevealZoom
         ]
       });
     </script>
diff --git a/data/templates/styles.html b/data/templates/styles.html
--- a/data/templates/styles.html
+++ b/data/templates/styles.html
@@ -10,3 +10,6 @@
 $if(highlighting-css)$
 $highlighting-css$
 $endif$
+$if(displaymath-css)$
+.display.math{display: block; text-align: center; margin: 0.5rem auto;}
+$endif$
diff --git a/man/pandoc.1 b/man/pandoc.1
--- a/man/pandoc.1
+++ b/man/pandoc.1
@@ -1,7 +1,7 @@
 .\"t
-.\" Automatically generated by Pandoc 2.9.2
+.\" Automatically generated by Pandoc 2.10
 .\"
-.TH "Pandoc User\[aq]s Guide" "" "March 23, 2020" "pandoc 2.9.2.1" ""
+.TH "Pandoc User\[aq]s Guide" "" "June 29, 2020" "pandoc 2.10" ""
 .hy
 .SH NAME
 pandoc - general markup converter
@@ -255,7 +255,7 @@
 .IP \[bu] 2
 \f[C]jats\f[R] (JATS XML)
 .IP \[bu] 2
-\f[C]jira\f[R] (Jira wiki markup)
+\f[C]jira\f[R] (Jira/Confluence wiki markup)
 .IP \[bu] 2
 \f[C]json\f[R] (JSON version of native AST)
 .IP \[bu] 2
@@ -352,7 +352,7 @@
 .IP \[bu] 2
 \f[C]jats\f[R] (alias for \f[C]jats_archiving\f[R])
 .IP \[bu] 2
-\f[C]jira\f[R] (Jira wiki markup)
+\f[C]jira\f[R] (Jira/Confluence wiki markup)
 .IP \[bu] 2
 \f[C]json\f[R] (JSON version of native AST)
 .IP \[bu] 2
@@ -481,7 +481,6 @@
 .TP
 \f[B]\f[CB]--verbose\f[B]\f[R]
 Give verbose debugging output.
-Currently this only has an effect with PDF output.
 .TP
 \f[B]\f[CB]--quiet\f[B]\f[R]
 Suppress warning messages.
@@ -936,6 +935,11 @@
 line, or when resources used in a document must be downloaded).
 If you\[aq]re behind a proxy, you also need to set the environment
 variable \f[C]http_proxy\f[R] to \f[C]http://...\f[R].
+.TP
+\[ga]--no-check-certificate
+Disable the certificate verification to allow access to unsecure HTTP
+resources (for example when the certificate is no longer valid or self
+signed).
 .SS Options affecting specific writers
 .TP
 \f[B]\f[CB]--self-contained\f[B]\f[R]
@@ -1366,7 +1370,8 @@
 \f[C]-t context\f[R]: \f[C]context\f[R]
 .IP \[bu] 2
 \f[C]-t html\f[R]: \f[C]wkhtmltopdf\f[R] (other options:
-\f[C]prince\f[R], \f[C]weasyprint\f[R])
+\f[C]prince\f[R], \f[C]weasyprint\f[R]; see print-css.rocks for a good
+introduction to PDF generation from HTML/CSS.)
 .IP \[bu] 2
 \f[C]-t ms\f[R]: \f[C]pdfroff\f[R]
 .RE
@@ -2053,21 +2058,31 @@
 .fi
 .SS Partials
 .PP
-Partials (subtemplates stored in different files) may be included using
-the syntax
+Partials (subtemplates stored in different files) may be included by
+using the name of the partial, followed by \f[C]()\f[R], for example:
 .IP
 .nf
 \f[C]
-${ boilerplate() }
+${ styles() }
 \f[R]
 .fi
 .PP
-Partials will be sought in the directory containing the main template,
-and will be assumed to have the same extension as the main template if
-they lack an explicit extension.
-(If the partials are not found here, they will also be sought in the
-\f[C]templates\f[R] subdirectory of the user data directory.)
+Partials will be sought in the directory containing the main template.
+The file name will be assumed to have the same extension as the main
+template if it lacks an extension.
+When calling the partial, the full name including file extension can
+also be used:
+.IP
+.nf
+\f[C]
+${ styles.html() }
+\f[R]
+.fi
 .PP
+(If a partial is not found in the directory of the template, it will
+also be sought in the \f[C]templates\f[R] subdirectory of the user data
+directory.)
+.PP
 Partials may optionally be applied to variables using a colon:
 .IP
 .nf
@@ -2232,6 +2247,18 @@
 \f[C]reverse\f[R]: Reverses a textual value or array, and has no effect
 on other values.
 .IP \[bu] 2
+\f[C]first\f[R]: Returns the first value of an array, if applied to a
+non-empty array; otherwise returns the original value.
+.IP \[bu] 2
+\f[C]last\f[R]: Returns the last value of an array, if applied to a
+non-empty array; otherwise returns the original value.
+.IP \[bu] 2
+\f[C]rest\f[R]: Returns all but the first value of an array, if applied
+to a non-empty array; otherwise returns the original value.
+.IP \[bu] 2
+\f[C]allbutlast\f[R]: Returns all but the last value of an array, if
+applied to a non-empty array; otherwise returns the original value.
+.IP \[bu] 2
 \f[C]chomp\f[R]: Removes trailing newlines (and breakable space).
 .IP \[bu] 2
 \f[C]nowrap\f[R]: Disables line wrapping on breakable spaces.
@@ -2398,7 +2425,8 @@
 \f[C]0\f[R].
 .TP
 \f[B]\f[CB]revealjs-url\f[B]\f[R]
-base URL for reveal.js documents (defaults to \f[C]reveal.js\f[R])
+base URL for reveal.js documents (defaults to
+\f[C]https://unpkg.com/reveal.js\[at]\[ha]4/\f[R])
 .TP
 \f[B]\f[CB]s5-url\f[B]\f[R]
 base URL for S5 documents (defaults to \f[C]s5/default\f[R])
@@ -3247,7 +3275,7 @@
 .TP
 output formats
 \f[C]odt\f[R], \f[C]opendocument\f[R]
-.SS Extension: \f[C]styles\f[R]
+.SS Extension: \f[C]styles\f[R] {#ext-styles}
 .PP
 When converting from docx, read all docx styles as divs (for paragraph
 styles) and spans (for character styles) regardless of whether pandoc
@@ -4404,7 +4432,7 @@
 .PP
 The cells of pipe tables cannot contain block elements like paragraphs
 and lists, and cannot span multiple lines.
-If a pipe table contains a row whose printable content is wider than the
+If a pipe table contains a row whose Markdown content is wider than the
 column width (see \f[C]--columns\f[R]), then the table will take up the
 full text width and the cell contents will wrap, with the relative cell
 widths determined by the number of dashes in the line separating the
@@ -4454,7 +4482,11 @@
 \f[C]
 %
 % Author
-
+\f[R]
+.fi
+.IP
+.nf
+\f[C]
 % My title
 %
 % June 15, 2006
@@ -4479,9 +4511,17 @@
 \f[C]
 % Author One
   Author Two
-
+\f[R]
+.fi
+.IP
+.nf
+\f[C]
 % Author One; Author Two
-
+\f[R]
+.fi
+.IP
+.nf
+\f[C]
 % Author One;
   Author Two
 \f[R]
@@ -5398,11 +5438,12 @@
 \f[R]
 .fi
 .IP \[bu] 2
-Dimensions are converted to inches for output in page-based formats like
-LaTeX.
-Dimensions are converted to pixels for output in HTML-like formats.
-Use the \f[C]--dpi\f[R] option to specify the number of pixels per inch.
-The default is 96dpi.
+Dimensions may be converted to a form that is compatible with the output
+format (for example, dimensions given in pixels will be converted to
+inches when converting HTML to LaTeX).
+Conversion between pixels and physical measurements is affected by the
+\f[C]--dpi\f[R] option (by default, 96 dpi is assumed, unless the image
+itself contains dpi information).
 .IP \[bu] 2
 The \f[C]%\f[R] unit is generally relative to some available space.
 For example the above example will render to the following.
@@ -6371,6 +6412,51 @@
 ::::::::::::::
 \f[R]
 .fi
+.SS Additional columns attributes in beamer
+.PP
+The div containers with classes \f[C]columns\f[R] and \f[C]column\f[R]
+can optionally have an \f[C]align\f[R] attribute.
+The class \f[C]columns\f[R] can optionally have a \f[C]totalwidth\f[R]
+attribute or an \f[C]onlytextwidth\f[R] class.
+.IP
+.nf
+\f[C]
+:::::::::::::: {.columns align=center totalwidth=8em}
+::: {.column width=\[dq]40%\[dq]}
+contents...
+:::
+::: {.column width=\[dq]60%\[dq] align=bottom}
+contents...
+:::
+::::::::::::::
+\f[R]
+.fi
+.PP
+The \f[C]align\f[R] attributes on \f[C]columns\f[R] and \f[C]column\f[R]
+can be used with the values \f[C]top\f[R], \f[C]top-baseline\f[R],
+\f[C]center\f[R] and \f[C]bottom\f[R] to vertically align the columns.
+It defaults to \f[C]top\f[R] in \f[C]columns\f[R].
+.PP
+The \f[C]totalwidth\f[R] attribute limits the width of the columns to
+the given value.
+.IP
+.nf
+\f[C]
+:::::::::::::: {.columns align=top .onlytextwidth}
+::: {.column width=\[dq]40%\[dq] align=center}
+contents...
+:::
+::: {.column width=\[dq]60%\[dq]}
+contents...
+:::
+::::::::::::::
+\f[R]
+.fi
+.PP
+The class \f[C]onlytextwidth\f[R] sets the \f[C]totalwidth\f[R] to
+\f[C]\[rs]textwidth\f[R].
+.PP
+See Section 12.7 of the Beamer User\[aq]s Guide for more details.
 .SS Frame attributes in beamer
 .PP
 Sometimes it is necessary to add the LaTeX \f[C][fragile]\f[R] option to
diff --git a/pandoc.cabal b/pandoc.cabal
--- a/pandoc.cabal
+++ b/pandoc.cabal
@@ -1,8 +1,8 @@
+cabal-version:   2.2
 name:            pandoc
-version:         2.9.2.1
-cabal-version:   2.0
+version:         2.10
 build-type:      Simple
-license:         GPL-2
+license:         GPL-2.0-or-later
 license-file:    COPYING.md
 copyright:       (c) 2006-2020 John MacFarlane
 author:          John MacFarlane <jgm@berkeley.edu>
@@ -11,7 +11,8 @@
 stability:       alpha
 homepage:        https://pandoc.org
 category:        Text
-tested-with:     GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.5
+tested-with:     GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.5,
+                 GHC == 8.8.3, GHC == 8.10.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
@@ -377,8 +378,7 @@
   Default:       False
 
 library
-  build-depends: base-noprelude >= 4.9 && < 5,
-                 base-compat >= 0.9,
+  build-depends: base >= 4.9 && < 5,
                  syb >= 0.1 && < 0.8,
                  containers >= 0.4.2.1 && < 0.7,
                  unordered-containers >= 0.2 && < 0.3,
@@ -394,39 +394,39 @@
                  safe >= 0.3 && < 0.4,
                  zip-archive >= 0.2.3.4 && < 0.5,
                  HTTP >= 4000.0.5 && < 4000.4,
-                 texmath >= 0.12.0.1 && < 0.13,
+                 texmath >= 0.12.0.2 && < 0.13,
                  xml >= 1.3.12 && < 1.4,
                  split >= 0.2 && < 0.3,
                  random >= 1 && < 1.2,
-                 pandoc-types >= 1.20 && < 1.21,
-                 aeson >= 0.7 && < 1.5,
+                 pandoc-types >= 1.21 && < 1.22,
+                 aeson >= 0.7 && < 1.6,
                  scientific >= 0.3 && < 0.4,
                  aeson-pretty >= 0.8.5 && < 0.9,
                  tagsoup >= 0.14.6 && < 0.15,
-                 base64-bytestring >= 0.1 && < 1.1,
+                 base64-bytestring >= 0.1 && < 1.2,
                  zlib >= 0.5 && < 0.7,
-                 skylighting >= 0.8.3.2 && < 0.9,
-                 skylighting-core >= 0.8.3.2 && < 0.9,
+                 skylighting >= 0.8.5 && < 0.9,
+                 skylighting-core >= 0.8.5 && < 0.9,
                  data-default >= 0.4 && < 0.8,
                  temporary >= 1.1 && < 1.4,
                  blaze-html >= 0.9 && < 0.10,
                  blaze-markup >= 0.8 && < 0.9,
-                 vector >= 0.10 && < 0.13,
-                 jira-wiki-markup >= 1.1.3 && < 1.2,
-                 hslua >= 1.0.1 && < 1.1,
+                 jira-wiki-markup >= 1.3.2 && < 1.4,
+                 hslua >= 1.1 && < 1.2,
                  hslua-module-system >= 0.2 && < 0.3,
-                 hslua-module-text >= 0.2 && < 0.3,
+                 hslua-module-text >= 0.2.1 && < 0.3,
                  binary >= 0.5 && < 0.11,
                  SHA >= 1.6 && < 1.7,
-                 haddock-library >= 1.8 && < 1.9,
+                 haddock-library >= 1.8 && < 1.10,
                  deepseq >= 1.3 && < 1.5,
                  JuicyPixels >= 3.1.6.1 && < 3.4,
                  Glob >= 0.7 && < 0.11,
                  cmark-gfm >= 0.2 && < 0.3,
-                 doctemplates >= 0.8 && < 0.9,
+                 doctemplates >= 0.8.2 && < 0.9,
                  network-uri >= 2.6 && < 2.7,
                  network >= 2.6,
-                 http-client >= 0.4.30 && < 0.7,
+                 connection >= 0.3.1,
+                 http-client >= 0.4.30 && < 0.8,
                  http-client-tls >= 0.2.4 && < 0.4,
                  http-types >= 0.8 && < 0.13,
                  case-insensitive >= 1.2 && < 1.3,
@@ -441,6 +441,10 @@
      build-depends: basement >= 0.0.10,
                     foundation >= 0.0.23
                     -- basement 0.0.9 won't build on 32-bit windows.
+  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
@@ -468,8 +472,7 @@
 
   default-language: Haskell2010
   other-extensions: NoImplicitPrelude
-  hs-source-dirs:  src,
-                   prelude
+  hs-source-dirs:  src
 
   exposed-modules: Text.Pandoc,
                    Text.Pandoc.App,
@@ -563,12 +566,12 @@
                    Text.Pandoc.ImageSize,
                    Text.Pandoc.BCP47,
                    Text.Pandoc.Class
-  other-modules:   Prelude,
-                   Text.Pandoc.App.CommandLineOptions,
+  other-modules:   Text.Pandoc.App.CommandLineOptions,
                    Text.Pandoc.App.FormatHeuristics,
                    Text.Pandoc.App.Opt,
                    Text.Pandoc.App.OutputSettings,
                    Text.Pandoc.Class.CommonState,
+                   Text.Pandoc.Class.IO,
                    Text.Pandoc.Class.PandocMonad,
                    Text.Pandoc.Class.PandocIO,
                    Text.Pandoc.Class.PandocPure,
@@ -609,6 +612,7 @@
                    Text.Pandoc.Writers.Roff,
                    Text.Pandoc.Writers.Powerpoint.Presentation,
                    Text.Pandoc.Writers.Powerpoint.Output,
+                   Text.Pandoc.Lua.ErrorConversion,
                    Text.Pandoc.Lua.Filter,
                    Text.Pandoc.Lua.Global,
                    Text.Pandoc.Lua.Init,
@@ -619,6 +623,7 @@
                    Text.Pandoc.Lua.Marshaling.Context,
                    Text.Pandoc.Lua.Marshaling.List,
                    Text.Pandoc.Lua.Marshaling.MediaBag,
+                   Text.Pandoc.Lua.Marshaling.PandocError,
                    Text.Pandoc.Lua.Marshaling.ReaderOptions,
                    Text.Pandoc.Lua.Marshaling.Version,
                    Text.Pandoc.Lua.Module.MediaBag,
@@ -627,6 +632,7 @@
                    Text.Pandoc.Lua.Module.Types,
                    Text.Pandoc.Lua.Module.Utils,
                    Text.Pandoc.Lua.Packages,
+                   Text.Pandoc.Lua.PandocLua,
                    Text.Pandoc.Lua.Util,
                    Text.Pandoc.Lua.Walk,
                    Text.Pandoc.CSS,
@@ -641,19 +647,19 @@
   buildable:       True
 
 executable pandoc
-  build-depends:   pandoc,
-                   base-noprelude >= 4.8 && < 5,
-                   base-compat >= 0.9
+  build-depends: pandoc, base >= 4.8 && < 5
+  if impl(ghc < 8.4)
+     hs-source-dirs: prelude
+     other-modules:  Prelude
+     build-depends:  base-compat >= 0.9
   if flag(static)
     ld-options:     -static
   default-language: Haskell2010
   other-extensions: NoImplicitPrelude
   hs-source-dirs:  .
-                   prelude
   main-is:         pandoc.hs
   buildable:       True
-  other-modules:   Paths_pandoc,
-                   Prelude
+  other-modules:   Paths_pandoc
   ghc-options:     -rtsopts -with-rtsopts=-K16m -threaded
                    -Wall -fno-warn-unused-do-bind
                    -Wincomplete-record-updates
@@ -668,16 +674,19 @@
 
 executable trypandoc
   main-is:         trypandoc.hs
-  hs-source-dirs:  trypandoc, prelude
+  hs-source-dirs:  trypandoc
   default-language: Haskell2010
   other-extensions: NoImplicitPrelude
-  other-modules:    Prelude
   if flag(trypandoc)
-    build-depends: base-noprelude, base-compat >= 0.9, aeson, pandoc,
+    build-depends: base, aeson, pandoc,
                    text, wai-extra, wai >= 0.3, http-types
     buildable:     True
   else
     buildable:     False
+  if impl(ghc < 8.4)
+     hs-source-dirs: prelude
+     other-modules:  Prelude
+     build-depends:  base-compat >= 0.9
   ghc-options:     -rtsopts -with-rtsopts=-K16m -threaded
                    -Wall -fno-warn-unused-do-bind
                    -Wincomplete-record-updates
@@ -693,16 +702,18 @@
 benchmark weigh-pandoc
   type:            exitcode-stdio-1.0
   main-is:         weigh-pandoc.hs
-  hs-source-dirs:  benchmark,
-                   prelude
+  hs-source-dirs:  benchmark
   build-depends:   pandoc,
-                   base-noprelude >= 4.8 && < 5,
-                   base-compat >= 0.9,
+                   base >= 4.8 && < 5,
                    text,
                    weigh >= 0.0 && < 0.1,
                    mtl >= 2.2 && < 2.3
+  if impl(ghc < 8.4)
+     hs-source-dirs: prelude
+     other-modules:  Prelude
+     build-depends:  base-compat >= 0.9
   default-language: Haskell2010
-  other-modules:   Prelude
+  other-extensions: NoImplicitPrelude
   ghc-options:     -rtsopts -with-rtsopts=-K16m -threaded
                    -Wall -fno-warn-unused-do-bind
                    -Wincomplete-record-updates
@@ -719,37 +730,40 @@
 test-suite test-pandoc
   type:           exitcode-stdio-1.0
   main-is:        test-pandoc.hs
-  hs-source-dirs: test,
-                  prelude
-  build-depends:  base-noprelude >= 4.8 && < 5,
-                  base-compat >= 0.9,
+  hs-source-dirs: test
+  build-depends:  base >= 4.8 && < 5,
                   pandoc,
-                  pandoc-types >= 1.20 && < 1.21,
+                  pandoc-types >= 1.21 && < 1.22,
                   mtl >= 2.2 && < 2.3,
                   bytestring >= 0.9 && < 0.11,
-                  base64-bytestring >= 0.1 && < 1.1,
+                  base64-bytestring >= 0.1 && < 1.2,
+                  exceptions >= 0.8 && < 0.11,
                   text >= 1.1.1.0 && < 1.3,
                   time >= 1.5 && < 1.10,
                   directory >= 1.2.3 && < 1.4,
+                  exceptions >= 0.8 && < 0.11,
                   filepath >= 1.1 && < 1.5,
-                  hslua >= 1.0 && < 1.1,
+                  hslua >= 1.1 && < 1.2,
                   process >= 1.2.3 && < 1.7,
                   temporary >= 1.1 && < 1.4,
                   Diff >= 0.2 && < 0.5,
-                  tasty >= 0.11 && < 1.3,
+                  tasty >= 0.11 && < 1.4,
                   tasty-hunit >= 0.9 && < 0.11,
                   tasty-lua >= 0.2 && < 0.3,
                   tasty-quickcheck >= 0.8 && < 0.11,
                   tasty-golden >= 2.3 && < 2.4,
-                  QuickCheck >= 2.4 && < 2.14,
+                  QuickCheck >= 2.4 && < 2.15,
                   containers >= 0.4.2.1 && < 0.7,
                   executable-path >= 0.0 && < 0.1,
                   zip-archive >= 0.2.3.4 && < 0.5,
                   xml >= 1.3.12 && < 1.4,
-                  doctemplates >= 0.8 && < 0.9,
+                  doctemplates >= 0.8.2 && < 0.9,
                   Glob >= 0.7 && < 0.11
-  other-modules:  Prelude
-                  Tests.Old
+  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
                   Tests.Lua
@@ -789,6 +803,7 @@
                   Tests.Writers.Docbook
                   Tests.Writers.HTML
                   Tests.Writers.JATS
+                  Tests.Writers.Jira
                   Tests.Writers.Markdown
                   Tests.Writers.Org
                   Tests.Writers.Plain
@@ -804,6 +819,7 @@
   if os(windows)
     cpp-options:      -D_WINDOWS
   default-language: Haskell2010
+  other-extensions: NoImplicitPrelude
   ghc-options:     -rtsopts -with-rtsopts=-K16m -threaded
                    -Wall -fno-warn-unused-do-bind
                    -Wincomplete-record-updates
@@ -820,17 +836,19 @@
 benchmark benchmark-pandoc
   type:            exitcode-stdio-1.0
   main-is:         benchmark-pandoc.hs
-  hs-source-dirs:  benchmark,
-                   prelude
+  hs-source-dirs:  benchmark
   build-depends:   pandoc,
                    time, bytestring, containers,
-                   base-noprelude >= 4.8 && < 5,
-                   base-compat >= 0.9,
+                   base >= 4.8 && < 5,
                    text >= 1.1.1.0 && < 1.3,
                    mtl >= 2.2 && < 2.3,
                    criterion >= 1.0 && < 1.6
+  if impl(ghc < 8.4)
+     hs-source-dirs: prelude
+     other-modules:  Prelude
+     build-depends:  base-compat >= 0.9
   default-language: Haskell2010
-  other-modules:    Prelude
+  other-extensions: NoImplicitPrelude
   ghc-options:     -rtsopts -with-rtsopts=-K16m -threaded
                    -Wall -fno-warn-unused-do-bind
                    -Wincomplete-record-updates
diff --git a/src/Text/Pandoc/App.hs b/src/Text/Pandoc/App.hs
--- a/src/Text/Pandoc/App.hs
+++ b/src/Text/Pandoc/App.hs
@@ -270,6 +270,8 @@
 
     mapM_ (uncurry setRequestHeader) (optRequestHeaders opts)
 
+    setNoCheckCertificate (optNoCheckCertificate opts)
+
     doc <- sourceToDoc sources >>=
               (   (if isJust (optExtractMedia opts)
                       then fillMediaBag
diff --git a/src/Text/Pandoc/App/CommandLineOptions.hs b/src/Text/Pandoc/App/CommandLineOptions.hs
--- a/src/Text/Pandoc/App/CommandLineOptions.hs
+++ b/src/Text/Pandoc/App/CommandLineOptions.hs
@@ -30,7 +30,7 @@
 import Data.Char (toLower)
 import Data.List (intercalate, sort)
 #ifdef _WINDOWS
-#if MIN_VERSION_base_noprelude(4,12,0)
+#if MIN_VERSION_base(4,12,0)
 import Data.List (isPrefixOf)
 #endif
 #endif
@@ -414,6 +414,11 @@
                   "NAME:VALUE")
                  ""
 
+    , Option "" ["no-check-certificate"]
+                (NoArg
+                 (\opt -> return opt { optNoCheckCertificate = True }))
+                "" -- "Disable certificate validation"
+
     , Option "" ["abbreviations"]
                 (ReqArg
                  (\arg opt -> return opt { optAbbreviations = Just arg })
@@ -1028,7 +1033,7 @@
 -- beginning with \\ to \\?\UNC\. -- See #5127.
 normalizePath :: FilePath -> FilePath
 #ifdef _WINDOWS
-#if MIN_VERSION_base_noprelude(4,12,0)
+#if MIN_VERSION_base(4,12,0)
 normalizePath fp =
   if "\\\\" `isPrefixOf` fp && not ("\\\\?\\" `isPrefixOf` fp)
     then "\\\\?\\UNC\\" ++ drop 2 fp
diff --git a/src/Text/Pandoc/App/Opt.hs b/src/Text/Pandoc/App/Opt.hs
--- a/src/Text/Pandoc/App/Opt.hs
+++ b/src/Text/Pandoc/App/Opt.hs
@@ -4,6 +4,7 @@
 {-# LANGUAGE DeriveGeneric       #-}
 {-# LANGUAGE TemplateHaskell     #-}
 {-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE FlexibleContexts    #-}
 {- |
    Module      : Text.Pandoc.App.Opt
    Copyright   : Copyright (C) 2006-2020 John MacFarlane
@@ -34,9 +35,12 @@
                             ObfuscationMethod (NoObfuscation),
                             CiteMethod (Citeproc))
 import Text.Pandoc.Shared (camelCaseStrToHyphenated)
-import Text.DocLayout (render)
-import Text.DocTemplates (Context(..), Val(..))
+import qualified Text.Pandoc.Parsing as P
+import Text.Pandoc.Readers.Metadata (yamlMap)
+import Text.Pandoc.Class.PandocPure
+import Text.DocTemplates (Context(..))
 import Data.Text (Text, unpack)
+import Data.Default (def)
 import qualified Data.Text as T
 import qualified Data.Map as M
 import Text.Pandoc.Definition (Meta(..), MetaValue(..), lookupMeta)
@@ -140,6 +144,7 @@
     , optIncludeInHeader       :: [FilePath]       -- ^ Files to include in header
     , optResourcePath          :: [FilePath] -- ^ Path to search for images etc
     , optRequestHeaders        :: [(Text, Text)] -- ^ Headers for HTTP requests
+    , optNoCheckCertificate    :: Bool       -- ^ Disable certificate validation
     , optEol                   :: LineEnding -- ^ Style of line-endings to use
     , optStripComments         :: Bool       -- ^ Skip HTML comments
     } deriving (Generic, Show)
@@ -184,8 +189,7 @@
       -- Note: x comes first because <> for Context is left-biased union
       -- and we want to favor later default files. See #5988.
     "metadata" ->
-      parseYAML v >>= \x -> return (\o -> o{ optMetadata = optMetadata o <>
-                                               contextToMeta x })
+      yamlToMeta v >>= \x -> return (\o -> o{ optMetadata = optMetadata o <> x })
     "metadata-files" ->
       parseYAML v >>= \x ->
                         return (\o -> o{ optMetadataFiles =
@@ -390,6 +394,9 @@
     "request-headers" ->
       parseYAML v >>= \x ->
              return (\o -> o{ optRequestHeaders = x })
+    "no-check-certificate" ->
+      parseYAML v >>= \x ->
+             return (\o -> o{ optNoCheckCertificate = x })
     "eol" ->
       parseYAML v >>= \x -> return (\o -> o{ optEol = x })
     "strip-comments" ->
@@ -466,20 +473,19 @@
     , optIncludeInHeader       = []
     , optResourcePath          = ["."]
     , optRequestHeaders        = []
+    , optNoCheckCertificate    = False
     , optEol                   = Native
     , optStripComments         = False
     }
 
-contextToMeta :: Context Text -> Meta
-contextToMeta (Context m) =
-  Meta . M.map valToMetaVal $ m
-
-valToMetaVal :: Val Text -> MetaValue
-valToMetaVal (MapVal (Context m)) =
-  MetaMap . M.map valToMetaVal $ m
-valToMetaVal (ListVal xs) = MetaList $ map valToMetaVal xs
-valToMetaVal (SimpleVal d) = MetaString $ render Nothing d
-valToMetaVal NullVal = MetaString ""
+yamlToMeta :: Node Pos -> Parser Meta
+yamlToMeta (Mapping _ _ m) =
+    either (fail . show) return $ runEverything (yamlMap pMetaString m)
+  where
+    pMetaString = pure . MetaString <$> P.manyChar P.anyChar
+    runEverything p = runPure (P.readWithM p def "")
+      >>= fmap (Meta . flip P.runF def)
+yamlToMeta _ = return mempty
 
 addMeta :: String -> String -> Meta -> Meta
 addMeta k v meta =
diff --git a/src/Text/Pandoc/Class/CommonState.hs b/src/Text/Pandoc/Class/CommonState.hs
--- a/src/Text/Pandoc/Class/CommonState.hs
+++ b/src/Text/Pandoc/Class/CommonState.hs
@@ -37,6 +37,8 @@
     -- ^ Absolute URL + dir of 1st source file
   , stRequestHeaders :: [(Text, Text)]
     -- ^ Headers to add for HTTP requests
+  , stNoCheckCertificate :: Bool
+    -- ^ Controls whether certificate validation is disabled
   , stMediaBag     :: MediaBag
     -- ^ Media parsed from binary containers
   , stTranslations :: Maybe (Lang, Maybe Translations)
@@ -67,6 +69,7 @@
   , stUserDataDir = Nothing
   , stSourceURL = Nothing
   , stRequestHeaders = []
+  , stNoCheckCertificate = False
   , stMediaBag = mempty
   , stTranslations = Nothing
   , stInputFiles = []
diff --git a/src/Text/Pandoc/Class/IO.hs b/src/Text/Pandoc/Class/IO.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/Class/IO.hs
@@ -0,0 +1,231 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedStrings #-}
+{- |
+Module      : Text.Pandoc.Class.IO
+Copyright   : Copyright (C) 2016-2020 Jesse Rosenthal, John MacFarlane
+License     : GNU GPL, version 2 or above
+
+Maintainer  : Jesse Rosenthal <jrosenthal@jhu.edu>
+Stability   : alpha
+Portability : portable
+
+Default ways to perform @'PandocMonad'@ actions in a @'MonadIO'@ type.
+
+These functions are used to make the @'PandocIO'@ type an instance of
+@'PandocMonad'@, but can be reused for any other MonadIO-conforming
+types.
+-}
+module Text.Pandoc.Class.IO
+  ( fileExists
+  , getCurrentTime
+  , getCurrentTimeZone
+  , getDataFileName
+  , getModificationTime
+  , glob
+  , logOutput
+  , logIOError
+  , lookupEnv
+  , newStdGen
+  , newUniqueHash
+  , openURL
+  , readFileLazy
+  , readFileStrict
+  , extractMedia
+ ) where
+
+import Control.Monad.Except (throwError)
+import Control.Monad.IO.Class (MonadIO, liftIO)
+import Data.ByteString.Base64 (decodeLenient)
+import Data.ByteString.Lazy (toChunks)
+import Data.Text (Text, pack, unpack)
+import Data.Time (TimeZone, UTCTime)
+import Data.Unique (hashUnique)
+import Network.Connection (TLSSettings (TLSSettingsSimple))
+import Network.HTTP.Client
+       (httpLbs, responseBody, responseHeaders,
+        Request(port, host, requestHeaders), parseRequest, newManager)
+import Network.HTTP.Client.Internal (addProxy)
+import Network.HTTP.Client.TLS (mkManagerSettings)
+import Network.HTTP.Types.Header ( hContentType )
+import Network.Socket (withSocketsDo)
+import Network.URI (unEscapeString)
+import System.Directory (createDirectoryIfMissing)
+import System.Environment (getEnv)
+import System.FilePath ((</>), takeDirectory, normalise)
+import System.IO (stderr)
+import System.IO.Error
+import System.Random (StdGen)
+import Text.Pandoc.Class.CommonState (CommonState (..))
+import Text.Pandoc.Class.PandocMonad
+       (PandocMonad, getsCommonState, getMediaBag, report)
+import Text.Pandoc.Definition (Pandoc, Inline (Image))
+import Text.Pandoc.Error (PandocError (..))
+import Text.Pandoc.Logging (LogMessage (..), messageVerbosity, showLogMessage)
+import Text.Pandoc.MIME (MimeType)
+import Text.Pandoc.MediaBag (MediaBag, lookupMedia, mediaDirectory)
+import Text.Pandoc.Walk (walk)
+import qualified Control.Exception as E
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.CaseInsensitive as CI
+import qualified Data.Text as T
+import qualified Data.Time
+import qualified Data.Time.LocalTime
+import qualified Data.Unique
+import qualified System.Directory
+import qualified System.Environment as Env
+import qualified System.FilePath.Glob
+import qualified System.Random
+import qualified Text.Pandoc.UTF8 as UTF8
+#ifndef EMBED_DATA_FILES
+import qualified Paths_pandoc as Paths
+#endif
+
+-- | Utility function to lift IO errors into 'PandocError's.
+liftIOError :: (PandocMonad m, MonadIO m) => (String -> IO a) -> String -> m a
+liftIOError f u = do
+  res <- liftIO $ tryIOError $ f u
+  case res of
+         Left e  -> throwError $ PandocIOError (pack u) e
+         Right r -> return r
+
+-- | Show potential IO errors to the user continuing execution anyway
+logIOError :: (PandocMonad m, MonadIO m) => IO () -> m ()
+logIOError f = do
+  res <- liftIO $ tryIOError f
+  case res of
+    Left e -> report $ IgnoredIOError $ pack $ E.displayException e
+    Right _ -> pure ()
+
+-- | Lookup an environment variable in the programs environment.
+lookupEnv :: MonadIO m => Text -> m (Maybe Text)
+lookupEnv = fmap (fmap pack) . liftIO . Env.lookupEnv . unpack
+
+-- | Get the current (UTC) time.
+getCurrentTime :: MonadIO m => m UTCTime
+getCurrentTime = liftIO Data.Time.getCurrentTime
+
+-- | Get the locale's time zone.
+getCurrentTimeZone :: MonadIO m => m TimeZone
+getCurrentTimeZone = liftIO Data.Time.LocalTime.getCurrentTimeZone
+
+-- | Return a new generator for random numbers.
+newStdGen :: MonadIO m => m StdGen
+newStdGen = liftIO System.Random.newStdGen
+
+-- | Return a new unique integer.
+newUniqueHash :: MonadIO m => m Int
+newUniqueHash = hashUnique <$> liftIO Data.Unique.newUnique
+
+openURL :: (PandocMonad m, MonadIO m) => Text -> m (B.ByteString, Maybe MimeType)
+openURL u
+ | Just u'' <- T.stripPrefix "data:" u = do
+     let mime     = T.takeWhile (/=',') u''
+     let contents = UTF8.fromString $
+                     unEscapeString $ T.unpack $ T.drop 1 $ T.dropWhile (/=',') u''
+     return (decodeLenient contents, Just mime)
+ | otherwise = do
+     let toReqHeader (n, v) = (CI.mk (UTF8.fromText n), UTF8.fromText v)
+     customHeaders <- map toReqHeader <$> getsCommonState stRequestHeaders
+     disableCertificateValidation <- getsCommonState stNoCheckCertificate
+     report $ Fetching u
+     res <- liftIO $ E.try $ withSocketsDo $ do
+       let parseReq = parseRequest
+       proxy <- tryIOError (getEnv "http_proxy")
+       let addProxy' x = case proxy of
+                            Left _ -> return x
+                            Right pr -> parseReq pr >>= \r ->
+                                return (addProxy (host r) (port r) x)
+       req <- parseReq (unpack u) >>= addProxy'
+       let req' = req{requestHeaders = customHeaders ++ requestHeaders req}
+       let tlsSimple = TLSSettingsSimple disableCertificateValidation False False
+       let tlsManagerSettings = mkManagerSettings tlsSimple  Nothing
+       resp <- newManager tlsManagerSettings >>= httpLbs req'
+       return (B.concat $ toChunks $ responseBody resp,
+               UTF8.toText `fmap` lookup hContentType (responseHeaders resp))
+
+     case res of
+          Right r -> return r
+          Left e  -> throwError $ PandocHttpError u e
+
+-- | Read the lazy ByteString contents from a file path, raising an error on
+-- failure.
+readFileLazy :: (PandocMonad m, MonadIO m) => FilePath -> m BL.ByteString
+readFileLazy s = liftIOError BL.readFile s
+
+-- | Read the strict ByteString contents from a file path,
+-- raising an error on failure.
+readFileStrict :: (PandocMonad m, MonadIO m) => FilePath -> m B.ByteString
+readFileStrict s = liftIOError B.readFile s
+
+-- | Return a list of paths that match a glob, relative to the working
+-- directory. See 'System.FilePath.Glob' for the glob syntax.
+glob :: (PandocMonad m, MonadIO m) => String -> m [FilePath]
+glob = liftIOError System.FilePath.Glob.glob
+
+-- | Returns True if file exists.
+fileExists :: (PandocMonad m, MonadIO m) => FilePath -> m Bool
+fileExists = liftIOError System.Directory.doesFileExist
+
+-- | Returns the path of data file.
+getDataFileName :: (PandocMonad m, MonadIO m) => FilePath -> m FilePath
+#ifdef EMBED_DATA_FILES
+getDataFileName = return
+#else
+getDataFileName = liftIOError Paths.getDataFileName
+#endif
+
+-- | Return the modification time of a file.
+getModificationTime :: (PandocMonad m, MonadIO m) => FilePath -> m UTCTime
+getModificationTime = liftIOError System.Directory.getModificationTime
+
+-- | Output a log message.
+logOutput :: (PandocMonad m, MonadIO m) => LogMessage -> m ()
+logOutput msg = liftIO $ do
+  UTF8.hPutStr stderr $
+      "[" ++ show (messageVerbosity msg) ++ "] "
+  alertIndent $ T.lines $ showLogMessage msg
+
+-- | Prints the list of lines to @stderr@, indenting every but the first
+-- line by two spaces.
+alertIndent :: [Text] -> IO ()
+alertIndent [] = return ()
+alertIndent (l:ls) = do
+  UTF8.hPutStrLn stderr $ unpack l
+  mapM_ go ls
+  where go l' = do UTF8.hPutStr stderr "  "
+                   UTF8.hPutStrLn stderr $ unpack l'
+
+-- | Extract media from the mediabag into a directory.
+extractMedia :: (PandocMonad m, MonadIO m) => FilePath -> Pandoc -> m Pandoc
+extractMedia dir d = do
+  media <- getMediaBag
+  case [fp | (fp, _, _) <- mediaDirectory media] of
+    []  -> return d
+    fps -> do
+      mapM_ (writeMedia dir media) fps
+      return $ walk (adjustImagePath dir fps) d
+
+-- | Write the contents of a media bag to a path.
+writeMedia :: (PandocMonad m, MonadIO m)
+           => FilePath -> MediaBag -> FilePath
+           -> m ()
+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 </> unEscapeString (normalise subpath)
+  let mbcontents = lookupMedia subpath mediabag
+  case mbcontents of
+       Nothing -> throwError $ PandocResourceNotFound $ pack subpath
+       Just (_, bs) -> do
+         report $ Extracting $ pack fullpath
+         liftIOError (createDirectoryIfMissing True) (takeDirectory fullpath)
+         logIOError $ BL.writeFile fullpath bs
+
+-- | If the given Inline element is an image with a @src@ path equal to
+-- one in the list of @paths@, then prepends @dir@ to the image source;
+-- returns the element unchanged otherwise.
+adjustImagePath :: FilePath -> [FilePath] -> Inline -> Inline
+adjustImagePath dir paths (Image attr lab (src, tit))
+   | unpack src `elem` paths = Image attr lab (pack dir <> "/" <> src, tit)
+adjustImagePath _ _ x = x
diff --git a/src/Text/Pandoc/Class/PandocIO.hs b/src/Text/Pandoc/Class/PandocIO.hs
--- a/src/Text/Pandoc/Class/PandocIO.hs
+++ b/src/Text/Pandoc/Class/PandocIO.hs
@@ -1,7 +1,5 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DeriveFunctor #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE OverloadedStrings #-}
 {- |
 Module      : Text.Pandoc.Class.PandocIO
 Copyright   : Copyright (C) 2016-2020 Jesse Rosenthal, John MacFarlane
@@ -16,78 +14,21 @@
 using IO operators.
 -}
 module Text.Pandoc.Class.PandocIO
-  ( getPOSIXTime
-  , getZonedTime
-  , readFileFromDirs
-  , report
-  , setTrace
-  , setRequestHeader
-  , getLog
-  , setVerbosity
-  , getVerbosity
-  , getMediaBag
-  , setMediaBag
-  , insertMedia
-  , setUserDataDir
-  , getUserDataDir
-  , fetchItem
-  , getInputFiles
-  , setInputFiles
-  , getOutputFile
-  , setOutputFile
-  , setResourcePath
-  , getResourcePath
-  , PandocIO(..)
+  ( PandocIO(..)
   , runIO
   , runIOorExplode
   , extractMedia
  ) where
 
-import Control.Monad.Except
-import Control.Monad.State.Strict
-import Data.ByteString.Base64 (decodeLenient)
-import Data.ByteString.Lazy (toChunks)
-import Data.Default
-import Data.Text (Text)
-import Data.Unique (hashUnique)
-import Network.HTTP.Client
-       (httpLbs, responseBody, responseHeaders,
-        Request(port, host, requestHeaders), parseRequest, newManager)
-import Network.HTTP.Client.Internal (addProxy)
-import Network.HTTP.Client.TLS (tlsManagerSettings)
-import Network.HTTP.Types.Header ( hContentType )
-import Network.Socket (withSocketsDo)
-import Network.URI ( unEscapeString )
-import Prelude
-import System.Directory (createDirectoryIfMissing)
-import System.Environment (getEnv)
-import System.FilePath ((</>), takeDirectory, normalise)
-import System.IO (stderr)
-import System.IO.Error
+import Control.Monad.Except (ExceptT, MonadError, runExceptT)
+import Control.Monad.IO.Class (MonadIO)
+import Control.Monad.State (StateT, evalStateT, lift, get, put)
+import Data.Default (Default (def))
 import Text.Pandoc.Class.CommonState (CommonState (..))
 import Text.Pandoc.Class.PandocMonad
 import Text.Pandoc.Definition
 import Text.Pandoc.Error
-import Text.Pandoc.Logging
-import Text.Pandoc.MediaBag (MediaBag, lookupMedia, mediaDirectory)
-import Text.Pandoc.Walk (walk)
-import qualified Control.Exception as E
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as BL
-import qualified Data.CaseInsensitive as CI
-import qualified Data.Text as T
-import qualified Data.Time as IO (getCurrentTime)
-import qualified Data.Time.LocalTime as IO (getCurrentTimeZone)
-import qualified Data.Unique as IO (newUnique)
-import qualified System.Directory as Directory
-import qualified System.Directory as IO (getModificationTime)
-import qualified System.Environment as IO (lookupEnv)
-import qualified System.FilePath.Glob as IO (glob)
-import qualified System.Random as IO (newStdGen)
-import qualified Text.Pandoc.UTF8 as UTF8
-#ifndef EMBED_DATA_FILES
-import qualified Paths_pandoc as Paths
-#endif
+import qualified Text.Pandoc.Class.IO as IO
 
 -- | Evaluate a 'PandocIO' operation.
 runIO :: PandocIO a -> IO (Either PandocError a)
@@ -107,112 +48,27 @@
              , MonadError PandocError
              )
 
--- | Utility function to lift IO errors into 'PandocError's.
-liftIOError :: (String -> IO a) -> String -> PandocIO a
-liftIOError f u = do
-  res <- liftIO $ tryIOError $ f u
-  case res of
-         Left e  -> throwError $ PandocIOError (T.pack 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 $ T.pack $ E.displayException e
-    Right _ -> pure ()
-
 instance PandocMonad PandocIO where
-  lookupEnv = fmap (fmap T.pack) . liftIO . IO.lookupEnv . T.unpack
-  getCurrentTime = liftIO IO.getCurrentTime
-  getCurrentTimeZone = liftIO IO.getCurrentTimeZone
-  newStdGen = liftIO IO.newStdGen
-  newUniqueHash = hashUnique <$> liftIO IO.newUnique
-
-  openURL u
-   | Just u'' <- T.stripPrefix "data:" u = do
-       let mime     = T.takeWhile (/=',') u''
-       let contents = UTF8.fromString $
-                       unEscapeString $ T.unpack $ T.drop 1 $ T.dropWhile (/=',') u''
-       return (decodeLenient contents, Just mime)
-   | otherwise = do
-       let toReqHeader (n, v) = (CI.mk (UTF8.fromText n), UTF8.fromText v)
-       customHeaders <- map toReqHeader <$> getsCommonState stRequestHeaders
-       report $ Fetching u
-       res <- liftIO $ E.try $ withSocketsDo $ do
-         let parseReq = parseRequest
-         proxy <- tryIOError (getEnv "http_proxy")
-         let addProxy' x = case proxy of
-                              Left _ -> return x
-                              Right pr -> parseReq pr >>= \r ->
-                                  return (addProxy (host r) (port r) x)
-         req <- parseReq (T.unpack u) >>= addProxy'
-         let req' = req{requestHeaders = customHeaders ++ requestHeaders req}
-         resp <- newManager tlsManagerSettings >>= httpLbs req'
-         return (B.concat $ toChunks $ responseBody resp,
-                 UTF8.toText `fmap` lookup hContentType (responseHeaders resp))
+  lookupEnv = IO.lookupEnv
+  getCurrentTime = IO.getCurrentTime
+  getCurrentTimeZone = IO.getCurrentTimeZone
+  newStdGen = IO.newStdGen
+  newUniqueHash = IO.newUniqueHash
 
-       case res of
-            Right r -> return r
-            Left e  -> throwError $ PandocHttpError u e
+  openURL = IO.openURL
+  readFileLazy = IO.readFileLazy
+  readFileStrict = IO.readFileStrict
 
-  readFileLazy s = liftIOError BL.readFile s
-  readFileStrict s = liftIOError B.readFile s
+  glob = IO.glob
+  fileExists = IO.fileExists
+  getDataFileName = IO.getDataFileName
+  getModificationTime = IO.getModificationTime
 
-  glob = liftIOError IO.glob
-  fileExists = liftIOError Directory.doesFileExist
-#ifdef EMBED_DATA_FILES
-  getDataFileName = return
-#else
-  getDataFileName = liftIOError Paths.getDataFileName
-#endif
-  getModificationTime = liftIOError IO.getModificationTime
   getCommonState = PandocIO $ lift get
-  putCommonState x = PandocIO $ lift $ put x
-  logOutput msg = liftIO $ do
-    UTF8.hPutStr stderr $
-        "[" ++ show (messageVerbosity msg) ++ "] "
-    alertIndent $ T.lines $ showLogMessage msg
+  putCommonState = PandocIO . lift . put
 
--- | Prints the list of lines to @stderr@, indenting every but the first
--- line by two spaces.
-alertIndent :: [Text] -> IO ()
-alertIndent [] = return ()
-alertIndent (l:ls) = do
-  UTF8.hPutStrLn stderr $ T.unpack l
-  mapM_ go ls
-  where go l' = do UTF8.hPutStr stderr "  "
-                   UTF8.hPutStrLn stderr $ T.unpack l'
+  logOutput = IO.logOutput
 
 -- | Extract media from the mediabag into a directory.
 extractMedia :: FilePath -> Pandoc -> PandocIO Pandoc
-extractMedia dir d = do
-  media <- getMediaBag
-  case [fp | (fp, _, _) <- mediaDirectory media] of
-        []  -> return d
-        fps -> do
-          mapM_ (writeMedia dir media) fps
-          return $ walk (adjustImagePath dir fps) d
-
--- | Write the contents of a media bag to a path.
-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 </> unEscapeString (normalise subpath)
-  let mbcontents = lookupMedia subpath mediabag
-  case mbcontents of
-       Nothing -> throwError $ PandocResourceNotFound $ T.pack subpath
-       Just (_, bs) -> do
-         report $ Extracting $ T.pack fullpath
-         liftIOError (createDirectoryIfMissing True) (takeDirectory fullpath)
-         logIOError $ BL.writeFile fullpath bs
-
--- | If the given Inline element is an image with a @src@ path equal to
--- one in the list of @paths@, then prepends @dir@ to the image source;
--- returns the element unchanged otherwise.
-adjustImagePath :: FilePath -> [FilePath] -> Inline -> Inline
-adjustImagePath dir paths (Image attr lab (src, tit))
-   | T.unpack src `elem` paths = Image attr lab (T.pack dir <> "/" <> src, tit)
-adjustImagePath _ _ x = x
+extractMedia = IO.extractMedia
diff --git a/src/Text/Pandoc/Class/PandocMonad.hs b/src/Text/Pandoc/Class/PandocMonad.hs
--- a/src/Text/Pandoc/Class/PandocMonad.hs
+++ b/src/Text/Pandoc/Class/PandocMonad.hs
@@ -27,6 +27,7 @@
   , report
   , setTrace
   , setRequestHeader
+  , setNoCheckCertificate
   , getLog
   , setVerbosity
   , getVerbosity
@@ -188,6 +189,10 @@
 setRequestHeader name val = modifyCommonState $ \st ->
   st{ stRequestHeaders =
        (name, val) : filter (\(n,_) -> n /= name) (stRequestHeaders st)  }
+
+-- | Determine whether certificate validation is disabled
+setNoCheckCertificate :: PandocMonad m => Bool -> m ()
+setNoCheckCertificate noCheckCertificate = modifyCommonState $ \st -> st{stNoCheckCertificate = noCheckCertificate}
 
 -- | Initialize the media bag.
 setMediaBag :: PandocMonad m => MediaBag -> m ()
diff --git a/src/Text/Pandoc/Class/PandocPure.hs b/src/Text/Pandoc/Class/PandocPure.hs
--- a/src/Text/Pandoc/Class/PandocPure.hs
+++ b/src/Text/Pandoc/Class/PandocPure.hs
@@ -40,7 +40,7 @@
 import System.Directory (doesDirectoryExist, getDirectoryContents)
 import System.FilePath ((</>))
 import System.FilePath.Glob (match, compile)
-import System.Random (StdGen, next, mkStdGen)
+import System.Random (StdGen, split, mkStdGen)
 import Text.Pandoc.Class.CommonState (CommonState (..))
 import Text.Pandoc.Class.PandocMonad
 import Text.Pandoc.Error
@@ -168,10 +168,10 @@
   getCurrentTimeZone = getsPureState stTimeZone
 
   newStdGen = do
-    g <- getsPureState stStdGen
-    let (_, nxtGen) = next g
-    modifyPureState $ \st -> st { stStdGen = nxtGen }
-    return g
+    oldGen <- getsPureState stStdGen
+    let (genToStore, genToReturn) = split oldGen
+    modifyPureState $ \st -> st { stStdGen = genToStore }
+    return genToReturn
 
   newUniqueHash = do
     uniqs <- getsPureState stUniqStore
diff --git a/src/Text/Pandoc/Error.hs b/src/Text/Pandoc/Error.hs
--- a/src/Text/Pandoc/Error.hs
+++ b/src/Text/Pandoc/Error.hs
@@ -47,6 +47,7 @@
                  | PandocPDFProgramNotFoundError Text
                  | PandocPDFError Text
                  | PandocFilterError Text Text
+                 | PandocLuaError Text
                  | PandocCouldNotFindDataFileError Text
                  | PandocResourceNotFound Text
                  | PandocTemplateError Text
@@ -100,6 +101,7 @@
     PandocPDFError logmsg -> err 43 $ "Error producing PDF.\n" <> logmsg
     PandocFilterError filtername msg -> err 83 $ "Error running filter " <>
         filtername <> ":\n" <> msg
+    PandocLuaError msg -> err 84 $ "Error running Lua:\n" <> msg
     PandocCouldNotFindDataFileError fn -> err 97 $
         "Could not find data file " <> fn
     PandocResourceNotFound fn -> err 99 $
diff --git a/src/Text/Pandoc/Extensions.hs b/src/Text/Pandoc/Extensions.hs
--- a/src/Text/Pandoc/Extensions.hs
+++ b/src/Text/Pandoc/Extensions.hs
@@ -435,6 +435,7 @@
     extensionsFromList
     [ Ext_raw_html
     , Ext_raw_tex            -- only supported in writer (for math)
+    , Ext_implicit_figures
     , Ext_hard_line_breaks
     , Ext_smart
     ]
diff --git a/src/Text/Pandoc/Filter/JSON.hs b/src/Text/Pandoc/Filter/JSON.hs
--- a/src/Text/Pandoc/Filter/JSON.hs
+++ b/src/Text/Pandoc/Filter/JSON.hs
@@ -23,7 +23,6 @@
 import System.Environment (getEnvironment)
 import System.Exit (ExitCode (..))
 import System.FilePath ((</>), takeExtension)
-import Text.Pandoc.Class.PandocIO (PandocIO)
 import Text.Pandoc.Error (PandocError (PandocFilterError))
 import Text.Pandoc.Definition (Pandoc)
 import Text.Pandoc.Options (ReaderOptions)
@@ -32,11 +31,12 @@
 import qualified Control.Exception as E
 import qualified Text.Pandoc.UTF8 as UTF8
 
-apply :: ReaderOptions
+apply :: MonadIO m
+      => ReaderOptions
       -> [String]
       -> FilePath
       -> Pandoc
-      -> PandocIO Pandoc
+      -> m Pandoc
 apply ropts args f = liftIO . externalFilter ropts f args
 
 externalFilter :: MonadIO m
diff --git a/src/Text/Pandoc/Filter/Lua.hs b/src/Text/Pandoc/Filter/Lua.hs
--- a/src/Text/Pandoc/Filter/Lua.hs
+++ b/src/Text/Pandoc/Filter/Lua.hs
@@ -16,9 +16,8 @@
 import qualified Data.Text as T
 import Text.Pandoc.Class.PandocIO (PandocIO)
 import Text.Pandoc.Definition (Pandoc)
-import Text.Pandoc.Error (PandocError (PandocFilterError))
-import Text.Pandoc.Lua (Global (..), LuaException (..),
-                        runLua, runFilterFile, setGlobals)
+import Text.Pandoc.Error (PandocError (PandocFilterError, PandocLuaError))
+import Text.Pandoc.Lua (Global (..), runLua, runFilterFile, setGlobals)
 import Text.Pandoc.Options (ReaderOptions)
 
 -- | Run the Lua filter in @filterPath@ for a transformation to the
@@ -40,7 +39,9 @@
                ]
     runFilterFile fp doc
 
-forceResult :: FilePath -> Either LuaException Pandoc -> PandocIO Pandoc
+forceResult :: FilePath -> Either PandocError Pandoc -> PandocIO Pandoc
 forceResult fp eitherResult = case eitherResult of
-  Right x               -> return x
-  Left (LuaException s) -> throw (PandocFilterError (T.pack fp) s)
+  Right x  -> return x
+  Left err -> throw . PandocFilterError (T.pack fp) $ case err of
+    PandocLuaError msg -> msg
+    _                  -> T.pack $ show err
diff --git a/src/Text/Pandoc/Lua.hs b/src/Text/Pandoc/Lua.hs
--- a/src/Text/Pandoc/Lua.hs
+++ b/src/Text/Pandoc/Lua.hs
@@ -10,7 +10,6 @@
 -}
 module Text.Pandoc.Lua
   ( runLua
-  , LuaException (..)
   -- * Lua globals
   , Global (..)
   , setGlobals
@@ -20,5 +19,5 @@
 
 import Text.Pandoc.Lua.Filter (runFilterFile)
 import Text.Pandoc.Lua.Global (Global (..), setGlobals)
-import Text.Pandoc.Lua.Init (LuaException (..), runLua)
+import Text.Pandoc.Lua.Init (runLua)
 import Text.Pandoc.Lua.Marshaling ()
diff --git a/src/Text/Pandoc/Lua/ErrorConversion.hs b/src/Text/Pandoc/Lua/ErrorConversion.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/Lua/ErrorConversion.hs
@@ -0,0 +1,61 @@
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{- |
+   Module      : Text.Pandoc.Lua.ErrorConversion
+   Copyright   : © 2020 Albert Krewinkel
+   License     : GNU GPL, version 2 or above
+
+   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
+   Stability   : alpha
+
+Define how Lua errors are converted into @'PandocError'@ Haskell
+exceptions, and /vice versa/.
+-}
+module Text.Pandoc.Lua.ErrorConversion
+  ( errorConversion
+  ) where
+
+import Foreign.Lua (Lua (..), NumResults)
+import Text.Pandoc.Error (PandocError (PandocLuaError))
+import Text.Pandoc.Lua.Marshaling.PandocError (pushPandocError, peekPandocError)
+
+import qualified Control.Monad.Catch as Catch
+import qualified Data.Text as T
+import qualified Foreign.Lua as Lua
+
+-- | Conversions between Lua errors and Haskell exceptions, assuming
+-- that all exceptions are of type @'PandocError'@.
+errorConversion :: Lua.ErrorConversion
+errorConversion = Lua.ErrorConversion
+  { Lua.addContextToException = addContextToException
+  , Lua.alternative           = alternative
+  , Lua.errorToException      = errorToException
+  , Lua.exceptionToError      = exceptionToError
+  }
+
+-- | Convert a Lua error, which must be at the top of the stack, into a
+-- @'PandocError'@, popping the value from the stack.
+errorToException :: forall a . Lua.State -> IO a
+errorToException l = Lua.unsafeRunWith l $ do
+  err <- peekPandocError Lua.stackTop
+  Lua.pop 1
+  Catch.throwM err
+
+-- | Try the first op -- if it doesn't succeed, run the second.
+alternative :: forall a . Lua a -> Lua a -> Lua a
+alternative x y = Catch.try x >>= \case
+  Left (_ :: PandocError) -> y
+  Right x' -> return x'
+
+-- | Add more context to an error
+addContextToException :: forall a . String -> Lua a -> Lua a
+addContextToException ctx op = op `Catch.catch` \case
+  PandocLuaError msg -> Catch.throwM $ PandocLuaError (T.pack ctx <> msg)
+  e -> Catch.throwM e
+
+-- | Catch a @'PandocError'@ exception and raise it as a Lua error.
+exceptionToError :: Lua NumResults -> Lua NumResults
+exceptionToError op = op `Catch.catch` \e -> do
+  pushPandocError e
+  Lua.error
diff --git a/src/Text/Pandoc/Lua/Filter.hs b/src/Text/Pandoc/Lua/Filter.hs
--- a/src/Text/Pandoc/Lua/Filter.hs
+++ b/src/Text/Pandoc/Lua/Filter.hs
@@ -18,14 +18,15 @@
                               ) where
 import Control.Applicative ((<|>))
 import Control.Monad (mplus, (>=>))
-import Control.Monad.Catch (finally)
+import Control.Monad.Catch (finally, try)
 import Data.Data (Data, DataType, dataTypeConstrs, dataTypeName, dataTypeOf,
                   showConstr, toConstr, tyconUQname)
 import Data.Foldable (foldrM)
 import Data.Map (Map)
 import Data.Maybe (fromMaybe)
-import Foreign.Lua (Lua, Peekable, Pushable)
+import Foreign.Lua (Lua, Peekable, Pushable, StackIndex)
 import Text.Pandoc.Definition
+import Text.Pandoc.Error (PandocError)
 import Text.Pandoc.Lua.Marshaling ()
 import Text.Pandoc.Lua.Marshaling.List (List (..))
 import Text.Pandoc.Lua.Walk (SingletonsList (..))
@@ -102,7 +103,7 @@
   if elementUnchanged
     then [x] <$ Lua.pop 1
     else do
-       mbres <- Lua.peekEither topOfStack
+       mbres <- peekEither topOfStack
        case mbres of
          Right res -> [res] <$ Lua.pop 1
          Left _    -> Lua.peekList topOfStack `finally` Lua.pop 1
@@ -234,11 +235,16 @@
   if elementUnchanged
     then x <$ Lua.pop 1
     else do
-    mbres <- Lua.peekEither (-1)
+    mbres <- peekEither (-1)
     case mbres of
       Right res -> res <$ Lua.pop 1
       Left err  -> do
         Lua.pop 1
-        Lua.throwException $
-          "Error while trying to get a filter's return " ++
-          "value from lua stack.\n" ++ err
+        Lua.throwMessage
+          ("Error while trying to get a filter's return " <>
+           "value from Lua stack.\n" <> show err)
+
+-- | Try to convert the value at the given stack index to a Haskell value.
+-- Returns @Left@ with an error message on failure.
+peekEither :: Peekable a => StackIndex -> Lua (Either PandocError a)
+peekEither = try . Lua.peek
diff --git a/src/Text/Pandoc/Lua/Init.hs b/src/Text/Pandoc/Lua/Init.hs
--- a/src/Text/Pandoc/Lua/Init.hs
+++ b/src/Text/Pandoc/Lua/Init.hs
@@ -9,96 +9,57 @@
 Functions to initialize the Lua interpreter.
 -}
 module Text.Pandoc.Lua.Init
-  ( LuaException (..)
-  , LuaPackageParams (..)
-  , runLua
-  , luaPackageParams
+  ( runLua
   ) where
 
+import Control.Monad.Catch (try)
 import Control.Monad.Trans (MonadIO (..))
 import Data.Data (Data, dataTypeConstrs, dataTypeOf, showConstr)
 import Foreign.Lua (Lua)
 import GHC.IO.Encoding (getForeignEncoding, setForeignEncoding, utf8)
 import Text.Pandoc.Class.PandocIO (PandocIO)
-import Text.Pandoc.Class.PandocMonad (getCommonState, getUserDataDir,
-                                      putCommonState)
-import Text.Pandoc.Lua.Global (Global (..), setGlobals)
-import Text.Pandoc.Lua.Packages (LuaPackageParams (..),
-                                 installPandocPackageSearcher)
-import Text.Pandoc.Lua.Util (loadScriptFromDataDir)
+import Text.Pandoc.Error (PandocError)
+import Text.Pandoc.Lua.Packages (installPandocPackageSearcher)
+import Text.Pandoc.Lua.PandocLua (PandocLua, liftPandocLua,
+                                  loadScriptFromDataDir, runPandocLua)
 
-import qualified Data.Text as Text
 import qualified Foreign.Lua as Lua
-import qualified Foreign.Lua.Module.Text as Lua
 import qualified Text.Pandoc.Definition as Pandoc
 import qualified Text.Pandoc.Lua.Module.Pandoc as ModulePandoc
 
--- | Lua error message
-newtype LuaException = LuaException Text.Text deriving (Show)
-
 -- | Run the lua interpreter, using pandoc's default way of environment
 -- initialization.
-runLua :: Lua a -> PandocIO (Either LuaException a)
+runLua :: Lua a -> PandocIO (Either PandocError a)
 runLua luaOp = do
-  luaPkgParams <- luaPackageParams
-  globals <- defaultGlobals
   enc <- liftIO $ getForeignEncoding <* setForeignEncoding utf8
-  res <- liftIO . Lua.runEither $ do
-    setGlobals globals
-    initLuaState luaPkgParams
-    -- run the given Lua operation
-    opResult <- luaOp
-    -- get the (possibly modified) state back
-    Lua.getglobal "PANDOC_STATE"
-    st <- Lua.peek Lua.stackTop
-    Lua.pop 1
-    -- done
-    return (opResult, st)
+  res <- runPandocLua . try $ do
+    initLuaState
+    liftPandocLua luaOp
   liftIO $ setForeignEncoding enc
-  case res of
-    Left (Lua.Exception msg) -> return $ Left (LuaException $ Text.pack msg)
-    Right (x, newState) -> do
-      putCommonState newState
-      return $ Right x
-
--- | Global variables which should always be set.
-defaultGlobals :: PandocIO [Global]
-defaultGlobals = do
-  commonState <- getCommonState
-  return
-    [ PANDOC_API_VERSION
-    , PANDOC_STATE commonState
-    , PANDOC_VERSION
-    ]
-
--- | Generate parameters required to setup pandoc's lua environment.
-luaPackageParams :: PandocIO LuaPackageParams
-luaPackageParams = do
-  datadir <- getUserDataDir
-  return LuaPackageParams { luaPkgDataDir = datadir }
+  return res
 
 -- | Initialize the lua state with all required values
-initLuaState :: LuaPackageParams -> Lua ()
-initLuaState pkgParams = do
-  Lua.openlibs
-  Lua.preloadTextModule "text"
-  installPandocPackageSearcher pkgParams
+initLuaState :: PandocLua ()
+initLuaState = do
+  liftPandocLua Lua.openlibs
+  installPandocPackageSearcher
   initPandocModule
-  loadScriptFromDataDir (luaPkgDataDir pkgParams) "init.lua"
+  loadScriptFromDataDir "init.lua"
  where
-  initPandocModule :: Lua ()
+  initPandocModule :: PandocLua ()
   initPandocModule = do
     -- Push module table
-    ModulePandoc.pushModule (luaPkgDataDir pkgParams)
+    ModulePandoc.pushModule
     -- register as loaded module
-    Lua.pushvalue Lua.stackTop
-    Lua.getfield Lua.registryindex Lua.loadedTableRegistryField
-    Lua.setfield (Lua.nthFromTop 2) "pandoc"
-    Lua.pop 1
+    liftPandocLua $ do
+      Lua.pushvalue Lua.stackTop
+      Lua.getfield Lua.registryindex Lua.loadedTableRegistryField
+      Lua.setfield (Lua.nthFromTop 2) "pandoc"
+      Lua.pop 1
     -- copy constructors into registry
     putConstructorsInRegistry
     -- assign module to global variable
-    Lua.setglobal "pandoc"
+    liftPandocLua $ Lua.setglobal "pandoc"
 
 -- | AST elements are marshaled via normal constructor functions in the
 -- @pandoc@ module. However, accessing Lua globals from Haskell is
@@ -108,8 +69,8 @@
 --
 -- This function expects the @pandoc@ module to be at the top of the
 -- stack.
-putConstructorsInRegistry :: Lua ()
-putConstructorsInRegistry = do
+putConstructorsInRegistry :: PandocLua ()
+putConstructorsInRegistry = liftPandocLua $ do
   constrsToReg $ Pandoc.Pandoc mempty mempty
   constrsToReg $ Pandoc.Str mempty
   constrsToReg $ Pandoc.Para mempty
diff --git a/src/Text/Pandoc/Lua/Marshaling.hs b/src/Text/Pandoc/Lua/Marshaling.hs
--- a/src/Text/Pandoc/Lua/Marshaling.hs
+++ b/src/Text/Pandoc/Lua/Marshaling.hs
@@ -13,6 +13,7 @@
 
 import Text.Pandoc.Lua.Marshaling.AST ()
 import Text.Pandoc.Lua.Marshaling.CommonState ()
-import Text.Pandoc.Lua.Marshaling.ReaderOptions ()
 import Text.Pandoc.Lua.Marshaling.Context ()
+import Text.Pandoc.Lua.Marshaling.PandocError()
+import Text.Pandoc.Lua.Marshaling.ReaderOptions ()
 import Text.Pandoc.Lua.Marshaling.Version ()
diff --git a/src/Text/Pandoc/Lua/Marshaling/AST.hs b/src/Text/Pandoc/Lua/Marshaling/AST.hs
--- a/src/Text/Pandoc/Lua/Marshaling/AST.hs
+++ b/src/Text/Pandoc/Lua/Marshaling/AST.hs
@@ -19,9 +19,11 @@
 import Control.Applicative ((<|>))
 import Foreign.Lua (Lua, Peekable, Pushable, StackIndex)
 import Text.Pandoc.Definition
+import Text.Pandoc.Error (PandocError)
 import Text.Pandoc.Lua.Util (defineHowTo, pushViaConstructor)
 import Text.Pandoc.Lua.Marshaling.CommonState ()
 
+import qualified Control.Monad.Catch as Catch
 import qualified Foreign.Lua as Lua
 import qualified Text.Pandoc.Lua.Util as LuaUtil
 
@@ -131,7 +133,7 @@
     Lua.TypeBoolean -> MetaBool <$> Lua.peek idx
     Lua.TypeString  -> MetaString <$> Lua.peek idx
     Lua.TypeTable   -> do
-      tag <- Lua.try $ LuaUtil.getTag idx
+      tag <- try $ LuaUtil.getTag idx
       case tag of
         Right "MetaBlocks"  -> MetaBlocks  <$> elementContent
         Right "MetaBool"    -> MetaBool    <$> elementContent
@@ -139,7 +141,7 @@
         Right "MetaInlines" -> MetaInlines <$> elementContent
         Right "MetaList"    -> MetaList    <$> elementContent
         Right "MetaString"  -> MetaString  <$> elementContent
-        Right t             -> Lua.throwException ("Unknown meta tag: " <> t)
+        Right t             -> Lua.throwMessage ("Unknown meta tag: " <> t)
         Left _ -> do
           -- no meta value tag given, try to guess.
           len <- Lua.rawlen idx
@@ -148,9 +150,9 @@
             else  (MetaInlines <$> Lua.peek idx)
                   <|> (MetaBlocks <$> Lua.peek idx)
                   <|> (MetaList <$> Lua.peek idx)
-    _        -> Lua.throwException "could not get meta value"
+    _        -> Lua.throwMessage "could not get meta value"
 
--- | Push an block element to the top of the lua stack.
+-- | Push a block element to the top of the Lua stack.
 pushBlock :: Block -> Lua ()
 pushBlock = \case
   BlockQuote blcks         -> pushViaConstructor "BlockQuote" blcks
@@ -167,8 +169,8 @@
   Para blcks               -> pushViaConstructor "Para" blcks
   Plain blcks              -> pushViaConstructor "Plain" blcks
   RawBlock f cs            -> pushViaConstructor "RawBlock" f cs
-  Table capt aligns widths headers rows ->
-    pushViaConstructor "Table" capt aligns widths headers rows
+  Table attr blkCapt specs thead tbody tfoot ->
+    pushViaConstructor "Table" attr blkCapt specs thead tbody tfoot
 
 -- | Return the value at the given index as block if possible.
 peekBlock :: StackIndex -> Lua Block
@@ -191,21 +193,117 @@
       "Para"           -> Para <$> elementContent
       "Plain"          -> Plain <$> elementContent
       "RawBlock"       -> uncurry RawBlock <$> elementContent
-      "Table"          -> (\(capt, aligns, widths, headers, body) ->
-                                  Table capt aligns widths headers body)
+      "Table"          -> (\(attr, capt, colSpecs, thead, tbodies, tfoot) ->
+                              Table (fromLuaAttr attr)
+                                    capt
+                                    colSpecs
+                                    thead
+                                    tbodies
+                                    tfoot)
                           <$> elementContent
-      _ -> Lua.throwException ("Unknown block type: " <> tag)
+      _ -> Lua.throwMessage ("Unknown block type: " <> tag)
  where
    -- Get the contents of an AST element.
    elementContent :: Peekable a => Lua a
    elementContent = LuaUtil.rawField idx "c"
 
+instance Pushable Caption where
+  push = pushCaption
+
+instance Peekable Caption where
+  peek = peekCaption
+
+-- | Push Caption element
+pushCaption :: Caption -> Lua ()
+pushCaption (Caption shortCaption longCaption) = do
+  Lua.newtable
+  LuaUtil.addField "short" (Lua.Optional shortCaption)
+  LuaUtil.addField "long" longCaption
+
+-- | Peek Caption element
+peekCaption :: StackIndex -> Lua Caption
+peekCaption idx = do
+  short <- Lua.fromOptional <$> LuaUtil.rawField idx "short"
+  long  <- LuaUtil.rawField idx "long"
+  return $ Caption short long
+
+instance Peekable ColWidth where
+  peek idx = do
+    width <- Lua.fromOptional <$> Lua.peek idx
+    return $ case width of
+      Nothing -> ColWidthDefault
+      Just w  -> ColWidth w
+
+instance Pushable ColWidth where
+  push = \case
+    (ColWidth w)    -> Lua.push w
+    ColWidthDefault -> Lua.pushnil
+
+instance Pushable Row where
+  push (Row attr cells) = Lua.push (attr, cells)
+
+instance Peekable Row where
+  peek = fmap (uncurry Row) . Lua.peek
+
+instance Pushable TableBody where
+  push (TableBody attr (RowHeadColumns rowHeadColumns) head' body) = do
+    Lua.newtable
+    LuaUtil.addField "attr" attr
+    LuaUtil.addField "row_head_columns" rowHeadColumns
+    LuaUtil.addField "head" head'
+    LuaUtil.addField "body" body
+
+instance Peekable TableBody where
+  peek idx = do
+    attr <- LuaUtil.rawField idx "attr"
+    rowHeadColumns <- LuaUtil.rawField idx "row_head_columns"
+    head' <- LuaUtil.rawField idx "head"
+    body <- LuaUtil.rawField idx "body"
+    return $ TableBody attr (RowHeadColumns rowHeadColumns) head' body
+
+instance Pushable TableHead where
+  push (TableHead attr cells) = Lua.push (attr, cells)
+
+instance Peekable TableHead where
+  peek = fmap (uncurry TableHead) . Lua.peek
+
+instance Pushable TableFoot where
+  push (TableFoot attr cells) = Lua.push (attr, cells)
+
+instance Peekable TableFoot where
+  peek = fmap (uncurry TableFoot) . Lua.peek
+
+instance Pushable Cell where
+  push = pushCell
+
+instance Peekable Cell where
+  peek = peekCell
+
+pushCell :: Cell -> Lua ()
+pushCell (Cell attr align (RowSpan rowSpan) (ColSpan colSpan) contents) = do
+  Lua.newtable
+  LuaUtil.addField "attr" attr
+  LuaUtil.addField "alignment" align
+  LuaUtil.addField "row_span" rowSpan
+  LuaUtil.addField "col_span" colSpan
+  LuaUtil.addField "contents" contents
+
+peekCell :: StackIndex -> Lua Cell
+peekCell idx = do
+  attr <- fromLuaAttr <$> LuaUtil.rawField idx "attr"
+  align <- LuaUtil.rawField idx "alignment"
+  rowSpan <- LuaUtil.rawField idx "row_span"
+  colSpan <- LuaUtil.rawField idx "col_span"
+  contents <- LuaUtil.rawField idx "contents"
+  return $ Cell attr align (RowSpan rowSpan) (ColSpan colSpan) contents
+
 -- | Push an inline element to the top of the lua stack.
 pushInline :: Inline -> Lua ()
 pushInline = \case
   Cite citations lst       -> pushViaConstructor "Cite" lst citations
   Code attr lst            -> pushViaConstructor "Code" lst (LuaAttr attr)
   Emph inlns               -> pushViaConstructor "Emph" inlns
+  Underline inlns          -> pushViaConstructor "Underline" inlns
   Image attr alt (src,tit) -> pushViaConstructor "Image" alt src tit (LuaAttr attr)
   LineBreak                -> pushViaConstructor "LineBreak"
   Link attr lst (src,tit)  -> pushViaConstructor "Link" lst src tit (LuaAttr attr)
@@ -231,6 +329,7 @@
     "Cite"       -> uncurry Cite <$> elementContent
     "Code"       -> withAttr Code <$> elementContent
     "Emph"       -> Emph <$> elementContent
+    "Underline"  -> Underline <$> elementContent
     "Image"      -> (\(LuaAttr attr, lst, tgt) -> Image attr lst tgt)
                     <$> elementContent
     "Link"       -> (\(LuaAttr attr, lst, tgt) -> Link attr lst tgt)
@@ -249,11 +348,14 @@
     "Strong"     -> Strong <$> elementContent
     "Subscript"  -> Subscript <$> elementContent
     "Superscript"-> Superscript <$> elementContent
-    _ -> Lua.throwException ("Unknown inline type: " <> tag)
+    _ -> Lua.throwMessage ("Unknown inline type: " <> tag)
  where
    -- Get the contents of an AST element.
    elementContent :: Peekable a => Lua a
    elementContent = LuaUtil.rawField idx "c"
+
+try :: Lua a -> Lua (Either PandocError a)
+try = Catch.try
 
 withAttr :: (Attr -> a -> b) -> (LuaAttr, a) -> b
 withAttr f (attributes, x) = f (fromLuaAttr attributes) x
diff --git a/src/Text/Pandoc/Lua/Marshaling/PandocError.hs b/src/Text/Pandoc/Lua/Marshaling/PandocError.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/Lua/Marshaling/PandocError.hs
@@ -0,0 +1,65 @@
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+{-# LANGUAGE LambdaCase           #-}
+{-# LANGUAGE OverloadedStrings    #-}
+{-# LANGUAGE ScopedTypeVariables  #-}
+{- |
+   Module      : Text.Pandoc.Lua.Marshaling.PandocError
+   Copyright   : © 2020 Albert Krewinkel
+   License     : GNU GPL, version 2 or above
+
+   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
+   Stability   : alpha
+
+Marshaling of @'PandocError'@ values.
+-}
+module Text.Pandoc.Lua.Marshaling.PandocError
+  ( peekPandocError
+  , pushPandocError
+  )
+  where
+
+import Foreign.Lua (Lua, Peekable, Pushable, StackIndex)
+import Text.Pandoc.Error (PandocError (PandocLuaError))
+
+import qualified Foreign.Lua as Lua
+import qualified Foreign.Lua.Userdata as Lua
+import qualified Text.Pandoc.Lua.Util as LuaUtil
+import qualified Text.Pandoc.UTF8 as UTF8
+
+-- | Userdata name used by Lua for the @PandocError@ type.
+pandocErrorName :: String
+pandocErrorName = "pandoc error"
+
+-- | Peek a @'PandocError'@ element to the Lua stack.
+pushPandocError :: PandocError -> Lua ()
+pushPandocError = Lua.pushAnyWithMetatable pushPandocErrorMT
+  where
+    pushPandocErrorMT = Lua.ensureUserdataMetatable pandocErrorName $
+      LuaUtil.addFunction "__tostring" __tostring
+
+-- | Retrieve a @'PandocError'@ from the Lua stack.
+peekPandocError :: StackIndex -> Lua PandocError
+peekPandocError idx = Lua.ltype idx >>= \case
+  Lua.TypeUserdata -> do
+    errMb <- Lua.toAnyWithName idx pandocErrorName
+    return $ case errMb of
+      Just err -> err
+      Nothing  -> PandocLuaError "could not retrieve original error"
+  _ -> do
+    Lua.pushvalue idx
+    msg <- Lua.state >>= \l -> Lua.liftIO (Lua.errorMessage l)
+    return $ PandocLuaError (UTF8.toText msg)
+
+-- | Convert to string.
+__tostring :: PandocError -> Lua String
+__tostring = return . show
+
+--
+-- Instances
+--
+
+instance Pushable PandocError where
+  push = pushPandocError
+
+instance Peekable PandocError where
+  peek = peekPandocError
diff --git a/src/Text/Pandoc/Lua/Marshaling/Version.hs b/src/Text/Pandoc/Lua/Marshaling/Version.hs
--- a/src/Text/Pandoc/Lua/Marshaling/Version.hs
+++ b/src/Text/Pandoc/Lua/Marshaling/Version.hs
@@ -57,7 +57,7 @@
     let parses = readP_to_S parseVersion versionStr
     case lastMay parses of
       Just (v, "") -> return v
-      _  -> Lua.throwException $ "could not parse as Version: " ++ versionStr
+      _  -> Lua.throwMessage $ "could not parse as Version: " ++ versionStr
 
   Lua.TypeUserdata ->
     reportValueOnFailure versionTypeName
@@ -71,7 +71,7 @@
     makeVersion <$> Lua.peek idx
 
   _ ->
-    Lua.throwException "could not peek Version"
+    Lua.throwMessage "could not peek Version"
 
 instance Peekable Version where
   peek = peekVersion
diff --git a/src/Text/Pandoc/Lua/Module/MediaBag.hs b/src/Text/Pandoc/Lua/Module/MediaBag.hs
--- a/src/Text/Pandoc/Lua/Module/MediaBag.hs
+++ b/src/Text/Pandoc/Lua/Module/MediaBag.hs
@@ -14,13 +14,13 @@
   ) where
 
 import Control.Monad (zipWithM_)
-import Foreign.Lua (Lua, NumResults, Optional, liftIO)
+import Foreign.Lua (Lua, NumResults, Optional)
 import Text.Pandoc.Class.CommonState (CommonState (..))
-import Text.Pandoc.Class.PandocIO (runIOorExplode)
-import Text.Pandoc.Class.PandocMonad (fetchItem, putCommonState, setMediaBag)
+import Text.Pandoc.Class.PandocMonad (fetchItem, getMediaBag, modifyCommonState,
+                                      setMediaBag)
 import Text.Pandoc.Lua.Marshaling ()
 import Text.Pandoc.Lua.Marshaling.MediaBag (pushIterator)
-import Text.Pandoc.Lua.Util (addFunction)
+import Text.Pandoc.Lua.PandocLua (PandocLua (..), liftPandocLua, addFunction)
 import Text.Pandoc.MIME (MimeType)
 
 import qualified Data.ByteString.Lazy as BL
@@ -31,9 +31,9 @@
 --
 -- MediaBag submodule
 --
-pushModule :: Lua NumResults
+pushModule :: PandocLua NumResults
 pushModule = do
-  Lua.newtable
+  liftPandocLua Lua.newtable
   addFunction "delete" delete
   addFunction "empty" empty
   addFunction "insert" insertMediaFn
@@ -43,66 +43,46 @@
   addFunction "fetch" fetch
   return 1
 
---
--- Port functions from Text.Pandoc.Class to the Lua monad.
--- TODO: reuse existing functions.
-
--- Get the current CommonState.
-getCommonState :: Lua CommonState
-getCommonState = do
-  Lua.getglobal "PANDOC_STATE"
-  Lua.peek Lua.stackTop
-
--- Replace MediaBag in CommonState.
-setCommonState :: CommonState -> Lua ()
-setCommonState st = do
-  Lua.push st
-  Lua.setglobal "PANDOC_STATE"
-
-modifyCommonState :: (CommonState -> CommonState) -> Lua ()
-modifyCommonState f = getCommonState >>= setCommonState . f
-
 -- | Delete a single item from the media bag.
-delete :: FilePath -> Lua NumResults
+delete :: FilePath -> PandocLua NumResults
 delete fp = 0 <$ modifyCommonState
   (\st -> st { stMediaBag = MB.deleteMedia fp (stMediaBag st) })
 
 -- | Delete all items from the media bag.
-empty :: Lua NumResults
+empty :: PandocLua NumResults
 empty = 0 <$ modifyCommonState (\st -> st { stMediaBag = mempty })
 
 -- | Insert a new item into the media bag.
 insertMediaFn :: FilePath
               -> Optional MimeType
               -> BL.ByteString
-              -> Lua NumResults
+              -> PandocLua NumResults
 insertMediaFn fp optionalMime contents = do
-  modifyCommonState $ \st ->
-    let mb = MB.insertMedia fp (Lua.fromOptional optionalMime) contents
-                               (stMediaBag st)
-    in st { stMediaBag = mb }
-  return 0
+  mb <- getMediaBag
+  setMediaBag $ MB.insertMedia fp (Lua.fromOptional optionalMime) contents mb
+  return (Lua.NumResults 0)
 
 -- | Returns iterator values to be used with a Lua @for@ loop.
-items :: Lua NumResults
-items = stMediaBag <$> getCommonState >>= pushIterator
+items :: PandocLua NumResults
+items = getMediaBag >>= liftPandocLua . pushIterator
 
 lookupMediaFn :: FilePath
-              -> Lua NumResults
+              -> PandocLua NumResults
 lookupMediaFn fp = do
-  res <- MB.lookupMedia fp . stMediaBag <$> getCommonState
-  case res of
+  res <- MB.lookupMedia fp <$> getMediaBag
+  liftPandocLua $ case res of
     Nothing -> 1 <$ Lua.pushnil
     Just (mimeType, contents) -> do
       Lua.push mimeType
       Lua.push contents
       return 2
 
-mediaDirectoryFn :: Lua NumResults
+mediaDirectoryFn :: PandocLua NumResults
 mediaDirectoryFn = do
-  dirContents <- MB.mediaDirectory . stMediaBag <$> getCommonState
-  Lua.newtable
-  zipWithM_ addEntry [1..] dirContents
+  dirContents <- MB.mediaDirectory <$> getMediaBag
+  liftPandocLua $ do
+    Lua.newtable
+    zipWithM_ addEntry [1..] dirContents
   return 1
  where
   addEntry :: Lua.Integer -> (FilePath, MimeType, Int) -> Lua ()
@@ -114,14 +94,9 @@
     Lua.rawseti (-2) idx
 
 fetch :: T.Text
-      -> Lua NumResults
+      -> PandocLua NumResults
 fetch src = do
-  commonState <- getCommonState
-  let mediaBag = stMediaBag commonState
-  (bs, mimeType) <- liftIO . runIOorExplode $ do
-    putCommonState commonState
-    setMediaBag mediaBag
-    fetchItem src
-  Lua.push $ maybe "" T.unpack mimeType
-  Lua.push bs
+  (bs, mimeType) <- fetchItem src
+  liftPandocLua . Lua.push $ maybe "" T.unpack mimeType
+  liftPandocLua $ Lua.push bs
   return 2 -- returns 2 values: contents, mimetype
diff --git a/src/Text/Pandoc/Lua/Module/Pandoc.hs b/src/Text/Pandoc/Lua/Module/Pandoc.hs
--- a/src/Text/Pandoc/Lua/Module/Pandoc.hs
+++ b/src/Text/Pandoc/Lua/Module/Pandoc.hs
@@ -24,6 +24,8 @@
 import Text.Pandoc.Definition (Block, Inline)
 import Text.Pandoc.Lua.Filter (walkInlines, walkBlocks, LuaFilter, SingletonsList (..))
 import Text.Pandoc.Lua.Marshaling ()
+import Text.Pandoc.Lua.PandocLua (PandocLua, addFunction, liftPandocLua,
+                                  loadScriptFromDataDir)
 import Text.Pandoc.Walk (Walkable)
 import Text.Pandoc.Options (ReaderOptions (readerExtensions))
 import Text.Pandoc.Process (pipeProcess)
@@ -38,28 +40,28 @@
 
 -- | Push the "pandoc" on the lua stack. Requires the `list` module to be
 -- loaded.
-pushModule :: Maybe FilePath -> Lua NumResults
-pushModule datadir = do
-  LuaUtil.loadScriptFromDataDir datadir "pandoc.lua"
-  LuaUtil.addFunction "read" readDoc
-  LuaUtil.addFunction "pipe" pipeFn
-  LuaUtil.addFunction "walk_block" walkBlock
-  LuaUtil.addFunction "walk_inline" walkInline
+pushModule :: PandocLua NumResults
+pushModule = do
+  loadScriptFromDataDir "pandoc.lua"
+  addFunction "read" readDoc
+  addFunction "pipe" pipeFn
+  addFunction "walk_block" walkBlock
+  addFunction "walk_inline" walkInline
   return 1
 
 walkElement :: (Walkable (SingletonsList Inline) a,
                 Walkable (SingletonsList Block) a)
-            => a -> LuaFilter -> Lua a
-walkElement x f = walkInlines f x >>= walkBlocks f
+            => a -> LuaFilter -> PandocLua a
+walkElement x f = liftPandocLua $ walkInlines f x >>= walkBlocks f
 
-walkInline :: Inline -> LuaFilter -> Lua Inline
+walkInline :: Inline -> LuaFilter -> PandocLua Inline
 walkInline = walkElement
 
-walkBlock :: Block -> LuaFilter -> Lua Block
+walkBlock :: Block -> LuaFilter -> PandocLua Block
 walkBlock = walkElement
 
-readDoc :: T.Text -> Optional T.Text -> Lua NumResults
-readDoc content formatSpecOrNil = do
+readDoc :: T.Text -> Optional T.Text -> PandocLua NumResults
+readDoc content formatSpecOrNil = liftPandocLua $ do
   let formatSpec = fromMaybe "markdown" (Lua.fromOptional formatSpecOrNil)
   res <- Lua.liftIO . runIO $
            getReader formatSpec >>= \(rdr,es) ->
@@ -80,8 +82,8 @@
 pipeFn :: String
        -> [String]
        -> BL.ByteString
-       -> Lua NumResults
-pipeFn command args input = do
+       -> PandocLua NumResults
+pipeFn command args input = liftPandocLua $ do
   (ec, output) <- Lua.liftIO $ pipeProcess Nothing command args input
   case ec of
     ExitSuccess -> 1 <$ Lua.push output
diff --git a/src/Text/Pandoc/Lua/Module/Utils.hs b/src/Text/Pandoc/Lua/Module/Utils.hs
--- a/src/Text/Pandoc/Lua/Module/Utils.hs
+++ b/src/Text/Pandoc/Lua/Module/Utils.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE ScopedTypeVariables #-}
 {- |
    Module      : Text.Pandoc.Lua.Module.Utils
    Copyright   : Copyright © 2017-2020 Albert Krewinkel
@@ -13,15 +14,15 @@
   ) where
 
 import Control.Applicative ((<|>))
+import Control.Monad.Catch (try)
 import Data.Default (def)
 import Data.Version (Version)
 import Foreign.Lua (Peekable, Lua, NumResults)
-import Text.Pandoc.Class.PandocIO (runIO)
-import Text.Pandoc.Class.PandocMonad (setUserDataDir)
 import Text.Pandoc.Definition ( Pandoc, Meta, MetaValue (..), Block, Inline
                               , Citation, Attr, ListAttributes)
+import Text.Pandoc.Error (PandocError)
 import Text.Pandoc.Lua.Marshaling ()
-import Text.Pandoc.Lua.Util (addFunction)
+import Text.Pandoc.Lua.PandocLua (PandocLua, addFunction, liftPandocLua)
 
 import qualified Data.Digest.Pure.SHA as SHA
 import qualified Data.ByteString.Lazy as BSL
@@ -32,14 +33,14 @@
 import qualified Text.Pandoc.Shared as Shared
 
 -- | Push the "pandoc.utils" module to the lua stack.
-pushModule :: Maybe FilePath -> Lua NumResults
-pushModule mbDatadir = do
-  Lua.newtable
+pushModule :: PandocLua NumResults
+pushModule = do
+  liftPandocLua Lua.newtable
   addFunction "blocks_to_inlines" blocksToInlines
   addFunction "equals" equals
   addFunction "make_sections" makeSections
   addFunction "normalize_date" normalizeDate
-  addFunction "run_json_filter" (runJSONFilter mbDatadir)
+  addFunction "run_json_filter" runJSONFilter
   addFunction "sha1" sha1
   addFunction "stringify" stringify
   addFunction "to_roman_numeral" toRomanNumeral
@@ -47,8 +48,8 @@
   return 1
 
 -- | Squashes a list of blocks into inlines.
-blocksToInlines :: [Block] -> Lua.Optional [Inline] -> Lua [Inline]
-blocksToInlines blks optSep = do
+blocksToInlines :: [Block] -> Lua.Optional [Inline] -> PandocLua [Inline]
+blocksToInlines blks optSep = liftPandocLua $ do
   let sep = case Lua.fromOptional optSep of
               Just x -> B.fromList x
               Nothing -> Shared.defaultBlocksSeparator
@@ -67,23 +68,17 @@
 normalizeDate = return . Lua.Optional . Shared.normalizeDate
 
 -- | Run a JSON filter on the given document.
-runJSONFilter :: Maybe FilePath
-              -> Pandoc
+runJSONFilter :: Pandoc
               -> FilePath
               -> Lua.Optional [String]
-              -> Lua NumResults
-runJSONFilter mbDatadir doc filterFile optArgs = do
+              -> PandocLua Pandoc
+runJSONFilter doc filterFile optArgs = do
   args <- case Lua.fromOptional optArgs of
             Just x -> return x
-            Nothing -> do
+            Nothing -> liftPandocLua $ do
               Lua.getglobal "FORMAT"
               (:[]) <$> Lua.popValue
-  filterRes <- Lua.liftIO . runIO $ do
-    setUserDataDir mbDatadir
-    JSONFilter.apply def args filterFile doc
-  case filterRes of
-    Left err -> Lua.raiseError (show err)
-    Right d -> (1 :: NumResults) <$ Lua.push d
+  JSONFilter.apply def args filterFile doc
 
 -- | Calculate the hash of the given contents.
 sha1 :: BSL.ByteString
@@ -93,7 +88,7 @@
 -- | Convert pandoc structure to a string with formatting removed.
 -- Footnotes are skipped (since we don't want their contents in link
 -- labels).
-stringify :: AstElement -> Lua T.Text
+stringify :: AstElement -> PandocLua T.Text
 stringify el = return $ case el of
   PandocElement pd -> Shared.stringify pd
   InlineElement i  -> Shared.stringify i
@@ -109,7 +104,7 @@
   MetaString s -> s
   _            -> Shared.stringify mv
 
-equals :: AstElement -> AstElement -> Lua Bool
+equals :: AstElement -> AstElement -> PandocLua Bool
 equals e1 e2 = return (e1 == e2)
 
 data AstElement
@@ -125,18 +120,18 @@
 
 instance Peekable AstElement where
   peek idx  = do
-    res <- Lua.try $  (PandocElement <$> Lua.peek idx)
-                  <|> (InlineElement <$> Lua.peek idx)
-                  <|> (BlockElement <$> Lua.peek idx)
-                  <|> (AttrElement <$> Lua.peek idx)
-                  <|> (ListAttributesElement <$> Lua.peek idx)
-                  <|> (MetaElement <$> Lua.peek idx)
-                  <|> (MetaValueElement <$> Lua.peek idx)
+    res <- try $  (PandocElement <$> Lua.peek idx)
+              <|> (InlineElement <$> Lua.peek idx)
+              <|> (BlockElement <$> Lua.peek idx)
+              <|> (AttrElement <$> Lua.peek idx)
+              <|> (ListAttributesElement <$> Lua.peek idx)
+              <|> (MetaElement <$> Lua.peek idx)
+              <|> (MetaValueElement <$> Lua.peek idx)
     case res of
       Right x -> return x
-      Left _ -> Lua.throwException
+      Left (_ :: PandocError) -> Lua.throwMessage
         "Expected an AST element, but could not parse value as such."
 
 -- | Convert a number < 4000 to uppercase roman numeral.
-toRomanNumeral :: Lua.Integer -> Lua T.Text
+toRomanNumeral :: Lua.Integer -> PandocLua T.Text
 toRomanNumeral = return . Shared.toRomanNumeral . fromIntegral
diff --git a/src/Text/Pandoc/Lua/Packages.hs b/src/Text/Pandoc/Lua/Packages.hs
--- a/src/Text/Pandoc/Lua/Packages.hs
+++ b/src/Text/Pandoc/Lua/Packages.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {- |
    Module      : Text.Pandoc.Lua.Packages
@@ -8,37 +9,34 @@
    Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
    Stability   : alpha
 
-Pandoc module for lua.
+Pandoc module for Lua.
 -}
 module Text.Pandoc.Lua.Packages
-  ( LuaPackageParams (..)
-  , installPandocPackageSearcher
+  ( installPandocPackageSearcher
   ) where
 
+import Control.Monad.Catch (try)
 import Control.Monad (forM_)
 import Data.ByteString (ByteString)
-import Foreign.Lua (Lua, NumResults, liftIO)
-import Text.Pandoc.Class.PandocIO (runIO)
-import Text.Pandoc.Class.PandocMonad (readDataFile, setUserDataDir)
+import Foreign.Lua (Lua, NumResults)
+import Text.Pandoc.Error (PandocError)
+import Text.Pandoc.Class.PandocMonad (readDataFile)
+import Text.Pandoc.Lua.PandocLua (PandocLua, liftPandocLua)
 
 import qualified Foreign.Lua as Lua
-import Text.Pandoc.Lua.Module.Pandoc as Pandoc
-import Text.Pandoc.Lua.Module.MediaBag as MediaBag
-import Text.Pandoc.Lua.Module.System as System
-import Text.Pandoc.Lua.Module.Types as Types
-import Text.Pandoc.Lua.Module.Utils as Utils
-
--- | Parameters used to create lua packages/modules.
-data LuaPackageParams = LuaPackageParams
-  { luaPkgDataDir :: Maybe FilePath
-  }
+import qualified Foreign.Lua.Module.Text as Text
+import qualified Text.Pandoc.Lua.Module.Pandoc as Pandoc
+import qualified Text.Pandoc.Lua.Module.MediaBag as MediaBag
+import qualified Text.Pandoc.Lua.Module.System as System
+import qualified Text.Pandoc.Lua.Module.Types as Types
+import qualified Text.Pandoc.Lua.Module.Utils as Utils
 
 -- | Insert pandoc's package loader as the first loader, making it the default.
-installPandocPackageSearcher :: LuaPackageParams -> Lua ()
-installPandocPackageSearcher luaPkgParams = do
+installPandocPackageSearcher :: PandocLua ()
+installPandocPackageSearcher = liftPandocLua $ do
   Lua.getglobal' "package.searchers"
   shiftArray
-  Lua.pushHaskellFunction (pandocPackageSearcher luaPkgParams)
+  Lua.pushHaskellFunction pandocPackageSearcher
   Lua.rawseti (Lua.nthFromTop 2) 1
   Lua.pop 1           -- remove 'package.searchers' from stack
  where
@@ -47,29 +45,27 @@
     Lua.rawseti (-2) (i + 1)
 
 -- | Load a pandoc module.
-pandocPackageSearcher :: LuaPackageParams -> String -> Lua NumResults
-pandocPackageSearcher pkgParams pkgName =
+pandocPackageSearcher :: String -> PandocLua NumResults
+pandocPackageSearcher pkgName =
   case pkgName of
-    "pandoc"          -> let datadir = luaPkgDataDir pkgParams
-                         in pushWrappedHsFun (Pandoc.pushModule datadir)
+    "pandoc"          -> pushWrappedHsFun Pandoc.pushModule
     "pandoc.mediabag" -> pushWrappedHsFun MediaBag.pushModule
     "pandoc.system"   -> pushWrappedHsFun System.pushModule
     "pandoc.types"    -> pushWrappedHsFun Types.pushModule
-    "pandoc.utils"    -> let datadir = luaPkgDataDir pkgParams
-                         in pushWrappedHsFun (Utils.pushModule datadir)
-    _ -> searchPureLuaLoader
+    "pandoc.utils"    -> pushWrappedHsFun Utils.pushModule
+    "text"            -> pushWrappedHsFun Text.pushModule
+    _                 -> searchPureLuaLoader
  where
-  pushWrappedHsFun f = do
+  pushWrappedHsFun f = liftPandocLua $ do
     Lua.pushHaskellFunction f
     return 1
   searchPureLuaLoader = do
     let filename = pkgName ++ ".lua"
-    modScript <- liftIO (dataDirScript (luaPkgDataDir pkgParams) filename)
-    case modScript of
-      Just script -> pushWrappedHsFun (loadStringAsPackage pkgName script)
-      Nothing -> do
+    try (readDataFile filename) >>= \case
+      Right script -> pushWrappedHsFun (loadStringAsPackage pkgName script)
+      Left (_ :: PandocError) -> liftPandocLua $ do
         Lua.push ("\n\tno file '" ++ filename ++ "' in pandoc's datadir")
-        return 1
+        return (1 :: NumResults)
 
 loadStringAsPackage :: String -> ByteString -> Lua NumResults
 loadStringAsPackage pkgName script = do
@@ -79,11 +75,3 @@
     else do
       msg <- Lua.popValue
       Lua.raiseError ("Error while loading `" <> pkgName <> "`.\n" <> msg)
-
--- | Get the ByteString representation of the pandoc module.
-dataDirScript :: Maybe FilePath -> FilePath -> IO (Maybe ByteString)
-dataDirScript datadir moduleFile = do
-  res <- runIO $ setUserDataDir datadir >> readDataFile moduleFile
-  return $ case res of
-    Left _ -> Nothing
-    Right s -> Just s
diff --git a/src/Text/Pandoc/Lua/PandocLua.hs b/src/Text/Pandoc/Lua/PandocLua.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/Lua/PandocLua.hs
@@ -0,0 +1,134 @@
+{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+{- |
+   Module      : Text.Pandoc.Lua.PandocLua
+   Copyright   : Copyright © 2020 Albert Krewinkel
+   License     : GNU GPL, version 2 or above
+
+   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
+   Stability   : alpha
+
+PandocMonad instance which allows execution of Lua operations and which
+uses Lua to handle state.
+-}
+module Text.Pandoc.Lua.PandocLua
+  ( PandocLua (..)
+  , runPandocLua
+  , liftPandocLua
+  , addFunction
+  , loadScriptFromDataDir
+  ) where
+
+import Control.Monad (when)
+import Control.Monad.Catch (MonadCatch, MonadMask, MonadThrow)
+import Control.Monad.Except (MonadError (catchError, throwError))
+import Control.Monad.IO.Class (MonadIO (liftIO))
+import Foreign.Lua (Lua (..), NumResults, Pushable, ToHaskellFunction)
+import Text.Pandoc.Class.PandocIO (PandocIO)
+import Text.Pandoc.Class.PandocMonad (PandocMonad (..), readDataFile)
+import Text.Pandoc.Error (PandocError)
+import Text.Pandoc.Lua.Global (Global (..), setGlobals)
+import Text.Pandoc.Lua.ErrorConversion (errorConversion)
+
+import qualified Control.Monad.Catch as Catch
+import qualified Foreign.Lua as Lua
+import qualified Text.Pandoc.Class.IO as IO
+import qualified Text.Pandoc.Lua.Util as LuaUtil
+
+-- | Type providing access to both, pandoc and Lua operations.
+newtype PandocLua a = PandocLua { unPandocLua :: Lua a }
+  deriving
+    ( Applicative
+    , Functor
+    , Monad
+    , MonadCatch
+    , MonadIO
+    , MonadMask
+    , MonadThrow
+    )
+
+-- | Lift a @'Lua'@ operation into the @'PandocLua'@ type.
+liftPandocLua :: Lua a -> PandocLua a
+liftPandocLua = PandocLua
+
+-- | Evaluate a @'PandocLua'@ computation, running all contained Lua
+-- operations..
+runPandocLua :: PandocLua a -> PandocIO a
+runPandocLua pLua = do
+  origState <- getCommonState
+  globals <- defaultGlobals
+  (result, newState) <- liftIO . Lua.run' errorConversion . unPandocLua $ do
+    putCommonState origState
+    liftPandocLua $ setGlobals globals
+    r <- pLua
+    c <- getCommonState
+    return (r, c)
+  putCommonState newState
+  return result
+
+instance {-# OVERLAPPING #-} ToHaskellFunction (PandocLua NumResults) where
+  toHsFun _narg = unPandocLua
+
+instance Pushable a => ToHaskellFunction (PandocLua a) where
+  toHsFun _narg x = 1 <$ (unPandocLua x >>= Lua.push)
+
+-- | Add a function to the table at the top of the stack, using the given name.
+addFunction :: ToHaskellFunction a => String -> a -> PandocLua ()
+addFunction name fn = liftPandocLua $ do
+  Lua.push name
+  Lua.pushHaskellFunction fn
+  Lua.rawset (-3)
+
+-- | Load a file from pandoc's data directory.
+loadScriptFromDataDir :: FilePath -> PandocLua ()
+loadScriptFromDataDir scriptFile = do
+  script <- readDataFile scriptFile
+  status <- liftPandocLua $ Lua.dostring script
+  when (status /= Lua.OK) . liftPandocLua $
+    LuaUtil.throwTopMessageAsError'
+      (("Couldn't load '" ++ scriptFile ++ "'.\n") ++)
+
+-- | Global variables which should always be set.
+defaultGlobals :: PandocIO [Global]
+defaultGlobals = do
+  commonState <- getCommonState
+  return
+    [ PANDOC_API_VERSION
+    , PANDOC_STATE commonState
+    , PANDOC_VERSION
+    ]
+
+instance MonadError PandocError PandocLua where
+  catchError = Catch.catch
+  throwError = Catch.throwM
+
+instance PandocMonad PandocLua where
+  lookupEnv = IO.lookupEnv
+  getCurrentTime = IO.getCurrentTime
+  getCurrentTimeZone = IO.getCurrentTimeZone
+  newStdGen = IO.newStdGen
+  newUniqueHash = IO.newUniqueHash
+
+  openURL = IO.openURL
+
+  readFileLazy = IO.readFileLazy
+  readFileStrict = IO.readFileStrict
+
+  glob = IO.glob
+  fileExists = IO.fileExists
+  getDataFileName = IO.getDataFileName
+  getModificationTime = IO.getModificationTime
+
+  getCommonState = PandocLua $ do
+    Lua.getglobal "PANDOC_STATE"
+    Lua.peek Lua.stackTop
+  putCommonState = PandocLua . setGlobals . (:[]) . PANDOC_STATE
+
+  logOutput = IO.logOutput
diff --git a/src/Text/Pandoc/Lua/Util.hs b/src/Text/Pandoc/Lua/Util.hs
--- a/src/Text/Pandoc/Lua/Util.hs
+++ b/src/Text/Pandoc/Lua/Util.hs
@@ -19,7 +19,6 @@
   , addFunction
   , addValue
   , pushViaConstructor
-  , loadScriptFromDataDir
   , defineHowTo
   , throwTopMessageAsError'
   , callWithTraceback
@@ -27,13 +26,11 @@
   ) where
 
 import Control.Monad (unless, when)
+import Data.Text (Text)
 import Foreign.Lua ( Lua, NumArgs, NumResults, Peekable, Pushable, StackIndex
                    , Status, ToHaskellFunction )
-import Text.Pandoc.Class.PandocIO (runIOorExplode)
-import Text.Pandoc.Class.PandocMonad (readDataFile, setUserDataDir)
 import qualified Foreign.Lua as Lua
 import qualified Text.Pandoc.UTF8 as UTF8
-import Data.Text (Text)
 
 -- | Get value behind key from table at given index.
 rawField :: Peekable a => StackIndex -> String -> Lua a
@@ -87,15 +84,6 @@
 pushViaConstructor :: PushViaCall a => String -> a
 pushViaConstructor pandocFn = pushViaCall ("pandoc." ++ pandocFn)
 
--- | Load a file from pandoc's data directory.
-loadScriptFromDataDir :: Maybe FilePath -> FilePath -> Lua ()
-loadScriptFromDataDir datadir scriptFile = do
-  script <- Lua.liftIO . runIOorExplode $
-            setUserDataDir datadir >> readDataFile scriptFile
-  status <- Lua.dostring script
-  when (status /= Lua.OK) $
-    throwTopMessageAsError' (("Couldn't load '" ++ scriptFile ++ "'.\n") ++)
-
 -- | Get the tag of a value. This is an optimized and specialized version of
 -- @Lua.getfield idx "tag"@. It only checks for the field on the table at index
 -- @idx@ and on its metatable, also ignoring any @__index@ value on the
@@ -107,7 +95,7 @@
   Lua.push ("tag" :: Text)
   Lua.rawget (Lua.nthFromTop 2)
   Lua.tostring Lua.stackTop <* Lua.pop 2 >>= \case
-    Nothing -> Lua.throwException "untagged value"
+    Nothing -> Lua.throwMessage "untagged value"
     Just x -> return (UTF8.toString x)
 
 -- | Modify the message at the top of the stack before throwing it as an
@@ -116,11 +104,12 @@
 throwTopMessageAsError' modifier = do
   msg <- Lua.tostring' Lua.stackTop
   Lua.pop 2 -- remove error and error string pushed by tostring'
-  Lua.throwException (modifier (UTF8.toString msg))
+  Lua.throwMessage (modifier (UTF8.toString msg))
 
 -- | Mark the context of a Lua computation for better error reporting.
 defineHowTo :: String -> Lua a -> Lua a
-defineHowTo ctx = Lua.withExceptionMessage (("Could not " <> ctx <> ": ") <>)
+defineHowTo ctx op = Lua.errorConversion >>= \ec ->
+  Lua.addContextToException ec ("Could not " <> ctx <> ": ") op
 
 -- | Like @'Lua.pcall'@, but uses a predefined error handler which adds a
 -- traceback on error.
@@ -143,7 +132,8 @@
 callWithTraceback :: NumArgs -> NumResults -> Lua ()
 callWithTraceback nargs nresults = do
   result <- pcallWithTraceback nargs nresults
-  when (result /= Lua.OK) Lua.throwTopMessage
+  when (result /= Lua.OK)
+    Lua.throwTopMessage
 
 -- | Run the given string as a Lua program, while also adding a traceback to the
 -- error message if an error occurs.
diff --git a/src/Text/Pandoc/Lua/Walk.hs b/src/Text/Pandoc/Lua/Walk.hs
--- a/src/Text/Pandoc/Lua/Walk.hs
+++ b/src/Text/Pandoc/Lua/Walk.hs
@@ -55,6 +55,30 @@
   walkM = walkBlockM
   query = queryBlock
 
+instance Walkable (SingletonsList Inline) Row where
+  walkM = walkRowM
+  query = queryRow
+
+instance Walkable (SingletonsList Inline) TableHead where
+  walkM = walkTableHeadM
+  query = queryTableHead
+
+instance Walkable (SingletonsList Inline) TableBody where
+  walkM = walkTableBodyM
+  query = queryTableBody
+
+instance Walkable (SingletonsList Inline) TableFoot where
+  walkM = walkTableFootM
+  query = queryTableFoot
+
+instance Walkable (SingletonsList Inline) Caption where
+  walkM = walkCaptionM
+  query = queryCaption
+
+instance Walkable (SingletonsList Inline) Cell where
+  walkM = walkCellM
+  query = queryCell
+
 instance Walkable (SingletonsList Inline) MetaValue where
   walkM = walkMetaValueM
   query = queryMetaValue
@@ -85,6 +109,30 @@
 instance Walkable (SingletonsList Block) Block where
   walkM = walkBlockM
   query = queryBlock
+
+instance Walkable (SingletonsList Block) Row where
+  walkM = walkRowM
+  query = queryRow
+
+instance Walkable (SingletonsList Block) TableHead where
+  walkM = walkTableHeadM
+  query = queryTableHead
+
+instance Walkable (SingletonsList Block) TableBody where
+  walkM = walkTableBodyM
+  query = queryTableBody
+
+instance Walkable (SingletonsList Block) TableFoot where
+  walkM = walkTableFootM
+  query = queryTableFoot
+
+instance Walkable (SingletonsList Block) Caption where
+  walkM = walkCaptionM
+  query = queryCaption
+
+instance Walkable (SingletonsList Block) Cell where
+  walkM = walkCellM
+  query = queryCell
 
 instance Walkable (SingletonsList Block) MetaValue where
   walkM = walkMetaValueM
diff --git a/src/Text/Pandoc/MIME.hs b/src/Text/Pandoc/MIME.hs
--- a/src/Text/Pandoc/MIME.hs
+++ b/src/Text/Pandoc/MIME.hs
@@ -461,7 +461,7 @@
            ,("ts","text/texmacs")
            ,("tsp","application/dsptype")
            ,("tsv","text/tab-separated-values")
-           ,("ttf","application/x-font-truetype")
+           ,("ttf","application/font-sfnt")
            ,("txt","text/plain")
            ,("udeb","application/x-debian-package")
            ,("uls","text/iuls")
diff --git a/src/Text/Pandoc/PDF.hs b/src/Text/Pandoc/PDF.hs
--- a/src/Text/Pandoc/PDF.hs
+++ b/src/Text/Pandoc/PDF.hs
@@ -33,7 +33,7 @@
 import System.Environment
 import System.Exit (ExitCode (..))
 import System.FilePath
-import System.IO (stdout, hClose)
+import System.IO (stderr, hClose)
 import System.IO.Temp (withSystemTempDirectory, withTempDirectory,
                        withTempFile)
 import qualified System.IO.Error as IE
@@ -153,7 +153,8 @@
                             (getField "margin-left" meta'))
                  ,("footer-html", getField "footer-html" meta')
                  ,("header-html", getField "header-html" meta')
-                 ] ++ pdfargs
+                 ] ++ ("--enable-local-file-access" : pdfargs)
+                 -- see #6474
   source <- writer opts doc
   verbosity <- getVerbosity
   liftIO $ html2pdf verbosity program args source
@@ -311,9 +312,9 @@
       (pipeProcess (Just env) program programArgs sourceBL)
       (handlePDFProgramNotFound program)
     when (verbosity >= INFO) $ liftIO $ do
-      putStrLn "[makePDF] Running"
-      BL.hPutStr stdout out
-      putStr "\n"
+      UTF8.hPutStrLn stderr "[makePDF] Running"
+      BL.hPutStr stderr out
+      UTF8.hPutStr stderr "\n"
     let pdfFile = tmpDir ++ "/texput.pdf"
     (_, pdf) <- getResultingPDF Nothing pdfFile
     return (exit, out, pdf)
@@ -377,9 +378,9 @@
             (pipeProcess (Just env'') program programArgs BL.empty)
             (handlePDFProgramNotFound program)
           when (verbosity >= INFO) $ liftIO $ do
-            putStrLn $ "[makePDF] Run #" ++ show runNumber
-            BL.hPutStr stdout out
-            putStr "\n"
+            UTF8.hPutStrLn stderr $ "[makePDF] Run #" ++ show runNumber
+            BL.hPutStr stderr out
+            UTF8.hPutStr stderr "\n"
           if runNumber < numRuns
              then runTeX (runNumber + 1)
              else do
@@ -431,8 +432,8 @@
         (pipeProcess (Just env') program programArgs BL.empty)
         (handlePDFProgramNotFound program)
       when (verbosity >= INFO) $ do
-        BL.hPutStr stdout out
-        putStr "\n"
+        BL.hPutStr stderr out
+        UTF8.hPutStr stderr "\n"
       pdfExists <- doesFileExist pdfFile
       mbPdf <- if pdfExists
                 -- We read PDF as a strict bytestring to make sure that the
@@ -464,8 +465,8 @@
       (pipeProcess (Just env') program programArgs BL.empty)
       (handlePDFProgramNotFound program)
     when (verbosity >= INFO) $ do
-      BL.hPutStr stdout out
-      putStr "\n"
+      BL.hPutStr stderr out
+      UTF8.hPutStr stderr "\n"
     let pdfFile = replaceExtension file ".pdf"
     pdfExists <- doesFileExist pdfFile
     mbPdf <- if pdfExists
@@ -491,17 +492,17 @@
 showVerboseInfo mbTmpDir program programArgs env source = do
   case mbTmpDir of
     Just tmpDir -> do
-      putStrLn "[makePDF] temp dir:"
-      putStrLn tmpDir
+      UTF8.hPutStrLn stderr "[makePDF] temp dir:"
+      UTF8.hPutStrLn stderr tmpDir
     Nothing -> return ()
-  putStrLn "[makePDF] Command line:"
-  putStrLn $ program ++ " " ++ unwords (map show programArgs)
-  putStr "\n"
-  putStrLn "[makePDF] Environment:"
-  mapM_ print env
-  putStr "\n"
-  putStrLn "[makePDF] Source:"
-  UTF8.putStrLn source
+  UTF8.hPutStrLn stderr "[makePDF] Command line:"
+  UTF8.hPutStrLn stderr $ program ++ " " ++ unwords (map show programArgs)
+  UTF8.hPutStr stderr "\n"
+  UTF8.hPutStrLn stderr "[makePDF] Environment:"
+  mapM_ (UTF8.hPutStrLn stderr . show) env
+  UTF8.hPutStr stderr "\n"
+  UTF8.hPutStrLn stderr "[makePDF] Source:"
+  UTF8.hPutStrLn stderr source
 
 handlePDFProgramNotFound :: String -> IE.IOError -> IO a
 handlePDFProgramNotFound program e
diff --git a/src/Text/Pandoc/Parsing.hs b/src/Text/Pandoc/Parsing.hs
--- a/src/Text/Pandoc/Parsing.hs
+++ b/src/Text/Pandoc/Parsing.hs
@@ -925,9 +925,16 @@
 tableWith headerParser rowParser lineParser footerParser = try $ do
   (aligns, widths, heads, rows) <- tableWith' headerParser rowParser
                                                 lineParser footerParser
-  return $ B.table mempty (zip aligns widths) <$> heads <*> rows
+  let th = TableHead nullAttr <$> heads
+      tb = (:[]) . TableBody nullAttr 0 [] <$> rows
+      tf = pure $ TableFoot nullAttr []
+  return $ B.table B.emptyCaption (zip aligns (map fromWidth widths)) <$> th <*> tb <*> tf
+  where
+    fromWidth n
+      | n > 0     = ColWidth n
+      | otherwise = ColWidthDefault
 
-type TableComponents mf = ([Alignment], [Double], mf [Blocks], mf [[Blocks]])
+type TableComponents mf = ([Alignment], [Double], mf [Row], mf [Row])
 
 tableWith' :: (Stream s m Char, HasReaderOptions st, Monad mf)
            => ParserT s st m (mf [Blocks], [Alignment], [Int])
@@ -943,7 +950,9 @@
     let widths = if null indices
                     then replicate (length aligns) 0.0
                     else widthsFromIndices numColumns indices
-    return (aligns, widths, heads, lines')
+    let toRow =  Row nullAttr . map B.simpleCell
+        toHeaderRow l = if null l then [] else [toRow l]
+    return (aligns, widths, toHeaderRow <$> heads, map toRow <$> lines')
 
 -- Calculate relative widths of table columns, based on indices
 widthsFromIndices :: Int      -- Number of columns on terminal
@@ -1083,8 +1092,8 @@
            Just (c, _) -> c == ' '
 
 -- | Parse footer for a grid table.
-gridTableFooter :: Stream s m Char => ParserT s st m Text
-gridTableFooter = blanklines
+gridTableFooter :: Stream s m Char => ParserT s st m ()
+gridTableFooter = optional blanklines
 
 ---
 
diff --git a/src/Text/Pandoc/Readers/CSV.hs b/src/Text/Pandoc/Readers/CSV.hs
--- a/src/Text/Pandoc/Readers/CSV.hs
+++ b/src/Text/Pandoc/Readers/CSV.hs
@@ -30,13 +30,19 @@
         -> m Pandoc
 readCSV _opts s =
   case parseCSV defaultCSVOptions (crFilter s) of
-    Right (r:rs) -> return $ B.doc $ B.table capt (zip aligns widths) hdrs rows
-       where capt = mempty
+    Right (r:rs) -> return $ B.doc $ B.table capt
+                                             (zip aligns widths)
+                                             (TableHead nullAttr hdrs)
+                                             [TableBody nullAttr 0 [] rows]
+                                             (TableFoot nullAttr [])
+       where capt = B.emptyCaption
              numcols = length r
-             toplain = B.plain . B.text . T.strip
-             hdrs = map toplain r
-             rows = map (map toplain) rs
+             toplain = B.simpleCell . B.plain . B.text . T.strip
+             toRow = Row nullAttr . map toplain
+             toHeaderRow l = if null l then [] else [toRow l]
+             hdrs = toHeaderRow r
+             rows = map toRow rs
              aligns = replicate numcols AlignDefault
-             widths = replicate numcols 0
+             widths = replicate numcols ColWidthDefault
     Right []     -> return $ B.doc mempty
     Left e       -> throwError $ PandocParsecError s e
diff --git a/src/Text/Pandoc/Readers/CommonMark.hs b/src/Text/Pandoc/Readers/CommonMark.hs
--- a/src/Text/Pandoc/Readers/CommonMark.hs
+++ b/src/Text/Pandoc/Readers/CommonMark.hs
@@ -76,7 +76,12 @@
 
 addBlock :: ReaderOptions -> Node -> [Block] -> [Block]
 addBlock opts (Node _ PARAGRAPH nodes) =
-  (Para (addInlines opts nodes) :)
+  case addInlines opts nodes of
+    [Image attr alt (src,tit)]
+      | isEnabled Ext_implicit_figures opts
+         -- the "fig:" prefix indicates an implicit figure
+      -> (Para [Image attr alt (src, "fig:" <> tit)] :)
+    ils -> (Para ils :)
 addBlock _ (Node _ THEMATIC_BREAK _) =
   (HorizontalRule :)
 addBlock opts (Node _ BLOCK_QUOTE nodes) =
@@ -111,31 +116,39 @@
                      PAREN_DELIM  -> OneParen
         exts = readerExtensions opts
 addBlock opts (Node _ (TABLE alignments) nodes) =
-  (Table [] aligns widths headers rows :)
+  (Table
+    nullAttr
+    (Caption Nothing [])
+    (zip aligns widths)
+    (TableHead nullAttr headers)
+    [TableBody nullAttr 0 [] rows]
+    (TableFoot nullAttr []) :)
   where aligns = map fromTableCellAlignment alignments
         fromTableCellAlignment NoAlignment   = AlignDefault
         fromTableCellAlignment LeftAligned   = AlignLeft
         fromTableCellAlignment RightAligned  = AlignRight
         fromTableCellAlignment CenterAligned = AlignCenter
-        widths = replicate numcols 0.0
+        widths = replicate numcols ColWidthDefault
         numcols = if null rows'
                      then 0
-                     else maximum $ map length rows'
+                     else maximum $ map rowLength rows'
         rows' = map toRow $ filter isRow nodes
         (headers, rows) = case rows' of
-                               (h:rs) -> (h, rs)
+                               (h:rs) -> ([h], rs)
                                []     -> ([], [])
         isRow (Node _ TABLE_ROW _) = True
         isRow _                    = False
         isCell (Node _ TABLE_CELL _) = True
         isCell _                     = False
-        toRow (Node _ TABLE_ROW ns) = map toCell $ filter isCell ns
+        toRow (Node _ TABLE_ROW ns) = Row nullAttr $ map toCell $ filter isCell ns
         toRow (Node _ t _) = error $ "toRow encountered non-row " ++ show t
-        toCell (Node _ TABLE_CELL []) = []
+        toCell (Node _ TABLE_CELL []) = fromSimpleCell []
         toCell (Node _ TABLE_CELL (n:ns))
-          | isBlockNode n = addBlocks opts (n:ns)
-          | otherwise     = [Plain (addInlines opts (n:ns))]
+          | isBlockNode n = fromSimpleCell $ addBlocks opts (n:ns)
+          | otherwise     = fromSimpleCell [Plain (addInlines opts (n:ns))]
         toCell (Node _ t _) = error $ "toCell encountered non-cell " ++ show t
+        fromSimpleCell = Cell nullAttr AlignDefault 1 1
+        rowLength (Row _ body) = length body -- all cells are 1×1
 addBlock _ (Node _ TABLE_ROW _) = id -- handled in TABLE
 addBlock _ (Node _ TABLE_CELL _) = id -- handled in TABLE
 addBlock _ _ = id
diff --git a/src/Text/Pandoc/Readers/DocBook.hs b/src/Text/Pandoc/Readers/DocBook.hs
--- a/src/Text/Pandoc/Readers/DocBook.hs
+++ b/src/Text/Pandoc/Readers/DocBook.hs
@@ -139,7 +139,7 @@
 [x] emphasis - Emphasized text
 [x] entry - A cell in a table
 [ ] entrytbl - A subtable appearing in place of an Entry in a table
-[ ] envar - A software environment variable
+[x] envar - A software environment variable
 [x] epigraph - A short inscription at the beginning of a document or component
     note:  also handle embedded attribution tag
 [x] equation - A displayed mathematical equation
@@ -305,7 +305,7 @@
 [ ] personblurb - A short description or note about a person
 [ ] personname - The personal name of an individual
 [ ] phone - A telephone number
-[ ] phrase - A span of text
+[x] phrase - A span of text
 [ ] pob - A post office box in an address
 [ ] postcode - A postal code in an address
 [x] preface - Introductory matter preceding the first chapter of a book
@@ -314,7 +314,7 @@
     sorted
 [ ] primaryie - A primary term in an index entry, not in the text
 [ ] printhistory - The printing history of a document
-[ ] procedure - A list of operations to be performed in a well-defined sequence
+[x] procedure - A list of operations to be performed in a well-defined sequence
 [ ] production - A production in a set of EBNF productions
 [ ] productionrecap - A cross-reference to an EBNF production
 [ ] productionset - A set of EBNF productions
@@ -363,7 +363,7 @@
 [x] releaseinfo - Information about a particular release of a document
 [ ] remark - A remark (or comment) intended for presentation in a draft
     manuscript
-[ ] replaceable - Content that may or must be replaced by the user
+[x] replaceable - Content that may or must be replaced by the user
 [ ] returnvalue - The value returned by a function
 [ ] revdescription - A extended description of a revision to a document
 [ ] revhistory - A history of the revisions to a document
@@ -419,10 +419,10 @@
     elements
 [x] simplelist - An undecorated list of single words or short phrases
 [ ] simplemsgentry - A wrapper for a simpler entry in a message set
-[ ] simplesect - A section of a document with no subdivisions
+[x] simplesect - A section of a document with no subdivisions
 [ ] spanspec - Formatting information for a spanned column in a table
 [ ] state - A state or province in an address
-[ ] step - A unit of action in a procedure
+[x] step - A unit of action in a procedure
 [ ] stepalternatives - Alternative steps in a procedure
 [ ] street - A street address in an address
 [ ] structfield - A field in a structure (in the programming language sense)
@@ -433,7 +433,7 @@
 [ ] subjectterm - A term in a group of terms describing the subject matter of
     a document
 [x] subscript - A subscript (as in H2O, the molecular formula for water)
-[ ] substeps - A wrapper for steps that occur within steps in a procedure
+[x] substeps - A wrapper for steps that occur within steps in a procedure
 [x] subtitle - The subtitle of a document
 [x] superscript - A superscript (as in x2, the mathematical notation for x
     multiplied by itself)
@@ -445,7 +445,7 @@
 [ ] synopfragmentref - A reference to a fragment of a command synopsis
 [ ] synopsis - A general-purpose element for representing the syntax of
     commands or functions
-[ ] systemitem - A system-related item or term
+[x] systemitem - A system-related item or term
 [ ] table - A formal table in a document
 [ ] task - A task to be completed
 [ ] taskprerequisites - The prerequisites for a task
@@ -521,6 +521,7 @@
                       , dbMeta         :: Meta
                       , dbBook         :: Bool
                       , dbFigureTitle  :: Inlines
+                      , dbFigureId     :: Text
                       , dbContent      :: [Content]
                       } deriving Show
 
@@ -530,6 +531,7 @@
                , dbMeta = mempty
                , dbBook = False
                , dbFigureTitle = mempty
+               , dbFigureId = mempty
                , dbContent = [] }
 
 
@@ -557,9 +559,10 @@
   tit <- case filterChild (named "title") e of
               Just t  -> getInlines t
               Nothing -> return mempty
-  modify $ \st -> st{ dbFigureTitle = tit }
+  let ident = attrValue "id" e
+  modify $ \st -> st{ dbFigureTitle = tit, dbFigureId = ident }
   res <- getBlocks e
-  modify $ \st -> st{ dbFigureTitle = mempty }
+  modify $ \st -> st{ dbFigureTitle = mempty, dbFigureId = mempty }
   return res
 
 -- normalize input, consolidating adjacent Text and CRef elements
@@ -627,12 +630,12 @@
 blockTags = ["toc","index","para","formalpara","simpara",
            "ackno","epigraph","blockquote","bibliography","bibliodiv",
            "biblioentry","glossee","glosseealso","glossary",
-           "glossdiv","glosslist","chapter","appendix","preface",
-           "bridgehead","sect1","sect2","sect3","sect4","sect5","section",
+           "glossdiv","glosslist","chapter","appendix","preface","bridgehead",
+           "sect1","sect2","sect3","sect4","sect5","section","simplesect",
            "refsect1","refsect2","refsect3","refsection", "qandadiv",
            "question","answer","abstract","itemizedlist","orderedlist",
            "variablelist","article","book","table","informaltable",
-           "informalexample", "linegroup",
+           "informalexample", "linegroup","procedure","substeps",
            "screen","programlisting","example","calloutlist"] ++ admonitionTags
 
 admonitionTags :: [String]
@@ -655,6 +658,8 @@
 -- A DocBook mediaobject is a wrapper around a set of alternative presentations
 getMediaobject :: PandocMonad m => Element -> DB m Inlines
 getMediaobject e = do
+  figTitle <- gets dbFigureTitle
+  ident <- gets dbFigureId
   (imageUrl, attr) <-
     case filterChild (named "imageobject") e of
       Nothing  -> return (mempty, nullAttr)
@@ -667,7 +672,11 @@
                                    h = case atVal "depth" of
                                          "" -> []
                                          d  -> [("height", d)]
-                                   atr = (atVal "id", T.words $ atVal "role", w ++ h)
+                                   id' = case atVal "id" of
+                                           x | T.null x  -> ident
+                                             | otherwise -> x
+                                   cs = T.words $ atVal "role"
+                                   atr = (id', cs, w ++ h)
                                in  return (atVal "fileref", atr)
   let getCaption el = case filterChild (\x -> named "caption" x
                                             || named "textobject" x
@@ -675,11 +684,10 @@
                         Nothing -> return mempty
                         Just z  -> mconcat <$>
                                          mapM parseInline (elContent z)
-  figTitle <- gets dbFigureTitle
-  let (caption, title) = if isNull figTitle
-                            then (getCaption e, "")
-                            else (return figTitle, "fig:")
-  fmap (imageWith attr imageUrl title) caption
+  let (capt, title) = if isNull figTitle
+                         then (getCaption e, "")
+                         else (return figTitle, "fig:")
+  fmap (imageWith attr imageUrl title) capt
 
 getBlocks :: PandocMonad m => Element -> DB m Blocks
 getBlocks e =  mconcat <$>
@@ -735,6 +743,9 @@
         "sect4" -> sect 4
         "sect5" -> sect 5
         "section" -> gets dbSectionLevel >>= sect . (+1)
+        "simplesect" ->
+          gets dbSectionLevel >>=
+          sectWith (attrValue "id" e,["unnumbered"],[]) . (+1)
         "refsect1" -> sect 1
         "refsect2" -> sect 2
         "refsect3" -> sect 3
@@ -758,11 +769,12 @@
                                "upperroman" -> UpperRoman
                                _            -> Decimal
           let start = fromMaybe 1 $
-                      (attrValue "override" <$> filterElement (named "listitem") e)
-                       >>= safeRead
+                      filterElement (named "listitem") e
+                       >>= safeRead . attrValue "override"
           orderedListWith (start,listStyle,DefaultDelim)
             <$> listitems
         "variablelist" -> definitionList <$> deflistitems
+        "procedure" -> bulletList <$> steps
         "figure" -> getFigure e
         "mediaobject" -> para <$> getMediaobject e
         "caption" -> skip
@@ -830,6 +842,7 @@
          callouts = mapM getBlocks $ filterChildren (named "callout") e
          deflistitems = mapM parseVarListEntry $ filterChildren
                      (named "varlistentry") e
+         steps = mapM getBlocks $ filterChildren (named "step") e
          parseVarListEntry e' = do
                      let terms = filterChildren (named "term") e'
                      let items = filterChildren (named "listitem") e'
@@ -844,9 +857,9 @@
                      return (mconcat $ intersperse (str "; ") terms', items')
          parseTable = do
                       let isCaption x = named "title" x || named "caption" x
-                      caption <- case filterChild isCaption e of
-                                       Just t  -> getInlines t
-                                       Nothing -> return mempty
+                      capt <- case filterChild isCaption e of
+                                    Just t  -> getInlines t
+                                    Nothing -> return mempty
                       let e' = fromMaybe e $ filterChild (named "tgroup") e
                       let isColspec x = named "colspec" x || named "col" x
                       let colspecs = case filterChild (named "colgroup") e' of
@@ -868,12 +881,12 @@
                                                 Just "right"  -> AlignRight
                                                 Just "center" -> AlignCenter
                                                 _             -> AlignDefault
-                      let toWidth c = case findAttr (unqual "colwidth") c of
-                                                Just w -> fromMaybe 0
-                                                   $ safeRead $ "0" <> T.filter (\x ->
+                      let toWidth c = do
+                            w <- findAttr (unqual "colwidth") c
+                            n <- safeRead $ "0" <> T.filter (\x ->
                                                      (x >= '0' && x <= '9')
                                                       || x == '.') (T.pack w)
-                                                Nothing -> 0 :: Double
+                            if n > 0 then Just n else Nothing
                       let numrows = case bodyrows of
                                          [] -> 0
                                          xs -> maximum $ map length xs
@@ -881,31 +894,34 @@
                                      [] -> replicate numrows AlignDefault
                                      cs -> map toAlignment cs
                       let widths = case colspecs of
-                                     []  -> replicate numrows 0
-                                     cs  -> let ws = map toWidth cs
-                                                tot = sum ws
-                                            in  if all (> 0) ws
-                                                   then map (/ tot) ws
-                                                   else replicate numrows 0
-                      let headrows' = if null headrows
-                                         then replicate numrows mempty
-                                         else headrows
-                      return $ table caption (zip aligns widths)
-                                 headrows' bodyrows
+                                     [] -> replicate numrows ColWidthDefault
+                                     cs -> let ws = map toWidth cs
+                                           in case sequence ws of
+                                                Just ws' -> let tot = sum ws'
+                                                            in  ColWidth . (/ tot) <$> ws'
+                                                Nothing  -> replicate numrows ColWidthDefault
+                      let toRow = Row nullAttr . map simpleCell
+                          toHeaderRow l = if null l then [] else [toRow l]
+                      return $ table (simpleCaption $ plain capt)
+                                     (zip aligns widths)
+                                     (TableHead nullAttr $ toHeaderRow headrows)
+                                     [TableBody nullAttr 0 [] $ map toRow bodyrows]
+                                     (TableFoot nullAttr [])
          isEntry x  = named "entry" x || named "td" x || named "th" x
          parseRow = mapM (parseMixed plain . elContent) . filterChildren isEntry
-         sect n = do isbook <- gets dbBook
-                     let n' = if isbook || n == 0 then n + 1 else n
-                     headerText <- case filterChild (named "title") e `mplus`
-                                        (filterChild (named "info") e >>=
-                                            filterChild (named "title")) of
-                                      Just t  -> getInlines t
-                                      Nothing -> return mempty
-                     modify $ \st -> st{ dbSectionLevel = n }
-                     b <- getBlocks e
-                     let ident = attrValue "id" e
-                     modify $ \st -> st{ dbSectionLevel = n - 1 }
-                     return $ headerWith (ident,[],[]) n' headerText <> b
+         sect n = sectWith (attrValue "id" e,[],[]) n
+         sectWith attr n = do
+           isbook <- gets dbBook
+           let n' = if isbook || n == 0 then n + 1 else n
+           headerText <- case filterChild (named "title") e `mplus`
+                              (filterChild (named "info") e >>=
+                                  filterChild (named "title")) of
+                            Just t  -> getInlines t
+                            Nothing -> return mempty
+           modify $ \st -> st{ dbSectionLevel = n }
+           b <- getBlocks e
+           modify $ \st -> st{ dbSectionLevel = n - 1 }
+           return $ headerWith attr n' headerText <> b
          lineItems = mapM getInlines $ filterChildren (named "line") e
          -- | Admonitions are parsed into a div. Following other Docbook tools that output HTML,
          -- we parse the optional title as a div with the @title@ class, and give the
@@ -942,6 +958,12 @@
   return $ text $ maybe (T.toUpper $ T.pack ref) T.pack $ lookupEntity ref
 parseInline (Elem e) =
   case qName (elName e) of
+        "phrase" -> do
+          let ident = attrValue "id" e
+          let classes = T.words $ attrValue "class" e
+          if ident /= "" || classes /= []
+            then spanWith (ident,classes,[]) <$> innerInlines
+            else innerInlines
         "equation" -> equation e displayMath
         "informalequation" -> equation e displayMath
         "inlineequation" -> equation e math
@@ -962,6 +984,7 @@
         "classname" -> codeWithLang
         "code" -> codeWithLang
         "filename" -> codeWithLang
+        "envar" -> codeWithLang
         "literal" -> codeWithLang
         "computeroutput" -> codeWithLang
         "prompt" -> codeWithLang
@@ -969,6 +992,8 @@
         "option" -> codeWithLang
         "optional" -> do x <- getInlines e
                          return $ str "[" <> x <> str "]"
+        "replaceable" -> do x <- getInlines e
+                            return $ str "<" <> x <> str ">"
         "markup" -> codeWithLang
         "wordasword" -> emph <$> innerInlines
         "command" -> codeWithLang
@@ -978,6 +1003,7 @@
         "symbol"  -> codeWithLang
         "constant" -> codeWithLang
         "userinput" -> codeWithLang
+        "systemitem" -> codeWithLang
         "varargs" -> return $ code "(...)"
         "keycap" -> return (str $ T.pack $ strContent e)
         "keycombo" -> keycombo <$>
diff --git a/src/Text/Pandoc/Readers/Docx.hs b/src/Text/Pandoc/Readers/Docx.hs
--- a/src/Text/Pandoc/Readers/Docx.hs
+++ b/src/Text/Pandoc/Readers/Docx.hs
@@ -72,12 +72,12 @@
 import Data.Sequence (ViewL (..), viewl)
 import qualified Data.Sequence as Seq
 import qualified Data.Set as Set
-import Text.Pandoc.Builder
+import Text.Pandoc.Builder as Pandoc
 import Text.Pandoc.MediaBag (MediaBag)
 import Text.Pandoc.Options
 import Text.Pandoc.Readers.Docx.Combine
 import Text.Pandoc.Readers.Docx.Lists
-import Text.Pandoc.Readers.Docx.Parse
+import Text.Pandoc.Readers.Docx.Parse as Docx
 import Text.Pandoc.Shared
 import Text.Pandoc.Walk
 import Text.TeXMath (writeTeX)
@@ -91,14 +91,18 @@
          => ReaderOptions
          -> B.ByteString
          -> m Pandoc
-readDocx opts bytes
-  | Right archive <- toArchiveOrFail bytes
-  , Right (docx, parserWarnings) <- archiveToDocxWithWarnings archive = do
-      mapM_ (P.report . DocxParserWarning) parserWarnings
-      (meta, blks) <- docxToOutput opts docx
-      return $ Pandoc meta blks
-readDocx _ _ =
-  throwError $ PandocSomeError "couldn't parse docx file"
+readDocx opts bytes = do
+  case toArchiveOrFail bytes of
+    Right archive -> do
+      case archiveToDocxWithWarnings archive of
+        Right (docx, parserWarnings) -> do
+          mapM_ (P.report . DocxParserWarning) parserWarnings
+          (meta, blks) <- docxToOutput opts docx
+          return $ Pandoc meta blks
+        Left docxerr -> throwError $ PandocSomeError $
+                         "couldn't parse docx file: " <> T.pack (show docxerr)
+    Left err -> throwError $ PandocSomeError $
+                  "couldn't unpack docx container: " <> T.pack err
 
 data DState = DState { docxAnchorMap :: M.Map T.Text T.Text
                      , docxAnchorSet :: Set.Set T.Text
@@ -192,12 +196,7 @@
   return $ Meta mp'
 
 fixAuthors :: MetaValue -> MetaValue
-fixAuthors (MetaBlocks blks) =
-  MetaList $ map g $ filter f blks
-    where f (Para _) = True
-          f _        = False
-          g (Para ils) = MetaInlines ils
-          g _          = MetaInlines []
+fixAuthors (MetaBlocks blks) = MetaList [MetaInlines ils | Para ils <- blks]
 fixAuthors mv = mv
 
 isInheritedFromStyles :: (Eq (StyleName s), HasStyleName s, HasParentStyle s) => [StyleName s] -> s -> Bool
@@ -254,9 +253,7 @@
 resolveDependentRunStyle :: PandocMonad m => RunStyle -> DocxContext m RunStyle
 resolveDependentRunStyle rPr
   | Just s  <- rParentStyle rPr
-  , getStyleName s `elem` blacklistedCharStyles =
-    return rPr
-  | Just s  <- rParentStyle rPr = do
+  , getStyleName s `notElem` blacklistedCharStyles = do
       opts <- asks docxOptions
       if isEnabled Ext_styles opts
         then return rPr
@@ -302,7 +299,7 @@
       return $ subscript . transform
   | Just "single" <- rUnderline rPr = do
       transform <- runStyleToTransform rPr{rUnderline = Nothing}
-      return $ underlineSpan . transform
+      return $ Pandoc.underline . transform
   | otherwise = return id
 
 runToInlines :: PandocMonad m => Run -> DocxContext m Inlines
@@ -319,12 +316,8 @@
       let ils = smushInlines (map runElemToInlines runElems)
       transform <- runStyleToTransform rPr
       return $ transform ils
-runToInlines (Footnote bps) = do
-  blksList <- smushBlocks <$> mapM bodyPartToBlocks bps
-  return $ note blksList
-runToInlines (Endnote bps) = do
-  blksList <- smushBlocks <$> mapM bodyPartToBlocks bps
-  return $ note blksList
+runToInlines (Footnote bps) = note . smushBlocks <$> mapM bodyPartToBlocks bps
+runToInlines (Endnote bps) = note . smushBlocks <$> mapM bodyPartToBlocks bps
 runToInlines (InlineDrawing fp title alt bs ext) = do
   (lift . lift) $ P.insertMedia fp Nothing bs
   return $ imageWith (extentToAttr ext) (T.pack fp) title $ text alt
@@ -339,15 +332,14 @@
 
 blocksToInlinesWarn :: PandocMonad m => T.Text -> Blocks -> DocxContext m Inlines
 blocksToInlinesWarn cmtId blks = do
-  let blkList = toList blks
-      paraOrPlain :: Block -> Bool
+  let paraOrPlain :: Block -> Bool
       paraOrPlain (Para _)  = True
       paraOrPlain (Plain _) = True
       paraOrPlain _         = False
-  unless (all paraOrPlain blkList) $
+  unless (all paraOrPlain blks) $
     lift $ P.report $ DocxParserWarning $
       "Docx comment " <> cmtId <> " will not retain formatting"
-  return $ blocksToInlines' blkList
+  return $ blocksToInlines' (toList blks)
 
 -- The majority of work in this function is done in the primed
 -- subfunction `partPartToInlines'`. We make this wrapper so that we
@@ -457,9 +449,7 @@
 parPartToInlines' NullParPart = return mempty
 
 isAnchorSpan :: Inline -> Bool
-isAnchorSpan (Span (_, classes, kvs) _) =
-  classes == ["anchor"] &&
-  null kvs
+isAnchorSpan (Span (_, ["anchor"], []) _) = True
 isAnchorSpan _ = False
 
 dummyAnchors :: [T.Text]
@@ -504,13 +494,13 @@
       singleton $ Plain ils
 singleParaToPlain blks = blks
 
-cellToBlocks :: PandocMonad m => Cell -> DocxContext m Blocks
-cellToBlocks (Cell bps) = do
+cellToBlocks :: PandocMonad m => Docx.Cell -> DocxContext m Blocks
+cellToBlocks (Docx.Cell bps) = do
   blks <- smushBlocks <$> mapM bodyPartToBlocks bps
   return $ fromList $ blocksToDefinitions $ blocksToBullets $ toList blks
 
-rowToBlocksList :: PandocMonad m => Row -> DocxContext m [Blocks]
-rowToBlocksList (Row cells) = do
+rowToBlocksList :: PandocMonad m => Docx.Row -> DocxContext m [Blocks]
+rowToBlocksList (Docx.Row cells) = do
   blksList <- mapM cellToBlocks cells
   return $ map singleParaToPlain blksList
 
@@ -531,31 +521,30 @@
               else id
 
 parStyleToTransform :: PandocMonad m => ParagraphStyle -> DocxContext m (Blocks -> Blocks)
-parStyleToTransform pPr
-  | (c:cs) <- pStyle pPr
-  , getStyleName c `elem` divsToKeep = do
-      let pPr' = pPr { pStyle = cs }
-      transform <- parStyleToTransform pPr'
-      return $ divWith ("", [normalizeToClassName $ getStyleName c], []) . transform
-  | (c:cs) <- pStyle pPr,
-    getStyleName c `elem` listParagraphStyles = do
-      let pPr' = pPr { pStyle = cs, indentation = Nothing}
-      transform <- parStyleToTransform pPr'
-      return $ divWith ("", [normalizeToClassName $ getStyleName c], []) . transform
-  | (c:cs) <- pStyle pPr = do
-      let pPr' = pPr { pStyle = cs }
-      transform <- parStyleToTransform pPr'
-      ei <- extraInfo divWith c
-      return $ ei . (if isBlockQuote c then blockQuote else id) . transform
-  | null (pStyle pPr)
-  , Just left <- indentation pPr >>= leftParIndent = do
-    let pPr' = pPr { indentation = Nothing }
-        hang = fromMaybe 0 $ indentation pPr >>= hangingParIndent
-    transform <- parStyleToTransform pPr'
-    return $ if (left - hang) > 0
-             then blockQuote . transform
-             else transform
-parStyleToTransform _ = return id
+parStyleToTransform pPr = case pStyle pPr of
+  c@(getStyleName -> styleName):cs
+    | styleName `elem` divsToKeep -> do
+        let pPr' = pPr { pStyle = cs }
+        transform <- parStyleToTransform pPr'
+        return $ divWith ("", [normalizeToClassName styleName], []) . transform
+    | styleName `elem` listParagraphStyles -> do
+        let pPr' = pPr { pStyle = cs, indentation = Nothing}
+        transform <- parStyleToTransform pPr'
+        return $ divWith ("", [normalizeToClassName styleName], []) . transform
+    | otherwise -> do
+        let pPr' = pPr { pStyle = cs }
+        transform <- parStyleToTransform pPr'
+        ei <- extraInfo divWith c
+        return $ ei . (if isBlockQuote c then blockQuote else id) . transform
+  []
+    | Just left <- indentation pPr >>= leftParIndent -> do
+        let pPr' = pPr { indentation = Nothing }
+            hang = fromMaybe 0 $ indentation pPr >>= hangingParIndent
+        transform <- parStyleToTransform pPr'
+        return $ if (left - hang) > 0
+                 then blockQuote . transform
+                 else transform
+    | otherwise -> return id
 
 normalizeToClassName :: (FromStyleName a) => a -> T.Text
 normalizeToClassName = T.map go . fromStyleName
@@ -592,47 +581,41 @@
       then do modify $ \s -> s { docxDropCap = ils' }
               return mempty
       else do modify $ \s -> s { docxDropCap = mempty }
-              let ils'' = prevParaIls <>
-                          (if isNull prevParaIls then mempty else space) <>
-                          ils'
+              let ils'' = (if isNull prevParaIls then mempty
+                          else prevParaIls <> space) <> ils'
                   handleInsertion = do
                     modify $ \s -> s {docxPrevPara = mempty}
                     transform <- parStyleToTransform pPr'
                     return $ transform $ paraOrPlain ils''
               opts <- asks docxOptions
-              if  | isNull ils'' && not (isEnabled Ext_empty_paragraphs opts) ->
+              case (pChange pPr', readerTrackChanges opts) of
+                  _ | isNull ils'', not (isEnabled Ext_empty_paragraphs opts) ->
                     return mempty
-                  | Just (TrackedChange Insertion _) <- pChange pPr'
-                  , AcceptChanges <- readerTrackChanges opts ->
+                  (Just (TrackedChange Insertion _), AcceptChanges) ->
                       handleInsertion
-                  | Just (TrackedChange Insertion _) <- pChange pPr'
-                  , RejectChanges <- readerTrackChanges opts -> do
+                  (Just (TrackedChange Insertion _), RejectChanges) -> do
                       modify $ \s -> s {docxPrevPara = ils''}
                       return mempty
-                  | Just (TrackedChange Insertion cInfo) <- pChange pPr'
-                  , AllChanges <- readerTrackChanges opts
-                  , ChangeInfo _ cAuthor cDate <- cInfo -> do
+                  (Just (TrackedChange Insertion (ChangeInfo _ cAuthor cDate))
+                   , AllChanges) -> do
                       let attr = ("", ["paragraph-insertion"], [("author", cAuthor), ("date", cDate)])
                           insertMark = spanWith attr mempty
                       transform <- parStyleToTransform pPr'
                       return $ transform $
                         paraOrPlain $ ils'' <> insertMark
-                  | Just (TrackedChange Deletion _) <- pChange pPr'
-                  , AcceptChanges <- readerTrackChanges opts -> do
+                  (Just (TrackedChange Deletion _), AcceptChanges) -> do
                       modify $ \s -> s {docxPrevPara = ils''}
                       return mempty
-                  | Just (TrackedChange Deletion _) <- pChange pPr'
-                  , RejectChanges <- readerTrackChanges opts ->
+                  (Just (TrackedChange Deletion _), RejectChanges) ->
                       handleInsertion
-                  | Just (TrackedChange Deletion cInfo) <- pChange pPr'
-                  , AllChanges <- readerTrackChanges opts
-                  , ChangeInfo _ cAuthor cDate <- cInfo -> do
+                  (Just (TrackedChange Deletion (ChangeInfo _ cAuthor cDate))
+                   , AllChanges) -> do
                       let attr = ("", ["paragraph-deletion"], [("author", cAuthor), ("date", cDate)])
                           insertMark = spanWith attr mempty
                       transform <- parStyleToTransform pPr'
                       return $ transform $
                         paraOrPlain $ ils'' <> insertMark
-                  | otherwise -> handleInsertion
+                  _ -> handleInsertion
 bodyPartToBlocks (ListItem pPr numId lvl (Just levelInfo) parparts) = do
   -- We check whether this current numId has previously been used,
   -- since Docx expects us to pick up where we left off.
@@ -651,11 +634,8 @@
   modify $ \st -> st{ docxListState =
     -- expire all the continuation data for lists of level > this one:
     -- a new level 1 list item resets continuation for level 2+
-    let expireKeys = [ (numid', lvl')
-                     |  (numid', lvl') <- M.keys listState
-                     , lvl' > lvl
-                     ]
-    in foldr M.delete (M.insert (numId, lvl) start listState) expireKeys }
+    let notExpired (_, lvl') _ = lvl' <= lvl
+    in M.insert (numId, lvl) start (M.filterWithKey notExpired listState) }
   blks <- bodyPartToBlocks (Paragraph pPr parparts)
   return $ divWith ("", ["list-item"], kvs) blks
 bodyPartToBlocks (ListItem pPr _ _ _ parparts) =
@@ -665,7 +645,7 @@
 bodyPartToBlocks (Tbl _ _ _ []) =
   return $ para mempty
 bodyPartToBlocks (Tbl cap _ look parts@(r:rs)) = do
-  let caption = text cap
+  let cap' = simpleCaption $ plain $ text cap
       (hdr, rows) = case firstRowFormatting look of
         True | null rs -> (Nothing, [r])
              | otherwise -> (Just r, rs)
@@ -679,16 +659,19 @@
       -- https://github.com/jgm/pandoc/pull/4361#issuecomment-365416155
       nonEmpty [] = Nothing
       nonEmpty l  = Just l
-      rowLength :: Row -> Int
-      rowLength (Row c) = length c
+      rowLength :: Docx.Row -> Int
+      rowLength (Docx.Row c) = length c
 
+  let toRow = Pandoc.Row nullAttr . map simpleCell
+      toHeaderRow l = if null l then [] else [toRow l]
+
   -- 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
+  let cells' = map (\row -> toRow $ take width (row ++ repeat mempty)) cells
 
   hdrCells <- case hdr of
-    Just r' -> rowToBlocksList r'
-    Nothing -> return $ replicate width mempty
+    Just r' -> toHeaderRow <$> rowToBlocksList r'
+    Nothing -> return []
 
       -- The two following variables (horizontal column alignment and
       -- relative column widths) go to the default at the
@@ -696,9 +679,13 @@
       -- so should be possible. Alignment might be more difficult,
       -- since there doesn't seem to be a column entity in docx.
   let alignments = replicate width AlignDefault
-      widths = replicate width 0 :: [Double]
+      widths = replicate width ColWidthDefault
 
-  return $ table caption (zip alignments widths) hdrCells cells'
+  return $ table cap'
+                 (zip alignments widths)
+                 (TableHead nullAttr hdrCells)
+                 [TableBody nullAttr 0 [] cells']
+                 (TableFoot nullAttr [])
 bodyPartToBlocks (OMathPara e) =
   return $ para $ displayMath (writeTeX e)
 
diff --git a/src/Text/Pandoc/Readers/DokuWiki.hs b/src/Text/Pandoc/Readers/DokuWiki.hs
--- a/src/Text/Pandoc/Readers/DokuWiki.hs
+++ b/src/Text/Pandoc/Readers/DokuWiki.hs
@@ -29,7 +29,7 @@
 import Text.Pandoc.Error (PandocError (PandocParsecError))
 import Text.Pandoc.Options
 import Text.Pandoc.Parsing hiding (enclosed, nested)
-import Text.Pandoc.Shared (crFilter, trim, underlineSpan, stringify, tshow)
+import Text.Pandoc.Shared (crFilter, trim, stringify, tshow)
 
 -- | Read DokuWiki from an input string and return a Pandoc document.
 readDokuWiki :: PandocMonad m
@@ -162,7 +162,7 @@
 italic = try $ B.emph <$> enclosed (string "//") nestedInlines
 
 underlined :: PandocMonad m => DWParser m B.Inlines
-underlined = try $ underlineSpan <$> enclosed (string "__") nestedInlines
+underlined = try $ B.underline <$> enclosed (string "__") nestedInlines
 
 nowiki :: PandocMonad m => DWParser m B.Inlines
 nowiki = try $ B.text <$ string "<nowiki>" <*> manyTillChar anyChar (try $ string "</nowiki>")
@@ -470,8 +470,14 @@
   let (headerRow, body) = if firstSeparator == '^'
                             then (head rows, tail rows)
                             else ([], rows)
-  let attrs = (AlignDefault, 0.0) <$ transpose rows
-  pure $ B.table mempty attrs headerRow body
+  let attrs = (AlignDefault, ColWidthDefault) <$ transpose rows
+  let toRow = Row nullAttr . map B.simpleCell
+      toHeaderRow l = if null l then [] else [toRow l]
+  pure $ B.table B.emptyCaption
+                 attrs
+                 (TableHead nullAttr $ toHeaderRow headerRow)
+                 [TableBody nullAttr 0 [] $ map toRow body]
+                 (TableFoot nullAttr [])
 
 tableRows :: PandocMonad m => DWParser m [[B.Blocks]]
 tableRows = many1 tableRow
diff --git a/src/Text/Pandoc/Readers/HTML.hs b/src/Text/Pandoc/Readers/HTML.hs
--- a/src/Text/Pandoc/Readers/HTML.hs
+++ b/src/Text/Pandoc/Readers/HTML.hs
@@ -61,7 +61,7 @@
 import Text.Pandoc.Parsing hiding ((<|>))
 import Text.Pandoc.Shared (addMetaField, blocksToInlines', crFilter, escapeURI,
                            extractSpaces, htmlSpanLikeElements, elemText, splitTextBy,
-                           onlySimpleTableCells, safeRead, underlineSpan, tshow)
+                           onlySimpleTableCells, safeRead, tshow)
 import Text.Pandoc.Walk
 import Text.Parsec.Error
 import Text.TeXMath (readMathML, writeTeX)
@@ -389,9 +389,8 @@
       isDivLike "main"    = True
       isDivLike _         = False
   TagOpen tag attr' <- lookAhead $ pSatisfy $ tagOpen isDivLike (const True)
-  let attr = toStringAttr attr'
+  let (ident, classes, kvs) = toAttr attr'
   contents <- pInTags tag block
-  let (ident, classes, kvs) = mkAttr attr
   let classes' = if tag == "section"
                     then "section":classes
                     else classes
@@ -479,7 +478,8 @@
 
 pTable :: PandocMonad m => TagParser m Blocks
 pTable = try $ do
-  TagOpen _ _ <- pSatisfy (matchTagOpen "table" [])
+  TagOpen _ attribs' <- pSatisfy (matchTagOpen "table" [])
+  let attribs = toAttr attribs'
   skipMany pBlank
   caption <- option mempty $ pInTags "caption" inline <* skipMany pBlank
   widths' <- (mconcat <$> many1 pColgroup) <|> many pCol
@@ -513,12 +513,19 @@
                     _      -> replicate cols AlignDefault
   let widths = if null widths'
                   then if isSimple
-                       then replicate cols 0
-                       else replicate cols (1.0 / fromIntegral cols)
+                       then replicate cols ColWidthDefault
+                       else replicate cols (ColWidth (1.0 / fromIntegral cols))
                   else widths'
-  return $ B.table caption (zip aligns widths) head' rows
+  let toRow = Row nullAttr . map B.simpleCell
+      toHeaderRow l = if null l then [] else [toRow l]
+  return $ B.tableWith attribs
+                   (B.simpleCaption $ B.plain caption)
+                   (zip aligns widths)
+                   (TableHead nullAttr $ toHeaderRow head')
+                   [TableBody nullAttr 0 [] $ map toRow rows]
+                   (TableFoot nullAttr [])
 
-pCol :: PandocMonad m => TagParser m Double
+pCol :: PandocMonad m => TagParser m ColWidth
 pCol = try $ do
   TagOpen _ attribs' <- pSatisfy (matchTagOpen "col" [])
   let attribs = toStringAttr attribs'
@@ -535,10 +542,10 @@
                   fromMaybe 0.0 $ safeRead xs
                 _ -> 0.0
   if width > 0.0
-    then return $ width / 100.0
-    else return 0.0
+    then return $ ColWidth $ width / 100.0
+    else return ColWidthDefault
 
-pColgroup :: PandocMonad m => TagParser m [Double]
+pColgroup :: PandocMonad m => TagParser m [ColWidth]
 pColgroup = try $ do
   pSatisfy (matchTagOpen "colgroup" [])
   skipMany pBlank
@@ -613,7 +620,7 @@
 pCodeBlock :: PandocMonad m => TagParser m Blocks
 pCodeBlock = try $ do
   TagOpen _ attr' <- pSatisfy (matchTagOpen "pre" [])
-  let attr = toStringAttr attr'
+  let attr = toAttr attr'
   contents <- manyTill pAny (pCloses "pre" <|> eof)
   let rawText = T.concat $ map tagToText contents
   -- drop leading newline if any
@@ -624,7 +631,7 @@
   let result = case T.unsnoc result' of
                     Just (result'', '\n') -> result''
                     _                     -> result'
-  return $ B.codeBlockWith (mkAttr attr) result
+  return $ B.codeBlockWith attr result
 
 tagToText :: Tag Text -> Text
 tagToText (TagText s)      = s
@@ -648,6 +655,7 @@
            , pLineBreak
            , pLink
            , pImage
+           , pBdo
            , pCode
            , pCodeWithClass [("samp","sample"),("var","variable")]
            , pSpan
@@ -724,7 +732,7 @@
   where
     parseTag tagName = do
       TagOpen _ attrs <- pSatisfy $ tagOpenLit tagName (const True)
-      let (ids, cs, kvs) = mkAttr . toStringAttr $ attrs
+      let (ids, cs, kvs) = toAttr attrs
       content <- mconcat <$> manyTill inline (pCloses tagName <|> eof)
       return $ B.spanWith (ids, tagName : cs, kvs) content
 
@@ -741,7 +749,7 @@
             return $ B.strikeout contents)
 
 pUnderline :: PandocMonad m => TagParser m Inlines
-pUnderline = pInlinesInTags "u" underlineSpan <|> pInlinesInTags "ins" underlineSpan
+pUnderline = pInlinesInTags "u" B.underline <|> pInlinesInTags "ins" B.underline
 
 pLineBreak :: PandocMonad m => TagParser m Inlines
 pLineBreak = do
@@ -790,7 +798,7 @@
   let tagTest = flip elem . fmap fst $ elemToClass
   TagOpen open attr' <- pSatisfy $ tagOpen tagTest (const True)
   result <- manyTill pAny (pCloses open)
-  let (ids,cs,kvs) = mkAttr . toStringAttr $ attr'
+  let (ids,cs,kvs) = toAttr attr'
       cs'          = maybe cs (:cs) . lookup open $ elemToClass
   return . B.codeWith (ids,cs',kvs) .
     T.unwords . T.lines . innerText $ result
@@ -798,22 +806,34 @@
 pCode :: PandocMonad m => TagParser m Inlines
 pCode = try $ do
   (TagOpen open attr') <- pSatisfy $ tagOpen (`elem` ["code","tt"]) (const True)
-  let attr = toStringAttr attr'
+  let attr = toAttr attr'
   result <- manyTill pAny (pCloses open)
-  return $ B.codeWith (mkAttr attr) $ T.unwords $ T.lines $ innerText result
+  return $ B.codeWith attr $ T.unwords $ T.lines $ innerText result
 
+-- https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdo
+-- Bidirectional Text Override
+pBdo :: PandocMonad m => TagParser m Inlines
+pBdo = try $ do
+  TagOpen _ attr' <- lookAhead $ pSatisfy $ tagOpen (=="bdo") (const True)
+  let attr = toStringAttr attr'
+  contents <- pInTags "bdo" inline
+  return $ case lookup "dir" attr of
+    -- Only bdo with a direction matters
+    Just dir -> B.spanWith ("", [], [("dir",T.toLower dir)]) contents
+    Nothing  -> contents
+
 pSpan :: PandocMonad m => TagParser m Inlines
 pSpan = try $ do
   guardEnabled Ext_native_spans
   TagOpen _ attr' <- lookAhead $ pSatisfy $ tagOpen (=="span") (const True)
-  let attr = toStringAttr attr'
+  let attr = toAttr attr'
   contents <- pInTags "span" inline
   let isSmallCaps = fontVariant == "small-caps" || "smallcaps" `elem` classes
-                    where styleAttr   = fromMaybe "" $ lookup "style" attr
+                    where styleAttr   = fromMaybe "" $ lookup "style" attr'
                           fontVariant = fromMaybe "" $ pickStyleAttrProps ["font-variant"] styleAttr
                           classes     = maybe []
-                                          T.words $ lookup "class" attr
-  let tag = if isSmallCaps then B.smallcaps else B.spanWith (mkAttr attr)
+                                          T.words $ lookup "class" attr'
+  let tag = if isSmallCaps then B.smallcaps else B.spanWith attr
   return $ tag contents
 
 pRawHtmlInline :: PandocMonad m => TagParser m Inlines
@@ -909,6 +929,7 @@
        (TagClose "ol") | tagtype == "li" -> return ()
        (TagClose "dl") | tagtype == "dd" -> return ()
        (TagClose "table") | tagtype == "td" -> return ()
+       (TagClose "table") | tagtype == "th" -> return ()
        (TagClose "table") | tagtype == "tr" -> return ()
        (TagClose "td") | tagtype `Set.member` blockHtmlTags -> return ()
        (TagClose "th") | tagtype `Set.member` blockHtmlTags -> return ()
@@ -1046,7 +1067,7 @@
     "h5", "h6", "head", "header", "hgroup", "hr", "html",
     "isindex", "main", "menu", "meta", "noframes", "nav",
     "ol", "output", "p", "pre",
-    "section", "table", "tbody", "textarea",
+    "section", "summary", "table", "tbody", "textarea",
     "thead", "tfoot", "ul", "dd",
     "dt", "frameset", "li", "tbody", "td", "tfoot",
     "th", "thead", "tr", "script", "style"]
@@ -1140,7 +1161,7 @@
 "object" `closes` "object" = True
 _ `closes` t | t `elem` ["option","style","script","textarea","title"] = True
 t `closes` "select" | t /= "option" = True
-"thead" `closes` t | t `elem` ["colgroup"] = True
+"thead" `closes` "colgroup" = True
 "tfoot" `closes` t | t `elem` ["thead","colgroup"] = True
 "tbody" `closes` t | t `elem` ["tbody","tfoot","thead","colgroup"] = True
 t `closes` t2 |
@@ -1277,6 +1298,9 @@
         attribsClasses = T.words (fromMaybe "" $ lookup "class" attr) <> epubTypes
         attribsKV = filter (\(k,_) -> k /= "class" && k /= "id") attr
         epubTypes = T.words $ fromMaybe "" $ lookup "epub:type" attr
+
+toAttr :: [(Text, Text)] -> Attr
+toAttr = mkAttr . toStringAttr
 
 -- Strip namespace prefixes
 stripPrefixes :: [Tag Text] -> [Tag Text]
diff --git a/src/Text/Pandoc/Readers/Haddock.hs b/src/Text/Pandoc/Readers/Haddock.hs
--- a/src/Text/Pandoc/Readers/Haddock.hs
+++ b/src/Text/Pandoc/Readers/Haddock.hs
@@ -85,14 +85,20 @@
                     , tableBodyRows = bodyRows
                     }
       -> let toCells = map (docHToBlocks . tableCellContents) . tableRowCells
+             toRow = Row nullAttr . map B.simpleCell
+             toHeaderRow l = if null l then [] else [toRow l]
              (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
+                             (AlignDefault, ColWidthDefault)
+         in  B.table B.emptyCaption
+                     colspecs
+                     (TableHead nullAttr $ toHeaderRow header)
+                     [TableBody nullAttr 0 [] $ map toRow body]
+                     (TableFoot nullAttr [])
 
   where inlineFallback = B.plain $ docHToInlines False d'
         consolidatePlains = B.fromList . consolidatePlains' . B.toList
diff --git a/src/Text/Pandoc/Readers/Ipynb.hs b/src/Text/Pandoc/Readers/Ipynb.hs
--- a/src/Text/Pandoc/Readers/Ipynb.hs
+++ b/src/Text/Pandoc/Readers/Ipynb.hs
@@ -69,7 +69,7 @@
   return $ Pandoc (Meta $ M.insert "jupyter" (MetaMap m) mempty) blocks
 
 cellToBlocks :: PandocMonad m
-             => ReaderOptions -> Text -> Cell a -> m B.Blocks
+             => ReaderOptions -> Text -> Ipynb.Cell a -> m B.Blocks
 cellToBlocks opts lang c = do
   let Source ts = cellSource c
   let source = mconcat ts
@@ -156,8 +156,8 @@
   where
 
     dataBlock :: PandocMonad m => (MimeType, MimeData) -> m B.Blocks
-    dataBlock (mt, BinaryData bs)
-     | "image/" `T.isPrefixOf` mt
+    dataBlock (mt, d)
+     | "image/" `T.isPrefixOf` mt || mt == "application/pdf"
       = do
       -- normally metadata maps from mime types to key-value map;
       -- but not always...
@@ -168,7 +168,10 @@
                        Error _   -> mempty
                    _ -> mempty
       let metaPairs = jsonMetaToPairs meta
-      let bl = BL.fromStrict bs
+      let bl = case d of
+                 BinaryData bs  -> BL.fromStrict bs
+                 TextualData t  -> BL.fromStrict $ UTF8.fromText t
+                 JsonData v     -> encode v
       -- SHA1 hash for filename
       let fname = T.pack (showDigest (sha1 bl)) <>
             case extensionFromMimeType mt of
@@ -176,7 +179,6 @@
               Just ext -> "." <> ext
       insertMedia (T.unpack fname) (Just mt) bl
       return $ B.para $ B.imageWith ("",[],metaPairs) fname "" mempty
-     | otherwise = return mempty
 
     dataBlock ("text/html", TextualData t)
       = return $ B.rawBlock "html" t
diff --git a/src/Text/Pandoc/Readers/JATS.hs b/src/Text/Pandoc/Readers/JATS.hs
--- a/src/Text/Pandoc/Readers/JATS.hs
+++ b/src/Text/Pandoc/Readers/JATS.hs
@@ -26,7 +26,7 @@
 import Text.Pandoc.Builder
 import Text.Pandoc.Class.PandocMonad (PandocMonad)
 import Text.Pandoc.Options
-import Text.Pandoc.Shared (underlineSpan, crFilter, safeRead)
+import Text.Pandoc.Shared (crFilter, safeRead)
 import Text.TeXMath (readMathML, writeTeX)
 import Text.XML.Light
 import qualified Data.Set as S (fromList, member)
@@ -134,14 +134,14 @@
            => Maybe (Inlines, Text) -> Element -> JATS m Inlines
 getGraphic mbfigdata e = do
   let atVal a = attrValue a e
-      (ident, title, caption) =
+      (ident, title, capt) =
          case mbfigdata of
-           Just (capt, i) -> (i, "fig:" <> atVal "title", capt)
+           Just (capt', i) -> (i, "fig:" <> atVal "title", capt')
            Nothing        -> (atVal "id", atVal "title",
                               text (atVal "alt-text"))
       attr = (ident, T.words $ atVal "role", [])
       imageUrl = atVal "href"
-  return $ imageWith attr imageUrl title caption
+  return $ imageWith attr imageUrl title capt
 
 getBlocks :: PandocMonad m => Element -> JATS m Blocks
 getBlocks e =  mconcat <$>
@@ -164,9 +164,9 @@
                     "bullet" -> bulletList <$> listitems
                     listType -> do
                       let start = fromMaybe 1 $
-                                  (textContent <$> (filterElement (named "list-item") e
-                                               >>= filterElement (named "label")))
-                                   >>= safeRead
+                                  (filterElement (named "list-item") e
+                                               >>= filterElement (named "label"))
+                                   >>= safeRead . textContent
                       orderedListWith (start, parseListStyleType listType, DefaultDelim)
                         <$> listitems
         "def-list" -> definitionList <$> deflistitems
@@ -176,6 +176,7 @@
         "article-meta" -> parseMetadata e
         "custom-meta" -> parseMetadata e
         "title" -> return mempty -- processed by header
+        "label" -> return mempty -- processed by header
         "table" -> parseTable
         "fig" -> parseFigure
         "fig-group" -> divWith (attrValue "id" e, ["fig-group"], [])
@@ -229,20 +230,20 @@
            -- implicit figure.  otherwise, we emit a div with the contents
            case filterChildren (named "graphic") e of
                   [g] -> do
-                         caption <- case filterChild (named "caption") e of
-                                           Just t  -> mconcat .
-                                             intersperse linebreak <$>
-                                             mapM getInlines
-                                             (filterChildren (const True) t)
-                                           Nothing -> return mempty
-                         img <- getGraphic (Just (caption, attrValue "id" e)) g
+                         capt <- case filterChild (named "caption") e of
+                                        Just t  -> mconcat .
+                                          intersperse linebreak <$>
+                                          mapM getInlines
+                                          (filterChildren (const True) t)
+                                        Nothing -> return mempty
+                         img <- getGraphic (Just (capt, attrValue "id" e)) g
                          return $ para img
                   _   -> divWith (attrValue "id" e, ["fig"], []) <$> getBlocks e
          parseTable = do
                       let isCaption x = named "title" x || named "caption" x
-                      caption <- case filterChild isCaption e of
-                                       Just t  -> getInlines t
-                                       Nothing -> return mempty
+                      capt <- case filterChild isCaption e of
+                                    Just t  -> getInlines t
+                                    Nothing -> return mempty
                       let e' = fromMaybe e $ filterChild (named "tgroup") e
                       let isColspec x = named "colspec" x || named "col" x
                       let colspecs = case filterChild (named "colgroup") e' of
@@ -264,35 +265,41 @@
                                                 Just "right"  -> AlignRight
                                                 Just "center" -> AlignCenter
                                                 _             -> AlignDefault
-                      let toWidth c = case findAttrText (unqual "colwidth") c of
-                                                Just w -> fromMaybe 0
-                                                   $ safeRead $ "0" <> T.filter (\x ->
-                                                     isDigit x || x == '.') w
-                                                Nothing -> 0 :: Double
+                      let toWidth c = do
+                            w <- findAttrText (unqual "colwidth") c
+                            n <- safeRead $ "0" <> T.filter (\x -> isDigit x || x == '.') w
+                            if n > 0 then Just n else Nothing
                       let numrows = foldl' max 0 $ map length bodyrows
                       let aligns = case colspecs of
                                      [] -> replicate numrows AlignDefault
                                      cs -> map toAlignment cs
                       let widths = case colspecs of
-                                     []  -> replicate numrows 0
-                                     cs  -> let ws = map toWidth cs
-                                                tot = sum ws
-                                            in  if all (> 0) ws
-                                                   then map (/ tot) ws
-                                                   else replicate numrows 0
-                      let headrows' = if null headrows
-                                         then replicate numrows mempty
-                                         else headrows
-                      return $ table caption (zip aligns widths)
-                                 headrows' bodyrows
+                                     [] -> replicate numrows ColWidthDefault
+                                     cs -> let ws = map toWidth cs
+                                           in case sequence ws of
+                                                Just ws' -> let tot = sum ws'
+                                                            in  ColWidth . (/ tot) <$> ws'
+                                                Nothing  -> replicate numrows ColWidthDefault
+                      let toRow = Row nullAttr . map simpleCell
+                          toHeaderRow l = if null l then [] else [toRow l]
+                      return $ table (simpleCaption $ plain capt)
+                                     (zip aligns widths)
+                                     (TableHead nullAttr $ toHeaderRow headrows)
+                                     [TableBody nullAttr 0 [] $ map toRow bodyrows]
+                                     (TableFoot nullAttr [])
          isEntry x  = named "entry" x || named "td" x || named "th" x
          parseRow = mapM (parseMixed plain . elContent) . filterChildren isEntry
          sect n = do isbook <- gets jatsBook
                      let n' = if isbook || n == 0 then n + 1 else n
+                     labelText <- case filterChild (named "label") e of
+                                    Just t -> (<> ("." <> space)) <$>
+                                              getInlines t
+                                    Nothing -> return mempty
                      headerText <- case filterChild (named "title") e `mplus`
                                         (filterChild (named "info") e >>=
                                             filterChild (named "title")) of
-                                      Just t  -> getInlines t
+                                      Just t  -> (labelText <>) <$>
+                                                  getInlines t
                                       Nothing -> return mempty
                      oldN <- gets jatsSectionLevel
                      modify $ \st -> st{ jatsSectionLevel = n }
@@ -310,6 +317,7 @@
   getTitle e
   getAuthors e
   getAffiliations e
+  getAbstract e
   return mempty
 
 getTitle :: PandocMonad m => Element -> JATS m ()
@@ -341,6 +349,14 @@
   affs <- mapM getInlines $ filterChildren (named "aff") x
   unless (null affs) $ addMeta "institute" affs
 
+getAbstract :: PandocMonad m => Element -> JATS m ()
+getAbstract e =
+  case filterElement (named "abstract") e of
+    Just s -> do
+      blks <- getBlocks s
+      addMeta "abstract" blks
+    Nothing -> pure ()
+
 getContrib :: PandocMonad m => Element -> JATS m Inlines
 getContrib x = do
   given <- maybe (return mempty) getInlines
@@ -449,7 +465,7 @@
         "strike" -> strikeout <$> innerInlines
         "sub" -> subscript <$> innerInlines
         "sup" -> superscript <$> innerInlines
-        "underline" -> underlineSpan <$> innerInlines
+        "underline" -> underline <$> innerInlines
         "break" -> return linebreak
         "sc" -> smallcaps <$> innerInlines
 
diff --git a/src/Text/Pandoc/Readers/Jira.hs b/src/Text/Pandoc/Readers/Jira.hs
--- a/src/Text/Pandoc/Readers/Jira.hs
+++ b/src/Text/Pandoc/Readers/Jira.hs
@@ -16,7 +16,7 @@
 import Text.HTML.TagSoup.Entity (lookupEntity)
 import Text.Jira.Parser (parse)
 import Text.Pandoc.Class.PandocMonad (PandocMonad (..))
-import Text.Pandoc.Builder
+import Text.Pandoc.Builder hiding (cell)
 import Text.Pandoc.Error (PandocError (PandocParseError))
 import Text.Pandoc.Options (ReaderOptions)
 import Text.Pandoc.Shared (stringify)
@@ -119,12 +119,14 @@
 jiraToPandocInlines = \case
   Jira.Anchor t          -> spanWith (t, [], []) mempty
   Jira.AutoLink url      -> link (Jira.fromURL url) "" (str (Jira.fromURL url))
+  Jira.Citation ils      -> str "—" <> space <> emph (fromInlines ils)
   Jira.ColorInline c ils -> spanWith ("", [], [("color", colorName c)]) $
                                      fromInlines ils
   Jira.Emoji icon        -> str . iconUnicode $ icon
   Jira.Entity entity     -> str . fromEntity $ entity
-  Jira.Image _ url       -> image (Jira.fromURL url)  "" mempty
-  Jira.Link alias url    -> link (Jira.fromURL url) "" (fromInlines alias)
+  Jira.Image params url  -> let (title, attr) = imgParams params
+                            in imageWith attr (Jira.fromURL url) title mempty
+  Jira.Link lt alias url -> jiraLinkToPandoc lt alias url
   Jira.Linebreak         -> linebreak
   Jira.Monospaced inlns  -> code . stringify . toList . fromInlines $ inlns
   Jira.Space             -> space
@@ -139,12 +141,36 @@
 
     fromStyle = \case
       Jira.Emphasis    -> emph
-      Jira.Insert      -> spanWith ("", ["inserted"], [])
+      Jira.Insert      -> underline
       Jira.Strikeout   -> strikeout
       Jira.Strong      -> strong
       Jira.Subscript   -> subscript
       Jira.Superscript -> superscript
 
+    imgParams :: [Jira.Parameter] -> (Text, Attr)
+    imgParams = foldr addImgParam ("", ("", [], []))
+
+    addImgParam :: Jira.Parameter -> (Text, Attr) -> (Text, Attr)
+    addImgParam p (title, attr@(ident, classes, kvs)) =
+      case Jira.parameterKey p of
+        "title"     -> (Jira.parameterValue p, attr)
+        "thumbnail" -> (title, (ident, "thumbnail":classes, kvs))
+        _           -> let kv = (Jira.parameterKey p, Jira.parameterValue p)
+                       in (title, (ident, classes, kv:kvs))
+
+-- | Convert a Jira link to pandoc inlines.
+jiraLinkToPandoc :: Jira.LinkType -> [Jira.Inline] -> Jira.URL -> Inlines
+jiraLinkToPandoc linkType alias url =
+  let url' = (if linkType == Jira.User then ("~" <>) else id) $ Jira.fromURL url
+      alias' = case alias of
+                 [] -> str url'
+                 _  -> foldMap jiraToPandocInlines alias
+  in case linkType of
+    Jira.External   -> link url' "" alias'
+    Jira.Email      -> link ("mailto:" <> url') "" alias'
+    Jira.Attachment -> linkWith ("", ["attachment"], []) url' "" alias'
+    Jira.User       -> linkWith ("", ["user-account"], []) url' "" alias'
+
 -- | Get unicode representation of a Jira icon.
 iconUnicode :: Jira.Icon -> Text
 iconUnicode = \case
@@ -156,18 +182,18 @@
   Jira.IconThumbsUp        -> "👍"
   Jira.IconThumbsDown      -> "👎"
   Jira.IconInfo            -> "ℹ"
-  Jira.IconCheckmark       -> "✓"
-  Jira.IconX               -> "🅇"
-  Jira.IconAttention       -> "⚠"
-  Jira.IconPlus            -> "⊞"
-  Jira.IconMinus           -> "⊟"
-  Jira.IconQuestionmark    -> "?"
+  Jira.IconCheckmark       -> "✔"
+  Jira.IconX               -> "❌"
+  Jira.IconAttention       -> "❗"
+  Jira.IconPlus            -> "➕"
+  Jira.IconMinus           -> "➖"
+  Jira.IconQuestionmark    -> "❓"
   Jira.IconOn              -> "💡"
-  Jira.IconOff             -> "💡"
-  Jira.IconStar            -> "★"
-  Jira.IconStarRed         -> "★"
-  Jira.IconStarGreen       -> "★"
-  Jira.IconStarBlue        -> "★"
-  Jira.IconStarYellow      -> "★"
+  Jira.IconOff             -> "🌙"
+  Jira.IconStar            -> "⭐"
+  Jira.IconStarRed         -> "⭐"
+  Jira.IconStarGreen       -> "⭐"
+  Jira.IconStarBlue        -> "⭐"
+  Jira.IconStarYellow      -> "⭐"
   Jira.IconFlag            -> "⚑"
   Jira.IconFlagOff         -> "⚐"
diff --git a/src/Text/Pandoc/Readers/LaTeX.hs b/src/Text/Pandoc/Readers/LaTeX.hs
--- a/src/Text/Pandoc/Readers/LaTeX.hs
+++ b/src/Text/Pandoc/Readers/LaTeX.hs
@@ -909,7 +909,7 @@
   , ("slash", lit "/")
   , ("textbf", extractSpaces strong <$> tok)
   , ("textnormal", extractSpaces (spanWith ("",["nodecor"],[])) <$> tok)
-  , ("underline", underlineSpan <$> tok)
+  , ("underline", underline <$> tok)
   , ("ldots", lit "…")
   , ("vdots", lit "\8942")
   , ("dots", lit "…")
@@ -923,7 +923,7 @@
   , ("eqref", rawInlineOr "eqref" $ doref "eqref")   -- from amsmath.sty
   , ("mbox", rawInlineOr "mbox" $ processHBox <$> tok)
   , ("hbox", rawInlineOr "hbox" $ processHBox <$> tok)
-  , ("lettrine", optional opt >> extractSpaces (spanWith ("",["lettrine"],[])) <$> tok)
+  , ("lettrine", rawInlineOr "lettrine" $ lettrine)
   , ("(", mathInline . untokenize <$> manyTill anyTok (controlSeq ")"))
   , ("[", mathDisplay . untokenize <$> manyTill anyTok (controlSeq "]"))
   , ("ensuremath", mathInline . untokenize <$> braced)
@@ -1018,16 +1018,16 @@
   , ("lstinline", dolstinline)
   , ("mintinline", domintinline)
   , ("Verb", doverb)
-  , ("url", ((unescapeURL . untokenize) <$> bracedUrl) >>= \url ->
-                  pure (link url "" (str url)))
-  , ("nolinkurl", ((unescapeURL . untokenize) <$> bracedUrl) >>= \url ->
-                  pure (code url))
-  , ("href", (unescapeURL . untokenize <$>
-                 bracedUrl <* sp) >>= \url ->
-                   tok >>= \lab -> pure (link url "" lab))
+  , ("url", (\url -> link url "" (str url)) . unescapeURL . untokenize <$>
+                  bracedUrl)
+  , ("nolinkurl", code . unescapeURL . untokenize <$> bracedUrl)
+  , ("href", do url <- bracedUrl
+                sp
+                link (unescapeURL $ untokenize url) "" <$> tok)
   , ("includegraphics", do options <- option [] keyvals
-                           src <- unescapeURL . removeDoubleQuotes . untokenize <$> braced
-                           mkImage options src)
+                           src <- braced
+                           mkImage options . unescapeURL . removeDoubleQuotes $
+                               untokenize src)
   , ("enquote*", enquote True Nothing)
   , ("enquote", enquote False Nothing)
   -- foreignquote is supposed to use native quote marks
@@ -1171,13 +1171,20 @@
   -- include
   , ("input", rawInlineOr "input" $ include "input")
   -- soul package
-  , ("ul", underlineSpan <$> tok)
+  , ("ul", underline <$> tok)
   -- ulem package
-  , ("uline", underlineSpan <$> tok)
+  , ("uline", underline <$> tok)
   -- plain tex stuff that should just be passed through as raw tex
   , ("ifdim", ifdim)
   ]
 
+lettrine :: PandocMonad m => LP m Inlines
+lettrine = do
+  optional opt
+  x <- tok
+  y <- tok
+  return $ extractSpaces (spanWith ("",["lettrine"],[])) x <> smallcaps y
+
 ifdim :: PandocMonad m => LP m Inlines
 ifdim = do
   contents <- manyTill anyTok (controlSeq "fi")
@@ -1503,26 +1510,38 @@
      then rawBlock "latex" <$> getRawCommand name ("\\" <> name)
      else fallback
 
+doSubfile :: PandocMonad m => LP m Blocks
+doSubfile = do
+  skipMany opt
+  f <- T.unpack . removeDoubleQuotes . T.strip . untokenize <$> braced
+  oldToks <- getInput
+  setInput []
+  insertIncluded ".tex" f
+  bs <- blocks
+  eof
+  setInput oldToks
+  return bs
+
 include :: (PandocMonad m, Monoid a) => Text -> LP m a
 include name = do
   skipMany opt
   fs <- (map (T.unpack . removeDoubleQuotes . T.strip) . T.splitOn "," .
          untokenize) <$> braced
-  let addExt f = case takeExtension f of
-                      ".tex" -> f
-                      ".sty" -> f
-                      -- note, we can have cc_by_4.0 for example...
-                      _ | name == "usepackage" -> addExtension f ".sty"
-                        | otherwise -> addExtension f ".tex"
-  dirs <- (map T.unpack . splitTextBy (==':') . fromMaybe ".") <$> lookupEnv "TEXINPUTS"
-  mapM_ (insertIncluded dirs . addExt) fs
+  let defaultExt | name == "usepackage" = ".sty"
+                 | otherwise            = ".tex"
+  mapM_ (insertIncluded defaultExt) fs
   return mempty
 
 insertIncluded :: PandocMonad m
-               => [FilePath]
+               => FilePath
                -> FilePath
                -> LP m ()
-insertIncluded dirs f = do
+insertIncluded defaultExtension f' = do
+  let f = case takeExtension f' of
+                ".tex" -> f'
+                ".sty" -> f'
+                _      -> addExtension f' defaultExtension
+  dirs <- (map T.unpack . splitTextBy (==':') . fromMaybe ".") <$> lookupEnv "TEXINPUTS"
   pos <- getPosition
   containers <- getIncludeFiles <$> getState
   when (T.pack f `elem` containers) $
@@ -1856,7 +1875,7 @@
          addMeta "bibliography" . splitBibs . untokenize))
    , ("addbibresource", mempty <$ (skipopts *> braced >>=
          addMeta "bibliography" . splitBibs . untokenize))
-   , ("endinput", mempty <$ skipMany tok)
+   , ("endinput", mempty <$ skipMany anyTok)
    -- includes
    , ("lstinputlisting", inputListing)
    , ("inputminted", inputMinted)
@@ -1879,7 +1898,7 @@
    -- include
    , ("include", rawBlockOr "include" $ include "include")
    , ("input", rawBlockOr "input" $ include "input")
-   , ("subfile", rawBlockOr "subfile" $ include "subfile")
+   , ("subfile", rawBlockOr "subfile" doSubfile)
    , ("usepackage", rawBlockOr "usepackage" $ include "usepackage")
    -- preamble
    , ("PackageError", mempty <$ (braced >> braced >> braced))
@@ -1890,7 +1909,7 @@
 
 environments :: PandocMonad m => M.Map Text (LP m Blocks)
 environments = M.fromList
-   [ ("document", env "document" blocks)
+   [ ("document", env "document" blocks <* skipMany anyTok)
    , ("abstract", mempty <$ (env "abstract" blocks >>= addMeta "abstract"))
    , ("sloppypar", env "sloppypar" $ blocks)
    , ("letter", env "letter" letterContents)
@@ -2261,7 +2280,7 @@
          setInput $ map (Tok spos Symbol . T.singleton) (T.unpack t) <> rest
        _ -> return ()
 
-parseAligns :: PandocMonad m => LP m [(Alignment, Double, ([Tok], [Tok]))]
+parseAligns :: PandocMonad m => LP m [(Alignment, ColWidth, ([Tok], [Tok]))]
 parseAligns = try $ do
   let maybeBar = skipMany
         (try $ sp *> (() <$ symbol '|' <|> () <$ (symbol '@' >> braced)))
@@ -2282,17 +2301,15 @@
         ds <- trim . untokenize <$> manyTill anyTok (controlSeq "linewidth")
         spaces
         symbol '}'
-        case safeRead ds of
-              Just w  -> return w
-              Nothing -> return 0.0
+        return $ safeRead ds
   let alignSpec = do
         pref <- option [] alignPrefix
         spaces
         al <- alignChar
-        width <- colWidth <|> option 0.0 (do s <- untokenize <$> braced
-                                             pos <- getPosition
-                                             report $ SkippedContent s pos
-                                             return 0.0)
+        width <- colWidth <|> option Nothing (do s <- untokenize <$> braced
+                                                 pos <- getPosition
+                                                 report $ SkippedContent s pos
+                                                 return Nothing)
         spaces
         suff <- option [] alignSuffix
         return (al, width, (pref, suff))
@@ -2314,7 +2331,11 @@
   spaces
   egroup
   spaces
-  return aligns'
+  return $ map toSpec aligns'
+  where
+    toColWidth (Just w) | w > 0 = ColWidth w
+    toColWidth _                = ColWidthDefault
+    toSpec (x, y, z) = (x, toColWidth y, z)
 
 parseTableRow :: PandocMonad m
               => Text   -- ^ table environment name
@@ -2363,7 +2384,6 @@
   skipopts
   colspecs <- parseAligns
   let (aligns, widths, prefsufs) = unzip3 colspecs
-  let cols = length colspecs
   optional $ controlSeq "caption" *> setCaption
   spaces
   optional label
@@ -2384,19 +2404,22 @@
   spaces
   optional lbreak
   spaces
-  let header'' = if null header'
-                    then replicate cols mempty
-                    else header'
   lookAhead $ controlSeq "end" -- make sure we're at end
-  return $ table mempty (zip aligns widths) header'' rows
+  let toRow = Row nullAttr . map simpleCell
+      toHeaderRow l = if null l then [] else [toRow l]
+  return $ table emptyCaption
+                 (zip aligns widths)
+                 (TableHead nullAttr $ toHeaderRow header')
+                 [TableBody nullAttr 0 [] $ map toRow rows]
+                 (TableFoot nullAttr [])
 
 addTableCaption :: PandocMonad m => Blocks -> LP m Blocks
 addTableCaption = walkM go
-  where go (Table c als ws hs rs) = do
+  where go (Table attr c spec th tb tf) = do
           st <- getState
           let mblabel = sLastLabel st
           capt <- case (sCaption st, mblabel) of
-                   (Just ils, Nothing)  -> return $ toList ils
+                   (Just ils, Nothing)  -> return $ caption Nothing (plain ils)
                    (Just ils, Just lab) -> do
                      num <- getNextNumber sLastTableNum
                      setState
@@ -2404,12 +2427,21 @@
                          , sLabels = M.insert lab
                                     [Str (renderDottedNum num)]
                                     (sLabels st) }
-                     return $ toList ils -- add number??
+                     return $ caption Nothing (plain ils) -- add number??
                    (Nothing, _)  -> return c
-          return $ maybe id (\ident -> Div (ident, [], []) . (:[])) mblabel $
-                     Table capt als ws hs rs
+          let attr' = case (attr, mblabel) of
+                        ((_,classes,kvs), Just ident) ->
+                           (ident,classes,kvs)
+                        _ -> attr
+          return $ addAttrDiv attr' $ Table nullAttr capt spec th tb tf
         go x = return x
 
+-- TODO: For now we add a Div to contain table attributes, since
+-- most writers don't do anything yet with attributes on Table.
+-- This can be removed when that changes.
+addAttrDiv :: Attr -> Block -> Block
+addAttrDiv ("",[],[]) b = b
+addAttrDiv attr b       = Div attr [b]
 
 block :: PandocMonad m => LP m Blocks
 block = do
diff --git a/src/Text/Pandoc/Readers/Man.hs b/src/Text/Pandoc/Readers/Man.hs
--- a/src/Text/Pandoc/Readers/Man.hs
+++ b/src/Text/Pandoc/Readers/Man.hs
@@ -107,11 +107,12 @@
       bodyRows <- mapM (mapM parseTableCell . snd) bodyRows'
       isPlainTable <- tableCellsPlain <$> getState
       let widths = if isPlainTable
-                      then repeat 0.0
-                      else repeat ((1.0 / fromIntegral (length alignments))
-                                   :: Double)
-      return $ B.table mempty (zip alignments widths)
-                  headerRow bodyRows) <|> fallback pos
+                      then repeat ColWidthDefault
+                      else repeat $ ColWidth (1.0 / fromIntegral (length alignments))
+      return $ B.table B.emptyCaption (zip alignments widths)
+                  (TableHead nullAttr $ toHeaderRow headerRow)
+                  [TableBody nullAttr 0 [] $ map toRow bodyRows]
+                  (TableFoot nullAttr [])) <|> fallback pos
     [] -> fallback pos
 
  where
@@ -160,6 +161,8 @@
       'r' -> Just AlignRight
       _   -> Nothing
 
+  toRow = Row nullAttr . map simpleCell
+  toHeaderRow l = if null l then [] else [toRow l]
 
 parseNewParagraph :: PandocMonad m => ManParser m Blocks
 parseNewParagraph = do
diff --git a/src/Text/Pandoc/Readers/Markdown.hs b/src/Text/Pandoc/Readers/Markdown.hs
--- a/src/Text/Pandoc/Readers/Markdown.hs
+++ b/src/Text/Pandoc/Readers/Markdown.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE RelaxedPolyRec      #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TupleSections       #-}
 {-# LANGUAGE OverloadedStrings   #-}
@@ -28,11 +27,11 @@
 import qualified Data.Text.Lazy as TL
 import qualified Data.ByteString.Lazy as BL
 import System.FilePath (addExtension, takeExtension)
-import Text.HTML.TagSoup
+import Text.HTML.TagSoup hiding (Row)
 import Text.Pandoc.Builder (Blocks, Inlines)
 import qualified Text.Pandoc.Builder as B
 import Text.Pandoc.Class.PandocMonad (PandocMonad (..), report)
-import Text.Pandoc.Definition
+import Text.Pandoc.Definition as Pandoc
 import Text.Pandoc.Emoji (emojiToInline)
 import Text.Pandoc.Error
 import Text.Pandoc.Logging
@@ -68,15 +67,13 @@
            -> m Meta
 yamlToMeta opts bstr = do
   let parser = do
-        meta <- yamlBsToMeta parseBlocks bstr
+        meta <- yamlBsToMeta (fmap B.toMetaValue <$> parseBlocks) bstr
         return $ runF meta defaultParserState
   parsed <- readWithM parser def{ stateOptions = opts } ""
   case parsed of
     Right result -> return result
     Left e       -> throwError e
 
-
-
 --
 -- Constants and data structure definitions
 --
@@ -241,7 +238,7 @@
   -- by including --- and ..., we allow yaml blocks with just comments:
   let rawYaml = T.unlines ("---" : (rawYamlLines ++ ["..."]))
   optional blanklines
-  newMetaF <- yamlBsToMeta parseBlocks
+  newMetaF <- yamlBsToMeta (fmap B.toMetaValue <$> parseBlocks)
               $ UTF8.fromTextLazy $ TL.fromStrict rawYaml
   -- Since `<>` is left-biased, existing values are not touched:
   updateState $ \st -> st{ stateMeta' = stateMeta' st <> newMetaF }
@@ -1163,7 +1160,7 @@
                  else return rawContent
   let aligns   = zipWith alignType (map (: []) rawHeads) lengths
   let rawHeads' = if headless
-                     then replicate (length dashes) ""
+                     then []
                      else rawHeads
   heads <- fmap sequence
            $
@@ -1235,7 +1232,7 @@
 -- Parse a simple table with '---' header and one line per row.
 simpleTable :: PandocMonad m
             => Bool  -- ^ Headerless table
-            -> MarkdownParser m ([Alignment], [Double], F [Blocks], F [[Blocks]])
+            -> MarkdownParser m ([Alignment], [Double], F [Row], F [Row])
 simpleTable headless = do
   (aligns, _widths, heads', lines') <-
        tableWith (simpleTableHeader headless) tableLine
@@ -1250,7 +1247,7 @@
 -- ending with a footer (dashed line followed by blank line).
 multilineTable :: PandocMonad m
                => Bool -- ^ Headerless table
-               -> MarkdownParser m ([Alignment], [Double], F [Blocks], F [[Blocks]])
+               -> MarkdownParser m ([Alignment], [Double], F [Row], F [Row])
 multilineTable headless =
   tableWith (multilineTableHeader headless) multilineRow blanklines tableFooter
 
@@ -1281,7 +1278,7 @@
                            rawContent
   let aligns   = zipWith alignType rawHeadsList lengths
   let rawHeads = if headless
-                    then replicate (length dashes) ""
+                    then []
                     else map (T.unlines . map trim) rawHeadsList
   heads <- fmap sequence $
             mapM (parseFromString' (mconcat <$> many plain).trim) rawHeads
@@ -1292,7 +1289,7 @@
 -- which may be grid, separated by blank lines, and
 -- ending with a footer (dashed line followed by blank line).
 gridTable :: PandocMonad m => Bool -- ^ Headerless table
-          -> MarkdownParser m ([Alignment], [Double], F [Blocks], F [[Blocks]])
+          -> MarkdownParser m ([Alignment], [Double], F [Row], F [Row])
 gridTable headless = gridTableWith' parseBlocks headless
 
 pipeBreak :: PandocMonad m => MarkdownParser m ([Alignment], [Int])
@@ -1307,7 +1304,7 @@
   blankline
   return $ unzip (first:rest)
 
-pipeTable :: PandocMonad m => MarkdownParser m ([Alignment], [Double], F [Blocks], F [[Blocks]])
+pipeTable :: PandocMonad m => MarkdownParser m ([Alignment], [Double], F [Row], F [Row])
 pipeTable = try $ do
   nonindentSpaces
   lookAhead nonspaceChar
@@ -1323,7 +1320,7 @@
                          fromIntegral len / fromIntegral (sum seplengths))
                          seplengths
                   else replicate (length aligns) 0.0
-  return (aligns, widths, heads', sequence lines'')
+  return (aligns, widths, toHeaderRow <$> heads', map toRow <$> sequence lines'')
 
 sepPipe :: PandocMonad m => MarkdownParser m ()
 sepPipe = try $ do
@@ -1339,8 +1336,8 @@
   -- split into cells
   let chunk = void (code <|> math <|> rawHtmlInline <|> escapedChar <|> rawLaTeXInline')
        <|> void (noneOf "|\n\r")
-  let cellContents = ((trim . snd) <$> withRaw (many chunk)) >>=
-        parseFromString' pipeTableCell
+  let cellContents = withRaw (many chunk) >>=
+        parseFromString' pipeTableCell . trim . snd
   cells <- cellContents `sepEndBy1` char '|'
   -- surrounding pipes needed for a one-column table:
   guard $ not (length cells == 1 && not openPipe)
@@ -1384,7 +1381,7 @@
           -> ([Int] -> MarkdownParser m (F [Blocks]))
           -> MarkdownParser m sep
           -> MarkdownParser m end
-          -> MarkdownParser m ([Alignment], [Double], F [Blocks], F [[Blocks]])
+          -> MarkdownParser m ([Alignment], [Double], F [Row], F [Row])
 tableWith headerParser rowParser lineParser footerParser = try $ do
     (heads, aligns, indices) <- headerParser
     lines' <- fmap sequence $ rowParser indices `sepEndBy1` lineParser
@@ -1393,7 +1390,7 @@
     let widths = if null indices
                     then replicate (length aligns) 0.0
                     else widthsFromIndices numColumns indices
-    return (aligns, widths, heads, lines')
+    return (aligns, widths, toHeaderRow <$> heads, map toRow <$> lines')
 
 table :: PandocMonad m => MarkdownParser m (F Blocks)
 table = try $ do
@@ -1417,11 +1414,18 @@
   let widths' = if totalWidth < 1
                    then widths
                    else map (/ totalWidth) widths
+  let strictPos w
+        | w > 0     = ColWidth w
+        | otherwise = ColWidthDefault
   return $ do
     caption' <- caption
     heads' <- heads
     lns' <- lns
-    return $ B.table caption' (zip aligns widths') heads' lns'
+    return $ B.table (B.simpleCaption $ B.plain caption')
+                     (zip aligns (strictPos <$> widths'))
+                     (TableHead nullAttr heads')
+                     [TableBody nullAttr 0 [] lns']
+                     (TableFoot nullAttr [])
 
 --
 -- inline
@@ -1517,12 +1521,17 @@
 code = try $ do
   starts <- many1 (char '`')
   skipSpaces
-  result <- (trim . T.concat) <$>
-            manyTill (notFollowedBy (inList >> listStart) >>
-                      (many1Char (noneOf "`\n") <|> many1Char (char '`') <|>
-                       (char '\n' >> notFollowedBy' blankline >> return " ")))
-                      (try (skipSpaces >> count (length starts) (char '`') >>
-                      notFollowedBy (char '`')))
+  result <- trim . T.concat
+        <$> manyTill
+              (   many1Char (noneOf "`\n")
+              <|> many1Char (char '`')
+              <|> (char '\n'
+                    >> notFollowedBy (inList >> listStart)
+                    >> notFollowedBy' blankline
+                    >> return " "))
+              (try $ skipSpaces
+                  >> count (length starts) (char '`')
+                  >> notFollowedBy (char '`'))
   rawattr <-
      (Left <$> try (guardEnabled Ext_raw_attribute >> rawAttribute))
     <|>
@@ -1739,7 +1748,9 @@
   attr <- attributes
   return $ if isSmallCaps attr
               then B.smallcaps <$> lab
-              else B.spanWith attr <$> lab
+              else if isUnderline attr
+                      then B.underline <$> lab
+                      else B.spanWith attr <$> lab
 
 -- | We treat a span as SmallCaps if class is "smallcaps" (and
 -- no other attributes are set or if style is "font-variant:small-caps"
@@ -1753,6 +1764,13 @@
        Nothing -> False
 isSmallCaps _ = False
 
+-- | We treat a span as Underline if class is "ul" or
+-- "underline" (and no other attributes are set).
+isUnderline :: Attr -> Bool
+isUnderline ("",["ul"],[]) = True
+isUnderline ("",["underline"],[]) = True
+isUnderline _ = False
+
 regLink :: PandocMonad m
         => (Attr -> Text -> Text -> Inlines -> Inlines)
         -> F Inlines
@@ -1901,7 +1919,9 @@
   let keyvals = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"]
   return $ if isSmallCaps (ident, classes, keyvals)
               then B.smallcaps <$> contents
-              else B.spanWith (ident, classes, keyvals) <$> contents
+              else if isUnderline (ident, classes, keyvals)
+                      then B.underline <$> contents
+                      else B.spanWith (ident, classes, keyvals) <$> contents
 
 divHtml :: PandocMonad m => MarkdownParser m (F Blocks)
 divHtml = try $ do
@@ -2105,3 +2125,9 @@
   withQuoteContext InDoubleQuote $
     fmap B.doubleQuoted . trimInlinesF . mconcat <$>
       many1Till inline doubleQuoteEnd
+
+toRow :: [Blocks] -> Row
+toRow = Row nullAttr . map B.simpleCell
+
+toHeaderRow :: [Blocks] -> [Row]
+toHeaderRow l = if null l then [] else [toRow l]
diff --git a/src/Text/Pandoc/Readers/MediaWiki.hs b/src/Text/Pandoc/Readers/MediaWiki.hs
--- a/src/Text/Pandoc/Readers/MediaWiki.hs
+++ b/src/Text/Pandoc/Readers/MediaWiki.hs
@@ -1,6 +1,4 @@
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RelaxedPolyRec    #-}
--- RelaxedPolyRec needed for inlinesBetween on GHC < 7
 {- |
    Module      : Text.Pandoc.Readers.MediaWiki
    Copyright   : Copyright (C) 2012-2020 John MacFarlane
@@ -221,9 +219,9 @@
   let restwidth = tableWidth - sum widths
   let zerocols = length $ filter (==0.0) widths
   let defaultwidth = if zerocols == 0 || zerocols == length widths
-                        then 0.0
-                        else restwidth / fromIntegral zerocols
-  let widths' = map (\w -> if w == 0 then defaultwidth else w) widths
+                        then ColWidthDefault
+                        else ColWidth $ restwidth / fromIntegral zerocols
+  let widths' = map (\w -> if w > 0 then ColWidth w else defaultwidth) widths
   let cellspecs = zip (map fst cellspecs') widths'
   rows' <- many $ try $ rowsep *> (map snd <$> tableRow)
   optional blanklines
@@ -232,7 +230,13 @@
   let (headers,rows) = if hasheader
                           then (hdr, rows')
                           else (replicate cols mempty, hdr:rows')
-  return $ B.table caption cellspecs headers rows
+  let toRow = Row nullAttr . map B.simpleCell
+      toHeaderRow l = if null l then [] else [toRow l]
+  return $ B.table (B.simpleCaption $ B.plain caption)
+                   cellspecs
+                   (TableHead nullAttr $ toHeaderRow headers)
+                   [TableBody nullAttr 0 [] $ map toRow rows]
+                   (TableFoot nullAttr [])
 
 parseAttrs :: PandocMonad m => MWParser m [(Text,Text)]
 parseAttrs = many1 parseAttr
@@ -395,7 +399,10 @@
   lev <- length <$> many1 (char '=')
   guard $ lev <= 6
   contents <- trimInlines . mconcat <$> manyTill inline (count lev $ char '=')
-  attr <- modifyIdentifier <$> registerHeader nullAttr contents
+  opts <- mwOptions <$> getState
+  attr <- (if isEnabled Ext_gfm_auto_identifiers opts
+              then id
+              else modifyIdentifier) <$> registerHeader nullAttr contents
   return $ B.headerWith attr lev contents
 
 -- See #4731:
diff --git a/src/Text/Pandoc/Readers/Metadata.hs b/src/Text/Pandoc/Readers/Metadata.hs
--- a/src/Text/Pandoc/Readers/Metadata.hs
+++ b/src/Text/Pandoc/Readers/Metadata.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE RelaxedPolyRec      #-}
-{-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE OverloadedStrings   #-}
 {- |
    Module      : Text.Pandoc.Readers.Metadata
@@ -12,7 +10,7 @@
 
 Parse YAML/JSON metadata to 'Pandoc' 'Meta'.
 -}
-module Text.Pandoc.Readers.Metadata ( yamlBsToMeta ) where
+module Text.Pandoc.Readers.Metadata ( yamlBsToMeta, yamlMap ) where
 
 import Control.Monad
 import Control.Monad.Except (throwError)
@@ -22,8 +20,6 @@
 import qualified Data.Text as T
 import qualified Data.YAML as YAML
 import qualified Data.YAML.Event as YE
-import qualified Text.Pandoc.Builder as B
-import Text.Pandoc.Builder (Blocks)
 import Text.Pandoc.Class.PandocMonad (PandocMonad (..))
 import Text.Pandoc.Definition
 import Text.Pandoc.Error
@@ -32,14 +28,14 @@
 import Text.Pandoc.Shared
 
 yamlBsToMeta :: PandocMonad m
-             => ParserT Text ParserState m (F Blocks)
+             => ParserT Text ParserState m (F MetaValue)
              -> BL.ByteString
              -> ParserT Text ParserState m (F Meta)
-yamlBsToMeta pBlocks bstr = do
+yamlBsToMeta pMetaValue bstr = do
   pos <- getPosition
   case YAML.decodeNode' YAML.failsafeSchemaResolver False False bstr of
        Right (YAML.Doc (YAML.Mapping _ _ o):_)
-                -> fmap Meta <$> yamlMap pBlocks o
+                -> fmap Meta <$> yamlMap pMetaValue o
        Right [] -> return . return $ mempty
        Right [YAML.Doc (YAML.Scalar _ YAML.SNull)]
                 -> return . return $ mempty
@@ -59,27 +55,21 @@
 nodeToKey _  = throwError $ PandocParseError
                               "Non-string key in YAML mapping"
 
-toMetaValue :: PandocMonad m
-            => ParserT Text ParserState m (F Blocks)
-            -> Text
-            -> ParserT Text ParserState m (F MetaValue)
-toMetaValue pBlocks x =
+normalizeMetaValue :: PandocMonad m
+                   => ParserT Text ParserState m (F MetaValue)
+                   -> Text
+                   -> ParserT Text ParserState m (F MetaValue)
+normalizeMetaValue pMetaValue x =
    -- Note: a standard quoted or unquoted YAML value will
    -- not end in a newline, but a "block" set off with
    -- `|` or `>` will.
    if "\n" `T.isSuffixOf` x
-      then parseFromString' (asBlocks <$> pBlocks) (x <> "\n")
-      else parseFromString' pInlines x
-  where pInlines = do
-          bs <- pBlocks
-          return $ do
-            bs' <- bs
-            return $
-              case B.toList bs' of
-                [Plain ils] -> MetaInlines ils
-                [Para ils]  -> MetaInlines ils
-                xs          -> MetaBlocks xs
-        asBlocks p = MetaBlocks . B.toList <$> p
+      then parseFromString' pMetaValue (x <> "\n")
+      else parseFromString' asInlines x
+  where asInlines = fmap b2i <$> pMetaValue
+        b2i (MetaBlocks [Plain ils]) = MetaInlines ils
+        b2i (MetaBlocks [Para ils]) = MetaInlines ils
+        b2i bs = bs
 
 checkBoolean :: Text -> Maybe Bool
 checkBoolean t
@@ -88,44 +78,42 @@
   | otherwise = Nothing
 
 yamlToMetaValue :: PandocMonad m
-                => ParserT Text ParserState m (F Blocks)
+                => ParserT Text ParserState m (F MetaValue)
                 -> YAML.Node YE.Pos
                 -> ParserT Text ParserState m (F MetaValue)
-yamlToMetaValue pBlocks (YAML.Scalar _ x) =
+yamlToMetaValue pMetaValue (YAML.Scalar _ x) =
   case x of
-       YAML.SStr t       -> toMetaValue pBlocks t
+       YAML.SStr t       -> normalizeMetaValue pMetaValue t
        YAML.SBool b      -> return $ return $ MetaBool b
        YAML.SFloat d     -> return $ return $ MetaString $ tshow d
        YAML.SInt i       -> return $ return $ MetaString $ tshow i
        YAML.SUnknown _ t ->
          case checkBoolean t of
            Just b        -> return $ return $ MetaBool b
-           Nothing       -> toMetaValue pBlocks t
+           Nothing       -> normalizeMetaValue pMetaValue t
        YAML.SNull        -> return $ return $ MetaString ""
 
-yamlToMetaValue pBlocks (YAML.Sequence _ _ xs) = do
-  xs' <- mapM (yamlToMetaValue pBlocks) xs
-  return $ do
-    xs'' <- sequence xs'
-    return $ B.toMetaValue xs''
-yamlToMetaValue pBlocks (YAML.Mapping _ _ o) =
-  fmap B.toMetaValue <$> yamlMap pBlocks o
+yamlToMetaValue pMetaValue (YAML.Sequence _ _ xs) =
+  fmap MetaList . sequence
+  <$> mapM (yamlToMetaValue pMetaValue) xs
+yamlToMetaValue pMetaValue (YAML.Mapping _ _ o) =
+  fmap MetaMap <$> yamlMap pMetaValue o
 yamlToMetaValue _ _ = return $ return $ MetaString ""
 
 yamlMap :: PandocMonad m
-        => ParserT Text ParserState m (F Blocks)
+        => ParserT Text ParserState m (F MetaValue)
         -> M.Map (YAML.Node YE.Pos) (YAML.Node YE.Pos)
         -> ParserT Text ParserState m (F (M.Map Text MetaValue))
-yamlMap pBlocks o = do
+yamlMap pMetaValue o = do
     kvs <- forM (M.toList o) $ \(key, v) -> do
              k <- nodeToKey key
              return (k, v)
     let kvs' = filter (not . ignorable . fst) kvs
-    (fmap M.fromList . sequence) <$> mapM toMeta kvs'
+    fmap M.fromList . sequence <$> mapM toMeta kvs'
   where
     ignorable t = "_" `T.isSuffixOf` t
     toMeta (k, v) = do
-      fv <- yamlToMetaValue pBlocks v
+      fv <- yamlToMetaValue pMetaValue v
       return $ do
         v' <- fv
         return (k, v')
diff --git a/src/Text/Pandoc/Readers/Muse.hs b/src/Text/Pandoc/Readers/Muse.hs
--- a/src/Text/Pandoc/Readers/Muse.hs
+++ b/src/Text/Pandoc/Readers/Muse.hs
@@ -29,7 +29,7 @@
 import Data.Maybe (fromMaybe, isNothing, maybeToList)
 import Data.Text (Text)
 import qualified Data.Text as T
-import Text.Pandoc.Builder (Blocks, Inlines)
+import Text.Pandoc.Builder (Blocks, Inlines, underline)
 import qualified Text.Pandoc.Builder as B
 import Text.Pandoc.Class.PandocMonad (PandocMonad (..))
 import Text.Pandoc.Definition
@@ -37,7 +37,7 @@
 import Text.Pandoc.Logging
 import Text.Pandoc.Options
 import Text.Pandoc.Parsing hiding (F)
-import Text.Pandoc.Shared (crFilter, trimr, underlineSpan, tshow)
+import Text.Pandoc.Shared (crFilter, trimr, tshow)
 
 -- | Read Muse from an input string and return a Pandoc document.
 readMuse :: PandocMonad m
@@ -645,9 +645,15 @@
 
 museToPandocTable :: MuseTable -> Blocks
 museToPandocTable (MuseTable caption headers body footers) =
-  B.table caption attrs headRow (rows ++ body ++ footers)
-  where attrs = (AlignDefault, 0.0) <$ transpose (headers ++ body ++ footers)
+  B.table (B.simpleCaption $ B.plain caption)
+          attrs
+          (TableHead nullAttr $ toHeaderRow headRow)
+          [TableBody nullAttr 0 [] $ map toRow $ rows ++ body ++ footers]
+          (TableFoot nullAttr [])
+  where attrs = (AlignDefault, ColWidthDefault) <$ transpose (headers ++ body ++ footers)
         (headRow, rows) = fromMaybe ([], []) $ uncons headers
+        toRow = Row nullAttr . map B.simpleCell
+        toHeaderRow l = if null l then [] else [toRow l]
 
 museAppendElement :: MuseTableElement
                   -> MuseTable
@@ -693,8 +699,13 @@
   indent <- getIndent
   indices <- museGridTableHeader
   fmap rowsToTable . sequence <$> many1 (museGridTableRow indent indices)
-  where rowsToTable rows = B.table mempty attrs [] rows
-                           where attrs = (AlignDefault, 0.0) <$ transpose rows
+  where rowsToTable rows = B.table B.emptyCaption
+                                   attrs
+                                   (TableHead nullAttr [])
+                                   [TableBody nullAttr 0 [] $ map toRow rows]
+                                   (TableFoot nullAttr [])
+                           where attrs = (AlignDefault, ColWidthDefault) <$ transpose rows
+                                 toRow = Row nullAttr . map B.simpleCell
 
 -- | Parse a table.
 table :: PandocMonad m => MuseParser m (F Blocks)
@@ -838,7 +849,7 @@
 -- | Parse underline inline markup, indicated by @_@.
 -- Supported only in Emacs Muse mode, not Text::Amuse.
 underlined :: PandocMonad m => MuseParser m (F Inlines)
-underlined = fmap underlineSpan
+underlined = fmap underline
   <$  guardDisabled Ext_amuse -- Supported only by Emacs Muse
   <*> emphasisBetween (char '_')
 
diff --git a/src/Text/Pandoc/Readers/Odt/ContentReader.hs b/src/Text/Pandoc/Readers/Odt/ContentReader.hs
--- a/src/Text/Pandoc/Readers/Odt/ContentReader.hs
+++ b/src/Text/Pandoc/Readers/Odt/ContentReader.hs
@@ -37,7 +37,7 @@
 import Text.TeXMath (readMathML, writeTeX)
 import qualified Text.XML.Light as XML
 
-import Text.Pandoc.Builder
+import Text.Pandoc.Builder hiding (underline)
 import Text.Pandoc.MediaBag (MediaBag, insertMedia)
 import Text.Pandoc.Shared
 import Text.Pandoc.Extensions (extensionsFromList, Extension(..))
@@ -921,8 +921,8 @@
   Pandoc m (post_process' blocks)
 
 post_process' :: [Block] -> [Block]
-post_process' (Table _ a w h r : Div ("", ["caption"], _) [Para inlines] : xs) =
-  Table inlines a w h r : post_process' xs
+post_process' (Table attr _ specs th tb tf : Div ("", ["caption"], _) blks : xs)
+  = Table attr (Caption Nothing blks) specs th tb tf : post_process' xs
 post_process' bs = bs
 
 read_body :: OdtReader _x (Pandoc, MediaBag)
diff --git a/src/Text/Pandoc/Readers/Org/Blocks.hs b/src/Text/Pandoc/Readers/Org/Blocks.hs
--- a/src/Text/Pandoc/Readers/Org/Blocks.hs
+++ b/src/Text/Pandoc/Readers/Org/Blocks.hs
@@ -34,7 +34,7 @@
 import Control.Monad (foldM, guard, mplus, mzero, void)
 import Data.Char (isSpace)
 import Data.Default (Default)
-import Data.List (foldl')
+import Data.List (foldl', intersperse)
 import Data.Maybe (fromMaybe, isJust, isNothing)
 import Data.Text (Text)
 
@@ -76,6 +76,7 @@
                , list
                , latexFragment
                , noteBlock
+               , rawOrgLine
                , paraOrPlain
                ] <?> "block"
 
@@ -559,6 +560,8 @@
        | otherwise        -> Para content
       _ -> blk
 
+-- | Parses a meta line which defines a raw block. Currently recognized:
+-- @#+LATEX:@, @#+HTML:@, @#+TEXINFO:@, and @#+BEAMER@.
 rawExportLine :: PandocMonad m => OrgParser m Blocks
 rawExportLine = try $ do
   metaLineStart
@@ -567,6 +570,14 @@
     then B.rawBlock key <$> anyLine
     else mzero
 
+-- | Parses any meta line, i.e., a line starting with @#+@, into a raw
+-- org block. This should be the last resort when trying to parse
+-- keywords. Leading spaces are discarded.
+rawOrgLine :: PandocMonad m => OrgParser m (F Blocks)
+rawOrgLine = do
+  line <- metaLineStart *> anyLine
+  returnF $ B.rawBlock "org" $ ("#+" <> line)
+
 commentLine :: Monad m => OrgParser m Blocks
 commentLine = commentLineStart *> anyLine *> pure mempty
 
@@ -627,16 +638,22 @@
   let totalWidth = if any (isJust . columnRelWidth) colProps
                    then Just . sum $ map (fromMaybe 1 . columnRelWidth) colProps
                    else Nothing
-  in B.table caption (map (convertColProp totalWidth) colProps) heads lns
+  in B.table (B.simpleCaption $ B.plain caption)
+             (map (convertColProp totalWidth) colProps)
+             (TableHead nullAttr $ toHeaderRow heads)
+             [TableBody nullAttr 0 [] $ map toRow lns]
+             (TableFoot nullAttr [])
  where
-   convertColProp :: Maybe Int -> ColumnProperty -> (Alignment, Double)
+   toRow = Row nullAttr . map B.simpleCell
+   toHeaderRow l = if null l then [] else [toRow l]
+   convertColProp :: Maybe Int -> ColumnProperty -> (Alignment, ColWidth)
    convertColProp totalWidth colProp =
      let
        align' = fromMaybe AlignDefault $ columnAlignment colProp
-       width' = fromMaybe 0 $ (\w t -> (fromIntegral w / fromIntegral t))
-                              <$> columnRelWidth colProp
-                              <*> totalWidth
-     in (align', width')
+       width' = (\w t -> (fromIntegral w / fromIntegral t))
+                <$> columnRelWidth colProp
+                <*> totalWidth
+     in (align', maybe ColWidthDefault ColWidth width')
 
 tableRows :: PandocMonad m => OrgParser m [OrgTableRow]
 tableRows = try $ many (tableAlignRow <|> tableHline <|> tableContentRow)
@@ -658,16 +675,16 @@
   return $ OrgAlignRow colProps
 
 columnPropertyCell :: Monad m => OrgParser m ColumnProperty
-columnPropertyCell = emptyCell <|> propCell <?> "alignment info"
+columnPropertyCell = emptyOrgCell <|> propCell <?> "alignment info"
  where
-   emptyCell = ColumnProperty Nothing Nothing <$ try (skipSpaces *> endOfCell)
+   emptyOrgCell = ColumnProperty Nothing Nothing <$ try (skipSpaces *> endOfCell)
    propCell = try $ ColumnProperty
                  <$> (skipSpaces
                       *> char '<'
                       *> optionMaybe tableAlignFromChar)
                  <*> (optionMaybe (many1Char digit >>= safeRead)
                       <* char '>'
-                      <* emptyCell)
+                      <* emptyOrgCell)
 
 tableAlignFromChar :: Monad m => OrgParser m Alignment
 tableAlignFromChar = try $
@@ -733,22 +750,26 @@
 --
 -- LaTeX fragments
 --
-latexFragment :: Monad m => OrgParser m (F Blocks)
+latexFragment :: PandocMonad m => OrgParser m (F Blocks)
 latexFragment = try $ do
   envName <- latexEnvStart
-  content <- mconcat <$> manyTill anyLineNewline (latexEnd envName)
-  returnF $ B.rawBlock "latex" (content `inLatexEnv` envName)
+  texOpt  <- getExportSetting exportWithLatex
+  let envStart = "\\begin{" <> envName <> "}"
+  let envEnd = "\\end{" <> envName <> "}"
+  envLines <- do
+    content <- manyTill anyLine (latexEnd envName)
+    return $ envStart : content ++ [envEnd]
+  returnF $ case texOpt of
+    TeXExport -> B.rawBlock "latex" . T.unlines $ envLines
+    TeXIgnore   -> mempty
+    TeXVerbatim -> B.para . mconcat . intersperse B.softbreak $
+                   map B.str envLines
  where
-   c `inLatexEnv` e = mconcat [ "\\begin{", e, "}\n"
-                              , c
-                              , "\\end{", e, "}\n"
-                              ]
-
-latexEnd :: Monad m => Text -> OrgParser m ()
-latexEnd envName = try $
-  () <$ skipSpaces
-     <* textStr ("\\end{" <> envName <> "}")
-     <* blankline
+  latexEnd :: Monad m => Text -> OrgParser m ()
+  latexEnd envName = try . void
+     $ skipSpaces
+    <* textStr ("\\end{" <> envName <> "}")
+    <* blankline
 
 
 --
diff --git a/src/Text/Pandoc/Readers/Org/ExportSettings.hs b/src/Text/Pandoc/Readers/Org/ExportSettings.hs
--- a/src/Text/Pandoc/Readers/Org/ExportSettings.hs
+++ b/src/Text/Pandoc/Readers/Org/ExportSettings.hs
@@ -20,7 +20,7 @@
 import Control.Monad (mzero, void)
 import Data.Char (toLower)
 import Data.Maybe (listToMaybe)
-import Data.Text (Text)
+import Data.Text (Text, unpack)
 
 -- | Read and handle space separated org-mode export settings.
 exportSettings :: PandocMonad m => OrgParser m ()
@@ -59,7 +59,7 @@
   , ignoredSetting "stat"
   , booleanSetting "tags" (\val es -> es { exportWithTags = val })
   , ignoredSetting "tasks"
-  , ignoredSetting "tex"
+  , texSetting     "tex" (\val es -> es { exportWithLatex = val })
   , ignoredSetting "timestamp"
   , ignoredSetting "title"
   , ignoredSetting "toc"
@@ -68,6 +68,8 @@
   , ignoreAndWarn
   ] <?> "export setting"
 
+-- | Generic handler for export settings. Takes a parser which converts
+-- the plain option text into a data structure.
 genericExportSetting :: Monad m
                      => OrgParser m a
                      -> Text
@@ -101,10 +103,8 @@
 archivedTreeSetting =
   genericExportSetting $ archivedTreesHeadlineSetting <|> archivedTreesBoolean
  where
-   archivedTreesHeadlineSetting = try $ do
-     _ <- string "headline"
-     lookAhead (newline <|> spaceChar)
-     return ArchivedTreesHeadlineOnly
+   archivedTreesHeadlineSetting =
+     ArchivedTreesHeadlineOnly <$ optionString "headline"
 
    archivedTreesBoolean = try $ do
      exportBool <- elispBoolean
@@ -143,6 +143,22 @@
      char '"'
        *> manyTillChar alphaNum (char '"')
 
+-- | Parses either @t@, @nil@, or @verbatim@ into a 'TeXExport' value.
+texSetting :: Monad m
+           => Text
+           -> ExportSettingSetter TeXExport
+           -> OrgParser m ()
+texSetting = genericExportSetting $ texVerbatim <|> texBoolean
+ where
+   texVerbatim = TeXVerbatim <$ optionString "verbatim"
+
+   texBoolean = try $ do
+     exportBool <- elispBoolean
+     return $
+       if exportBool
+       then TeXExport
+       else TeXIgnore
+
 -- | Read but ignore the export setting.
 ignoredSetting :: Monad m => Text -> OrgParser m ()
 ignoredSetting s = try (() <$ textStr s <* char ':' <* many1 nonspaceChar)
@@ -164,3 +180,11 @@
              "{}"  -> False
              "()"  -> False
              _     -> True
+
+-- | Try to parse a literal string as the option value. Returns the
+-- string on success.
+optionString :: Monad m => Text -> OrgParser m Text
+optionString s = try $ do
+  _ <- string (unpack s)
+  lookAhead (newline <|> spaceChar)
+  return s
diff --git a/src/Text/Pandoc/Readers/Org/Inlines.hs b/src/Text/Pandoc/Readers/Org/Inlines.hs
--- a/src/Text/Pandoc/Readers/Org/Inlines.hs
+++ b/src/Text/Pandoc/Readers/Org/Inlines.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE OverloadedStrings #-}
 {- |
    Module      : Text.Pandoc.Readers.Org.Inlines
@@ -27,7 +28,6 @@
 import Text.Pandoc.Definition
 import Text.Pandoc.Options
 import Text.Pandoc.Readers.LaTeX (inlineCommand, rawLaTeXInline)
-import Text.Pandoc.Shared (underlineSpan)
 import Text.TeXMath (DisplayType (..), readTeX, writePandoc)
 import qualified Text.TeXMath.Readers.MathML.EntityMap as MathMLEntityMap
 
@@ -567,7 +567,7 @@
 strikeout = fmap B.strikeout    <$> emphasisBetween '+'
 
 underline :: PandocMonad m => OrgParser m (F Inlines)
-underline = fmap underlineSpan  <$> emphasisBetween '_'
+underline = fmap B.underline    <$> emphasisBetween '_'
 
 verbatim  :: PandocMonad m => OrgParser m (F Inlines)
 verbatim  = return . B.code     <$> verbatimBetween '='
@@ -789,15 +789,17 @@
 inlineLaTeX :: PandocMonad m => OrgParser m (F Inlines)
 inlineLaTeX = try $ do
   cmd <- inlineLaTeXCommand
-  ils <- (lift . lift) $ parseAsInlineLaTeX cmd
+  texOpt <- getExportSetting exportWithLatex
+  ils <- parseAsInlineLaTeX cmd texOpt
   maybe mzero returnF $
-     parseAsMathMLSym cmd `mplus` parseAsMath cmd `mplus` ils
+     parseAsMathMLSym cmd `mplus` parseAsMath cmd texOpt `mplus` ils
  where
-   parseAsMath :: Text -> Maybe Inlines
-   parseAsMath cs = B.fromList <$> texMathToPandoc cs
-
-   parseAsInlineLaTeX :: PandocMonad m => Text -> m (Maybe Inlines)
-   parseAsInlineLaTeX cs = maybeRight <$> runParserT inlineCommand state "" cs
+   parseAsInlineLaTeX :: PandocMonad m
+                      => Text -> TeXExport -> OrgParser m (Maybe Inlines)
+   parseAsInlineLaTeX cs = \case
+     TeXExport -> maybeRight <$> runParserT inlineCommand state "" cs
+     TeXIgnore -> return (Just mempty)
+     TeXVerbatim -> return (Just $ B.str cs)
 
    parseAsMathMLSym :: Text -> Maybe Inlines
    parseAsMathMLSym cs = B.str <$> MathMLEntityMap.getUnicode (clean cs)
@@ -808,8 +810,12 @@
    state = def{ stateOptions = def{ readerExtensions =
                     enableExtension Ext_raw_tex (readerExtensions def) } }
 
-   texMathToPandoc :: Text -> Maybe [Inline]
-   texMathToPandoc cs = maybeRight (readTeX cs) >>= writePandoc DisplayInline
+   parseAsMath :: Text -> TeXExport -> Maybe Inlines
+   parseAsMath cs = \case
+     TeXExport -> maybeRight (readTeX cs) >>=
+                  fmap B.fromList . writePandoc DisplayInline
+     TeXIgnore -> Just mempty
+     TeXVerbatim -> Just $ B.str cs
 
 maybeRight :: Either a b -> Maybe b
 maybeRight = either (const Nothing) Just
@@ -821,7 +827,7 @@
   parsed <- (lift . lift) $ runParserT rawLaTeXInline st "source" rest
   case parsed of
     Right cs -> do
-      -- drop any trailing whitespace, those are not be part of the command as
+      -- drop any trailing whitespace, those are not part of the command as
       -- far as org mode is concerned.
       let cmdNoSpc = T.dropWhileEnd isSpace cs
       let len = T.length cmdNoSpc
diff --git a/src/Text/Pandoc/Readers/Org/Meta.hs b/src/Text/Pandoc/Readers/Org/Meta.hs
--- a/src/Text/Pandoc/Readers/Org/Meta.hs
+++ b/src/Text/Pandoc/Readers/Org/Meta.hs
@@ -1,5 +1,5 @@
 {-# LANGUAGE FlexibleContexts  #-}
-{-# LANGUAGE TupleSections     #-}
+{-# LANGUAGE LambdaCase        #-}
 {-# LANGUAGE OverloadedStrings #-}
 {- |
    Module      : Text.Pandoc.Readers.Org.Meta
@@ -26,16 +26,17 @@
 import qualified Text.Pandoc.Builder as B
 import Text.Pandoc.Class.PandocMonad (PandocMonad)
 import Text.Pandoc.Definition
-import Text.Pandoc.Shared (safeRead)
+import Text.Pandoc.Shared (blocksToInlines, safeRead)
 
-import Control.Monad (mzero, void, when)
-import Data.List (intersperse)
+import Control.Monad (mzero, void)
+import Data.List (intercalate, intersperse)
+import Data.Map (Map)
 import Data.Maybe (fromMaybe)
-import qualified Data.Map as M
-import qualified Data.Set as Set
 import Data.Text (Text)
-import qualified Data.Text as T
 import Network.HTTP (urlEncode)
+import qualified Data.Map as Map
+import qualified Data.Set as Set
+import qualified Data.Text as T
 
 -- | Returns the current meta, respecting export options.
 metaExport :: Monad m => OrgParser m (F Meta)
@@ -50,122 +51,139 @@
 removeMeta :: Text -> Meta -> Meta
 removeMeta key meta' =
   let metaMap = unMeta meta'
-  in Meta $ M.delete key metaMap
+  in Meta $ Map.delete key metaMap
 
 -- | Parse and handle a single line containing meta information
 -- The order, in which blocks are tried, makes sure that we're not looking at
 -- the beginning of a block, so we don't need to check for it
 metaLine :: PandocMonad m => OrgParser m Blocks
-metaLine = mempty <$ metaLineStart <* (optionLine <|> declarationLine)
+metaLine = try $ mempty <$ metaLineStart <* keywordLine
 
-declarationLine :: PandocMonad m => OrgParser m ()
-declarationLine = try $ do
+keywordLine :: PandocMonad m => OrgParser m ()
+keywordLine = try $ do
   key   <- T.toLower <$> metaKey
-  (key', value) <- metaValue key
-  let addMetaValue st =
-        st { orgStateMeta = B.setMeta key' <$> value <*> orgStateMeta st }
-  when (key' /= "results") $ updateState addMetaValue
+  case Map.lookup key keywordHandlers of
+    Nothing -> fail $ "Unknown keyword: " ++ T.unpack key
+    Just hd -> hd
 
 metaKey :: Monad m => OrgParser m Text
 metaKey = T.toLower <$> many1Char (noneOf ": \n\r")
                     <*  char ':'
                     <*  skipSpaces
 
-metaValue :: PandocMonad m => Text -> OrgParser m (Text, F MetaValue)
-metaValue key =
-  let inclKey = "header-includes"
-  in case key of
-    "author"          -> (key,) <$> metaInlinesCommaSeparated
-    "keywords"        -> (key,) <$> metaInlinesCommaSeparated
-    "title"           -> (key,) <$> metaInlines
-    "subtitle"        -> (key,) <$> metaInlines
-    "date"            -> (key,) <$> metaInlines
-    "nocite"          -> (key,) <$> accumulatingList key metaInlines
-    "header-includes" -> (key,) <$> accumulatingList key metaInlines
-    "latex_header"    -> (inclKey,) <$>
-                         accumulatingList inclKey (metaExportSnippet "latex")
-    "latex_class"     -> ("documentclass",) <$> metaString
-    -- Org-mode expects class options to contain the surrounding brackets,
-    -- pandoc does not.
-    "latex_class_options" -> ("classoption",) <$>
-                             metaModifiedString (T.filter (`notElem` ("[]" :: String)))
-    "html_head"       -> (inclKey,) <$>
-                         accumulatingList inclKey (metaExportSnippet "html")
-    _                 -> (key,) <$> metaString
-
-metaInlines :: PandocMonad m => OrgParser m (F MetaValue)
-metaInlines = fmap (MetaInlines . B.toList) <$> inlinesTillNewline
+infix 0 ~~>
+(~~>) :: a -> b -> (a, b)
+a ~~> b = (a, b)
 
-metaInlinesCommaSeparated :: PandocMonad m => OrgParser m (F MetaValue)
-metaInlinesCommaSeparated = do
-  itemStrs <- many1Char (noneOf ",\n") `sepBy1` char ','
-  newline
-  items <- mapM (parseFromString inlinesTillNewline . (<> "\n")) itemStrs
-  let toMetaInlines = MetaInlines . B.toList
-  return $ MetaList . map toMetaInlines <$> sequence items
+keywordHandlers :: PandocMonad m => Map Text (OrgParser m ())
+keywordHandlers = Map.fromList
+  [ "author" ~~> lineOfInlines `parseThen` collectLines "author"
+  , "creator" ~~> fmap pure anyLine `parseThen` B.setMeta "creator"
+  , "date" ~~> lineOfInlines `parseThen` B.setMeta "date"
+  , "description" ~~> lineOfInlines `parseThen` collectLines "description"
+  , "email" ~~> fmap pure anyLine `parseThen` B.setMeta "email"
+  , "exclude_tags" ~~> tagList >>= updateState . setExcludedTags
+  , "header-includes" ~~>
+    lineOfInlines `parseThen` collectLines "header-includes"
+  -- HTML-specifix export settings
+  , "html_head" ~~>
+    metaExportSnippet "html" `parseThen` collectAsList "header-includes"
+  , "html_head_extra" ~~>
+    metaExportSnippet "html" `parseThen` collectAsList "header-includes"
+  , "institute" ~~> lineOfInlines `parseThen` collectLines "institute"
+  -- topic keywords
+  , "keywords" ~~> lineOfInlines `parseThen` collectLines "keywords"
+  -- LaTeX-specific export settings
+  , "latex_class" ~~> fmap pure anyLine `parseThen` B.setMeta "documentclass"
+  , "latex_class_options" ~~>
+      (pure . T.filter (`notElem` ("[]" :: String)) <$> anyLine)
+      `parseThen` B.setMeta "classoption"
+  , "latex_header" ~~>
+      metaExportSnippet "latex" `parseThen` collectAsList "header-includes"
+  , "latex_header_extra" ~~>
+      metaExportSnippet "latex" `parseThen` collectAsList "header-includes"
+  -- link and macro
+  , "link" ~~> addLinkFormatter
+  , "macro" ~~> macroDefinition >>= updateState . registerMacro
+  -- pandoc-specific way to include references in the bibliography
+  , "nocite" ~~> lineOfInlines `parseThen` collectLines "nocite"
+  -- compact way to set export settings
+  , "options"  ~~> exportSettings
+  -- pandoc-specific way to configure emphasis recognition
+  , "pandoc-emphasis-post" ~~> emphChars >>= updateState . setEmphasisPostChar
+  , "pandoc-emphasis-pre" ~~> emphChars >>= updateState . setEmphasisPreChar
+  -- result markers (ignored)
+  , "result" ~~> void anyLine
+  , "select_tags" ~~> tagList >>= updateState . setSelectedTags
+  , "seq_todo" ~~> todoSequence >>= updateState . registerTodoSequence
+  , "subtitle" ~~> lineOfInlines `parseThen` collectLines "subtitle"
+  , "title" ~~> lineOfInlines `parseThen` collectLines "title"
+  , "todo" ~~> todoSequence >>= updateState . registerTodoSequence
+  , "typ_todo" ~~> todoSequence >>= updateState . registerTodoSequence
+  ]
 
-metaString :: Monad m => OrgParser m (F MetaValue)
-metaString = metaModifiedString id
+parseThen :: PandocMonad m
+          => OrgParser m (F a)
+          -> (a -> Meta -> Meta)
+          -> OrgParser m ()
+parseThen p modMeta = do
+  value <- p
+  meta  <- orgStateMeta <$> getState
+  updateState (\st -> st { orgStateMeta = modMeta <$> value <*> meta })
 
-metaModifiedString :: Monad m => (Text -> Text) -> OrgParser m (F MetaValue)
-metaModifiedString f = return . MetaString . f <$> anyLine
+collectLines :: Text -> Inlines -> Meta -> Meta
+collectLines key value meta =
+  let value' = appendValue meta (B.toList value)
+  in B.setMeta key value' meta
+ where
+  appendValue :: Meta -> [Inline] -> MetaValue
+  appendValue m v = MetaInlines $ curInlines m <> v
 
--- | Read an format specific meta definition
-metaExportSnippet :: Monad m => Text -> OrgParser m (F MetaValue)
-metaExportSnippet format =
-  return . MetaInlines . B.toList . B.rawInline format <$> anyLine
+  curInlines m = case collectInlines <$> lookupMeta key m of
+    Nothing -> []
+    Just [] -> []
+    Just xs -> xs <> [B.SoftBreak]
 
--- | Accumulate the result of the @parser@ in a list under @key@.
-accumulatingList :: Monad m => Text
-                 -> OrgParser m (F MetaValue)
-                 -> OrgParser m (F MetaValue)
-accumulatingList key p = do
-  value <- p
-  meta' <- orgStateMeta <$> getState
-  return $ (\m v -> MetaList (curList m ++ [v])) <$> meta' <*> value
- where curList m = case lookupMeta key m of
-                     Just (MetaList ms) -> ms
-                     Just x             -> [x]
-                     _                  -> []
+  collectInlines :: MetaValue -> [Inline]
+  collectInlines = \case
+    MetaInlines inlns -> inlns
+    MetaList ml       -> intercalate [B.SoftBreak] $ map collectInlines ml
+    MetaString s      -> [B.Str s]
+    MetaBlocks blks   -> blocksToInlines blks
+    MetaMap _map      -> []
+    MetaBool _bool    -> []
 
---
--- export options
---
-optionLine :: PandocMonad m => OrgParser m ()
-optionLine = try $ do
-  key <- metaKey
-  case key of
-    "link"     -> parseLinkFormat >>= uncurry addLinkFormat
-    "options"  -> exportSettings
-    "todo"     -> todoSequence >>= updateState . registerTodoSequence
-    "seq_todo" -> todoSequence >>= updateState . registerTodoSequence
-    "typ_todo" -> todoSequence >>= updateState . registerTodoSequence
-    "macro"    -> macroDefinition >>= updateState . registerMacro
-    "exclude_tags" -> tagList >>= updateState . setExcludedTags
-    "select_tags" -> tagList >>= updateState . setSelectedTags
-    "pandoc-emphasis-pre" -> emphChars >>= updateState . setEmphasisPreChar
-    "pandoc-emphasis-post" -> emphChars >>= updateState . setEmphasisPostChar
-    _          -> mzero
+-- | Accumulate the result as a MetaList under the given key.
+collectAsList :: Text -> Inlines -> Meta -> Meta
+collectAsList key value meta =
+  let value' = metaListAppend meta (B.toMetaValue value)
+  in B.setMeta key value' meta
+ where
+  metaListAppend m v = MetaList (curList m ++ [v])
+  curList m = case lookupMeta key m of
+                Just (MetaList ms) -> ms
+                Just x             -> [x]
+                _                  -> []
 
-addLinkFormat :: Monad m => Text
-              -> (Text -> Text)
-              -> OrgParser m ()
-addLinkFormat key formatter = updateState $ \s ->
-  let fs = orgStateLinkFormatters s
-  in s{ orgStateLinkFormatters = M.insert key formatter fs }
+-- | Read an format specific meta definition
+metaExportSnippet :: Monad m => Text -> OrgParser m (F Inlines)
+metaExportSnippet format = pure . B.rawInline format <$> anyLine
 
-parseLinkFormat :: Monad m => OrgParser m (Text, Text -> Text)
-parseLinkFormat = try $ do
+-- | Parse a link type definition (like @wp https://en.wikipedia.org/wiki/@).
+addLinkFormatter :: Monad m => OrgParser m ()
+addLinkFormatter = try $ do
   linkType <- T.cons <$> letter <*> manyChar (alphaNum <|> oneOf "-_") <* skipSpaces
-  linkSubst <- parseFormat
-  return (linkType, linkSubst)
+  formatter <- parseFormat
+  updateState $ \s ->
+    let fs = orgStateLinkFormatters s
+    in s{ orgStateLinkFormatters = Map.insert linkType formatter fs }
 
 -- | An ad-hoc, single-argument-only implementation of a printf-style format
 -- parser.
 parseFormat :: Monad m => OrgParser m (Text -> Text)
 parseFormat = try $ replacePlain <|> replaceUrl <|> justAppend
  where
-   -- inefficient, but who cares
+   -- inefficient
    replacePlain = try $ (\x -> T.concat . flip intersperse x)
                      <$> sequence [tillSpecifier 's', rest]
    replaceUrl   = try $ (\x -> T.concat . flip intersperse x . T.pack . urlEncode . T.unpack)
@@ -204,26 +222,25 @@
   let postChars = fromMaybe (orgStateEmphasisPostChars defaultOrgParserState) csMb
   in st { orgStateEmphasisPostChars = postChars }
 
+-- | Parses emphasis border character like @".,?!"@
 emphChars :: Monad m => OrgParser m (Maybe [Char])
 emphChars = do
   skipSpaces
   safeRead <$> anyLine
 
-inlinesTillNewline :: PandocMonad m => OrgParser m (F Inlines)
-inlinesTillNewline = do
+lineOfInlines :: PandocMonad m => OrgParser m (F Inlines)
+lineOfInlines = do
   updateLastPreCharPos
   trimInlinesF . mconcat <$> manyTill inline newline
 
---
--- ToDo Sequences and Keywords
---
+-- | Parses ToDo sequences / keywords like @TODO DOING | DONE@.
 todoSequence :: Monad m => OrgParser m TodoSequence
 todoSequence = try $ do
   todoKws <- todoKeywords
   doneKws <- optionMaybe $ todoDoneSep *> todoKeywords
   newline
-  -- There must be at least one DONE keyword. The last TODO keyword is taken if
-  -- necessary.
+  -- There must be at least one DONE keyword. The last TODO keyword is
+  -- taken if necessary.
   case doneKws of
     Just done  -> return $ keywordsToSequence todoKws done
     Nothing    -> case reverse todoKws of
diff --git a/src/Text/Pandoc/Readers/Org/ParserState.hs b/src/Text/Pandoc/Readers/Org/ParserState.hs
--- a/src/Text/Pandoc/Readers/Org/ParserState.hs
+++ b/src/Text/Pandoc/Readers/Org/ParserState.hs
@@ -35,6 +35,7 @@
   , returnF
   , ExportSettings (..)
   , ArchivedTreesOption (..)
+  , TeXExport (..)
   , optionsToParserState
   ) where
 
@@ -231,6 +232,13 @@
   | ArchivedTreesNoExport     -- ^ Exclude archived trees from exporting
   | ArchivedTreesHeadlineOnly -- ^ Export only the headline, discard the contents
 
+-- | Options for the handling of LaTeX environments and fragments.
+-- Represents allowed values of Emacs variable @org-export-with-latex@.
+data TeXExport
+  = TeXExport                 -- ^ Include raw TeX in the output
+  | TeXIgnore                 -- ^ Ignore raw TeX
+  | TeXVerbatim               -- ^ Keep everything in verbatim
+
 -- | Export settings <http://orgmode.org/manual/Export-settings.html>
 -- These settings can be changed via OPTIONS statements.
 data ExportSettings = ExportSettings
@@ -249,6 +257,7 @@
   , exportWithAuthor       :: Bool -- ^ Include author in final meta-data
   , exportWithCreator      :: Bool -- ^ Include creator in final meta-data
   , exportWithEmail        :: Bool -- ^ Include email in final meta-data
+  , exportWithLatex        :: TeXExport -- ^ Handling of raw TeX commands
   , exportWithPlanning     :: Bool -- ^ Keep planning info after headlines
   , exportWithTags         :: Bool -- ^ Keep tags as part of headlines
   , exportWithTodoKeywords :: Bool -- ^ Keep TODO keywords in headers
@@ -270,6 +279,7 @@
   , exportWithAuthor = True
   , exportWithCreator = True
   , exportWithEmail = True
+  , exportWithLatex = TeXExport
   , exportWithPlanning = False
   , exportWithTags = True
   , exportWithTodoKeywords = True
diff --git a/src/Text/Pandoc/Readers/Org/Shared.hs b/src/Text/Pandoc/Readers/Org/Shared.hs
--- a/src/Text/Pandoc/Readers/Org/Shared.hs
+++ b/src/Text/Pandoc/Readers/Org/Shared.hs
@@ -26,7 +26,8 @@
 isImageFilename :: Text -> Bool
 isImageFilename fp = hasImageExtension && (isValid (T.unpack fp) || isKnownProtocolUri)
  where
-   hasImageExtension = takeExtension (T.unpack fp) `elem` imageExtensions
+   hasImageExtension = takeExtension (T.unpack $ T.toLower fp)
+                       `elem` imageExtensions
    isKnownProtocolUri = any (\x -> (x <> "://") `T.isPrefixOf` fp) protocols
 
    imageExtensions = [ ".jpeg", ".jpg", ".png", ".gif", ".svg" ]
diff --git a/src/Text/Pandoc/Readers/RST.hs b/src/Text/Pandoc/Readers/RST.hs
--- a/src/Text/Pandoc/Readers/RST.hs
+++ b/src/Text/Pandoc/Readers/RST.hs
@@ -21,13 +21,14 @@
 import Data.Char (isHexDigit, isSpace, toUpper, isAlphaNum)
 import Data.List (deleteFirstsBy, elemIndex, nub, sort, transpose)
 import qualified Data.Map as M
-import Data.Maybe (fromMaybe, maybeToList)
+import Data.Maybe (fromMaybe, maybeToList, isJust)
 import Data.Sequence (ViewR (..), viewr)
 import Data.Text (Text)
 import qualified Data.Text as T
 import Text.Pandoc.Builder (Blocks, Inlines, fromList, setMeta, trimInlines)
 import qualified Text.Pandoc.Builder as B
-import Text.Pandoc.Class.PandocMonad (PandocMonad, fetchItem, readFileFromDirs)
+import Text.Pandoc.Class.PandocMonad (PandocMonad, fetchItem,
+                                      readFileFromDirs, getCurrentTime)
 import Text.Pandoc.CSV (CSVOptions (..), defaultCSVOptions, parseCSV)
 import Text.Pandoc.Definition
 import Text.Pandoc.Error
@@ -38,6 +39,7 @@
 import Text.Pandoc.Shared
 import qualified Text.Pandoc.UTF8 as UTF8
 import Text.Printf (printf)
+import Data.Time.Format
 
 -- TODO:
 -- [ ] .. parsed-literal
@@ -485,10 +487,9 @@
   let contents' = T.unlines contentLines'' <> "\n"
   case lookup "code" fields of
        Just lang -> do
-         let numberLines = lookup "number-lines" fields
          let classes =  maybe [] T.words (lookup "class" fields)
          let ident = maybe "" trimr $ lookup "name" fields
-         codeblock ident classes numberLines (trimr lang) contents' False
+         codeblock ident classes fields (trimr lang) contents' False
        Nothing   -> case lookup "literal" fields of
                          Just _  -> return $ B.rawBlock "rst" contents'
                          Nothing -> do
@@ -682,6 +683,13 @@
                           parseFromString' parseBlocks body'
         "replace" -> B.para <$>  -- consumed by substKey
                    parseInlineFromText (trim top)
+        "date" -> B.para <$> do  -- consumed by substKey
+                     t <- getCurrentTime
+                     let format = case T.unpack (T.strip top) of
+                                    [] -> "%Y-%m-%d"
+                                    x  -> x
+                     return $ B.text $
+                              T.pack $ formatTime defaultTimeLocale format t
         "unicode" -> B.para <$>  -- consumed by substKey
                    parseInlineFromText (trim $ unicodeTransform top)
         "compound" -> parseFromString' parseBlocks body'
@@ -722,8 +730,8 @@
                                      ""   -> stateRstHighlight def
                                      lang -> Just lang })
         x | x == "code" || x == "code-block" || x == "sourcecode" ->
-          codeblock name classes
-                    (lookup "number-lines" fields) (trim top) body True
+          codeblock name classes (map (second trimr) fields)
+             (trim top) body True
         "aafig" -> do
           let attribs = (name, ["aafig"], map (second trimr) fields)
           return $ B.codeBlockWith attribs $ stripTrailingNewlines body
@@ -761,24 +769,34 @@
 tableDirective top fields body = do
   bs <- parseFromString' parseBlocks body
   case B.toList bs of
-       [Table _ aligns' widths' header' rows'] -> do
+       [Table attr _ tspecs' thead@(TableHead _ thrs) tbody tfoot] -> do
+         let (aligns', widths') = unzip tspecs'
          title <- parseFromString' (trimInlines . mconcat <$> many inline) top
          columns <- getOption readerColumns
-         let numOfCols = length header'
+         let numOfCols = case thrs of
+               [] -> 0
+               (r:_) -> rowLength r
          let normWidths ws =
-                map (/ max 1.0 (fromIntegral (columns - numOfCols))) ws
+                strictPos . (/ max 1.0 (fromIntegral (columns - numOfCols))) <$> ws
          let widths = case trim <$> lookup "widths" fields of
-                           Just "auto" -> replicate numOfCols 0.0
+                           Just "auto" -> replicate numOfCols ColWidthDefault
                            Just "grid" -> widths'
                            Just specs -> normWidths
                                $ map (fromMaybe (0 :: Double) . safeRead)
                                $ splitTextBy (`elem` (" ," :: String)) specs
                            Nothing -> widths'
          -- align is not applicable since we can't represent whole table align
-         return $ B.singleton $ Table (B.toList title)
-                                  aligns' widths header' rows'
+         let tspecs = zip aligns' widths
+         return $ B.singleton $ Table attr (B.caption Nothing (B.plain title))
+                                  tspecs thead tbody tfoot
        _ -> return mempty
-
+  where
+    -- only valid on the very first row of a table section
+    rowLength (Row _ rb) = sum $ cellLength <$> rb
+    cellLength (Cell _ _ _ (ColSpan w) _) = max 1 w
+    strictPos w
+      | w > 0     = ColWidth w
+      | otherwise = ColWidthDefault
 
 -- TODO: :stub-columns:.
 -- Only the first row becomes the header even if header-rows: > 1,
@@ -799,19 +817,25 @@
                    else ([], rows, length x)
         _ -> ([],[],0)
       widths = case trim <$> lookup "widths" fields of
-        Just "auto" -> replicate numOfCols 0
+        Just "auto" -> replicate numOfCols ColWidthDefault
         Just specs -> normWidths $ map (fromMaybe (0 :: Double) . safeRead) $
                            splitTextBy (`elem` (" ," :: String)) specs
-        _ -> replicate numOfCols 0
-  return $ B.table title
+        _ -> replicate numOfCols ColWidthDefault
+      toRow = Row nullAttr . map B.simpleCell
+      toHeaderRow l = if null l then [] else [toRow l]
+  return $ B.table (B.simpleCaption $ B.plain title)
              (zip (replicate numOfCols AlignDefault) widths)
-             headerRow
-             bodyRows
+             (TableHead nullAttr $ toHeaderRow headerRow)
+             [TableBody nullAttr 0 [] $ map toRow bodyRows]
+             (TableFoot nullAttr [])
     where takeRows [BulletList rows] = map takeCells rows
           takeRows _                 = []
           takeCells [BulletList cells] = map B.fromList cells
           takeCells _                  = []
-          normWidths ws = map (/ max 1 (sum ws)) ws
+          normWidths ws = strictPos . (/ max 1 (sum ws)) <$> ws
+          strictPos w
+            | w > 0     = ColWidth w
+            | otherwise = ColWidthDefault
 
 csvTableDirective :: PandocMonad m
                    => Text -> [(Text, Text)] -> Text
@@ -864,18 +888,24 @@
                           else ([], rows, length x)
                    _ -> ([],[],0)
          title <- parseFromString' (trimInlines . mconcat <$> many inline) top
-         let normWidths ws = map (/ max 1 (sum ws)) ws
+         let strictPos w
+               | w > 0     = ColWidth w
+               | otherwise = ColWidthDefault
+         let normWidths ws = strictPos . (/ max 1 (sum ws)) <$> ws
          let widths =
                case trim <$> lookup "widths" fields of
-                 Just "auto" -> replicate numOfCols 0
+                 Just "auto" -> replicate numOfCols ColWidthDefault
                  Just specs -> normWidths
                                $ map (fromMaybe (0 :: Double) . safeRead)
                                $ splitTextBy (`elem` (" ," :: String)) specs
-                 _ -> replicate numOfCols 0
-         return $ B.table title
-                  (zip (replicate numOfCols AlignDefault) widths)
-                  headerRow
-                  bodyRows
+                 _ -> replicate numOfCols ColWidthDefault
+         let toRow = Row nullAttr . map B.simpleCell
+             toHeaderRow l = if null l then [] else [toRow l]
+         return $ B.table (B.simpleCaption $ B.plain title)
+                          (zip (replicate numOfCols AlignDefault) widths)
+                          (TableHead nullAttr $ toHeaderRow headerRow)
+                          [TableBody nullAttr 0 [] $ map toRow bodyRows]
+                          (TableFoot nullAttr [])
 
 -- TODO:
 --  - Only supports :format: fields with a single format for :raw: roles,
@@ -976,21 +1006,22 @@
                           then "\\begin{aligned}\n" <> s <> "\n\\end{aligned}"
                           else s
 
-codeblock :: Text -> [Text] -> Maybe Text -> Text -> Text -> Bool
+codeblock :: Text -> [Text] -> [(Text, Text)] -> Text -> Text -> Bool
           -> RSTParser m Blocks
-codeblock ident classes numberLines lang body rmTrailingNewlines =
+codeblock ident classes fields lang body rmTrailingNewlines = do
   return $ B.codeBlockWith attribs $ stripTrailingNewlines' body
     where stripTrailingNewlines' = if rmTrailingNewlines
                                      then stripTrailingNewlines
                                      else id
           attribs = (ident, classes', kvs)
           classes' = lang
-                    : maybe [] (const ["numberLines"]) numberLines
+                    : ["numberLines" | isJust (lookup "number-lines" fields)]
                     ++ classes
-          kvs = maybe [] (\n -> case trimr n of
-                                   "" -> []
-                                   xs -> [("startFrom", xs)])
-                            numberLines
+          kvs = [(k,v) | (k,v) <- fields, k /= "number-lines", k /= "class",
+                                          k /= "id", k /= "name"]
+                ++ case lookup "number-lines" fields of
+                     Just v | not (T.null v) -> [("startFrom", v)]
+                     _ -> []
 
 ---
 --- note block
@@ -1284,13 +1315,14 @@
            sep simpleTableFooter
   -- Simple tables get 0s for relative column widths (i.e., use default)
   case B.toList tbl of
-       [Table c a _w h l]  -> return $ B.singleton $
-                                 Table c a (replicate (length a) 0) h l
+       [Table attr cap spec th tb tf] -> return $ B.singleton $
+                                         Table attr cap (rewidth spec) th tb tf
        _ ->
          throwError $ PandocShouldNeverHappenError
             "tableWith returned something unexpected"
  where
   sep = return () -- optional (simpleTableSep '-')
+  rewidth = fmap $ fmap $ const ColWidthDefault
 
 gridTable :: PandocMonad m
           => Bool -- ^ Headerless table
diff --git a/src/Text/Pandoc/Readers/TWiki.hs b/src/Text/Pandoc/Readers/TWiki.hs
--- a/src/Text/Pandoc/Readers/TWiki.hs
+++ b/src/Text/Pandoc/Readers/TWiki.hs
@@ -1,7 +1,5 @@
 {-# LANGUAGE FlexibleContexts  #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RelaxedPolyRec    #-}
--- RelaxedPolyRec needed for inlinesBetween on GHC < 7
 {- |
    Module      : Text.Pandoc.Readers.TWiki
    Copyright   : Copyright (C) 2014 Alexander Sulfrian
@@ -228,12 +226,18 @@
   return $ buildTable mempty rows $ fromMaybe (align rows, columns rows) tableHead
   where
     buildTable caption rows (aligns, heads)
-                    = B.table caption aligns heads rows
-    align rows      = replicate (columCount rows) (AlignDefault, 0)
+                    = B.table (B.simpleCaption $ B.plain caption)
+                              aligns
+                              (TableHead nullAttr $ toHeaderRow heads)
+                              [TableBody nullAttr 0 [] $ map toRow rows]
+                              (TableFoot nullAttr [])
+    align rows      = replicate (columCount rows) (AlignDefault, ColWidthDefault)
     columns rows    = replicate (columCount rows) mempty
     columCount rows = length $ head rows
+    toRow           = Row nullAttr . map B.simpleCell
+    toHeaderRow l = if null l then [] else [toRow l]
 
-tableParseHeader :: PandocMonad m => TWParser m ((Alignment, Double), B.Blocks)
+tableParseHeader :: PandocMonad m => TWParser m ((Alignment, ColWidth), B.Blocks)
 tableParseHeader = try $ do
   char '|'
   leftSpaces <- length <$> many spaceChar
@@ -245,9 +249,9 @@
   return (tableAlign leftSpaces rightSpaces, content)
   where
     tableAlign left right
-      | left >= 2 && left == right = (AlignCenter, 0)
-      | left > right = (AlignRight, 0)
-      | otherwise = (AlignLeft, 0)
+      | left >= 2 && left == right = (AlignCenter, ColWidthDefault)
+      | left > right = (AlignRight, ColWidthDefault)
+      | otherwise = (AlignLeft, ColWidthDefault)
 
 tableParseRow :: PandocMonad m => TWParser m [B.Blocks]
 tableParseRow = many1Till tableParseColumn newline
diff --git a/src/Text/Pandoc/Readers/Textile.hs b/src/Text/Pandoc/Readers/Textile.hs
--- a/src/Text/Pandoc/Readers/Textile.hs
+++ b/src/Text/Pandoc/Readers/Textile.hs
@@ -52,7 +52,7 @@
 import Text.Pandoc.Parsing
 import Text.Pandoc.Readers.HTML (htmlTag, isBlockTag, isInlineTag)
 import Text.Pandoc.Readers.LaTeX (rawLaTeXBlock, rawLaTeXInline)
-import Text.Pandoc.Shared (crFilter, trim, underlineSpan, tshow)
+import Text.Pandoc.Shared (crFilter, trim, tshow)
 
 -- | Parse a Textile text and return a Pandoc document.
 readTextile :: PandocMonad m
@@ -133,14 +133,14 @@
   return mempty
 
 codeBlock :: PandocMonad m => ParserT Text ParserState m Blocks
-codeBlock = codeBlockBc <|> codeBlockPre
+codeBlock = codeBlockTextile <|> codeBlockHtml
 
-codeBlockBc :: PandocMonad m => ParserT Text ParserState m Blocks
-codeBlockBc = try $ do
-  string "bc."
+codeBlockTextile :: PandocMonad m => ParserT Text ParserState m Blocks
+codeBlockTextile = try $ do
+  string "bc." <|> string "pre."
   extended <- option False (True <$ char '.')
   char ' '
-  let starts = ["p", "table", "bq", "bc", "h1", "h2", "h3",
+  let starts = ["p", "table", "bq", "bc", "pre", "h1", "h2", "h3",
                 "h4", "h5", "h6", "pre", "###", "notextile"]
   let ender = choice $ map explicitBlockStart starts
   contents <- if extended
@@ -155,8 +155,8 @@
 trimTrailingNewlines = T.dropWhileEnd (=='\n')
 
 -- | Code Blocks in Textile are between <pre> and </pre>
-codeBlockPre :: PandocMonad m => ParserT Text ParserState m Blocks
-codeBlockPre = try $ do
+codeBlockHtml :: PandocMonad m => ParserT Text ParserState m Blocks
+codeBlockHtml = try $ do
   (t@(TagOpen _ attrs),_) <- htmlTag (tagOpen (=="pre") (const True))
   result' <- T.pack <$> manyTill anyChar (htmlTag (tagClose (=="pre")))
   -- drop leading newline if any
@@ -243,7 +243,7 @@
 genericListItemAtDepth c depth = try $ do
   count depth (char c) >> attributes >> whitespace
   contents <- mconcat <$> many ((B.plain . mconcat <$> many1 inline) <|>
-                                try (newline >> codeBlockPre))
+                                try (newline >> codeBlockHtml))
   newline
   sublist <- option mempty (anyListAtDepth (depth + 1))
   return $ contents <> sublist
@@ -377,10 +377,13 @@
                              _ -> (mempty, rawrows)
   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))
-    (map snd headers)
-    (map (map snd) rows)
+  let toRow = Row nullAttr . map B.simpleCell
+      toHeaderRow l = if null l then [] else [toRow l]
+  return $ B.table (B.simpleCaption $ B.plain caption)
+    (zip aligns (replicate nbOfCols ColWidthDefault))
+    (TableHead nullAttr $ toHeaderRow $ map snd headers)
+    [TableBody nullAttr 0 [] $ map (toRow . map snd) rows]
+    (TableFoot nullAttr [])
 
 -- | Ignore markers for cols, thead, tfoot.
 ignorableRow :: PandocMonad m => ParserT Text ParserState m ()
@@ -448,7 +451,7 @@
                       , simpleInline (string "__") B.emph
                       , simpleInline (char '*') B.strong
                       , simpleInline (char '_') B.emph
-                      , simpleInline (char '+') underlineSpan
+                      , simpleInline (char '+') B.underline
                       , simpleInline (char '-' <* notFollowedBy (char '-')) B.strikeout
                       , simpleInline (char '^') B.superscript
                       , simpleInline (char '~') B.subscript
diff --git a/src/Text/Pandoc/Readers/TikiWiki.hs b/src/Text/Pandoc/Readers/TikiWiki.hs
--- a/src/Text/Pandoc/Readers/TikiWiki.hs
+++ b/src/Text/Pandoc/Readers/TikiWiki.hs
@@ -1,6 +1,5 @@
 {-# LANGUAGE FlexibleContexts  #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RelaxedPolyRec    #-}
 
 {- |
    Module      : Text.Pandoc.Readers.TikiWiki
diff --git a/src/Text/Pandoc/Readers/Txt2Tags.hs b/src/Text/Pandoc/Readers/Txt2Tags.hs
--- a/src/Text/Pandoc/Readers/Txt2Tags.hs
+++ b/src/Text/Pandoc/Readers/Txt2Tags.hs
@@ -31,8 +31,7 @@
 import Text.Pandoc.Definition
 import Text.Pandoc.Options
 import Text.Pandoc.Parsing hiding (space, spaces, uri)
-import Text.Pandoc.Shared (compactify, compactifyDL, crFilter, escapeURI,
-                           underlineSpan)
+import Text.Pandoc.Shared (compactify, compactifyDL, crFilter, escapeURI)
 
 type T2T = ParserT Text ParserState (Reader T2TMeta)
 
@@ -267,9 +266,13 @@
   let size = maximum (map length rows')
   let rowsPadded = map (pad size) rows'
   let headerPadded = if null tableHeader then mempty else pad size tableHeader
-  return $ B.table mempty
-                    (zip aligns (replicate ncolumns 0.0))
-                      headerPadded rowsPadded
+  let toRow = Row nullAttr . map B.simpleCell
+      toHeaderRow l = if null l then [] else [toRow l]
+  return $ B.table B.emptyCaption
+                    (zip aligns (replicate ncolumns ColWidthDefault))
+                      (TableHead nullAttr $ toHeaderRow headerPadded)
+                      [TableBody nullAttr 0 [] $ map toRow rowsPadded]
+                      (TableFoot nullAttr [])
 
 pad :: (Monoid a) => Int -> [a] -> [a]
 pad n xs = xs ++ replicate (n - length xs) mempty
@@ -374,7 +377,7 @@
 bold = inlineMarkup inline B.strong '*' B.str
 
 underline :: T2T Inlines
-underline = inlineMarkup inline underlineSpan '_' B.str
+underline = inlineMarkup inline B.underline '_' B.str
 
 strike :: T2T Inlines
 strike = inlineMarkup inline B.strikeout '-' B.str
diff --git a/src/Text/Pandoc/Readers/Vimwiki.hs b/src/Text/Pandoc/Readers/Vimwiki.hs
--- a/src/Text/Pandoc/Readers/Vimwiki.hs
+++ b/src/Text/Pandoc/Readers/Vimwiki.hs
@@ -236,7 +236,11 @@
 makeAttr :: Text -> Attr
 makeAttr s =
   let xs = splitTextBy (`elem` (" \t" :: String)) s in
-    ("", [], mapMaybe nameValue xs)
+    ("", syntax xs, mapMaybe nameValue xs)
+
+syntax :: [Text] -> [Text]
+syntax (s:_) | not $ T.isInfixOf "=" s = [s]
+syntax _ = []
 
 nameValue :: Text -> Maybe (Text, Text)
 nameValue s =
diff --git a/src/Text/Pandoc/Shared.hs b/src/Text/Pandoc/Shared.hs
--- a/src/Text/Pandoc/Shared.hs
+++ b/src/Text/Pandoc/Shared.hs
@@ -579,7 +579,8 @@
     rest' <- go rest
     let kvs' = -- don't touch number if already present
                case lookup "number" kvs of
-                  Nothing | numbering ->
+                  Nothing | numbering
+                          , not ("unnumbered" `elem` classes) ->
                         ("number", T.intercalate "." (map tshow newnum)) : kvs
                   _ -> kvs
     let divattr = (ident, "section":classes, kvs')
@@ -667,7 +668,7 @@
 
 -- | Detect if table rows contain only cells consisting of a single
 -- paragraph that has no @LineBreak@.
-onlySimpleTableCells :: [[TableCell]] -> Bool
+onlySimpleTableCells :: [[[Block]]] -> Bool
 onlySimpleTableCells = all isSimpleCell . concat
   where
     isSimpleCell [Plain ils] = not (hasLineBreak ils)
@@ -750,11 +751,12 @@
         go xs
           = xs
 
--- | Builder for underline.
+{-# DEPRECATED underlineSpan "Use Text.Pandoc.Builder.underline instead" #-}
+-- | Builder for underline (deprecated).
 -- This probably belongs in Builder.hs in pandoc-types.
 -- Will be replaced once Underline is an element.
 underlineSpan :: Inlines -> Inlines
-underlineSpan = B.spanWith ("", ["underline"], [])
+underlineSpan = B.underline
 
 -- | Set of HTML elements that are represented as Span with a class equal as
 -- the element tag itself.
@@ -836,7 +838,7 @@
 renderTags' :: [Tag T.Text] -> T.Text
 renderTags' = renderTagsOptions
                renderOptions{ optMinimize = matchTags ["hr", "br", "img",
-                                                       "meta", "link"]
+                                                       "meta", "link", "col"]
                             , optRawTag   = matchTags ["script", "style"] }
               where matchTags tags = flip elem tags . T.toLower
 
@@ -992,9 +994,14 @@
       mconcat (map blocksToInlines' blkslst)
 blockToInlines (Header _ _  ils) = B.fromList ils
 blockToInlines HorizontalRule = mempty
-blockToInlines (Table _ _ _ headers rows) =
+blockToInlines (Table _ _ _ (TableHead _ hbd) bodies (TableFoot _ fbd)) =
   mconcat $ intersperse B.linebreak $
-    map (mconcat . map blocksToInlines') (headers:rows)
+    map (mconcat . map blocksToInlines') (plainRowBody <$> hbd <> unTableBodies bodies <> fbd)
+  where
+    plainRowBody (Row _ body) = cellBody <$> body
+    cellBody (Cell _ _ _ _ body) = body
+    unTableBody (TableBody _ _ hd bd) = hd <> bd
+    unTableBodies = concatMap unTableBody
 blockToInlines (Div _ blks) = blocksToInlines' blks
 blockToInlines Null = mempty
 
@@ -1015,7 +1022,6 @@
   -- This is used in the pandoc.utils.blocks_to_inlines function. Docs
   -- there should be updated if this is changed.
   B.space <> B.str "¶" <> B.space
-
 
 --
 -- Safe read
diff --git a/src/Text/Pandoc/UUID.hs b/src/Text/Pandoc/UUID.hs
--- a/src/Text/Pandoc/UUID.hs
+++ b/src/Text/Pandoc/UUID.hs
@@ -11,12 +11,13 @@
 in RFC4122. See http://tools.ietf.org/html/rfc4122
 -}
 
-module Text.Pandoc.UUID ( UUID(..), getRandomUUID, getUUID ) where
+module Text.Pandoc.UUID ( UUID(..), getRandomUUID ) where
 
 import Data.Bits (clearBit, setBit)
 import Data.Word
-import System.Random (RandomGen, getStdGen, randoms)
+import System.Random (RandomGen, randoms)
 import Text.Printf (printf)
+import Text.Pandoc.Class.PandocMonad
 
 data UUID = UUID Word8 Word8 Word8 Word8 Word8 Word8 Word8 Word8
                  Word8 Word8 Word8 Word8 Word8 Word8 Word8 Word8
@@ -56,5 +57,5 @@
          in  UUID a b c d e f g' h i' j k l m n o p
        _ -> error "not enough random numbers for UUID" -- should not happen
 
-getRandomUUID :: IO UUID
-getRandomUUID = getUUID <$> getStdGen
+getRandomUUID :: PandocMonad m => m UUID
+getRandomUUID = getUUID <$> newStdGen
diff --git a/src/Text/Pandoc/Writers/AsciiDoc.hs b/src/Text/Pandoc/Writers/AsciiDoc.hs
--- a/src/Text/Pandoc/Writers/AsciiDoc.hs
+++ b/src/Text/Pandoc/Writers/AsciiDoc.hs
@@ -191,7 +191,8 @@
                      else contents
   let bar = text "____"
   return $ bar $$ chomp contents' $$ bar <> blankline
-blockToAsciiDoc opts (Table caption aligns widths headers rows) =  do
+blockToAsciiDoc opts (Table _ blkCapt specs thead tbody tfoot) = do
+  let (caption, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot
   caption' <- inlineListToAsciiDoc opts caption
   let caption'' = if null caption
                      then empty
@@ -298,7 +299,7 @@
                       chomp admonitionBody $$
                       "===="
          _ -> blockListToAsciiDoc opts bs
-  return $ identifier $$ contents
+  return $ identifier $$ contents $$ blankline
 
 -- | Convert bullet list item (list of blocks) to asciidoc.
 bulletListItemToAsciiDoc :: PandocMonad m
@@ -432,6 +433,9 @@
   isIntraword <- gets intraword
   let marker = if isIntraword then "__" else "_"
   return $ marker <> contents <> marker
+inlineToAsciiDoc opts (Underline lst) = do
+  contents <- inlineListToAsciiDoc opts lst
+  return $ "+++" <> contents <> "+++"
 inlineToAsciiDoc opts (Strong lst) = do
   contents <- inlineListToAsciiDoc opts lst
   isIntraword <- gets intraword
diff --git a/src/Text/Pandoc/Writers/CommonMark.hs b/src/Text/Pandoc/Writers/CommonMark.hs
--- a/src/Text/Pandoc/Writers/CommonMark.hs
+++ b/src/Text/Pandoc/Writers/CommonMark.hs
@@ -154,71 +154,72 @@
           Plain (term ++ [LineBreak] ++ xs) : ys ++ concat zs
         dlToBullet (term, xs) =
           Para term : concat xs
-blockToNodes opts t@(Table capt aligns _widths headers rows) ns =
-  if isEnabled Ext_pipe_tables opts && onlySimpleTableCells (headers:rows)
-     then do
-       -- We construct a table manually as a CUSTOM_BLOCK, for
-       -- two reasons:  (1) cmark-gfm currently doesn't support
-       -- rendering TABLE nodes; (2) we can align the column sides;
-       -- (3) we can render the caption as a regular paragraph.
-       let capt' = node PARAGRAPH (inlinesToNodes opts capt)
-       -- backslash | in code and raw:
-       let fixPipe (Code attr xs) =
-             Code attr (T.replace "|" "\\|" xs)
-           fixPipe (RawInline format xs) =
-             RawInline format (T.replace "|" "\\|" xs)
-           fixPipe x = x
-       let toCell [Plain ils] = T.strip
-                                $ nodeToCommonmark [] Nothing
-                                $ node (CUSTOM_INLINE mempty mempty)
-                                $ inlinesToNodes opts
-                                $ walk (fixPipe . softBreakToSpace) ils
-           toCell [Para  ils] = T.strip
-                                $ nodeToCommonmark [] Nothing
-                                $ node (CUSTOM_INLINE mempty mempty)
-                                $ inlinesToNodes opts
-                                $ walk (fixPipe . softBreakToSpace) ils
-           toCell []          = ""
-           toCell xs          = error $ "toCell encountered " ++ show xs
-       let separator = " | "
-       let starter = "| "
-       let ender   = " |"
-       let rawheaders = map toCell headers
-       let rawrows = map (map toCell) rows
-       let maximum' [] = 0
-           maximum' xs = maximum xs
-       let colwidths = map (maximum' . map T.length) $
-                        transpose (rawheaders:rawrows)
-       let toHeaderLine len AlignDefault = T.replicate len "-"
-           toHeaderLine len AlignLeft    = ":" <>
-                  T.replicate (max (len - 1) 1) "-"
-           toHeaderLine len AlignRight   =
-                  T.replicate (max (len - 1) 1) "-" <> ":"
-           toHeaderLine len AlignCenter  = ":" <>
-                  T.replicate (max (len - 2) 1) (T.pack "-") <> ":"
-       let rawheaderlines = zipWith toHeaderLine colwidths aligns
-       let headerlines = starter <> T.intercalate separator rawheaderlines <>
-                          ender
-       let padContent (align, w) t' =
-             let padding = w - T.length t'
-                 halfpadding = padding `div` 2
-             in  case align of
-                      AlignRight -> T.replicate padding " " <> t'
-                      AlignCenter -> T.replicate halfpadding " " <> t' <>
-                                     T.replicate (padding - halfpadding) " "
-                      _ -> t' <> T.replicate padding " "
-       let toRow xs = starter <> T.intercalate separator
-                      (zipWith padContent (zip aligns colwidths) xs) <>
-                      ender
-       let table' = toRow rawheaders <> "\n" <> headerlines <> "\n" <>
-                     T.intercalate "\n" (map toRow rawrows)
-       return (node (CUSTOM_BLOCK table' mempty) [] :
-               if null capt
-                  then ns
-                  else capt' : ns)
-     else do -- fall back to raw HTML
-       s <- writeHtml5String def $! Pandoc nullMeta [t]
-       return (node (HTML_BLOCK s) [] : ns)
+blockToNodes opts t@(Table _ blkCapt specs thead tbody tfoot) ns =
+  let (capt, aligns, _widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot
+  in if isEnabled Ext_pipe_tables opts && onlySimpleTableCells (headers : rows)
+        then do
+          -- We construct a table manually as a CUSTOM_BLOCK, for
+          -- two reasons:  (1) cmark-gfm currently doesn't support
+          -- rendering TABLE nodes; (2) we can align the column sides;
+          -- (3) we can render the caption as a regular paragraph.
+          let capt' = node PARAGRAPH (inlinesToNodes opts capt)
+          -- backslash | in code and raw:
+          let fixPipe (Code attr xs) =
+                Code attr (T.replace "|" "\\|" xs)
+              fixPipe (RawInline format xs) =
+                RawInline format (T.replace "|" "\\|" xs)
+              fixPipe x = x
+          let toCell [Plain ils] = T.strip
+                                   $ nodeToCommonmark [] Nothing
+                                   $ node (CUSTOM_INLINE mempty mempty)
+                                   $ inlinesToNodes opts
+                                   $ walk (fixPipe . softBreakToSpace) ils
+              toCell [Para  ils] = T.strip
+                                   $ nodeToCommonmark [] Nothing
+                                   $ node (CUSTOM_INLINE mempty mempty)
+                                   $ inlinesToNodes opts
+                                   $ walk (fixPipe . softBreakToSpace) ils
+              toCell []          = ""
+              toCell xs          = error $ "toCell encountered " ++ show xs
+          let separator = " | "
+          let starter = "| "
+          let ender   = " |"
+          let rawheaders = map toCell headers
+          let rawrows = map (map toCell) rows
+          let maximum' [] = 0
+              maximum' xs = maximum xs
+          let colwidths = map (maximum' . map T.length) $
+                           transpose (rawheaders:rawrows)
+          let toHeaderLine len AlignDefault = T.replicate len "-"
+              toHeaderLine len AlignLeft    = ":" <>
+                     T.replicate (max (len - 1) 1) "-"
+              toHeaderLine len AlignRight   =
+                     T.replicate (max (len - 1) 1) "-" <> ":"
+              toHeaderLine len AlignCenter  = ":" <>
+                     T.replicate (max (len - 2) 1) (T.pack "-") <> ":"
+          let rawheaderlines = zipWith toHeaderLine colwidths aligns
+          let headerlines = starter <> T.intercalate separator rawheaderlines <>
+                             ender
+          let padContent (align, w) t' =
+                let padding = w - T.length t'
+                    halfpadding = padding `div` 2
+                in  case align of
+                         AlignRight -> T.replicate padding " " <> t'
+                         AlignCenter -> T.replicate halfpadding " " <> t' <>
+                                        T.replicate (padding - halfpadding) " "
+                         _ -> t' <> T.replicate padding " "
+          let toRow xs = starter <> T.intercalate separator
+                         (zipWith padContent (zip aligns colwidths) xs) <>
+                         ender
+          let table' = toRow rawheaders <> "\n" <> headerlines <> "\n" <>
+                        T.intercalate "\n" (map toRow rawrows)
+          return (node (CUSTOM_BLOCK table' mempty) [] :
+                  if null capt
+                     then ns
+                     else capt' : ns)
+        else do -- fall back to raw HTML
+          s <- writeHtml5String def $! Pandoc nullMeta [t]
+          return (node (HTML_BLOCK s) [] : ns)
 blockToNodes _ Null ns = return ns
 
 inlinesToNodes :: WriterOptions -> [Inline] -> [Node]
@@ -236,6 +237,11 @@
   | writerWrapText opts == WrapNone     = (node (TEXT " ") [] :)
   | otherwise                           = (node SOFTBREAK [] :)
 inlineToNodes opts (Emph xs) = (node EMPH (inlinesToNodes opts xs) :)
+inlineToNodes opts (Underline xs)
+  | isEnabled Ext_raw_html opts =
+    ((node (HTML_INLINE (T.pack "<u>")) [] : inlinesToNodes opts xs ++
+      [node (HTML_INLINE (T.pack "</u>")) []]) ++ )
+  | otherwise = (node EMPH (inlinesToNodes opts xs) :)
 inlineToNodes opts (Strong xs) = (node STRONG (inlinesToNodes opts xs) :)
 inlineToNodes opts (Strikeout xs)
   | isEnabled Ext_strikeout opts = (node (CUSTOM_INLINE "~~" "~~") (inlinesToNodes opts xs) :)
diff --git a/src/Text/Pandoc/Writers/ConTeXt.hs b/src/Text/Pandoc/Writers/ConTeXt.hs
--- a/src/Text/Pandoc/Writers/ConTeXt.hs
+++ b/src/Text/Pandoc/Writers/ConTeXt.hs
@@ -255,7 +255,8 @@
 blockToConTeXt HorizontalRule = return $ "\\thinrule" <> blankline
 -- If this is ever executed, provide a default for the reference identifier.
 blockToConTeXt (Header level attr lst) = sectionHeader attr level lst
-blockToConTeXt (Table caption aligns widths heads rows) = do
+blockToConTeXt (Table _ blkCapt specs thead tbody tfoot) = do
+    let (caption, aligns, widths, heads, rows) = toLegacyTable blkCapt specs thead tbody tfoot
     opts <- gets stOptions
     let tabl = if isEnabled Ext_ntb opts
           then Ntb
@@ -367,6 +368,9 @@
 inlineToConTeXt (Emph lst) = do
   contents <- inlineListToConTeXt lst
   return $ braces $ "\\em " <> contents
+inlineToConTeXt (Underline lst) = do
+  contents <- inlineListToConTeXt lst
+  return $ "\\underbar" <> braces contents
 inlineToConTeXt (Strong lst) = do
   contents <- inlineListToConTeXt lst
   return $ braces $ "\\bf " <> contents
diff --git a/src/Text/Pandoc/Writers/Custom.hs b/src/Text/Pandoc/Writers/Custom.hs
--- a/src/Text/Pandoc/Writers/Custom.hs
+++ b/src/Text/Pandoc/Writers/Custom.hs
@@ -20,17 +20,14 @@
 import qualified Data.Map as M
 import qualified Data.Text as T
 import Data.Text (Text, pack)
-import Data.Typeable
 import Foreign.Lua (Lua, Pushable)
 import Text.DocLayout (render, literal)
 import Text.Pandoc.Class.PandocIO (PandocIO)
 import Text.Pandoc.Definition
-import Text.Pandoc.Lua (Global (..), LuaException (LuaException),
-                        runLua, setGlobals)
+import Text.Pandoc.Lua (Global (..), runLua, setGlobals)
 import Text.Pandoc.Lua.Util (addField, dofileWithTraceback)
 import Text.Pandoc.Options
 import Text.Pandoc.Templates (renderTemplate)
-import qualified Text.Pandoc.UTF8 as UTF8
 import Text.Pandoc.Writers.Shared
 
 import qualified Foreign.Lua as Lua
@@ -81,11 +78,6 @@
     Lua.push v
     Lua.rawset (Lua.nthFromTop 3)
 
-data PandocLuaException = PandocLuaException Text
-    deriving (Show, Typeable)
-
-instance Exception PandocLuaException
-
 -- | Convert Pandoc to custom markup.
 writeCustom :: FilePath -> WriterOptions -> Pandoc -> PandocIO Text
 writeCustom luaFile opts doc@(Pandoc meta _) = do
@@ -97,21 +89,20 @@
     stat <- dofileWithTraceback luaFile
     -- check for error in lua script (later we'll change the return type
     -- to handle this more gracefully):
-    when (stat /= Lua.OK) $
-      Lua.tostring' (-1) >>= throw . PandocLuaException . UTF8.toText
+    when (stat /= Lua.OK)
+      Lua.throwTopMessage
     rendered <- docToCustom opts doc
     context <- metaToContext opts
                (fmap (literal . pack) . blockListToCustom)
                (fmap (literal . pack) . inlineListToCustom)
                meta
     return (pack rendered, context)
-  let (body, context) = case res of
-        Left (LuaException msg) -> throw (PandocLuaException msg)
-        Right x -> x
-  return $
-    case writerTemplate opts of
-       Nothing  -> body
-       Just tpl -> render Nothing $
+  case res of
+    Left msg -> throw msg
+    Right (body, context) -> return $
+      case writerTemplate opts of
+        Nothing  -> body
+        Just tpl -> render Nothing $
                     renderTemplate tpl $ setField "body" body context
 
 docToCustom :: WriterOptions -> Pandoc -> Lua String
@@ -149,8 +140,9 @@
 blockToCustom (BlockQuote blocks) =
   Lua.callFunc "BlockQuote" (Stringify blocks)
 
-blockToCustom (Table capt aligns widths headers rows) =
-  let aligns' = map show aligns
+blockToCustom (Table _ blkCapt specs thead tbody tfoot) =
+  let (capt, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot
+      aligns' = map show aligns
       capt' = Stringify capt
       headers' = map Stringify headers
       rows' = map (map Stringify) rows
@@ -193,6 +185,8 @@
 inlineToCustom SoftBreak = Lua.callFunc "SoftBreak"
 
 inlineToCustom (Emph lst) = Lua.callFunc "Emph" (Stringify lst)
+
+inlineToCustom (Underline lst) = Lua.callFunc "Underline" (Stringify lst)
 
 inlineToCustom (Strong lst) = Lua.callFunc "Strong" (Stringify lst)
 
diff --git a/src/Text/Pandoc/Writers/Docbook.hs b/src/Text/Pandoc/Writers/Docbook.hs
--- a/src/Text/Pandoc/Writers/Docbook.hs
+++ b/src/Text/Pandoc/Writers/Docbook.hs
@@ -47,7 +47,8 @@
   let colwidth = if writerWrapText opts == WrapAuto
                     then Just $ writerColumns opts
                     else Nothing
-  return $ B.rawInline "docbook" $ render colwidth $
+  return $ B.rawInline "docbook" $
+    render colwidth $ inTags True "personname" [] $
       if T.any (== ',') name
          then -- last name first
               let (lastname, rest) = T.break (==',') name
@@ -262,7 +263,8 @@
       report $ BlockNotRendered b
       return empty
 blockToDocbook _ HorizontalRule = return empty -- not semantic
-blockToDocbook opts (Table caption aligns widths headers rows) = do
+blockToDocbook opts (Table _ blkCapt specs thead tbody tfoot) = do
+  let (caption, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot
   captionDoc <- if null caption
                    then return empty
                    else inTagsIndented "title" <$>
@@ -278,7 +280,7 @@
   body' <- (inTagsIndented "tbody" . vcat) <$>
               mapM (tableRowToDocbook opts) rows
   return $ inTagsIndented tableType $ captionDoc $$
-        inTags True "tgroup" [("cols", tshow (length headers))] (
+        inTags True "tgroup" [("cols", tshow (length aligns))] (
          coltags $$ head' $$ body')
 
 hasLineBreaks :: [Inline] -> Bool
@@ -321,6 +323,8 @@
 inlineToDocbook _ (Str str) = return $ literal $ escapeStringForXML str
 inlineToDocbook opts (Emph lst) =
   inTagsSimple "emphasis" <$> inlinesToDocbook opts lst
+inlineToDocbook opts (Underline lst) =
+  inTags False "emphasis" [("role", "underline")] <$> inlinesToDocbook opts lst
 inlineToDocbook opts (Strong lst) =
   inTags False "emphasis" [("role", "strong")] <$> inlinesToDocbook opts lst
 inlineToDocbook opts (Strikeout lst) =
diff --git a/src/Text/Pandoc/Writers/Docx.hs b/src/Text/Pandoc/Writers/Docx.hs
--- a/src/Text/Pandoc/Writers/Docx.hs
+++ b/src/Text/Pandoc/Writers/Docx.hs
@@ -23,7 +23,7 @@
 import Control.Monad.State.Strict
 import qualified Data.ByteString as B
 import qualified Data.ByteString.Lazy as BL
-import Data.Char (isSpace, ord, isLetter)
+import Data.Char (isSpace, isLetter)
 import Data.List (intercalate, isPrefixOf, isSuffixOf)
 import Data.String (fromString)
 import qualified Data.Map as M
@@ -34,7 +34,7 @@
 import Data.Time.Clock.POSIX
 import Data.Digest.Pure.SHA (sha1, showDigest)
 import Skylighting
-import System.Random (randomR, StdGen, mkStdGen)
+import System.Random (randomRs, mkStdGen)
 import Text.Pandoc.BCP47 (getLang, renderLang)
 import Text.Pandoc.Class.PandocMonad (PandocMonad, report, toLang)
 import qualified Text.Pandoc.Class.PandocMonad as P
@@ -89,8 +89,7 @@
                         }
 
 instance Semigroup EnvProps where
-  EnvProps Nothing es <> EnvProps s es' = EnvProps s (es ++ es')
-  EnvProps s       es <> EnvProps _ es' = EnvProps s (es ++ es')
+  EnvProps s es <> EnvProps s' es' = EnvProps (s <|> s') (es ++ es')
 
 instance Monoid EnvProps where
   mempty = EnvProps Nothing []
@@ -172,10 +171,8 @@
   | otherwise = renumIdMap n es
 
 replaceAttr :: (QName -> Bool) -> String -> [XML.Attr] -> [XML.Attr]
-replaceAttr _ _ [] = []
-replaceAttr f val (a:as) | f (attrKey a) =
-                             XML.Attr (attrKey a) val : replaceAttr f val as
-                         | otherwise = a : replaceAttr f val as
+replaceAttr f val = map $
+    \a -> if f (attrKey a) then XML.Attr (attrKey a) val else a
 
 renumId :: (QName -> Bool) -> M.Map String String -> Element -> Element
 renumId f renumMap e
@@ -202,14 +199,12 @@
 
 -- | See XML reference
 isValidChar :: Char -> Bool
-isValidChar (ord -> c)
-  | c == 0x9                      = True
-  | c == 0xA                      = True
-  | c == 0xD                      = True
-  | 0x20 <= c &&  c <= 0xD7FF     = True
-  | 0xE000 <= c && c <= 0xFFFD    = True
-  | 0x10000 <= c && c <= 0x10FFFF = True
-  | otherwise                     = False
+isValidChar '\t' = True
+isValidChar '\n' = True
+isValidChar '\r' = True
+isValidChar '\xFFFE' = False
+isValidChar '\xFFFF' = False
+isValidChar c = (' ' <= c && c <= '\xD7FF') || ('\xE000' <= c)
 
 writeDocx :: (PandocMonad m)
           => WriterOptions  -- ^ Writer options
@@ -219,12 +214,11 @@
   let doc' = walk fixDisplayMath doc
   username <- P.lookupEnv "USERNAME"
   utctime <- P.getCurrentTime
-  distArchive <- toArchive . BL.fromStrict <$> do
-    oldUserDataDir <- P.getUserDataDir
-    P.setUserDataDir Nothing
-    res <- P.readDefaultDataFile "reference.docx"
-    P.setUserDataDir oldUserDataDir
-    return res
+  oldUserDataDir <- P.getUserDataDir
+  P.setUserDataDir Nothing
+  res <- P.readDefaultDataFile "reference.docx"
+  P.setUserDataDir oldUserDataDir
+  let distArchive = toArchive $ BL.fromStrict res
   refArchive <- case writerReferenceDoc opts of
                      Just f  -> toArchive <$> P.readFileLazy f
                      Nothing -> toArchive . BL.fromStrict <$>
@@ -236,26 +230,25 @@
 
   -- Gets the template size
   let mbpgsz = mbsectpr >>= filterElementName (wname (=="pgSz"))
-  let mbAttrSzWidth = (elAttribs <$> mbpgsz) >>= lookupAttrTextBy ((=="w") . qName)
+  let mbAttrSzWidth = mbpgsz >>= lookupAttrTextBy ((=="w") . qName) . elAttribs
 
   let mbpgmar = mbsectpr >>= filterElementName (wname (=="pgMar"))
-  let mbAttrMarLeft = (elAttribs <$> mbpgmar) >>= lookupAttrTextBy ((=="left") . qName)
-  let mbAttrMarRight = (elAttribs <$> mbpgmar) >>= lookupAttrTextBy ((=="right") . qName)
+  let mbAttrMarLeft = mbpgmar >>= lookupAttrTextBy ((=="left") . qName) . elAttribs
+  let mbAttrMarRight = mbpgmar >>= lookupAttrTextBy ((=="right") . qName) . elAttribs
 
   -- Get the available area (converting the size and the margins to int and
   -- doing the difference
-  let pgContentWidth = mbAttrSzWidth >>= safeRead
-                       >>= subtrct mbAttrMarRight
-                       >>= subtrct mbAttrMarLeft
-        where
-          subtrct mbStr x = mbStr >>= safeRead >>= (\y -> Just $ x - y)
+  let pgContentWidth = do
+                         w <- mbAttrSzWidth >>= safeRead
+                         r <- mbAttrMarRight >>= safeRead
+                         l <- mbAttrMarLeft >>= safeRead
+                         pure $ w - r - l
 
   -- styles
   mblang <- toLang $ getLang opts meta
   let addLang :: Element -> Element
-      addLang e = case mblang >>= \l ->
-                         (return . XMLC.toTree . go (T.unpack $ renderLang l)
-                                 . XMLC.fromElement) e of
+      addLang e = case (\l -> XMLC.toTree . go (T.unpack $ renderLang l) $
+                                 XMLC.fromElement e) <$> mblang of
                     Just (Elem e') -> e'
                     _              -> e -- return original
         where go :: String -> Cursor -> Cursor
@@ -482,9 +475,7 @@
 
   let newstyles = map newParaPropToOpenXml newDynamicParaProps ++
                   map newTextPropToOpenXml newDynamicTextProps ++
-                  (case writerHighlightStyle opts of
-                        Nothing  -> []
-                        Just sty -> styleToOpenXml styleMaps sty)
+                  maybe [] (styleToOpenXml styleMaps) (writerHighlightStyle opts)
   let styledoc' = styledoc{ elContent = elContent styledoc ++
                                            map Elem newstyles }
   let styleEntry = toEntry stylepath epochtime $ renderXml styledoc'
@@ -492,7 +483,7 @@
   -- construct word/numbering.xml
   let numpath = "word/numbering.xml"
   numbering <- parseXml refArchive distArchive numpath
-  newNumElts <- mkNumbering (stLists st)
+  let newNumElts = mkNumbering (stLists st)
   let pandocAdded e =
        case findAttrTextBy ((== "abstractNumId") . qName) e >>= safeRead of
          Just numid -> numid >= (990 :: Int)
@@ -597,9 +588,8 @@
   themeEntry <- entryFromArchive refArchive "word/theme/theme1.xml"
   fontTableEntry <- entryFromArchive refArchive "word/fontTable.xml"
   webSettingsEntry <- entryFromArchive refArchive "word/webSettings.xml"
-  headerFooterEntries <- mapM (entryFromArchive refArchive) $
-                     mapMaybe (fmap ("word/" ++) . extractTarget)
-                     (headers ++ footers)
+  headerFooterEntries <- mapM (entryFromArchive refArchive . ("word/" ++)) $
+                     mapMaybe extractTarget (headers ++ footers)
   let miscRelEntries = [ e | e <- zEntries refArchive
                        , "word/_rels/" `isPrefixOf` eRelativePath e
                        , ".xml.rels" `isSuffixOf` eRelativePath e
@@ -700,10 +690,11 @@
 baseListId :: Int
 baseListId = 1000
 
-mkNumbering :: (PandocMonad m) => [ListMarker] -> m [Element]
-mkNumbering lists = do
-  elts <- evalStateT (mapM mkAbstractNum (ordNub lists)) (mkStdGen 1848)
-  return $ elts ++ zipWith mkNum lists [baseListId..(baseListId + length lists - 1)]
+mkNumbering :: [ListMarker] -> [Element]
+mkNumbering lists =
+  elts ++ zipWith mkNum lists [baseListId..(baseListId + length lists - 1)]
+    where elts = zipWith mkAbstractNum (ordNub lists) $
+                     randomRs (0x10000000, 0xFFFFFFFF) $ mkStdGen 1848
 
 maxListLevel :: Int
 maxListLevel = 8
@@ -720,12 +711,9 @@
               $ mknode "w:startOverride" [("w:val",show start)] ())
                 [0..maxListLevel]
 
-mkAbstractNum :: (PandocMonad m) => ListMarker -> StateT StdGen m Element
-mkAbstractNum marker = do
-  gen <- get
-  let (nsid, gen') = randomR (0x10000000 :: Integer, 0xFFFFFFFF :: Integer) gen
-  put gen'
-  return $ mknode "w:abstractNum" [("w:abstractNumId",listMarkerToId marker)]
+mkAbstractNum :: ListMarker -> Integer -> Element
+mkAbstractNum marker nsid =
+  mknode "w:abstractNum" [("w:abstractNumId",listMarkerToId marker)]
     $ mknode "w:nsid" [("w:val", printf "%8x" nsid)] ()
     : mknode "w:multiLevelType" [("w:val","multilevel")] ()
     : map (mkLvl marker)
@@ -951,9 +939,9 @@
                                  [x] -> isDisplayMath x
                                  _   -> False
       paraProps <- getParaProps displayMathPara
-      bodyTextStyle <- if isFirstPara
-                       then pStyleM "First Paragraph"
-                       else pStyleM "Body Text"
+      bodyTextStyle <- pStyleM $ if isFirstPara
+                       then "First Paragraph"
+                       else "Body Text"
       let paraProps' = case paraProps of
             []               -> [mknode "w:pPr" [] [bodyTextStyle]]
             ps               -> ps
@@ -982,7 +970,8 @@
     $ mknode "v:rect" [("style","width:0;height:1.5pt"),
                        ("o:hralign","center"),
                        ("o:hrstd","t"),("o:hr","t")] () ]
-blockToOpenXML' opts (Table caption aligns widths headers rows) = do
+blockToOpenXML' opts (Table _ blkCapt specs thead tbody tfoot) = do
+  let (caption, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot
   setFirstPara
   modify $ \s -> s { stInTable = True }
   let captionStr = stringify caption
@@ -995,9 +984,9 @@
   -- Not in the spec but in Word 2007, 2010. See #4953.
   let cellToOpenXML (al, cell) = do
         es <- withParaProp (alignmentFor al) $ blocksToOpenXML opts cell
-        if any (\e -> qName (elName e) == "p") es
-           then return es
-           else return $ es ++ [mknode "w:p" [] ()]
+        return $ if any (\e -> qName (elName e) == "p") es
+           then es
+           else es ++ [mknode "w:p" [] ()]
   headers' <- mapM cellToOpenXML $ zip aligns headers
   rows' <- mapM (mapM cellToOpenXML . zip aligns) rows
   let borderProps = mknode "w:tcPr" []
@@ -1005,11 +994,11 @@
                       $ mknode "w:bottom" [("w:val","single")] ()
                     , mknode "w:vAlign" [("w:val","bottom")] () ]
   compactStyle <- pStyleM "Compact"
-  let emptyCell = [mknode "w:p" [] [mknode "w:pPr" [] [compactStyle]]]
+  let emptyCell' = [mknode "w:p" [] [mknode "w:pPr" [] [compactStyle]]]
   let mkcell border contents = mknode "w:tc" []
                             $ [ borderProps | border ] ++
                             if null contents
-                               then emptyCell
+                               then emptyCell'
                                else contents
   let mkrow border cells = mknode "w:tr" [] $
                         [mknode "w:trPr" [] [
@@ -1020,7 +1009,7 @@
   let rowwidth = fullrow * sum widths
   let mkgridcol w = mknode "w:gridCol"
                        [("w:w", show (floor (textwidth * w) :: Integer))] ()
-  let hasHeader = not (all null headers)
+  let hasHeader = any (not . null) headers
   modify $ \s -> s { stInTable = False }
   return $
     caption' ++
@@ -1028,7 +1017,12 @@
       ( mknode "w:tblPr" []
         (   mknode "w:tblStyle" [("w:val","Table")] () :
             mknode "w:tblW" [("w:type", "pct"), ("w:w", show rowwidth)] () :
-            mknode "w:tblLook" [("w:firstRow",if hasHeader then "1" else "0") ] () :
+            mknode "w:tblLook" [("w:firstRow",if hasHeader then "1" else "0")
+                               ,("w:lastRow","0")
+                               ,("w:firstColumn","0")
+                               ,("w:lastColumn","0")
+                               ,("w:noHBand","0")
+                               ,("w:noVBand","0")] () :
           [ mknode "w:tblCaption" [("w:val", T.unpack captionStr)] ()
           | not (null caption) ] )
       : mknode "w:tblGrid" []
@@ -1111,7 +1105,9 @@
   where ep = if isStyle d then EnvProps (Just d) [] else EnvProps Nothing [d]
 
 withTextPropM :: PandocMonad m => WS m Element -> WS m a -> WS m a
-withTextPropM = (. flip withTextProp) . (>>=)
+withTextPropM md p = do
+  d <- md
+  withTextProp d p
 
 getParaProps :: PandocMonad m => Bool -> WS m [Element]
 getParaProps displayMathPara = do
@@ -1131,7 +1127,9 @@
   where ep = if isStyle d then EnvProps (Just d) [] else EnvProps Nothing [d]
 
 withParaPropM :: PandocMonad m => WS m Element -> WS m a -> WS m a
-withParaPropM = (. flip withParaProp) . (>>=)
+withParaPropM md p = do
+  d <- md
+  withParaProp d p
 
 formattedString :: PandocMonad m => T.Text -> WS m [Element]
 formattedString str =
@@ -1165,9 +1163,6 @@
   formattedString str
 inlineToOpenXML' opts Space = inlineToOpenXML opts (Str " ")
 inlineToOpenXML' opts SoftBreak = inlineToOpenXML opts (Str " ")
-inlineToOpenXML' opts (Span (_,["underline"],_) ils) =
-  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.
@@ -1241,6 +1236,9 @@
   withTextProp (mknode "w:b" [] ()) $ inlinesToOpenXML opts lst
 inlineToOpenXML' opts (Emph lst) =
   withTextProp (mknode "w:i" [] ()) $ inlinesToOpenXML opts lst
+inlineToOpenXML' opts (Underline lst) =
+  withTextProp (mknode "w:u" [("w:val","single")] ()) $
+    inlinesToOpenXML opts lst
 inlineToOpenXML' opts (Subscript lst) =
   withTextProp (mknode "w:vertAlign" [("w:val","subscript")] ())
   $ inlinesToOpenXML opts lst
diff --git a/src/Text/Pandoc/Writers/DokuWiki.hs b/src/Text/Pandoc/Writers/DokuWiki.hs
--- a/src/Text/Pandoc/Writers/DokuWiki.hs
+++ b/src/Text/Pandoc/Writers/DokuWiki.hs
@@ -38,7 +38,7 @@
                            removeFormatting, trimr, tshow)
 import Text.Pandoc.Templates (renderTemplate)
 import Text.DocLayout (render, literal)
-import Text.Pandoc.Writers.Shared (defField, metaToContext)
+import Text.Pandoc.Writers.Shared (defField, metaToContext, toLegacyTable)
 
 data WriterState = WriterState {
   }
@@ -166,7 +166,8 @@
      then return $ T.unlines $ map ("> " <>) $ T.lines contents
      else return $ "<HTML><blockquote>\n" <> contents <> "</blockquote></HTML>"
 
-blockToDokuWiki opts (Table capt aligns _ headers rows) = do
+blockToDokuWiki opts (Table _ blkCapt specs thead tbody tfoot) = do
+  let (capt, aligns, _, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot
   captionDoc <- if null capt
                    then return ""
                    else do
@@ -400,6 +401,10 @@
 inlineToDokuWiki opts (Emph lst) = do
   contents <- inlineListToDokuWiki opts lst
   return $ "//" <> contents <> "//"
+
+inlineToDokuWiki opts (Underline lst) = do
+  contents <- inlineListToDokuWiki opts lst
+  return $ "__" <> contents <> "__"
 
 inlineToDokuWiki opts (Strong lst) = do
   contents <- inlineListToDokuWiki opts lst
diff --git a/src/Text/Pandoc/Writers/EPUB.hs b/src/Text/Pandoc/Writers/EPUB.hs
--- a/src/Text/Pandoc/Writers/EPUB.hs
+++ b/src/Text/Pandoc/Writers/EPUB.hs
@@ -50,7 +50,7 @@
 import Text.Pandoc.Shared (makeSections, normalizeDate, renderTags',
                            safeRead, stringify, trim, uniqueIdent, tshow)
 import qualified Text.Pandoc.UTF8 as UTF8
-import Text.Pandoc.UUID (getUUID)
+import Text.Pandoc.UUID (getRandomUUID)
 import Text.Pandoc.Walk (query, walk, walkM)
 import Text.Pandoc.Writers.HTML (writeHtmlStringForEPUB)
 import Text.Printf (printf)
@@ -163,8 +163,8 @@
   let addIdentifier m =
        if null (epubIdentifier m)
           then do
-            randomId <- (show . getUUID) <$> lift P.newStdGen
-            return $ m{ epubIdentifier = [Identifier randomId Nothing] }
+            randomId <- getRandomUUID
+            return $ m{ epubIdentifier = [Identifier (show randomId) Nothing] }
           else return m
   let addLanguage m =
        if null (epubLanguage m)
diff --git a/src/Text/Pandoc/Writers/FB2.hs b/src/Text/Pandoc/Writers/FB2.hs
--- a/src/Text/Pandoc/Writers/FB2.hs
+++ b/src/Text/Pandoc/Writers/FB2.hs
@@ -40,8 +40,8 @@
 import Text.Pandoc.Logging
 import Text.Pandoc.Options (HTMLMathMethod (..), WriterOptions (..), def)
 import Text.Pandoc.Shared (capitalize, isURI, orderedListMarkers,
-                           makeSections, tshow)
-import Text.Pandoc.Writers.Shared (lookupMetaString)
+                           makeSections, tshow, stringify)
+import Text.Pandoc.Writers.Shared (lookupMetaString, toLegacyTable)
 
 -- | Data to be written at the end of the document:
 -- (foot)notes, URLs, references, images.
@@ -116,7 +116,7 @@
         im <- insertImage InlineImage img
         return [el "coverpage" im]
   coverpage <- case lookupMeta "cover-image" meta' of
-                    Just (MetaInlines [Str s]) -> coverimage s
+                    Just (MetaInlines ils) -> coverimage (stringify ils)
                     Just (MetaString s) -> coverimage s
                     _       -> return []
   return $ el "description"
@@ -334,17 +334,18 @@
   report $ BlockNotRendered h
   return []
 blockToXml HorizontalRule = return [ el "empty-line" () ]
-blockToXml (Table caption aligns _ headers rows) = do
-    hd <- mkrow "th" headers aligns
+blockToXml (Table _ blkCapt specs thead tbody tfoot) = do
+    let (caption, aligns, _, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot
+    hd <- if null headers then pure [] else (:[]) <$> mkrow "th" headers aligns
     bd <- mapM (\r -> mkrow "td" r aligns) rows
     c <- el "emphasis" <$> cMapM toXml caption
-    return [el "table" (hd : bd), el "p" c]
+    return [el "table" (hd <> bd), el "p" c]
     where
-      mkrow :: PandocMonad m => String -> [TableCell] -> [Alignment] -> FBM m Content
+      mkrow :: PandocMonad m => String -> [[Block]] -> [Alignment] -> FBM m Content
       mkrow tag cells aligns' =
         el "tr" <$> mapM (mkcell tag) (zip cells aligns')
       --
-      mkcell :: PandocMonad m => String -> (TableCell, Alignment) -> FBM m Content
+      mkcell :: PandocMonad m => String -> ([Block], Alignment) -> FBM m Content
       mkcell tag (cell, align) = do
         cblocks <- cMapM blockToXml cell
         return $ el tag ([align_attr align], cblocks)
@@ -405,6 +406,7 @@
 toXml (Str s) = return [txt s]
 toXml (Span _ ils) = cMapM toXml ils
 toXml (Emph ss) = list `liftM` wrap "emphasis" ss
+toXml (Underline ss) = list `liftM` wrap "underline" ss
 toXml (Strong ss) = list `liftM` wrap "strong" ss
 toXml (Strikeout ss) = list `liftM` wrap "strikethrough" ss
 toXml (Superscript ss) = list `liftM` wrap "sup" ss
@@ -528,6 +530,7 @@
 plain :: Inline -> String
 plain (Str s)               = T.unpack s
 plain (Emph ss)             = cMap plain ss
+plain (Underline ss)        = cMap plain ss
 plain (Span _ ss)           = cMap plain ss
 plain (Strong ss)           = cMap plain ss
 plain (Strikeout ss)        = cMap plain ss
diff --git a/src/Text/Pandoc/Writers/HTML.hs b/src/Text/Pandoc/Writers/HTML.hs
--- a/src/Text/Pandoc/Writers/HTML.hs
+++ b/src/Text/Pandoc/Writers/HTML.hs
@@ -281,12 +281,14 @@
           H.script $ text $ T.unlines [
               "document.addEventListener(\"DOMContentLoaded\", function () {"
             , " var mathElements = document.getElementsByClassName(\"math\");"
+            , " var macros = [];"
             , " for (var i = 0; i < mathElements.length; i++) {"
             , "  var texText = mathElements[i].firstChild;"
             , "  if (mathElements[i].tagName == \"SPAN\") {"
             , "   katex.render(texText.data, mathElements[i], {"
             , "    displayMode: mathElements[i].classList.contains('display'),"
             , "    throwOnError: false,"
+            , "    macros: macros,"
             , "    fleqn: " <> katexFlushLeft
             , "   });"
             , "}}});"
@@ -318,6 +320,10 @@
                                      defField "mathjaxurl"
                                        (T.takeWhile (/='?') u)
                         _         -> defField "mathjax" False) $
+                  (case writerHTMLMathMethod opts of
+                        PlainMath -> defField "displaymath-css" True
+                        WebTeX _  -> defField "displaymath-css" True
+                        _         -> id) $
                   defField "quotes" (stQuotes st) $
                   -- for backwards compatibility we populate toc
                   -- with the contents of the toc, rather than a
@@ -334,7 +340,7 @@
                   defField "slidy-url"
                     ("https://www.w3.org/Talks/Tools/Slidy2" :: Text) $
                   defField "slideous-url" ("slideous" :: Text) $
-                  defField "revealjs-url" ("reveal.js" :: Text) $
+                  defField "revealjs-url" ("https://unpkg.com/reveal.js@^4/" :: Text) $
                   defField "s5-url" ("s5/default" :: Text) $
                   defField "html5" (stHtml5 st)
                   metadata
@@ -885,7 +891,8 @@
                      return $ mconcat $ nl opts : term' : nl opts :
                                         intersperse (nl opts) defs') lst
   defList opts contents
-blockToHtml opts (Table capt aligns widths headers rows') = do
+blockToHtml opts (Table attr blkCapt specs thead tbody tfoot) = do
+  let (capt, aligns, widths, headers, rows') = toLegacyTable blkCapt specs thead tbody tfoot
   captionDoc <- if null capt
                    then return mempty
                    else do
@@ -912,15 +919,19 @@
                 return $ H.thead (nl opts >> contents) >> nl opts
   body' <- liftM (\x -> H.tbody (nl opts >> mconcat x)) $
                zipWithM (tableRowToHtml opts aligns) [1..] rows'
-  let tbl = H.table $
-              nl opts >> captionDoc >> coltags >> head' >> body' >> nl opts
-  let totalWidth = sum widths
+  let (ident,classes,kvs) = attr
   -- When widths of columns are < 100%, we need to set width for the whole
-  -- table, or some browsers give us skinny columns with lots of space between:
-  return $ if totalWidth == 0 || totalWidth == 1
-              then tbl
-              else tbl ! A.style (toValue $ "width:" <>
-                              show (round (totalWidth * 100) :: Int) <> "%;")
+  -- table, or some browsers give us skinny columns with lots of space
+  -- between:
+  let totalWidth = sum widths
+  let attr' = case lookup "style" kvs of
+                Nothing | totalWidth < 1 && totalWidth > 0
+                  -> (ident,classes, ("style","width:" <>
+                         T.pack (show (round (totalWidth * 100) :: Int))
+                         <> "%;"):kvs)
+                _ -> attr
+  addAttrs opts attr' $ H.table $
+    nl opts >> captionDoc >> coltags >> head' >> body' >> nl opts
 
 tableRowToHtml :: PandocMonad m
                => WriterOptions
@@ -1044,6 +1055,7 @@
                                          ]
 
     (Emph lst)       -> H.em <$> inlineListToHtml opts lst
+    (Underline lst)  -> H.u <$> inlineListToHtml opts lst
     (Strong lst)     -> H.strong <$> inlineListToHtml opts lst
     (Code attr@(ids,cs,kvs) str)
                      -> case hlCode of
@@ -1102,14 +1114,11 @@
               let s = case t of
                            InlineMath  -> "\\textstyle "
                            DisplayMath -> "\\displaystyle "
-              let m = imtag ! A.style "vertical-align:middle"
-                            ! A.src (toValue $ url <> T.pack (urlEncode (T.unpack $ s <> str)))
-                            ! A.alt (toValue str)
-                            ! A.title (toValue str)
-              let brtag = if html5 then H5.br else H.br
-              return $ case t of
-                        InlineMath  -> m
-                        DisplayMath -> brtag >> m >> brtag
+              return $ imtag ! A.style "vertical-align:middle"
+                             ! A.src (toValue $ url <> T.pack (urlEncode (T.unpack $ s <> str)))
+                             ! A.alt (toValue str)
+                             ! A.title (toValue str)
+                             ! A.class_ mathClass
            GladTeX ->
               return $
                 customParent (textTag "eq") !
@@ -1136,11 +1145,7 @@
                 DisplayMath -> str
            PlainMath -> do
               x <- lift (texMathToInlines t str) >>= inlineListToHtml opts
-              let m = H.span ! A.class_ mathClass $ x
-              let brtag = if html5 then H5.br else H.br
-              return  $ case t of
-                         InlineMath  -> m
-                         DisplayMath -> brtag >> m >> brtag
+              return $ H.span ! A.class_ mathClass $ x
     (RawInline f str) -> do
       ishtml <- isRawHtml f
       if ishtml
diff --git a/src/Text/Pandoc/Writers/Haddock.hs b/src/Text/Pandoc/Writers/Haddock.hs
--- a/src/Text/Pandoc/Writers/Haddock.hs
+++ b/src/Text/Pandoc/Writers/Haddock.hs
@@ -115,7 +115,8 @@
 -- Nothing in haddock corresponds to block quotes:
 blockToHaddock opts (BlockQuote blocks) =
   blockListToHaddock opts blocks
-blockToHaddock opts (Table caption aligns widths headers rows) = do
+blockToHaddock opts (Table _ blkCapt specs thead tbody tfoot) = do
+  let (caption, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot
   caption' <- inlineListToHaddock opts caption
   let caption'' = if null caption
                      then empty
@@ -123,7 +124,7 @@
   tbl <- gridTable opts blockListToHaddock
               (all null headers) (map (const AlignDefault) aligns)
                 widths headers rows
-  return $ prefixed "> " (tbl $$ blankline $$ caption'') $$ blankline
+  return $ (tbl $$ blankline $$ caption'') $$ blankline
 blockToHaddock opts (BulletList items) = do
   contents <- mapM (bulletListItemToHaddock opts) items
   return $ (if isTightList items then vcat else vsep) contents <> blankline
@@ -208,6 +209,9 @@
 inlineToHaddock opts (Emph lst) = do
   contents <- inlineListToHaddock opts lst
   return $ "/" <> contents <> "/"
+-- Underline is not supported, treat the same as Emph
+inlineToHaddock opts (Underline lst) =
+  inlineToHaddock opts (Emph lst)
 inlineToHaddock opts (Strong lst) = do
   contents <- inlineListToHaddock opts lst
   return $ "__" <> contents <> "__"
diff --git a/src/Text/Pandoc/Writers/ICML.hs b/src/Text/Pandoc/Writers/ICML.hs
--- a/src/Text/Pandoc/Writers/ICML.hs
+++ b/src/Text/Pandoc/Writers/ICML.hs
@@ -60,6 +60,7 @@
 
 -- inline names (appear in InDesign's character styles pane)
 emphName        :: Text
+underlineName   :: Text
 strongName      :: Text
 strikeoutName   :: Text
 superscriptName :: Text
@@ -68,6 +69,7 @@
 codeName        :: Text
 linkName        :: Text
 emphName        = "Italic"
+underlineName   = "Underline"
 strongName      = "Bold"
 strikeoutName   = "Strikeout"
 superscriptName = "Superscript"
@@ -321,8 +323,9 @@
                    else ""
   in parStyle opts stl lst
 blockToICML _ _ HorizontalRule = return empty -- we could insert a page break instead
-blockToICML opts style (Table caption aligns widths headers rows) =
-  let style' = tableName : style
+blockToICML opts style (Table _ blkCapt specs thead tbody tfoot) =
+  let (caption, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot
+      style' = tableName : style
       noHeader  = all null headers
       nrHeaders = if noHeader
                      then "0"
@@ -426,6 +429,7 @@
 inlineToICML :: PandocMonad m => WriterOptions -> Style -> Inline -> WS m (Doc Text)
 inlineToICML _    style (Str str) = charStyle style $ literal $ escapeStringForXML str
 inlineToICML opts style (Emph lst) = inlinesToICML opts (emphName:style) lst
+inlineToICML opts style (Underline lst) = inlinesToICML opts (underlineName:style) lst
 inlineToICML opts style (Strong lst) = inlinesToICML opts (strongName:style) lst
 inlineToICML opts style (Strikeout lst) = inlinesToICML opts (strikeoutName:style) lst
 inlineToICML opts style (Superscript lst) = inlinesToICML opts (superscriptName:style) lst
diff --git a/src/Text/Pandoc/Writers/Ipynb.hs b/src/Text/Pandoc/Writers/Ipynb.hs
--- a/src/Text/Pandoc/Writers/Ipynb.hs
+++ b/src/Text/Pandoc/Writers/Ipynb.hs
@@ -97,7 +97,7 @@
   return $ Image attr lab ("attachment:" <> src, tit)
 addAttachment x = return x
 
-extractCells :: PandocMonad m => WriterOptions -> [Block] -> m [Cell a]
+extractCells :: PandocMonad m => WriterOptions -> [Block] -> m [Ipynb.Cell a]
 extractCells _ [] = return []
 extractCells opts (Div (_id,classes,kvs) xs : bs)
   | "cell" `elem` classes
@@ -106,7 +106,7 @@
       (newdoc, attachments) <-
         runStateT (walkM addAttachment (Pandoc nullMeta xs)) mempty
       source <- writeMarkdown opts{ writerTemplate = Nothing } newdoc
-      (Cell{
+      (Ipynb.Cell{
           cellType = Markdown
         , cellSource = Source $ breakLines $ T.stripEnd source
         , cellMetadata = meta
@@ -123,7 +123,7 @@
       let meta = pairsToJSONMeta kvs
       outputs <- catMaybes <$> mapM blockToOutput rest
       let exeCount = lookup "execution_count" kvs >>= safeRead
-      (Cell{
+      (Ipynb.Cell{
           cellType = Ipynb.Code {
                 codeExecutionCount = exeCount
               , codeOutputs = outputs
@@ -143,7 +143,7 @@
                   "markdown" -> "text/markdown"
                   "rst"      -> "text/x-rst"
                   _          -> f
-          (Cell{
+          (Ipynb.Cell{
               cellType = Raw
             , cellSource = Source $ breakLines raw
             , cellMetadata = if format' == "ipynb" -- means no format given
@@ -156,7 +156,7 @@
   | "code" `elem` classes = do
       let meta = pairsToJSONMeta kvs
       let exeCount = lookup "execution_count" kvs >>= safeRead
-      (Cell{
+      (Ipynb.Cell{
           cellType = Ipynb.Code {
                 codeExecutionCount = exeCount
               , codeOutputs = []
diff --git a/src/Text/Pandoc/Writers/JATS.hs b/src/Text/Pandoc/Writers/JATS.hs
--- a/src/Text/Pandoc/Writers/JATS.hs
+++ b/src/Text/Pandoc/Writers/JATS.hs
@@ -356,21 +356,25 @@
       report $ BlockNotRendered b
       return empty
 blockToJATS _ HorizontalRule = return empty -- not semantic
-blockToJATS opts (Table [] aligns widths headers rows) = do
-  let percent w    = tshow (truncate (100*w) :: Integer) <> "*"
-  let coltags = vcat $ zipWith (\w al -> selfClosingTag "col"
-                       ([("width", percent w) | w > 0] ++
-                        [("align", alignmentToText al)])) widths aligns
-  thead <- if all null headers
-              then return empty
-              else inTagsIndented "thead" <$> tableRowToJATS opts True headers
-  tbody <- (inTagsIndented "tbody" . vcat) <$>
-                mapM (tableRowToJATS opts False) rows
-  return $ inTags True "table" [] $ coltags $$ thead $$ tbody
-blockToJATS opts (Table caption aligns widths headers rows) = do
-  captionDoc <- inTagsIndented "caption" <$> blockToJATS opts (Para caption)
-  tbl <- blockToJATS opts (Table [] aligns widths headers rows)
-  return $ inTags True "table-wrap" [] $ captionDoc $$ tbl
+blockToJATS opts (Table _ blkCapt specs th tb tf) =
+  case toLegacyTable blkCapt specs th tb tf of
+    ([], aligns, widths, headers, rows) -> captionlessTable aligns widths headers rows
+    (caption, aligns, widths, headers, rows) -> do
+      captionDoc <- inTagsIndented "caption" <$> blockToJATS opts (Para caption)
+      tbl <- captionlessTable aligns widths headers rows
+      return $ inTags True "table-wrap" [] $ captionDoc $$ tbl
+  where
+    captionlessTable aligns widths headers rows = do
+      let percent w = tshow (truncate (100*w) :: Integer) <> "*"
+      let coltags = vcat $ zipWith (\w al -> selfClosingTag "col"
+                           ([("width", percent w) | w > 0] ++
+                            [("align", alignmentToText al)])) widths aligns
+      thead <- if all null headers
+                  then return empty
+                  else inTagsIndented "thead" <$> tableRowToJATS opts True headers
+      tbody <- (inTagsIndented "tbody" . vcat) <$>
+                    mapM (tableRowToJATS opts False) rows
+      return $ inTags True "table" [] $ coltags $$ thead $$ tbody
 
 alignmentToText :: Alignment -> Text
 alignmentToText alignment = case alignment of
@@ -420,6 +424,8 @@
 inlineToJATS _ (Str str) = return $ text $ T.unpack $ escapeStringForXML str
 inlineToJATS opts (Emph lst) =
   inTagsSimple "italic" <$> inlinesToJATS opts lst
+inlineToJATS opts (Underline lst) =
+  inTagsSimple "underline" <$> inlinesToJATS opts lst
 inlineToJATS opts (Strong lst) =
   inTagsSimple "bold" <$> inlinesToJATS opts lst
 inlineToJATS opts (Strikeout lst) =
diff --git a/src/Text/Pandoc/Writers/Jira.hs b/src/Text/Pandoc/Writers/Jira.hs
--- a/src/Text/Pandoc/Writers/Jira.hs
+++ b/src/Text/Pandoc/Writers/Jira.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PatternGuards #-}
 {- |
    Module      : Text.Pandoc.Writers.Jira
    Copyright   : © 2010-2020 Albert Krewinkel, John MacFarlane
@@ -25,10 +26,10 @@
 import Text.Pandoc.Definition
 import Text.Pandoc.Options (WriterOptions (writerTemplate, writerWrapText),
                             WrapOption (..))
-import Text.Pandoc.Shared (linesToPara)
+import Text.Pandoc.Shared (linesToPara, stringify)
 import Text.Pandoc.Templates (renderTemplate)
 import Text.Pandoc.Writers.Math (texMathToInlines)
-import Text.Pandoc.Writers.Shared (defField, metaToContext)
+import Text.Pandoc.Writers.Shared (defField, metaToContext, toLegacyTable)
 import Text.DocLayout (literal, render)
 import qualified Data.Text as T
 import qualified Text.Jira.Markup as Jira
@@ -97,7 +98,8 @@
         Plain xs             -> singleton . Jira.Para <$> toJiraInlines xs
         RawBlock fmt cs      -> rawBlockToJira fmt cs
         Null                 -> return mempty
-        Table _ _ _ hd body  -> singleton <$> do
+        Table _ blkCapt specs thead tbody tfoot -> singleton <$> do
+          let (_, _, _, hd, body) = toLegacyTable blkCapt specs thead tbody tfoot
           headerRow <- if all null hd
                        then pure Nothing
                        else Just <$> toRow Jira.HeaderCell hd
@@ -111,7 +113,7 @@
 
 toRow :: PandocMonad m
       => ([Jira.Block] -> Jira.Cell)
-      -> [TableCell]
+      -> [[Block]]
       -> JiraConverter m Jira.Row
 toRow mkCell cells = Jira.Row <$>
   mapM (fmap mkCell . toJiraBlocks) cells
@@ -191,10 +193,10 @@
         Code _ cs          -> return . singleton $
                               Jira.Monospaced (escapeSpecialChars cs)
         Emph xs            -> styled Jira.Emphasis xs
-        Image _ _ (src, _) -> pure . singleton $ Jira.Image [] (Jira.URL src)
+        Underline xs       -> styled Jira.Insert xs
+        Image attr _ tgt   -> imageToJira attr (fst tgt) (snd tgt)
         LineBreak          -> pure . singleton $ Jira.Linebreak
-        Link _ xs (tgt, _) -> singleton . flip Jira.Link (Jira.URL tgt)
-                              <$> toJiraInlines xs
+        Link attr xs tgt   -> toJiraLink attr tgt xs
         Math mtype cs      -> mathToJira mtype cs
         Note bs            -> registerNotes bs
         Quoted qt xs       -> quotedToJira qt xs
@@ -206,7 +208,7 @@
                                   then Jira.Linebreak
                                   else Jira.Space
         Space              -> pure . singleton $ Jira.Space
-        Span _attr xs      -> toJiraInlines xs
+        Span attr xs       -> spanToJira attr xs
         Str s              -> pure $ escapeSpecialChars s
         Strikeout xs       -> styled Jira.Strikeout xs
         Strong xs          -> styled Jira.Strong xs
@@ -230,6 +232,40 @@
   Right xs -> xs
   Left _  -> singleton $ Jira.Str t
 
+imageToJira :: PandocMonad m
+            => Attr -> Text -> Text
+            -> JiraConverter m [Jira.Inline]
+imageToJira (_, classes, kvs) src title =
+  let imgParams = if "thumbnail" `elem` classes
+                  then [Jira.Parameter "thumbnail" ""]
+                  else map (uncurry Jira.Parameter) kvs
+      imgParams' = if T.null title
+                   then imgParams
+                   else Jira.Parameter "title" title : imgParams
+  in pure . singleton $ Jira.Image imgParams' (Jira.URL src)
+
+-- | Creates a Jira Link element.
+toJiraLink :: PandocMonad m
+           => Attr
+           -> Target
+           -> [Inline]
+           -> JiraConverter m [Jira.Inline]
+toJiraLink (_, classes, _) (url, _) alias = do
+  let (linkType, url') = toLinkType url
+  description <- if url `elem` [stringify alias, "mailto:" <> stringify alias]
+                 then pure mempty
+                 else toJiraInlines alias
+  pure . singleton $ Jira.Link linkType description (Jira.URL url')
+ where
+  toLinkType url'
+    | Just email <- T.stripPrefix "mailto:" url' = (Jira.Email, email)
+    | "user-account" `elem` classes              = (Jira.User, dropTilde url)
+    | "attachment" `elem` classes                = (Jira.Attachment, url)
+    | otherwise                                  = (Jira.External, url)
+  dropTilde txt = case T.uncons txt of
+    Just ('~', username) -> username
+    _                    -> txt
+
 mathToJira :: PandocMonad m
            => MathType
            -> Text
@@ -250,6 +286,11 @@
                     SingleQuote -> "'"
   let surroundWithQuotes = (Jira.Str quoteChar :) . (++ [Jira.Str quoteChar])
   surroundWithQuotes <$> toJiraInlines xs
+
+spanToJira :: PandocMonad m
+           => Attr -> [Inline]
+           -> JiraConverter m [Jira.Inline]
+spanToJira (_, _classes, _) = toJiraInlines
 
 registerNotes :: PandocMonad m => [Block] -> JiraConverter m [Jira.Inline]
 registerNotes contents = do
diff --git a/src/Text/Pandoc/Writers/LaTeX.hs b/src/Text/Pandoc/Writers/LaTeX.hs
--- a/src/Text/Pandoc/Writers/LaTeX.hs
+++ b/src/Text/Pandoc/Writers/LaTeX.hs
@@ -155,7 +155,8 @@
                                           _               -> "article"
   when (documentClass `elem` chaptersClasses) $
      modify $ \s -> s{ stHasChapters = True }
-  case T.toLower . render Nothing <$> getField "csquotes" metadata of
+  case lookupContext "csquotes" (writerVariables options) `mplus`
+       (stringify <$> lookupMeta "csquotes" meta) of
      Nothing      -> return ()
      Just "false" -> return ()
      Just _       -> modify $ \s -> s{stCsquotes = True}
@@ -758,7 +759,8 @@
   hdr <- sectionHeader classes id' level lst
   modify $ \s -> s{stInHeading = False}
   return hdr
-blockToLaTeX (Table caption aligns widths heads rows) = do
+blockToLaTeX (Table _ blkCapt specs thead tbody tfoot) = do
+  let (caption, aligns, widths, heads, rows) = toLegacyTable blkCapt specs thead tbody tfoot
   (captionText, captForLof, captNotes) <- getCaption False caption
   let toHeaders hs = do contents <- tableRowToLaTeX True aligns widths hs
                         return ("\\toprule" $$ contents $$ "\\midrule")
@@ -1029,6 +1031,14 @@
                                 braces txtNoNotes
                          else empty
 
+mapAlignment :: Text -> Text
+mapAlignment a = case a of
+                   "top" -> "T"
+                   "top-baseline" -> "t"
+                   "bottom" -> "b"
+                   "center" -> "c"
+                   _ -> a 
+
 wrapDiv :: PandocMonad m => Attr -> Doc Text -> LW m (Doc Text)
 wrapDiv (_,classes,kvs) t = do
   beamer <- gets stBeamer
@@ -1036,14 +1046,25 @@
   lang <- toLang $ lookup "lang" kvs
   let wrapColumns = if beamer && "columns" `elem` classes
                     then \contents ->
-                           inCmd "begin" "columns" <> brackets "T"
-                           $$ contents
-                           $$ inCmd "end" "columns"
+                           let valign = maybe "T" mapAlignment (lookup "align" kvs)
+                               totalwidth = maybe [] (\x -> ["totalwidth=" <> x])
+                                 (lookup "totalwidth" kvs)
+                               onlytextwidth = filter ((==) "onlytextwidth") classes
+                               options = text $ T.unpack $ T.intercalate "," $
+                                 valign : totalwidth ++ onlytextwidth 
+                           in inCmd "begin" "columns" <> brackets options
+                              $$ contents
+                              $$ inCmd "end" "columns"
                     else id
       wrapColumn  = if beamer && "column" `elem` classes
                     then \contents ->
-                           let w = maybe "0.48" fromPct (lookup "width" kvs)
-                           in  inCmd "begin" "column" <>
+                           let valign =
+                                 maybe ""
+                                 (brackets . text . T.unpack . mapAlignment)
+                                 (lookup "align" kvs)
+                               w = maybe "0.48" fromPct (lookup "width" kvs) 
+                           in  inCmd "begin" "column" <> 
+                               valign <>
                                braces (literal w <> "\\textwidth")
                                $$ contents
                                $$ inCmd "end" "column"
@@ -1138,6 +1159,7 @@
                then braces contents
                else foldr inCmd contents cmds)
 inlineToLaTeX (Emph lst) = inCmd "emph" <$> inlineListToLaTeX lst
+inlineToLaTeX (Underline lst) = inCmd "underline" <$> inlineListToLaTeX lst
 inlineToLaTeX (Strong lst) = inCmd "textbf" <$> inlineListToLaTeX lst
 inlineToLaTeX (Strikeout lst) = do
   -- we need to protect VERB in an mbox or we get an error
@@ -1182,7 +1204,7 @@
         let chr = case "!\"'()*,-./:;?@" \\ T.unpack str of
                        (c:_) -> c
                        []    -> '!'
-        let str' = escapeStringUsing (backslashEscapes "\\{}%~_&#") str
+        let str' = escapeStringUsing (backslashEscapes "\\{}%~_&#^") str
         -- we always put lstinline in a dummy 'passthrough' command
         -- (defined in the default template) so that we don't have
         -- to change the way we escape characters depending on whether
@@ -1212,7 +1234,9 @@
   csquotes <- liftM stCsquotes get
   opts <- gets stOptions
   if csquotes
-     then return $ "\\enquote" <> braces contents
+     then return $ case qt of
+               DoubleQuote -> "\\enquote" <> braces contents
+               SingleQuote -> "\\enquote*" <> braces contents
      else do
        let s1 = if not (null lst) && isQuoted (head lst)
                    then "\\,"
@@ -1260,29 +1284,33 @@
        WrapNone     -> return space
        WrapPreserve -> return cr
 inlineToLaTeX Space = return space
-inlineToLaTeX (Link _ txt (src,_))
-  | Just ('#', ident) <- T.uncons src
-  = do
-      contents <- inlineListToLaTeX txt
-      lab <- toLabel ident
-      return $ text "\\protect\\hyperlink" <> braces (literal lab) <> braces contents
-  | otherwise =
-  case txt of
-        [Str x] | unEscapeString (T.unpack x) == unEscapeString (T.unpack src) ->  -- autolink
-             do modify $ \s -> s{ stUrl = True }
-                src' <- stringToLaTeX URLString (escapeURI src)
-                return $ literal $ "\\url{" <> src' <> "}"
-        [Str x] | Just rest <- T.stripPrefix "mailto:" src,
-                  unEscapeString (T.unpack x) == unEscapeString (T.unpack rest) -> -- email autolink
-             do modify $ \s -> s{ stUrl = True }
-                src' <- stringToLaTeX URLString (escapeURI src)
-                contents <- inlineListToLaTeX txt
-                return $ "\\href" <> braces (literal src') <>
-                   braces ("\\nolinkurl" <> braces contents)
-        _ -> do contents <- inlineListToLaTeX txt
-                src' <- stringToLaTeX URLString (escapeURI src)
-                return $ literal ("\\href{" <> src' <> "}{") <>
-                         contents <> char '}'
+inlineToLaTeX (Link (id',_,_) txt (src,_)) =
+   (case T.uncons src of
+     Just ('#', ident) -> do
+        contents <- inlineListToLaTeX txt
+        lab <- toLabel ident
+        return $ text "\\protect\\hyperlink" <> braces (literal lab) <> braces contents
+     _ -> case txt of
+          [Str x] | unEscapeString (T.unpack x) == unEscapeString (T.unpack src) ->  -- autolink
+               do modify $ \s -> s{ stUrl = True }
+                  src' <- stringToLaTeX URLString (escapeURI src)
+                  return $ literal $ "\\url{" <> src' <> "}"
+          [Str x] | Just rest <- T.stripPrefix "mailto:" src,
+                    unEscapeString (T.unpack x) == unEscapeString (T.unpack rest) -> -- email autolink
+               do modify $ \s -> s{ stUrl = True }
+                  src' <- stringToLaTeX URLString (escapeURI src)
+                  contents <- inlineListToLaTeX txt
+                  return $ "\\href" <> braces (literal src') <>
+                     braces ("\\nolinkurl" <> braces contents)
+          _ -> do contents <- inlineListToLaTeX txt
+                  src' <- stringToLaTeX URLString (escapeURI src)
+                  return $ literal ("\\href{" <> src' <> "}{") <>
+                           contents <> char '}')
+     >>= (if T.null id'
+             then return
+             else \x -> do
+               linkAnchor <- hypertarget False id' x
+               return ("\\protect" <> linkAnchor))
 inlineToLaTeX il@(Image _ _ (src, _))
   | Just _ <- T.stripPrefix "data:" src = do
       report $ InlineNotRendered il
@@ -1423,14 +1451,14 @@
 type Suffix = [Inline]
 type CiteId = Text
 data CiteGroup = CiteGroup Prefix Suffix [CiteId]
-  
+
 citeArgumentsList :: PandocMonad m
               => CiteGroup -> LW m (Doc Text)
 citeArgumentsList (CiteGroup _ _ []) = return empty
-citeArgumentsList (CiteGroup pfxs sfxs ids) = do  
+citeArgumentsList (CiteGroup pfxs sfxs ids) = do
       pdoc <- inlineListToLaTeX pfxs
-      sdoc <- inlineListToLaTeX sfxs' 
-      return $ (optargs pdoc sdoc) <> 
+      sdoc <- inlineListToLaTeX sfxs'
+      return $ (optargs pdoc sdoc) <>
               (braces (literal (T.intercalate "," (reverse ids))))
       where sfxs' = stripLocatorBraces $ case sfxs of
                 (Str t : r) -> case T.uncons t of
@@ -1479,22 +1507,22 @@
                     NormalCitation -> "\\autocite"
       return $ text cmd <>
                braces (literal (T.intercalate "," (map citationId (c:cs))))
-  | otherwise 
-    = do  
+  | otherwise
+    = do
       let cmd = case citationMode c of
                     SuppressAuthor -> "\\autocites*"
                     AuthorInText   -> "\\textcites"
                     NormalCitation -> "\\autocites"
-      
+
       groups <- mapM citeArgumentsList (reverse (foldl' grouper [] (c:cs)))
 
       return $ text cmd <> (mconcat groups)
 
-  where grouper prev cit = case prev of  
+  where grouper prev cit = case prev of
          ((CiteGroup oPfx oSfx ids):rest)
              | null oSfx && null pfx -> (CiteGroup oPfx sfx (cid:ids)):rest
          _ -> (CiteGroup pfx sfx [cid]):prev
-         where pfx = citationPrefix cit 
+         where pfx = citationPrefix cit
                sfx = citationSuffix cit
                cid = citationId cit
 
diff --git a/src/Text/Pandoc/Writers/Man.hs b/src/Text/Pandoc/Writers/Man.hs
--- a/src/Text/Pandoc/Writers/Man.hs
+++ b/src/Text/Pandoc/Writers/Man.hs
@@ -139,8 +139,9 @@
 blockToMan opts (BlockQuote blocks) = do
   contents <- blockListToMan opts blocks
   return $ literal ".RS" $$ contents $$ literal ".RE"
-blockToMan opts (Table caption alignments widths headers rows) =
-  let aligncode AlignLeft    = "l"
+blockToMan opts (Table _ blkCapt specs thead tbody tfoot) =
+  let (caption, alignments, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot
+      aligncode AlignLeft    = "l"
       aligncode AlignRight   = "r"
       aligncode AlignCenter  = "c"
       aligncode AlignDefault = "l"
@@ -268,6 +269,9 @@
 inlineToMan :: PandocMonad m => WriterOptions -> Inline -> StateT WriterState m (Doc Text)
 inlineToMan opts (Span _ ils) = inlineListToMan opts ils
 inlineToMan opts (Emph lst) =
+  withFontFeature 'I' (inlineListToMan opts lst)
+-- Underline is not supported, so treat the same as Emph
+inlineToMan opts (Underline lst) =
   withFontFeature 'I' (inlineListToMan opts lst)
 inlineToMan opts (Strong lst) =
   withFontFeature 'B' (inlineListToMan opts lst)
diff --git a/src/Text/Pandoc/Writers/Markdown.hs b/src/Text/Pandoc/Writers/Markdown.hs
--- a/src/Text/Pandoc/Writers/Markdown.hs
+++ b/src/Text/Pandoc/Writers/Markdown.hs
@@ -313,7 +313,12 @@
               case cs of
                    '.':'.':rest -> '\\':'.':'.':'.':go rest
                    _            -> '.':go cs
-       _   -> c : go cs
+       _   -> case cs of
+                '_':x:xs
+                  | isEnabled Ext_intraword_underscores opts
+                  , isAlphaNum c
+                  , isAlphaNum x -> c : '_' : x : go xs
+                _                -> c : go cs
 
 attrsToMarkdown :: Attr -> Doc Text
 attrsToMarkdown attribs = braces $ hsep [attribId, attribClasses, attribKeys]
@@ -360,9 +365,9 @@
 
 notesAndRefs :: PandocMonad m => WriterOptions -> MD m (Doc Text)
 notesAndRefs opts = do
-  notes' <- reverse <$> gets stNotes >>= notesToMarkdown opts
+  notes' <- gets stNotes >>= notesToMarkdown opts . reverse
   modify $ \s -> s { stNotes = [] }
-  refs' <- reverse <$> gets stRefs >>= refsToMarkdown opts
+  refs' <- gets stRefs >>= refsToMarkdown opts . reverse
   modify $ \s -> s { stPrevRefs = stPrevRefs s ++ stRefs s
                    , stRefs = []}
 
@@ -574,14 +579,15 @@
                   else if plain then "  " else "> "
   contents <- blockListToMarkdown opts blocks
   return $ (prefixed leader contents) <> blankline
-blockToMarkdown' opts t@(Table caption aligns widths headers rows) =  do
+blockToMarkdown' opts t@(Table _ blkCapt specs thead tbody tfoot) = do
+  let (caption, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot
   let numcols = maximum (length aligns : length widths :
                            map length (headers:rows))
   caption' <- inlineListToMarkdown opts caption
   let caption'' = if null caption || not (isEnabled Ext_table_captions opts)
                      then blankline
                      else blankline $$ (": " <> caption') $$ blankline
-  let hasSimpleCells = onlySimpleTableCells $ headers:rows
+  let hasSimpleCells = onlySimpleTableCells $ headers : rows
   let isSimple = hasSimpleCells && all (==0) widths
   let isPlainBlock (Plain _) = True
       isPlainBlock _         = False
@@ -669,8 +675,8 @@
 pipeTable headless aligns rawHeaders rawRows = do
   let sp = literal " "
   let blockFor AlignLeft   x y = lblock (x + 2) (sp <> y) <> lblock 0 empty
-      blockFor AlignCenter x y = cblock (x + 2) (sp <> y) <> lblock 0 empty
-      blockFor AlignRight  x y = rblock (x + 2) (sp <> y) <> lblock 0 empty
+      blockFor AlignCenter x y = cblock (x + 2) (sp <> y <> sp) <> lblock 0 empty
+      blockFor AlignRight  x y = rblock (x + 2) (y <> sp) <> lblock 0 empty
       blockFor _           x y = lblock (x + 2) (sp <> y) <> lblock 0 empty
   let widths = map (max 3 . maximum . map offset) $ transpose (rawHeaders : rawRows)
   let torow cs = nowrap $ literal "|" <>
@@ -1039,6 +1045,21 @@
                       then "_" <> contents <> "_"
                       else contents
               else "*" <> contents <> "*"
+inlineToMarkdown _ (Underline []) = return empty
+inlineToMarkdown opts (Underline lst) = do
+  plain <- asks envPlain
+  contents <- inlineListToMarkdown opts lst
+  case plain of
+    True -> return contents
+    False | isEnabled Ext_bracketed_spans opts ->
+            return $ "[" <> contents <> "]" <> "{.ul}"
+          | isEnabled Ext_native_spans opts ->
+            return $ tagWithAttrs "span" ("", ["underline"], [])
+              <> contents
+              <> literal "</span>"
+          | isEnabled Ext_raw_html opts ->
+            return $ "<u>" <> contents <> "</u>"
+          | otherwise -> inlineToMarkdown opts (Emph lst)
 inlineToMarkdown _ (Strong []) = return empty
 inlineToMarkdown opts (Strong lst) = do
   plain <- asks envPlain
diff --git a/src/Text/Pandoc/Writers/MediaWiki.hs b/src/Text/Pandoc/Writers/MediaWiki.hs
--- a/src/Text/Pandoc/Writers/MediaWiki.hs
+++ b/src/Text/Pandoc/Writers/MediaWiki.hs
@@ -150,7 +150,8 @@
   contents <- blockListToMediaWiki blocks
   return $ "<blockquote>" <> contents <> "</blockquote>"
 
-blockToMediaWiki (Table capt aligns widths headers rows') = do
+blockToMediaWiki (Table _ blkCapt specs thead tbody tfoot) = do
+  let (capt, aligns, widths, headers, rows') = toLegacyTable blkCapt specs thead tbody tfoot
   caption <- if null capt
                 then return ""
                 else do
@@ -370,6 +371,10 @@
 inlineToMediaWiki (Emph lst) = do
   contents <- inlineListToMediaWiki lst
   return $ "''" <> contents <> "''"
+
+inlineToMediaWiki (Underline lst) = do
+  contents <- inlineListToMediaWiki lst
+  return $ "<u>" <> contents <> "</u>"
 
 inlineToMediaWiki (Strong lst) = do
   contents <- inlineListToMediaWiki lst
diff --git a/src/Text/Pandoc/Writers/Ms.hs b/src/Text/Pandoc/Writers/Ms.hs
--- a/src/Text/Pandoc/Writers/Ms.hs
+++ b/src/Text/Pandoc/Writers/Ms.hs
@@ -215,8 +215,9 @@
   contents <- blockListToMs opts blocks
   setFirstPara
   return $ literal ".QS" $$ contents $$ literal ".QE"
-blockToMs opts (Table caption alignments widths headers rows) =
-  let aligncode AlignLeft    = "l"
+blockToMs opts (Table _ blkCapt specs thead tbody tfoot) =
+  let (caption, alignments, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot
+      aligncode AlignLeft    = "l"
       aligncode AlignRight   = "r"
       aligncode AlignCenter  = "c"
       aligncode AlignDefault = "l"
@@ -350,6 +351,8 @@
 inlineToMs opts (Span _ ils) = inlineListToMs opts ils
 inlineToMs opts (Emph lst) =
   withFontFeature 'I' (inlineListToMs opts lst)
+inlineToMs opts (Underline lst) =
+  inlineToMs opts (Emph lst)
 inlineToMs opts (Strong lst) =
   withFontFeature 'B' (inlineListToMs opts lst)
 inlineToMs opts (Strikeout lst) = do
diff --git a/src/Text/Pandoc/Writers/Muse.hs b/src/Text/Pandoc/Writers/Muse.hs
--- a/src/Text/Pandoc/Writers/Muse.hs
+++ b/src/Text/Pandoc/Writers/Muse.hs
@@ -150,8 +150,8 @@
 
 simpleTable :: PandocMonad m
             => [Inline]
-            -> [TableCell]
-            -> [[TableCell]]
+            -> [[Block]]
+            -> [[[Block]]]
             -> Muse m (Doc Text)
 simpleTable caption headers rows = do
   topLevel <- asks envTopLevel
@@ -259,17 +259,18 @@
   return $ blankline <> attr' $$ nowrap (header' <> contents) <> blankline
 -- https://www.gnu.org/software/emacs-muse/manual/muse.html#Horizontal-Rules-and-Anchors
 blockToMuse HorizontalRule = return $ blankline $$ "----" $$ blankline
-blockToMuse (Table caption aligns widths headers rows) =
+blockToMuse (Table _ blkCapt specs thead tbody tfoot) =
   if isSimple && numcols > 1
     then simpleTable caption headers rows
     else do
       opts <- asks envOptions
       gridTable opts blocksToDoc True (map (const AlignDefault) aligns) widths headers rows
   where
+    (caption, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot
     blocksToDoc opts blocks =
       local (\env -> env { envOptions = opts }) $ blockListToMuse blocks
     numcols = maximum (length aligns : length widths : map length (headers:rows))
-    isSimple = onlySimpleTableCells (headers:rows) && all (== 0) widths
+    isSimple = onlySimpleTableCells (headers : rows) && all (== 0) widths
 blockToMuse (Div _ bs) = flatBlockListToMuse bs
 blockToMuse Null = return empty
 
@@ -593,6 +594,13 @@
     else if null lst' || startsWithSpace lst' || endsWithSpace lst'
            then emphasis "**<em>" "</em>**" lst'
            else emphasis "***" "***" lst'
+-- | Underline is only supported in Emacs Muse mode.
+inlineToMuse (Underline lst) = do
+  opts <- asks envOptions
+  contents <- inlineListToMuse lst
+  if isEnabled Ext_amuse opts
+     then return $ "_" <> contents <> "_"
+     else inlineToMuse (Emph lst)
 inlineToMuse (Strong lst) = do
   useTags <- gets stUseTags
   let lst' = normalizeInlineList lst
diff --git a/src/Text/Pandoc/Writers/Native.hs b/src/Text/Pandoc/Writers/Native.hs
--- a/src/Text/Pandoc/Writers/Native.hs
+++ b/src/Text/Pandoc/Writers/Native.hs
@@ -40,12 +40,42 @@
   prettyList (map deflistitem items)
     where deflistitem (term, defs) = "(" <> text (show term) <> "," <> cr <>
            nest 1 (prettyList $ map (prettyList . map prettyBlock) defs) <> ")"
-prettyBlock (Table caption aligns widths header rows) =
-  "Table " <> text (show caption) <> " " <> text (show aligns) <> " " <>
-  text (show widths) $$
-  prettyRow header $$
-  prettyList (map prettyRow rows)
-    where prettyRow cols = prettyList (map (prettyList . map prettyBlock) cols)
+prettyBlock (Table attr blkCapt specs thead tbody tfoot) =
+  mconcat [ "Table "
+          , text (show attr)
+          , " "
+          , prettyCaption blkCapt ] $$
+  prettyList (map (text . show) specs) $$
+  prettyHead thead $$
+  prettyBodies tbody $$
+  prettyFoot tfoot
+  where prettyRows = prettyList . map prettyRow
+        prettyRow (Row a body) =
+          text ("Row " <> show a) $$ prettyList (map prettyCell body)
+        prettyCell (Cell a ma h w b) =
+          mconcat [ "Cell "
+                  , text (show a)
+                  , " "
+                  , text (show ma)
+                  , " ("
+                  , text (show h)
+                  , ") ("
+                  , text (show w)
+                  , ")" ] $$
+          prettyList (map prettyBlock b)
+        prettyCaption (Caption mshort body) =
+          "(Caption " <> text (showsPrec 11 mshort "") $$ prettyList (map prettyBlock body) <> ")"
+        prettyHead (TableHead thattr body)
+          = "(TableHead " <> text (show thattr) $$ prettyRows body <> ")"
+        prettyBody (TableBody tbattr rhc hd bd)
+          = mconcat [ "(TableBody "
+                    , text (show tbattr)
+                    , " ("
+                    , text (show rhc)
+                    , ")" ] $$ prettyRows hd $$ prettyRows bd <> ")"
+        prettyBodies = prettyList . map prettyBody
+        prettyFoot (TableFoot tfattr body)
+          = "(TableFoot " <> text (show tfattr) $$ prettyRows body <> ")"
 prettyBlock (Div attr blocks) =
   text ("Div " <> show attr) $$ prettyList (map prettyBlock blocks)
 prettyBlock block = text $ show block
diff --git a/src/Text/Pandoc/Writers/OpenDocument.hs b/src/Text/Pandoc/Writers/OpenDocument.hs
--- a/src/Text/Pandoc/Writers/OpenDocument.hs
+++ b/src/Text/Pandoc/Writers/OpenDocument.hs
@@ -28,6 +28,7 @@
 import Text.Pandoc.Class.PandocMonad (PandocMonad, report, translateTerm,
                                       setTranslations, toLang)
 import Text.Pandoc.Definition
+import qualified Text.Pandoc.Builder as B
 import Text.Pandoc.Logging
 import Text.Pandoc.Options
 import Text.DocLayout
@@ -223,12 +224,18 @@
   let colwidth = if writerWrapText opts == WrapAuto
                     then Just $ writerColumns opts
                     else Nothing
+  let meta' = case lookupMetaBlocks "abstract" meta of
+                [] -> meta
+                xs -> B.setMeta "abstract"
+                        (B.divWith ("",[],[("custom-style","Abstract")])
+                          (B.fromList xs))
+                        meta
   ((body, metadata),s) <- flip runStateT
         defaultWriterState $ do
            m <- metaToContext opts
                   (blocksToOpenDocument opts)
                   (fmap chomp . inlinesToOpenDocument opts)
-                  meta
+                  meta'
            b <- blocksToOpenDocument opts blocks
            return (b, m)
   let styles   = stTableStyles s ++ stParaStyles s ++ formulaStyles ++
@@ -349,8 +356,12 @@
                                   then return empty
                                   else inParagraphTags =<< inlinesToOpenDocument o b
     | LineBlock      b <- bs = blockToOpenDocument o $ linesToPara b
-    | Div attr xs      <- bs = withLangFromAttr attr
-                                  (blocksToOpenDocument o xs)
+    | Div attr xs      <- bs = do
+        let (_,_,kvs) = attr
+        withLangFromAttr attr $
+          case lookup "custom-style" kvs of
+            Just sty -> withParagraphStyle o sty xs
+            _        -> blocksToOpenDocument o xs
     | Header     i (ident,_,_) b
                        <- bs = setFirstPara >> (inHeaderTags i ident
                                   =<< inlinesToOpenDocument o b)
@@ -359,7 +370,9 @@
     | BulletList     b <- bs = setFirstPara >> bulletListToOpenDocument o b
     | OrderedList  a b <- bs = setFirstPara >> orderedList a b
     | CodeBlock    _ s <- bs = setFirstPara >> preformatted s
-    | Table  c a w h r <- bs = setFirstPara >> table c a w h r
+    | Table _ bc s th tb tf
+                       <- bs = let (c, a, w, h, r) = toLegacyTable bc s th tb tf
+                               in setFirstPara >> table c a w h r
     | HorizontalRule   <- bs = setFirstPara >> return (selfClosingTag "text:p"
                                 [ ("text:style-name", "Horizontal_20_Line") ])
     | RawBlock f     s <- bs = if f == Format "opendocument"
@@ -510,6 +523,7 @@
     LineBreak     -> return $ selfClosingTag "text:line-break" []
     Str         s -> return $ handleSpaces $ escapeStringForXML s
     Emph        l -> withTextStyle Italic $ inlinesToOpenDocument o l
+    Underline   l -> withTextStyle Under  $ inlinesToOpenDocument o l
     Strong      l -> withTextStyle Bold   $ inlinesToOpenDocument o l
     Strikeout   l -> withTextStyle Strike $ inlinesToOpenDocument o l
     Superscript l -> withTextStyle Sup    $ inlinesToOpenDocument o l
@@ -690,6 +704,7 @@
 
 data TextStyle = Italic
                | Bold
+               | Under
                | Strike
                | Sub
                | Sup
@@ -708,6 +723,9 @@
     | Bold   <- s = Map.insert "fo:font-weight" "bold" .
                     Map.insert "style:font-weight-asian" "bold" .
                     Map.insert "style:font-weight-complex" "bold" $ m
+    | Under  <- s = Map.insert "style:text-underline-style" "solid" .
+                    Map.insert "style:text-underline-width" "auto" .
+                    Map.insert "style:text-underline-color" "font-color" $ m
     | Strike <- s = Map.insert "style:text-line-through-style" "solid" m
     | Sub    <- s = Map.insert "style:text-position" "sub 58%" m
     | Sup    <- s = Map.insert "style:text-position" "super 58%" m
diff --git a/src/Text/Pandoc/Writers/Org.hs b/src/Text/Pandoc/Writers/Org.hs
--- a/src/Text/Pandoc/Writers/Org.hs
+++ b/src/Text/Pandoc/Writers/Org.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PatternGuards #-}
 {- |
    Module      : Text.Pandoc.Writers.Org
    Copyright   : © 2010-2015 Puneeth Chaganti <punchagan@gmail.com>
@@ -98,36 +99,7 @@
            => Block         -- ^ Block element
            -> Org m (Doc Text)
 blockToOrg Null = return empty
-blockToOrg (Div (_,classes@(cls:_),kvs) bs) | "drawer" `elem` classes = do
-  contents <- blockListToOrg bs
-  let drawerNameTag = ":" <> literal cls <> ":"
-  let keys = vcat $ map (\(k,v) ->
-                       ":" <> literal k <> ":"
-                       <> space <> literal v) kvs
-  let drawerEndTag = text ":END:"
-  return $ drawerNameTag $$ cr $$ keys $$
-           blankline $$ contents $$
-           blankline $$ drawerEndTag $$
-           blankline
-blockToOrg (Div (ident, classes, kv) bs) = do
-  contents <- blockListToOrg bs
-  -- if one class looks like the name of a greater block then output as such:
-  -- The ID, if present, is added via the #+NAME keyword; other classes and
-  -- key-value pairs are kept as #+ATTR_HTML attributes.
-  let isGreaterBlockClass = (`elem` ["center", "quote"]) . T.toLower
-      (blockTypeCand, classes') = partition isGreaterBlockClass classes
-  return $ case blockTypeCand of
-    (blockType:classes'') ->
-      blankline $$ attrHtml (ident, classes'' <> classes', kv) $$
-      "#+BEGIN_" <> literal blockType $$ contents $$
-      "#+END_" <> literal blockType $$ blankline
-    _                     ->
-      -- fallback with id: add id as an anchor if present, discard classes and
-      -- key-value pairs, unwrap the content.
-      let contents' = if not (T.null ident)
-                      then "<<" <> literal ident <> ">>" $$ contents
-                      else contents
-      in blankline $$ contents' $$ blankline
+blockToOrg (Div attr bs) = divToOrg attr bs
 blockToOrg (Plain inlines) = inlineListToOrg inlines
 -- title beginning with fig: indicates that the image is a figure
 blockToOrg (Para [Image attr txt (src,tgt)])
@@ -183,7 +155,8 @@
   contents <- blockListToOrg blocks
   return $ blankline $$ "#+BEGIN_QUOTE" $$
            nest 2 contents $$ "#+END_QUOTE" $$ blankline
-blockToOrg (Table caption' _ _ headers rows) =  do
+blockToOrg (Table _ blkCapt specs thead tbody tfoot) =  do
+  let (caption', _, _, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot
   caption'' <- inlineListToOrg caption'
   let caption = if null caption'
                    then empty
@@ -286,6 +259,63 @@
    kvToOrgProperty (key, value) =
      text ":" <> literal key <> text ": " <> literal value <> cr
 
+-- | The different methods to represent a Div block.
+data DivBlockType
+  = GreaterBlock Text Attr   -- ^ Greater block like @center@ or @quote@.
+  | Drawer Text Attr         -- ^ Org drawer with of given name; keeps
+                             --   key-value pairs.
+  | UnwrappedWithAnchor Text -- ^ Not mapped to other type, only
+                             --   identifier is retained (if any).
+
+-- | Gives the most suitable method to render a list of blocks
+-- with attributes.
+divBlockType :: Attr-> DivBlockType
+divBlockType (ident, classes, kvs)
+  -- if any class is named "drawer", then output as org :drawer:
+  | ([_], drawerName:classes') <- partition (== "drawer") classes
+  = Drawer drawerName (ident, classes', kvs)
+  -- if any class is either @center@ or @quote@, then use a org block.
+  | (blockName:classes'', classes') <- partition isGreaterBlockClass classes
+  = GreaterBlock blockName (ident, classes' <> classes'', kvs)
+  -- if no better method is found, unwrap div and set anchor
+  | otherwise
+  = UnwrappedWithAnchor ident
+ where
+  isGreaterBlockClass :: Text -> Bool
+  isGreaterBlockClass = (`elem` ["center", "quote"]) . T.toLower
+
+-- | Converts a Div to an org-mode element.
+divToOrg :: PandocMonad m
+         => Attr -> [Block] -> Org m (Doc Text)
+divToOrg attr bs = do
+  contents <- blockListToOrg bs
+  case divBlockType attr of
+    GreaterBlock blockName attr' ->
+      -- Write as greater block. The ID, if present, is added via
+      -- the #+NAME keyword; other classes and key-value pairs
+      -- are kept as #+ATTR_HTML attributes.
+      return $ blankline $$ attrHtml attr'
+            $$ "#+BEGIN_" <> literal blockName
+            $$ contents
+            $$ "#+END_" <> literal blockName $$ blankline
+    Drawer drawerName (_,_,kvs) -> do
+      -- Write as drawer. Only key-value pairs are retained.
+      let keys = vcat $ map (\(k,v) ->
+                               ":" <> literal k <> ":"
+                              <> space <> literal v) kvs
+      return $ ":" <> literal drawerName <> ":" $$ cr
+            $$ keys $$ blankline
+            $$ contents $$ blankline
+            $$ text ":END:" $$ blankline
+    UnwrappedWithAnchor ident -> do
+      -- Unwrap the div. All attributes are discarded, except for
+      -- the identifier, which is added as an anchor before the
+      -- div contents.
+      let contents' = if T.null ident
+                      then contents
+                      else  "<<" <> literal ident <> ">>" $$ contents
+      return (blankline $$ contents' $$ blankline)
+
 attrHtml :: Attr -> Doc Text
 attrHtml (""   , []     , []) = mempty
 attrHtml (ident, classes, kvs) =
@@ -328,6 +358,9 @@
 inlineToOrg (Emph lst) = do
   contents <- inlineListToOrg lst
   return $ "/" <> contents <> "/"
+inlineToOrg (Underline lst) = do
+  contents <- inlineListToOrg lst
+  return $ "_" <> contents <> "_"
 inlineToOrg (Strong lst) = do
   contents <- inlineListToOrg lst
   return $ "*" <> contents <> "*"
diff --git a/src/Text/Pandoc/Writers/Powerpoint/Output.hs b/src/Text/Pandoc/Writers/Powerpoint/Output.hs
--- a/src/Text/Pandoc/Writers/Powerpoint/Output.hs
+++ b/src/Text/Pandoc/Writers/Powerpoint/Output.hs
@@ -106,6 +106,7 @@
                            -- are no notes for a slide, there will be
                            -- no entry in the map for it.
                            , envSpeakerNotesIdMap :: M.Map Int Int
+                           , envInSpeakerNotes :: Bool
                            }
                  deriving (Show)
 
@@ -123,6 +124,7 @@
                   , envContentType = NormalContent
                   , envSlideIdMap = mempty
                   , envSpeakerNotesIdMap = mempty
+                  , envInSpeakerNotes = False
                   }
 
 data ContentType = NormalContent
@@ -803,11 +805,14 @@
                           , mknode "a:t" [] $ T.unpack s
                           ]]
 paraElemToElements (MathElem mathType texStr) = do
-  res <- convertMath writeOMML mathType (unTeXString texStr)
-  case res of
-    Right r -> return [mknode "a14:m" [] $ addMathInfo r]
-    Left (Str s) -> paraElemToElements (Run def s)
-    Left _       -> throwError $ PandocShouldNeverHappenError "non-string math fallback"
+  isInSpkrNotes <- asks envInSpeakerNotes
+  if isInSpkrNotes
+    then paraElemToElements $ Run def $ unTeXString texStr
+    else do res <- convertMath writeOMML mathType (unTeXString texStr)
+            case res of
+              Right r -> return [mknode "a14:m" [] $ addMathInfo r]
+              Left (Str s) -> paraElemToElements (Run def s)
+              Left _       -> throwError $ PandocShouldNeverHappenError "non-string math fallback"
 paraElemToElements (RawOOXMLParaElem str) = return [ x | Elem x <- parseXML str ]
 
 
@@ -977,10 +982,10 @@
   headers' <- mapM cellToOpenXML hdrCells
   rows' <- mapM (mapM cellToOpenXML) rows
   let borderProps = mknode "a:tcPr" [] ()
-  let emptyCell = [mknode "a:p" [] [mknode "a:pPr" [] ()]]
+  let emptyCell' = [mknode "a:p" [] [mknode "a:pPr" [] ()]]
   let mkcell border contents = mknode "a:tc" []
                             $ (if null contents
-                               then emptyCell
+                               then emptyCell'
                                else contents) <> [ borderProps | border ]
   let mkrow border cells = mknode "a:tr" [("h", "0")] $ map (mkcell border) cells
 
@@ -1231,7 +1236,8 @@
 
 speakerNotesBody :: PandocMonad m => [Paragraph] -> P m Element
 speakerNotesBody paras = do
-  elements <- mapM paragraphToElement $ spaceParas $ map removeParaLinks paras
+  elements <- local (\env -> env{envInSpeakerNotes = True}) $
+              mapM paragraphToElement $ spaceParas $ map removeParaLinks paras
   let txBody = mknode "p:txBody" [] $
                [mknode "a:bodyPr" [] (), mknode "a:lstStyle" [] ()] <> elements
   return $
diff --git a/src/Text/Pandoc/Writers/Powerpoint/Presentation.hs b/src/Text/Pandoc/Writers/Powerpoint/Presentation.hs
--- a/src/Text/Pandoc/Writers/Powerpoint/Presentation.hs
+++ b/src/Text/Pandoc/Writers/Powerpoint/Presentation.hs
@@ -56,7 +56,8 @@
 import qualified Text.Pandoc.Shared as Shared -- so we don't overlap "Element"
 import Text.Pandoc.Shared (tshow)
 import Text.Pandoc.Writers.Shared (lookupMetaInlines, lookupMetaBlocks
-                                 , lookupMetaString, toTableOfContents)
+                                 , lookupMetaString, toTableOfContents
+                                 , toLegacyTable)
 import qualified Data.Map as M
 import qualified Data.Set as S
 import Data.Maybe (maybeToList, fromMaybe)
@@ -201,13 +202,17 @@
            | RawOOXMLShape T.Text
   deriving (Show, Eq)
 
-type Cell = [Paragraph]
+type TableCell = [Paragraph]
 
+-- TODO: remove when better handling of new
+-- tables is implemented
+type SimpleCell = [Block]
+
 data TableProps = TableProps { tblPrFirstRow :: Bool
                              , tblPrBandRow :: Bool
                              } deriving (Show, Eq)
 
-data Graphic = Tbl TableProps [Cell] [[Cell]]
+data Graphic = Tbl TableProps [TableCell] [[TableCell]]
   deriving (Show, Eq)
 
 
@@ -318,6 +323,9 @@
 inlineToParElems (Emph ils) =
   local (\r -> r{envRunProps = (envRunProps r){rPropItalics=True}}) $
   inlinesToParElems ils
+inlineToParElems (Underline ils) =
+  local (\r -> r{envRunProps = (envRunProps r){rPropUnderline=True}}) $
+  inlinesToParElems ils
 inlineToParElems (Strong ils) =
   local (\r -> r{envRunProps = (envRunProps r){rPropBold=True}}) $
   inlinesToParElems ils
@@ -362,9 +370,6 @@
     modify $ \st -> st { stNoteIds = M.insert curNoteId blks notes }
     local (\env -> env{envRunProps = (envRunProps env){rLink = Just $ InternalTarget endNotesSlideId}}) $
       inlineToParElems $ Superscript [Str $ tshow curNoteId]
-inlineToParElems (Span (_, ["underline"], _) ils) =
-  local (\r -> r{envRunProps = (envRunProps r){rPropUnderline=True}}) $
-  inlinesToParElems ils
 inlineToParElems (Span _ ils) = inlinesToParElems ils
 inlineToParElems (Quoted quoteType ils) =
   inlinesToParElems $ [Str open] ++ ils ++ [Str close]
@@ -503,7 +508,7 @@
     concatMapM blockToParagraphs bs
   return $ p ++ ps
 
-cellToParagraphs :: Alignment -> TableCell -> Pres [Paragraph]
+cellToParagraphs :: Alignment -> SimpleCell -> Pres [Paragraph]
 cellToParagraphs algn tblCell = do
   paras <- mapM blockToParagraphs tblCell
   let alignment = case algn of
@@ -514,7 +519,7 @@
       paras' = map (map (\p -> p{paraProps = (paraProps p){pPropAlign = alignment}})) paras
   return $ concat paras'
 
-rowToParagraphs :: [Alignment] -> [TableCell] -> Pres [[Paragraph]]
+rowToParagraphs :: [Alignment] -> [SimpleCell] -> Pres [[Paragraph]]
 rowToParagraphs algns tblCells = do
   -- We have to make sure we have the right number of alignments
   let pairs = zip (algns ++ repeat AlignDefault) tblCells
@@ -537,7 +542,8 @@
                             , Image attr ils (url, _) <- il' =
       (withAttr attr . Pic def{picPropLink = Just $ ExternalTarget target} (T.unpack url))
       <$> inlinesToParElems ils
-blockToShape (Table caption algn _ hdrCells rows) = do
+blockToShape (Table _ blkCapt specs thead tbody tfoot) = do
+  let (caption, algn, _, hdrCells, rows) = toLegacyTable blkCapt specs thead tbody tfoot
   caption' <- inlinesToParElems caption
   hdrCells' <- rowToParagraphs algn hdrCells
   rows' <- mapM (rowToParagraphs algn) rows
diff --git a/src/Text/Pandoc/Writers/RST.hs b/src/Text/Pandoc/Writers/RST.hs
--- a/src/Text/Pandoc/Writers/RST.hs
+++ b/src/Text/Pandoc/Writers/RST.hs
@@ -42,6 +42,7 @@
               , stHasRawTeX   :: Bool
               , stOptions     :: WriterOptions
               , stTopLevel    :: Bool
+              , stImageId     :: Int
               }
 
 type RST = StateT WriterState
@@ -52,7 +53,7 @@
   let st = WriterState { stNotes = [], stLinks = [],
                          stImages = [], stHasMath = False,
                          stHasRawTeX = False, stOptions = opts,
-                         stTopLevel = True }
+                         stTopLevel = True, stImageId = 1 }
   evalStateT (pandocToRST document) st
 
 -- | Return RST representation of document.
@@ -284,7 +285,8 @@
 blockToRST (BlockQuote blocks) = do
   contents <- blockListToRST blocks
   return $ nest 3 contents <> blankline
-blockToRST (Table caption aligns widths headers rows) = do
+blockToRST (Table _ blkCapt specs thead tbody tfoot) = do
+  let (caption, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot
   caption' <- inlineListToRST caption
   let blocksToDoc opts bs = do
          oldOpts <- gets stOptions
@@ -413,6 +415,7 @@
         hasContents :: Inline -> Bool
         hasContents (Str "")              = False
         hasContents (Emph [])             = False
+        hasContents (Underline [])        = False
         hasContents (Strong [])           = False
         hasContents (Strikeout [])        = False
         hasContents (Superscript [])      = False
@@ -472,6 +475,7 @@
         okBeforeComplex _ = False
         isComplex :: Inline -> Bool
         isComplex (Emph _)        = True
+        isComplex (Underline _)   = True
         isComplex (Strong _)      = True
         isComplex (SmallCaps _)   = True
         isComplex (Strikeout _)   = True
@@ -536,6 +540,7 @@
 dropInlineParent :: Inline -> [Inline]
 dropInlineParent (Link _ i _)    = i
 dropInlineParent (Emph i)        = i
+dropInlineParent (Underline i)   = i
 dropInlineParent (Strong i)      = i
 dropInlineParent (Strikeout i)   = i
 dropInlineParent (Superscript i) = i
@@ -550,6 +555,7 @@
 setInlineChildren :: Inline -> [Inline] -> Inline
 setInlineChildren (Link a _ t) i    = Link a i t
 setInlineChildren (Emph _) i        = Emph i
+setInlineChildren (Underline _) i   = Underline i
 setInlineChildren (Strong _) i      = Strong i
 setInlineChildren (Strikeout _) i   = Strikeout i
 setInlineChildren (Superscript _) i = Superscript i
@@ -580,6 +586,9 @@
 inlineToRST (Emph lst) = do
   contents <- writeInlines lst
   return $ "*" <> contents <> "*"
+-- Underline is not supported, fall back to Emph
+inlineToRST (Underline lst) =
+  inlineToRST (Emph lst)
 inlineToRST (Strong lst) = do
   contents <- writeInlines lst
   return $ "**" <> contents <> "**"
@@ -686,13 +695,23 @@
 registerImage :: PandocMonad m => Attr -> [Inline] -> Target -> Maybe Text -> RST m (Doc Text)
 registerImage attr alt (src,tit) mbtarget = do
   pics <- gets stImages
+  imgId <- gets stImageId
+  let getImageName = do
+        modify $ \st -> st{ stImageId = imgId + 1 }
+        return [Str ("image" <> tshow imgId)]
   txt <- case lookup alt pics of
-               Just (a,s,t,mbt) | (a,s,t,mbt) == (attr,src,tit,mbtarget)
-                 -> return alt
-               _ -> do
-                 let alt' = if null alt || alt == [Str ""]
-                               then [Str $ "image" <> tshow (length pics)]
-                               else alt
+               Just (a,s,t,mbt) ->
+                 if (a,s,t,mbt) == (attr,src,tit,mbtarget)
+                    then return alt
+                    else do
+                        alt' <- getImageName
+                        modify $ \st -> st { stImages =
+                           (alt', (attr,src,tit, mbtarget)):stImages st }
+                        return alt'
+               Nothing -> do
+                 alt' <- if null alt || alt == [Str ""]
+                            then getImageName
+                            else return alt
                  modify $ \st -> st { stImages =
                         (alt', (attr,src,tit, mbtarget)):stImages st }
                  return alt'
diff --git a/src/Text/Pandoc/Writers/RTF.hs b/src/Text/Pandoc/Writers/RTF.hs
--- a/src/Text/Pandoc/Writers/RTF.hs
+++ b/src/Text/Pandoc/Writers/RTF.hs
@@ -254,7 +254,8 @@
   contents <- inlinesToRTF lst
   return $ rtfPar indent 0 alignment $
              "\\b \\fs" <> tshow (40 - (level * 4)) <> " " <> contents
-blockToRTF indent alignment (Table caption aligns sizes headers rows) = do
+blockToRTF indent alignment (Table _ blkCapt specs thead tbody tfoot) = do
+  let (caption, aligns, sizes, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot
   caption' <- inlinesToRTF caption
   header' <- if all null headers
                 then return ""
@@ -350,6 +351,9 @@
 inlineToRTF (Emph lst) = do
   contents <- inlinesToRTF lst
   return $ "{\\i " <> contents <> "}"
+inlineToRTF (Underline lst) = do
+  contents <- inlinesToRTF lst
+  return $ "{\\ul " <> contents <> "}"
 inlineToRTF (Strong lst) = do
   contents <- inlinesToRTF lst
   return $ "{\\b " <> contents <> "}"
diff --git a/src/Text/Pandoc/Writers/Shared.hs b/src/Text/Pandoc/Writers/Shared.hs
--- a/src/Text/Pandoc/Writers/Shared.hs
+++ b/src/Text/Pandoc/Writers/Shared.hs
@@ -34,6 +34,7 @@
                      , toSuperscript
                      , toTableOfContents
                      , endsWithPlain
+                     , toLegacyTable
                      )
 where
 import Safe (lastMay)
@@ -50,7 +51,7 @@
 import Text.Pandoc.Definition
 import Text.Pandoc.Options
 import Text.DocLayout
-import Text.Pandoc.Shared (stringify, makeSections, deNote, deLink)
+import Text.Pandoc.Shared (stringify, makeSections, deNote, deLink, blocksToInlines)
 import Text.Pandoc.Walk (walk)
 import qualified Text.Pandoc.UTF8 as UTF8
 import Text.Pandoc.XML (escapeStringForXML)
@@ -426,3 +427,67 @@
   case lastMay xs of
     Just Plain{} -> True
     _            -> False
+
+-- | Convert the relevant components of a new-style table (with block
+-- caption, row headers, row and column spans, and so on) to those of
+-- an old-style table (inline caption, table head with one row, no
+-- foot, and so on). Cells with a 'RowSpan' and 'ColSpan' of @(h, w)@
+-- will be cut up into @h * w@ cells of dimension @(1, 1)@, with the
+-- content placed in the upper-left corner.
+toLegacyTable :: Caption
+              -> [ColSpec]
+              -> TableHead
+              -> [TableBody]
+              -> TableFoot
+              -> ([Inline], [Alignment], [Double], [[Block]], [[[Block]]])
+toLegacyTable (Caption _ cbody) specs thead tbodies tfoot
+  = (cbody', aligns, widths, th', tb')
+  where
+    numcols = length specs
+    (aligns, mwidths) = unzip specs
+    fromWidth (ColWidth w) | w > 0 = w
+    fromWidth _                    = 0
+    widths = map fromWidth mwidths
+    unRow (Row _ x) = x
+    unBody (TableBody _ _ hd bd) = hd <> bd
+    unBodies = concatMap unBody
+
+    TableHead _ th = Builder.normalizeTableHead numcols thead
+    tb = map (Builder.normalizeTableBody numcols) tbodies
+    TableFoot _ tf = Builder.normalizeTableFoot numcols tfoot
+
+    cbody' = blocksToInlines cbody
+
+    (th', tb') = case th of
+      r:rs -> let (pendingPieces, r') = placeCutCells [] $ unRow r
+                  rs' = cutRows pendingPieces $ rs <> unBodies tb <> tf
+              in (r', rs')
+      []    -> ([], cutRows [] $ unBodies tb <> tf)
+
+    -- Adapted from placeRowSection in Builders. There is probably a
+    -- more abstract foldRowSection that unifies them both.
+    placeCutCells pendingPieces cells
+      -- If there are any pending pieces for a column, add
+      -- them. Pending pieces have preference over cells due to grid
+      -- layout rules.
+      | (p:ps):pendingPieces' <- pendingPieces
+      = let (pendingPieces'', rowPieces) = placeCutCells pendingPieces' cells
+        in (ps : pendingPieces'', p : rowPieces)
+      -- Otherwise cut up a cell on the row and deal with its pieces.
+      | c:cells' <- cells
+      = let (h, w, cBody) = getComponents c
+            cRowPieces = cBody : replicate (w - 1) mempty
+            cPendingPieces = replicate w $ replicate (h - 1) mempty
+            pendingPieces' = dropWhile null pendingPieces
+            (pendingPieces'', rowPieces) = placeCutCells pendingPieces' cells'
+        in (cPendingPieces <> pendingPieces'', cRowPieces <> rowPieces)
+      | otherwise = ([], [])
+
+    cutRows pendingPieces (r:rs)
+      = let (pendingPieces', r') = placeCutCells pendingPieces $ unRow r
+            rs' = cutRows pendingPieces' rs
+        in r' : rs'
+    cutRows _ [] = []
+
+    getComponents (Cell _ _ (RowSpan h) (ColSpan w) body)
+      = (h, w, body)
diff --git a/src/Text/Pandoc/Writers/TEI.hs b/src/Text/Pandoc/Writers/TEI.hs
--- a/src/Text/Pandoc/Writers/TEI.hs
+++ b/src/Text/Pandoc/Writers/TEI.hs
@@ -194,8 +194,9 @@
 -- | TEI Tables
 -- TEI Simple's tables are composed of cells and rows; other
 -- table info in the AST is here lossily discard.
-blockToTEI opts (Table _ _ _ headers rows) = do
-  headers' <- tableHeadersToTEI opts headers
+blockToTEI opts (Table _ blkCapt specs thead tbody tfoot) = do
+  let (_, _, _, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot
+  headers' <- if null headers then pure mempty else tableHeadersToTEI opts headers
   rows' <- mapM (tableRowToTEI opts) rows
   return $ inTags True "table" [] $ headers' $$ vcat rows'
 
@@ -230,6 +231,8 @@
 inlineToTEI _ (Str str) = return $ literal $ escapeStringForXML str
 inlineToTEI opts (Emph lst) =
   inTags False "hi" [("rendition","simple:italic")] <$> inlinesToTEI opts lst
+inlineToTEI opts (Underline lst) =
+  inTags False "hi" [("rendition","simple:underline")] <$> inlinesToTEI opts lst
 inlineToTEI opts (Strong lst) =
   inTags False "hi" [("rendition", "simple:bold")] <$> inlinesToTEI opts lst
 inlineToTEI opts (Strikeout lst) =
diff --git a/src/Text/Pandoc/Writers/Texinfo.hs b/src/Text/Pandoc/Writers/Texinfo.hs
--- a/src/Text/Pandoc/Writers/Texinfo.hs
+++ b/src/Text/Pandoc/Writers/Texinfo.hs
@@ -228,7 +228,8 @@
       seccmd 4 = return "@subsubsection "
       seccmd _ = throwError $ PandocSomeError "illegal seccmd level"
 
-blockToTexinfo (Table caption aligns widths heads rows) = do
+blockToTexinfo (Table _ blkCapt specs thead tbody tfoot) = do
+  let (caption, aligns, widths, heads, rows) = toLegacyTable blkCapt specs thead tbody tfoot
   headers <- if all null heads
                 then return empty
                 else tableHeadToTexinfo aligns heads
@@ -390,6 +391,10 @@
 
 inlineToTexinfo (Emph lst) =
   inCmd "emph" <$> inlineListToTexinfo lst
+
+-- Underline isn't supported, fall back to Emph
+inlineToTexinfo (Underline lst) =
+  inlineToTexinfo (Emph lst)
 
 inlineToTexinfo (Strong lst) =
   inCmd "strong" <$> inlineListToTexinfo lst
diff --git a/src/Text/Pandoc/Writers/Textile.hs b/src/Text/Pandoc/Writers/Textile.hs
--- a/src/Text/Pandoc/Writers/Textile.hs
+++ b/src/Text/Pandoc/Writers/Textile.hs
@@ -168,44 +168,44 @@
   contents <- blockListToTextile opts blocks
   return $ "<blockquote>\n\n" <> contents <> "\n</blockquote>\n"
 
-blockToTextile opts (Table [] aligns widths headers rows') |
-         all (==0) widths = do
-  hs <- mapM (liftM (("_. " <>) . stripTrailingNewlines) . blockListToTextile opts) headers
-  let cellsToRow cells = "|" <> T.intercalate "|" cells <> "|"
-  let header = if all null headers then "" else cellsToRow hs <> "\n"
-  let blocksToCell (align, bs) = do
-        contents <- stripTrailingNewlines <$> blockListToTextile opts bs
-        let alignMarker = case align of
-                               AlignLeft    -> "<. "
-                               AlignRight   -> ">. "
-                               AlignCenter  -> "=. "
-                               AlignDefault -> ""
-        return $ alignMarker <> contents
-  let rowToCells = mapM blocksToCell . zip aligns
-  bs <- mapM rowToCells rows'
-  let body = T.unlines $ map cellsToRow bs
-  return $ header <> body
-
-blockToTextile opts (Table capt aligns widths headers rows') = do
-  let alignStrings = map alignmentToText aligns
-  captionDoc <- if null capt
-                   then return ""
-                   else do
-                      c <- inlineListToTextile opts capt
-                      return $ "<caption>" <> c <> "</caption>\n"
-  let percent w = tshow (truncate (100*w) :: Integer) <> "%"
-  let coltags = if all (== 0.0) widths
-                   then ""
-                   else T.unlines $ map
-                         (\w -> "<col width=\"" <> percent w <> "\" />") widths
-  head' <- if all null headers
-              then return ""
-              else do
-                 hs <- tableRowToTextile opts alignStrings 0 headers
-                 return $ "<thead>\n" <> hs <> "\n</thead>\n"
-  body' <- zipWithM (tableRowToTextile opts alignStrings) [1..] rows'
-  return $ "<table>\n" <> captionDoc <> coltags <> head' <>
-            "<tbody>\n" <> T.unlines body' <> "</tbody>\n</table>\n"
+blockToTextile opts (Table _ blkCapt specs thead tbody tfoot)
+  = case toLegacyTable blkCapt specs thead tbody tfoot of
+      ([], aligns, widths, headers, rows') | all (==0) widths -> do
+        hs <- mapM (liftM (("_. " <>) . stripTrailingNewlines) . blockListToTextile opts) headers
+        let cellsToRow cells = "|" <> T.intercalate "|" cells <> "|"
+        let header = if all null headers then "" else cellsToRow hs <> "\n"
+        let blocksToCell (align, bs) = do
+              contents <- stripTrailingNewlines <$> blockListToTextile opts bs
+              let alignMarker = case align of
+                                     AlignLeft    -> "<. "
+                                     AlignRight   -> ">. "
+                                     AlignCenter  -> "=. "
+                                     AlignDefault -> ""
+              return $ alignMarker <> contents
+        let rowToCells = mapM blocksToCell . zip aligns
+        bs <- mapM rowToCells rows'
+        let body = T.unlines $ map cellsToRow bs
+        return $ header <> body
+      (capt, aligns, widths, headers, rows') -> do
+        let alignStrings = map alignmentToText aligns
+        captionDoc <- if null capt
+                         then return ""
+                         else do
+                            c <- inlineListToTextile opts capt
+                            return $ "<caption>" <> c <> "</caption>\n"
+        let percent w = tshow (truncate (100*w) :: Integer) <> "%"
+        let coltags = if all (== 0.0) widths
+                         then ""
+                         else T.unlines $ map
+                               (\w -> "<col width=\"" <> percent w <> "\" />") widths
+        head' <- if all null headers
+                    then return ""
+                    else do
+                       hs <- tableRowToTextile opts alignStrings 0 headers
+                       return $ "<thead>\n" <> hs <> "\n</thead>\n"
+        body' <- zipWithM (tableRowToTextile opts alignStrings) [1..] rows'
+        return $ "<table>\n" <> captionDoc <> coltags <> head' <>
+                  "<tbody>\n" <> T.unlines body' <> "</tbody>\n</table>\n"
 
 blockToTextile opts x@(BulletList items) = do
   oldUseTags <- gets stUseTags
@@ -385,6 +385,12 @@
   return $ if '_' `elemText` contents
               then "<em>" <> contents <> "</em>"
               else "_" <> contents <> "_"
+
+inlineToTextile opts (Underline lst) = do
+  contents <- inlineListToTextile opts lst
+  return $ if '+' `elemText` contents
+              then "<u>" <> contents <> "</u>"
+              else "+" <> contents <> "+"
 
 inlineToTextile opts (Strong lst) = do
   contents <- inlineListToTextile opts lst
diff --git a/src/Text/Pandoc/Writers/XWiki.hs b/src/Text/Pandoc/Writers/XWiki.hs
--- a/src/Text/Pandoc/Writers/XWiki.hs
+++ b/src/Text/Pandoc/Writers/XWiki.hs
@@ -43,6 +43,7 @@
 import Text.Pandoc.Options
 import Text.Pandoc.Shared
 import Text.Pandoc.Writers.MediaWiki (highlightingLangs)
+import Text.Pandoc.Writers.Shared (toLegacyTable)
 
 data WriterState = WriterState {
   listLevel :: Text -- String at the beginning of items
@@ -122,8 +123,9 @@
   return $ vcat contents <> if Text.null lev then "\n" else ""
 
 -- TODO: support more features
-blockToXWiki (Table _ _ _ headers rows') = do
-  headers' <- mapM (tableCellXWiki True) headers
+blockToXWiki (Table _ blkCapt specs thead tbody tfoot) = do
+  let (_, _, _, headers, rows') = toLegacyTable blkCapt specs thead tbody tfoot
+  headers' <- mapM (tableCellXWiki True) $ take (length specs) $ headers ++ repeat []
   otherRows <- mapM formRow rows'
   return $ Text.unlines (Text.unwords headers':otherRows)
 
@@ -160,6 +162,10 @@
 inlineToXWiki (Emph lst) = do
   contents <- inlineListToXWiki lst
   return $ "//" <> contents <> "//"
+
+inlineToXWiki (Underline lst) = do
+  contents <- inlineListToXWiki lst
+  return $ "__" <> contents <> "__"
 
 inlineToXWiki (Strong lst) = do
   contents <- inlineListToXWiki lst
diff --git a/src/Text/Pandoc/Writers/ZimWiki.hs b/src/Text/Pandoc/Writers/ZimWiki.hs
--- a/src/Text/Pandoc/Writers/ZimWiki.hs
+++ b/src/Text/Pandoc/Writers/ZimWiki.hs
@@ -34,7 +34,7 @@
                           writerWrapText))
 import Text.Pandoc.Shared (escapeURI, isURI, linesToPara, removeFormatting, trimr)
 import Text.Pandoc.Templates (renderTemplate)
-import Text.Pandoc.Writers.Shared (defField, metaToContext)
+import Text.Pandoc.Writers.Shared (defField, metaToContext, toLegacyTable)
 
 data WriterState = WriterState {
     stIndent  :: Text,           -- Indent after the marker at the beginning of list items
@@ -132,7 +132,8 @@
   contents <- blockListToZimWiki opts blocks
   return $ T.unlines $ map ("> " <>) $ T.lines contents
 
-blockToZimWiki opts (Table capt aligns _ headers rows) = do
+blockToZimWiki opts (Table _ blkCapt specs thead tbody tfoot) = do
+  let (capt, aligns, _, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot
   captionDoc <- if null capt
                    then return ""
                    else do
@@ -271,6 +272,10 @@
 inlineToZimWiki opts (Emph lst) = do
   contents <- inlineListToZimWiki opts lst
   return $ "//" <> contents <> "//"
+
+inlineToZimWiki opts (Underline lst) = do
+  contents <- inlineListToZimWiki opts lst
+  return $ "__" <> contents <> "__"
 
 inlineToZimWiki opts (Strong lst) = do
   contents <- inlineListToZimWiki opts lst
diff --git a/stack.yaml b/stack.yaml
--- a/stack.yaml
+++ b/stack.yaml
@@ -12,19 +12,23 @@
 packages:
 - '.'
 extra-deps:
-- pandoc-types-1.20
-- texmath-0.12.0.1
-- haddock-library-1.8.0
-- skylighting-0.8.3.2
-- skylighting-core-0.8.3.2
-- regex-pcre-builtin-0.95.0.8.8.35
+- pandoc-types-1.21
+- pandoc-citeproc-0.17.0.1
+- texmath-0.12.0.2
+- haddock-library-1.9.0
+- skylighting-0.8.5
+- skylighting-core-0.8.5
+- regex-pcre-builtin-0.95.1.2.8.43
+- regex-base-0.94.0.0
 - doclayout-0.3
 - emojis-0.1
-- jira-wiki-markup-1.1.3
-- HsYAML-0.2.0.0
+- hslua-1.1.2
+- jira-wiki-markup-1.3.2
+- HsYAML-0.2.1.0
 - HsYAML-aeson-0.2.0.0
-- doctemplates-0.8.1
-- pandoc-citeproc-0.17
+- doctemplates-0.8.2
 ghc-options:
    "$locals": -fhide-source-paths -Wno-missing-home-modules
 resolver: lts-14.6
+nix:
+  packages: [zlib]
diff --git a/test/Tests/Command.hs b/test/Tests/Command.hs
--- a/test/Tests/Command.hs
+++ b/test/Tests/Command.hs
@@ -17,8 +17,10 @@
 import Data.Algorithm.Diff
 import qualified Data.ByteString as BS
 import qualified Data.Text as T
-import Data.List (isSuffixOf)
+import Data.List (isSuffixOf, intercalate)
+import Data.Maybe (catMaybes)
 import System.Directory
+import qualified System.Environment as Env
 import System.Exit
 import System.FilePath (joinPath, splitDirectories, takeDirectory, (</>))
 import System.IO (hPutStr, stderr)
@@ -38,15 +40,15 @@
         -> String    -- ^ Expected output
         -> TestTree
 runTest testname pandocpath cmd inp norm = testCase testname $ do
+  mldpath   <- Env.lookupEnv "LD_LIBRARY_PATH"
+  mdyldpath <- Env.lookupEnv "DYLD_LIBRARY_PATH"
   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 dynlibEnv = [("DYLD_LIBRARY_PATH", intercalate ":" $ catMaybes [mbDynlibDir, mdyldpath])
+                  ,("LD_LIBRARY_PATH",   intercalate ":" $ catMaybes [mbDynlibDir, mldpath])]
   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
diff --git a/test/Tests/Lua.hs b/test/Tests/Lua.hs
--- a/test/Tests/Lua.hs
+++ b/test/Tests/Lua.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 {- |
    Module      : Tests.Lua
    Copyright   : © 2017-2020 Albert Krewinkel
@@ -28,11 +29,13 @@
 import Text.Pandoc.Class (runIOorExplode, setUserDataDir)
 import Text.Pandoc.Definition (Block (BlockQuote, Div, Para), Inline (Emph, Str),
                                Attr, Meta, Pandoc, pandocTypesVersion)
+import Text.Pandoc.Error (PandocError (PandocLuaError))
 import Text.Pandoc.Filter (Filter (LuaFilter), applyFilters)
 import Text.Pandoc.Lua (runLua)
 import Text.Pandoc.Options (def)
 import Text.Pandoc.Shared (pandocVersion)
 
+import qualified Control.Monad.Catch as Catch
 import qualified Foreign.Lua as Lua
 import qualified Data.Text as T
 import qualified Data.Text.Encoding as TE
@@ -169,6 +172,12 @@
       Lua.liftIO . assertEqual "pandoc-types version is wrong" pandocTypesVersion
         =<< Lua.peek Lua.stackTop
 
+  , testCase "require file" $
+    assertFilterConversion "requiring file failed"
+      "require-file.lua"
+      (doc $ para "ignored")
+      (doc $ para (str . T.pack $ "lua" </> "require-file.lua"))
+
   , testCase "Allow singleton inline in constructors" . runLuaTest $ do
       Lua.liftIO . assertEqual "Not the exptected Emph" (Emph [Str "test"])
         =<< Lua.callFunc "pandoc.Emph" (Str "test")
@@ -197,12 +206,13 @@
 
   , testCase "informative error messages" . runLuaTest $ do
       Lua.pushboolean True
-      err <- Lua.peekEither Lua.stackTop
-      case (err :: Either String Pandoc) of
-        Left msg -> do
+      eitherPandoc <- Catch.try (Lua.peek Lua.stackTop :: Lua.Lua Pandoc)
+      case eitherPandoc of
+        Left (PandocLuaError msg) -> do
           let expectedMsg = "Could not get Pandoc value: "
                             <> "table expected, got boolean"
           Lua.liftIO $ assertEqual "unexpected error message" expectedMsg msg
+        Left e -> error ("Expected a Lua error, but got " <> show e)
         Right _ -> error "Getting a Pandoc element from a bool should fail."
   ]
 
@@ -223,10 +233,7 @@
     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
+    Lua.peek (-1)
 
 runLuaTest :: Lua.Lua a -> IO a
 runLuaTest op = runIOorExplode $ do
diff --git a/test/Tests/Old.hs b/test/Tests/Old.hs
--- a/test/Tests/Old.hs
+++ b/test/Tests/Old.hs
@@ -15,8 +15,11 @@
 import Prelude
 import Data.Algorithm.Diff
 import Prelude hiding (readFile)
+import Data.List (intercalate)
+import Data.Maybe (catMaybes)
 import System.Exit
 import System.FilePath (joinPath, splitDirectories, (<.>), (</>))
+import qualified System.Environment as Env
 import Text.Pandoc.Process (pipeProcess)
 import Test.Tasty (TestTree, testGroup)
 import Test.Tasty.Golden.Advanced (goldenTest)
@@ -298,12 +301,12 @@
     (compareValues norm options) updateGolden
   where getExpected = normalizer <$> readFile' norm
         getActual   = do
+              mldpath   <- Env.lookupEnv "LD_LIBRARY_PATH"
+              mdyldpath <- Env.lookupEnv "DYLD_LIBRARY_PATH"
               let mbDynlibDir = findDynlibDir (reverse $
                                  splitDirectories pandocPath)
-              let dynlibEnv = case mbDynlibDir of
-                                   Nothing  -> []
-                                   Just d   -> [("DYLD_LIBRARY_PATH", d),
-                                                ("LD_LIBRARY_PATH", d)]
+              let dynlibEnv = [("DYLD_LIBRARY_PATH", intercalate ":" $ catMaybes [mbDynlibDir, mdyldpath])
+                              ,("LD_LIBRARY_PATH",   intercalate ":" $ catMaybes [mbDynlibDir, mldpath])]
               let env = dynlibEnv ++
                         [("TMP","."),("LANG","en_US.UTF-8"),("HOME", "./")]
               (ec, out) <- pipeProcess (Just env) pandocPath options mempty
diff --git a/test/Tests/Readers/Docx.hs b/test/Tests/Readers/Docx.hs
--- a/test/Tests/Readers/Docx.hs
+++ b/test/Tests/Readers/Docx.hs
@@ -90,9 +90,8 @@
 -- testForWarnings = testForWarningsWithOpts defopts
 
 getMedia :: FilePath -> FilePath -> IO (Maybe B.ByteString)
-getMedia archivePath mediaPath = do
-  zf <- toArchive <$> B.readFile archivePath
-  return $ fromEntry <$> findEntryByPath ("word/" ++ mediaPath) zf
+getMedia archivePath mediaPath = fmap fromEntry . findEntryByPath
+    ("word/" ++ mediaPath) . toArchive <$> B.readFile archivePath
 
 compareMediaPathIO :: FilePath -> MediaBag -> FilePath -> IO Bool
 compareMediaPathIO mediaPath mediaBag docxPath = do
diff --git a/test/Tests/Readers/DokuWiki.hs b/test/Tests/Readers/DokuWiki.hs
--- a/test/Tests/Readers/DokuWiki.hs
+++ b/test/Tests/Readers/DokuWiki.hs
@@ -22,7 +22,6 @@
 import Text.Pandoc
 import Text.Pandoc.Arbitrary ()
 import Text.Pandoc.Builder
-import Text.Pandoc.Shared (underlineSpan)
 
 dokuwiki :: Text -> Pandoc
 dokuwiki = purely $ readDokuWiki def{ readerStandalone = True }
@@ -42,7 +41,7 @@
             para (emph "italic")
           , "Underlined" =:
             "__underlined__" =?>
-            para (underlineSpan "underlined")
+            para (underline "underlined")
           , "Monospaced" =:
             "''monospaced''" =?>
             para (code "monospaced")
@@ -51,7 +50,7 @@
             para (code "monospaced")
           , "Combined" =:
             "**__//''combine''//__**" =?>
-            para (strong $ underlineSpan $ emph $ code "combine")
+            para (strong $ underline $ emph $ code "combine")
           , "Nowiki" =:
             T.unlines [ "<nowiki>"
                       , "This is some text which contains addresses like this: http://www.splitbrain.org and **formatting**, but nothing is done with it."
@@ -296,27 +295,22 @@
           T.unlines [ "| foo | bar |"
                     , "| bat | baz |"
                     ] =?>
-          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]
-                       []
-                       [[plain "foo", plain "bar"]
-                       ,[plain "bat", plain "baz"]]
+          simpleTable [] [[plain "foo", plain "bar"]
+                         ,[plain "bat", plain "baz"]]
         , "Table with header" =:
           T.unlines [ "^ foo ^ bar ^"
                     , "| bat | baz |"
                     ] =?>
-          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]
-                       [plain "foo", plain "bar"]
-                       [[plain "bat", plain "baz"]]
+          simpleTable [plain "foo", plain "bar"] [[plain "bat", plain "baz"]]
         , "Table with colspan" =:
           T.unlines [ "^ 0,0 ^ 0,1 ^ 0,2 ^"
                     , "| 1,0 | 1,1 ||"
                     , "| 2,0 | 2,1 | 2,2 |"
                     ] =?>
-          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0), (AlignDefault, 0.0)]
-                       [plain "0,0", plain "0,1", plain "0,2"]
-                       [[plain "1,0", plain "1,1", mempty]
-                       ,[plain "2,0", plain "2,1", plain "2,2"]
-                       ]
+          simpleTable [plain "0,0", plain "0,1", plain "0,2"]
+                      [[plain "1,0", plain "1,1", mempty]
+                      ,[plain "2,0", plain "2,1", plain "2,2"]
+                      ]
         , "Indented code block" =:
           T.unlines [ "foo"
                     , "  bar"
diff --git a/test/Tests/Readers/HTML.hs b/test/Tests/Readers/HTML.hs
--- a/test/Tests/Readers/HTML.hs
+++ b/test/Tests/Readers/HTML.hs
@@ -21,7 +21,8 @@
 import Test.Tasty.Options (IsOption(defaultValue))
 import Tests.Helpers
 import Text.Pandoc
-import Text.Pandoc.Shared (isHeaderBlock)
+import Text.Pandoc.Writers.Shared (toLegacyTable)
+import Text.Pandoc.Shared (isHeaderBlock, onlySimpleTableCells)
 import Text.Pandoc.Arbitrary ()
 import Text.Pandoc.Builder
 import Text.Pandoc.Walk (walk)
@@ -39,6 +40,14 @@
 makeRoundTrip (Div attr bs) = Div attr $ filter (not . isHeaderBlock) bs
 -- avoids round-trip failures related to makeSections
 -- e.g. with [Div ("loc",[],[("a","11"),("b_2","a b c")]) [Header 3 ("",[],[]) []]]
+makeRoundTrip b@(Table _attr blkCapt specs thead tbody tfoot) =
+  let (_capt, _aligns, widths, headers, rows') =
+        toLegacyTable blkCapt specs thead tbody tfoot
+      isSimple = onlySimpleTableCells (headers:rows')
+  in
+     if all (== 0.0) widths && not isSimple
+        then Para [Str "weird table omitted"]
+        else b
 makeRoundTrip x           = x
 
 removeRawInlines :: Inline -> Inline
diff --git a/test/Tests/Readers/JATS.hs b/test/Tests/Readers/JATS.hs
--- a/test/Tests/Readers/JATS.hs
+++ b/test/Tests/Readers/JATS.hs
@@ -21,6 +21,8 @@
 import Text.Pandoc.Arbitrary ()
 import Text.Pandoc.Builder
 
+import qualified Data.Text as T
+
 jats :: Text -> Pandoc
 jats = purely $ readJATS def
 
@@ -125,5 +127,20 @@
             \  <title><inline-graphic mimetype=\"image\" mime-subtype=\"jpeg\" xlink:href=\"imgs/foo.jpg\" /></title>\n\
             \</sec>"
             =?> header 1 (image "imgs/foo.jpg" "" mempty)
+          ]
+
+        , testGroup "metadata"
+          [ test jats "abstract" $
+            T.unlines [ "<front>"
+                      , "<article-meta>"
+                      , "<abstract>"
+                      , "<p>Paragraph 1</p>"
+                      , "<p>Paragraph 2</p>"
+                      , "</abstract>"
+                      , "</article-meta>"
+                      , "</front>"
+                      ] =?>
+            let abstract = para "Paragraph 1" <> para "Paragraph 2"
+            in setMeta "abstract" abstract $ doc mempty
           ]
         ]
diff --git a/test/Tests/Readers/Jira.hs b/test/Tests/Readers/Jira.hs
--- a/test/Tests/Readers/Jira.hs
+++ b/test/Tests/Readers/Jira.hs
@@ -14,8 +14,8 @@
 -}
 module Tests.Readers.Jira (tests) where
 
-import Prelude
-import Data.Text (Text)
+import Prelude hiding (unlines)
+import Data.Text (Text, unlines)
 import Test.Tasty (TestTree, testGroup)
 import Tests.Helpers (ToString, purely, test, (=?>))
 import Text.Pandoc (def)
@@ -57,6 +57,16 @@
     [ "simple block quote" =:
       "bq. _Don't_ quote me on this." =?>
       blockQuote (para $ emph "Don't" <> space <> "quote me on this.")
+
+    , "block quote between paragraphs" =:
+      unlines [ "Regular text."
+              , "bq.This is a blockquote"
+              , "More text."
+              ] =?>
+      mconcat [ para "Regular text."
+              , blockQuote (para "This is a blockquote")
+              , para "More text."
+              ]
     ]
 
   , testGroup "table"
@@ -101,21 +111,68 @@
       "HCO ~3~^-^" =?>
       para ("HCO " <> subscript "3" <> superscript "-")
 
+    , "citation" =:
+      "Et tu, Brute? ??Caesar??" =?>
+      para ("Et tu, Brute? — " <> emph "Caesar")
+
     , "color" =:
       "This is {color:red}red{color}." =?>
       para ("This is " <> spanWith ("", [], [("color", "red")]) "red" <> ".")
 
+    , "hexcolor" =:
+      "{color:#00875A}green{color}" =?>
+      para (spanWith ("", [], [("color", "#00875A")]) "green")
+
     , "linebreak" =:
       "first\nsecond" =?>
       para ("first" <> linebreak <> "second")
 
-    , "link" =:
-      "[Example|https://example.org]" =?>
-      para (link "https://example.org" "" "Example")
+    , testGroup "links"
+      [ "external" =:
+        "[Example|https://example.org]" =?>
+        para (link "https://example.org" "" "Example")
 
+      , "email" =:
+        "[mailto:me@example.org]" =?>
+        para (link "mailto:me@example.org" "" "me@example.org")
+
+      , "email with description" =:
+        "[email|mailto:me@example.org]" =?>
+        para (link "mailto:me@example.org" "" "email")
+
+      , "attachment" =:
+        "[^example.txt]" =?>
+        para (linkWith ("", ["attachment"], []) "example.txt" "" "example.txt")
+
+      , "attachment with description" =:
+        "[an example^example.txt]" =?>
+        para (linkWith ("", ["attachment"], []) "example.txt" "" "an example")
+
+      , "user" =:
+        "[~johndoe]" =?>
+        para (linkWith ("", ["user-account"], []) "~johndoe" "" "~johndoe")
+
+      , "user with description" =:
+        "[John Doe|~johndoe]" =?>
+        para (linkWith ("", ["user-account"], []) "~johndoe" "" "John Doe")
+      ]
+
     , "image" =:
       "!https://example.com/image.jpg!" =?>
       para (image "https://example.com/image.jpg" "" mempty)
+
+    , "thumbnail image" =:
+      "!image.jpg|thumbnail!" =?>
+      para (imageWith ("", ["thumbnail"], []) "image.jpg" "" mempty)
+
+    , "image with attributes" =:
+      "!image.gif|align=right, vspace=4, title=Hello!" =?>
+      let attr = ("", [], [("align", "right"), ("vspace", "4")])
+      in para $ imageWith attr "image.gif" "Hello" mempty
+
+    , "inserted text" =:
+      "+the new version+" =?>
+      para (underline "the new version")
 
     , "HTML entity" =:
       "me &amp; you" =?> para "me & you"
diff --git a/test/Tests/Readers/LaTeX.hs b/test/Tests/Readers/LaTeX.hs
--- a/test/Tests/Readers/LaTeX.hs
+++ b/test/Tests/Readers/LaTeX.hs
@@ -36,8 +36,14 @@
 (=:) = test latex
 
 simpleTable' :: [Alignment] -> [[Blocks]] -> Blocks
-simpleTable' aligns = table "" (zip aligns (repeat 0.0))
-                      (map (const mempty) aligns)
+simpleTable' aligns rows
+  = table emptyCaption
+          (zip aligns (repeat ColWidthDefault))
+          (TableHead nullAttr [])
+          [TableBody nullAttr 0 [] $ map toRow rows]
+          (TableFoot nullAttr [])
+  where
+    toRow = Row nullAttr . map simpleCell
 
 tokUntokRt :: String -> Bool
 tokUntokRt s = untokenize (tokenize "random" t) == t
diff --git a/test/Tests/Readers/Man.hs b/test/Tests/Readers/Man.hs
--- a/test/Tests/Readers/Man.hs
+++ b/test/Tests/Readers/Man.hs
@@ -30,6 +30,9 @@
      => String -> (Text, c) -> TestTree
 (=:) = test man
 
+toRow :: [Blocks] -> Row
+toRow = Row nullAttr . map simpleCell
+
 tests :: [TestTree]
 tests = [
   -- .SH "HEllo bbb" "aaa"" as"
@@ -122,12 +125,21 @@
   testGroup "Tables" [
       "t1" =:
       ".TS\nallbox;\nl l l.\na\tb\tc\nd\te\tf\n.TE"
-      =?> table mempty (replicate 3 (AlignLeft, 0.0)) [] [
-        map (plain . str ) ["a", "b", "c"],
-        map (plain . str ) ["d", "e", "f"]
-      ],
+      =?> table
+            emptyCaption
+            (replicate 3 (AlignLeft, ColWidthDefault))
+            (TableHead nullAttr [])
+            [TableBody nullAttr 0 [] $ map toRow
+              [map (plain . str ) ["a", "b", "c"],
+               map (plain . str ) ["d", "e", "f"]]]
+            (TableFoot nullAttr []),
       "longcell" =:
       ".TS\n;\nr.\nT{\na\nb\nc d\nT}\nf\n.TE"
-      =?> table mempty [(AlignRight, 0.0)] [] [[plain $ text "a b c d"], [plain $ str "f"]]
+      =?> table
+            emptyCaption
+            [(AlignRight, ColWidthDefault)]
+            (TableHead nullAttr [])
+            [TableBody nullAttr 0 [] $ map toRow [[plain $ text "a b c d"], [plain $ str "f"]]]
+            (TableFoot nullAttr [])
     ]
   ]
diff --git a/test/Tests/Readers/Markdown.hs b/test/Tests/Readers/Markdown.hs
--- a/test/Tests/Readers/Markdown.hs
+++ b/test/Tests/Readers/Markdown.hs
@@ -171,6 +171,53 @@
             =?> para (code "*" <> space <> str "{.haskell" <> space <>
                       str ".special" <> space <> str "x=\"7\"}")
           ]
+        , testGroup "inline code in lists (regression tests for #6284)" $
+          let lists = [("ordered", "1. ", ol), ("bullet", "- ", ul)]
+              ol = orderedListWith (1, Decimal, Period)
+              ul = bulletList
+              items =
+                [ ("in text"                , ["If `(1) x`, then `2`"], [text "If " <> code "(1) x" <> text ", then " <> code "2"])
+                , ("at start"               , ["`#. x`"              ], [code "#. x"                                             ])
+                , ("at start"               , ["`- x`"               ], [code "- x"                                              ])
+                , ("after literal backticks", ["`x``#. x`"           ], [code "x``#. x"                                          ])
+                , ("after literal backticks", ["`x``- x`"            ], [code "x``- x"                                           ])
+                ]
+              lis = ["`text","y","x`"]
+              lis' = ["text","y","x"]
+              bldLsts w lsts txts
+                = let (res, res', f) =
+                         foldr (\((_, _, lt), lc) (acc, tacc, t) ->
+                             if lt [] == t []
+                             then (acc, lc : tacc, lt)
+                             else (join t tacc acc, [lc], lt))
+                           (mempty, [], mconcat)
+                           (zip lsts (map text txts))
+                      join t tacc acc = case tacc of
+                          [] -> acc
+                          [x] -> t [plain x] <> acc
+                          xs -> t (map w xs) <> acc
+                  in join f res' res
+          in ["code with list marker "<>mp<>" in " <> ln <> " list" =:
+              T.intercalate "\n" (map (lstr <>) istrs) =?> lbld (map plain iblds)
+              | (ln, lstr, lbld) <- lists, (mp, istrs, iblds) <- items]
+          <> [ "lists with newlines in backticks" =:
+               T.intercalate "\n" (zipWith (\i (_, lt, _) -> lt <> i) lis lsts)
+               =?> bldLsts plain lsts lis
+             | lsts <- [ [i, j, k] | i <- lists, j <- lists, k <- lists]
+             ]
+          <> [ "lists with newlines and indent in backticks" =:
+               T.intercalate ("\n" <> T.replicate 4 " ") (zipWith (\i (_, lt, _) -> lt <> i) lis lsts)
+               =?> let (_, _, f) = head lsts
+                   in f [plain $ code $ T.intercalate (T.replicate 5 " ") $ head lis' : zipWith (\i (_, lt, _) -> lt <> i) (tail lis') (tail lsts)]
+             | lsts <- [ [i, j, k] | i <- lists, j <- lists, k <- lists]
+             ]
+          <> [ "lists with blank lines and indent in backticks" =:
+               T.intercalate ("\n\n" <> T.replicate 4 " ") (zipWith (\i (_, lt, _) -> lt <> i) lis lsts)
+               <> "\n"
+               =?> let (_, _, f) = head lsts
+                   in f . pure $ (para . text $ head lis) <> bldLsts para (tail lsts) (tail lis)
+             | lsts <- [ [i, j, k] | i <- lists, j <- lists, k <- lists]
+             ]
         , testGroup "emph and strong"
           [ "two strongs in emph" =:
              "***a**b **c**d*" =?> para (emph (strong (str "a") <> str "b" <> space
diff --git a/test/Tests/Readers/Muse.hs b/test/Tests/Readers/Muse.hs
--- a/test/Tests/Readers/Muse.hs
+++ b/test/Tests/Readers/Muse.hs
@@ -25,7 +25,7 @@
 import Text.Pandoc
 import Text.Pandoc.Arbitrary ()
 import Text.Pandoc.Builder
-import Text.Pandoc.Shared (underlineSpan)
+import Text.Pandoc.Writers.Shared (toLegacyTable)
 import Text.Pandoc.Walk
 
 amuse :: Text -> Pandoc
@@ -42,23 +42,65 @@
 spcSep :: [Inlines] -> Inlines
 spcSep = mconcat . intersperse space
 
+simpleTable' :: Int -> Caption -> [Blocks] -> [[Blocks]] -> Blocks
+simpleTable' n capt headers rows
+  = table capt
+          (replicate n (AlignDefault, ColWidthDefault))
+          (TableHead nullAttr $ toHeaderRow headers)
+          [TableBody nullAttr 0 [] $ map toRow rows]
+          (TableFoot nullAttr [])
+  where
+    toRow = Row nullAttr . map simpleCell
+    toHeaderRow l = if null l then [] else [toRow l]
+
 -- Tables don't round-trip yet
 --
 makeRoundTrip :: Block -> Block
-makeRoundTrip t@(Table _caption aligns widths headers rows) =
+makeRoundTrip t@(Table tattr blkCapt specs thead tbody tfoot) =
   if isSimple && numcols > 1
     then t
     else Para [Str "table was here"]
-  where numcols = maximum (length aligns : length widths : map length (headers:rows))
-        hasSimpleCells = all isSimpleCell (concat (headers:rows))
+  where (_, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot
+        numcols = maximum (length aligns : length widths : map length (headers:rows))
         isLineBreak LineBreak = Any True
         isLineBreak _         = Any False
         hasLineBreak = getAny . query isLineBreak
-        isSimple = hasSimpleCells && all (== 0) widths
-        isSimpleCell [Plain ils] = not (hasLineBreak ils)
-        isSimpleCell [Para ils ] = not (hasLineBreak ils)
-        isSimpleCell []          = True
-        isSimpleCell _           = False
+        isSimple = and [ isSimpleHead thead
+                       , isSimpleBodies tbody
+                       , isSimpleFoot tfoot
+                       , all (== 0) widths
+                       , isNullAttr tattr
+                       , simpleCapt ]
+        isNullAttr ("", [], []) = True
+        isNullAttr _            = False
+        isAlignDefault AlignDefault = True
+        isAlignDefault _            = False
+        isSimpleRow (Row attr body) = isNullAttr attr && all isSimpleCell body
+        isSimpleCell (Cell attr ali h w body)
+          = and [ h == 1
+                , w == 1
+                , isNullAttr attr
+                , isAlignDefault ali
+                , isSimpleCellBody body ]
+        isSimpleCellBody [Plain ils] = not (hasLineBreak ils)
+        isSimpleCellBody [Para ils ] = not (hasLineBreak ils)
+        isSimpleCellBody []          = True
+        isSimpleCellBody _           = False
+        simpleCapt = case blkCapt of
+          Caption Nothing [Para _]  -> True
+          Caption Nothing [Plain _] -> True
+          _                         -> False
+        isSimpleHead (TableHead attr [r])
+          = isNullAttr attr && isSimpleRow r
+        isSimpleHead _ = False
+        isSimpleBody (TableBody attr rhc hd bd) = and [ isNullAttr attr
+                                                      , rhc == 0
+                                                      , null hd
+                                                      , all isSimpleRow bd ]
+        isSimpleBodies [b] = isSimpleBody b
+        isSimpleBodies _   = False
+        isSimpleFoot (TableFoot attr rs) = isNullAttr attr && null rs
+
 makeRoundTrip (OrderedList (start, LowerAlpha, _) items) = OrderedList (start, Decimal, Period) items
 makeRoundTrip (OrderedList (start, UpperAlpha, _) items) = OrderedList (start, Decimal, Period) items
 makeRoundTrip x = x
@@ -166,7 +208,7 @@
         para (strong . emph $ "foo******bar")
 
       , test emacsMuse "Underline"
-        ("_Underline_" =?> para (underlineSpan "Underline"))
+        ("_Underline_" =?> para (underline "Underline"))
 
       , "Superscript tag" =: "<sup>Superscript</sup>" =?> para (superscript "Superscript")
 
@@ -950,14 +992,10 @@
     , testGroup "Tables"
         [ "Two cell table" =:
           "One | Two" =?>
-          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]
-                       []
-                       [[plain "One", plain "Two"]]
+          simpleTable [] [[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"]]
+          simpleTable [] [[plain "One two", plain "three four"]]
         , "Not a table" =:
           "One| Two" =?>
           para (text "One| Two")
@@ -969,38 +1007,30 @@
             [ "One |  Two"
             , "Three  | Four"
             ] =?>
-          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]
-                       []
-                       [[plain "One", plain "Two"],
-                       [plain "Three", plain "Four"]]
+          simpleTable [] [[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"]]
+          simpleTable [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"]]
+          simpleTable [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"]]
+          simpleTable [plain "Baz", plain "foo"] [[plain "Bar", plain "baz"],
+                                                  [plain "Foo", plain "bar"]]
         , "Table with caption" =:
           T.unlines
             [ "Foo || bar || baz"
@@ -1008,32 +1038,30 @@
             , "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"]]
+          simpleTable' 3 (simpleCaption $ plain $ text "Table caption")
+                       [plain "Foo", plain "bar", plain "baz"]
+                       [[plain "First", plain "row", plain "here"],
+                        [plain "Second", plain "row", plain "there"]]
         , "Table caption with +" =:
           T.unlines
             [ "Foo | bar"
             , "|+ Table + caption +|"
             ] =?>
-          table (text "Table + caption") (replicate 2 (AlignDefault, 0.0))
-            []
-            [[plain "Foo", plain "bar"]]
+          simpleTable' 2 (simpleCaption $ plain $ text "Table + caption")
+                       []
+                       [[plain "Foo", plain "bar"]]
         , "Caption without table" =:
           "|+ Foo bar baz +|" =?>
-          table (text "Foo bar baz") [] [] []
+          simpleTable' 0 (simpleCaption $ plain $ 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"]]
+          simpleTable [] [[plain "Foo", plain "bar"],
+                          [plain "Baz", plain "foo"],
+                          [plain "Bar", plain "baz"]]
         , "Empty cells" =:
           T.unlines
             [ " | Foo"
@@ -1041,40 +1069,33 @@
             , " bar |"
             , " || baz"
             ] =?>
-          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]
-            [plain "", plain "baz"]
-            [[plain "", plain "Foo"],
-             [plain "", plain ""],
-             [plain "bar", plain ""]]
+          simpleTable [plain "", plain "baz"] [[plain "", plain "Foo"],
+                                               [plain "", plain ""],
+                                               [plain "bar", plain ""]]
         , "Empty cell in the middle" =:
           T.unlines
             [ " 1 | 2 | 3"
             , " 4 |   | 6"
             , " 7 | 8 | 9"
             ] =?>
-          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0), (AlignDefault, 0.0)]
-            []
-            [[plain "1", plain "2", plain "3"],
-             [plain "4", mempty,    plain "6"],
-             [plain "7", plain "8", plain "9"]]
+          simpleTable []
+                      [[plain "1", plain "2", plain "3"],
+                       [plain "4", mempty,    plain "6"],
+                       [plain "7", plain "8", plain "9"]]
         , "Grid table" =:
           T.unlines
             [ "+-----+-----+"
             , "| foo | bar |"
             , "+-----+-----+"
             ] =?>
-          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]
-                       []
-                       [[para "foo", para "bar"]]
+          simpleTable [] [[para "foo", para "bar"]]
         , "Grid table inside list" =:
           T.unlines
             [ " - +-----+-----+"
             , "   | foo | bar |"
             , "   +-----+-----+"
             ] =?>
-          bulletList [table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]
-                                   []
-                                   [[para "foo", para "bar"]]]
+          bulletList [simpleTable [] [[para "foo", para "bar"]]]
         , "Grid table with two rows" =:
           T.unlines
             [ "+-----+-----+"
@@ -1083,10 +1104,8 @@
             , "| bat | baz |"
             , "+-----+-----+"
             ] =?>
-          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]
-                       []
-                       [[para "foo", para "bar"]
-                       ,[para "bat", para "baz"]]
+          simpleTable [] [[para "foo", para "bar"]
+                         ,[para "bat", para "baz"]]
         , "Grid table inside grid table" =:
           T.unlines
             [ "+-----+"
@@ -1095,11 +1114,7 @@
             , "|+---+|"
             , "+-----+"
             ] =?>
-          table mempty [(AlignDefault, 0.0)]
-                       []
-                       [[table mempty [(AlignDefault, 0.0)]
-                                      []
-                                      [[para "foo"]]]]
+          simpleTable [] [[simpleTable [] [[para "foo"]]]]
         , "Grid table with example" =:
           T.unlines
             [ "+------------+"
@@ -1108,9 +1123,7 @@
             , "| </example> |"
             , "+------------+"
             ] =?>
-          table mempty [(AlignDefault, 0.0)]
-                       []
-                       [[codeBlock "foo"]]
+          simpleTable [] [[codeBlock "foo"]]
         ]
     , testGroup "Lists"
       [ "Bullet list" =:
@@ -1479,15 +1492,11 @@
                        ]
       , "Definition list with table" =:
         " foo :: bar | baz" =?>
-        definitionList [ ("foo", [ table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]
-                                                []
-                                                [[plain "bar", plain "baz"]]
+        definitionList [ ("foo", [ simpleTable [] [[plain "bar", plain "baz"]]
                                  ])]
       , "Definition list with table inside bullet list" =:
         " - foo :: bar | baz" =?>
-        bulletList [definitionList [ ("foo", [ table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]
-                                                            []
-                                                            [[plain "bar", plain "baz"]]
+        bulletList [definitionList [ ("foo", [ simpleTable [] [[plain "bar", plain "baz"]]
                                              ])]]
       , test emacsMuse "Multi-line definition lists from Emacs Muse manual"
         (T.unlines
diff --git a/test/Tests/Readers/Org/Block/Table.hs b/test/Tests/Readers/Org/Block/Table.hs
--- a/test/Tests/Readers/Org/Block/Table.hs
+++ b/test/Tests/Readers/Org/Block/Table.hs
@@ -24,8 +24,19 @@
              -> [Blocks]
              -> [[Blocks]]
              -> Blocks
-simpleTable' n = table "" (replicate n (AlignDefault, 0.0))
+simpleTable' n = simpleTable'' emptyCaption $ replicate n (AlignDefault, ColWidthDefault)
 
+simpleTable'' :: Caption -> [ColSpec] -> [Blocks] -> [[Blocks]] -> Blocks
+simpleTable'' capt spec headers rows
+  = table capt
+          spec
+          (TableHead nullAttr $ toHeaderRow headers)
+          [TableBody nullAttr 0 [] $ map toRow rows]
+          (TableFoot nullAttr [])
+  where
+    toRow = Row nullAttr . map simpleCell
+    toHeaderRow l = if null l then [] else [toRow l]
+
 tests :: [TestTree]
 tests =
   [ "Single cell table" =:
@@ -121,12 +132,16 @@
                 , "| 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"  ]
-            ]
+      simpleTable''
+        emptyCaption
+        (zip
+          [AlignCenter, AlignRight, AlignDefault]
+          [ColWidthDefault, ColWidthDefault, ColWidthDefault])
+        []
+        [ [ 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 " =?>
@@ -143,23 +158,26 @@
                 , "| 1       | One  | foo  |"
                 , "| 2"
                 ] =?>
-      table "" (zip [AlignCenter, AlignRight] [0, 0])
-            [ plain "Numbers", plain "Text" ]
-            [ [ plain "1" , plain "One" , plain "foo" ]
-            , [ plain "2" ]
-            ]
+      simpleTable''
+        emptyCaption
+        (zip [AlignCenter, AlignRight] [ColWidthDefault, ColWidthDefault])
+        [ 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" ]
-            ]
+      simpleTable''
+        (simpleCaption $ plain "Hitchhiker's Multiplication Table")
+        [(AlignDefault, ColWidthDefault), (AlignDefault, ColWidthDefault)]
+        []
+        [ [ plain "x", plain "6" ]
+        , [ plain "9", plain "42" ]
+        ]
 
   , "named table" =:
       T.unlines [ "#+NAME: x-marks-the-spot"
diff --git a/test/Tests/Readers/Org/Directive.hs b/test/Tests/Readers/Org/Directive.hs
--- a/test/Tests/Readers/Org/Directive.hs
+++ b/test/Tests/Readers/Org/Directive.hs
@@ -162,6 +162,79 @@
                   ] =?>
         headerWith ("headline", [], mempty) 1 "Headline"
 
+    , testGroup "LaTeX"
+      [ testGroup "Include LaTeX fragments"
+        [ "Inline command" =:
+          T.unlines [ "#+OPTIONS: tex:t"
+                    , "Hello \\emph{Name}"
+                    ] =?>
+          para ("Hello" <> space <> emph "Name")
+
+        , "Alpha" =:
+          T.unlines [ "#+OPTIONS: tex:t"
+                    , "\\alpha"
+                    ] =?>
+          para "α"
+
+        , "equation environment" =:
+          T.unlines [ "#+OPTIONS: tex:t"
+                    , "\\begin{equation}"
+                    , "f(x) = x^2"
+                    , "\\end{equation}"
+                    ] =?>
+          rawBlock "latex" (T.unlines [ "\\begin{equation}"
+                                      , "f(x) = x^2"
+                                      , "\\end{equation}"
+                                      ])
+        ]
+
+      , testGroup "Ignore LaTeX fragments"
+        [ "Inline command" =:
+          T.unlines [ "#+OPTIONS: tex:nil"
+                    , "Hello \\emph{Emphasised}"
+                    ] =?>
+          para "Hello"
+
+        , "MathML symbol (alpha)" =:
+          T.unlines [ "#+OPTIONS: tex:nil"
+                    , "\\alpha"
+                    ] =?>
+          para "α"
+
+        , "equation environment" =:
+          T.unlines [ "#+OPTIONS: tex:nil"
+                    , "\\begin{equation}"
+                    , "f(x) = x^2"
+                    , "\\end{equation}"
+                    ] =?>
+          (mempty :: Blocks)
+        ]
+
+      , testGroup "Verbatim LaTeX"
+        [ "Inline command" =:
+          T.unlines [ "#+OPTIONS: tex:verbatim"
+                    , "Hello \\emph{Emphasised}"
+                    ] =?>
+          para "Hello \\emph{Emphasised}"
+
+        , "MathML symbol (alpha)" =:
+          T.unlines [ "#+OPTIONS: tex:verbatim"
+                    , "\\alpha"
+                    ] =?>
+          para "α"
+
+        , "equation environment" =:
+          T.unlines [ "#+OPTIONS: tex:verbatim"
+                    , "\\begin{equation}"
+                    , "f(x) = x^2"
+                    , "\\end{equation}"
+                    ] =?>
+          para (str "\\begin{equation}" <> softbreak <>
+                str "f(x) = x^2" <> softbreak <>
+                str "\\end{equation}")
+        ]
+      ]
+
     , testGroup "planning information"
       [ "include planning info after headlines" =:
         T.unlines [ "#+OPTIONS: p:t"
diff --git a/test/Tests/Readers/Org/Inline.hs b/test/Tests/Readers/Org/Inline.hs
--- a/test/Tests/Readers/Org/Inline.hs
+++ b/test/Tests/Readers/Org/Inline.hs
@@ -19,7 +19,6 @@
 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
@@ -49,7 +48,7 @@
 
   , "Underline" =:
       "_underline_" =?>
-      para (underlineSpan "underline")
+      para (underline "underline")
 
   , "Strikeout" =:
       "+Kill Bill+" =?>
@@ -215,6 +214,10 @@
                 , "[[file:guinea-pig.gif]]"
                 ] =?>
       para (imageWith ("", [], [("width", "50%")]) "guinea-pig.gif" "" "")
+
+    , "Uppercase extension" =:
+      "[[file:test.PNG]]" =?>
+      para (image "test.PNG" "" "")
     ]
 
   , "Explicit link" =:
diff --git a/test/Tests/Readers/Org/Meta.hs b/test/Tests/Readers/Org/Meta.hs
--- a/test/Tests/Readers/Org/Meta.hs
+++ b/test/Tests/Readers/Org/Meta.hs
@@ -23,15 +23,16 @@
 
 tests :: [TestTree]
 tests =
-  [ "Comment" =:
+  [ testGroup "Comments"
+    [ "Comment" =:
       "# Nothing to see here" =?>
       (mempty::Blocks)
 
-  , "Not a comment" =:
+    , "Hash not followed by space is text" =:
       "#-tag" =?>
       para "#-tag"
 
-  , "Comment surrounded by Text" =:
+    , "Comment surrounded by Text" =:
       T.unlines [ "Before"
                 , "# Comment"
                 , "After"
@@ -39,77 +40,194 @@
       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
+  , testGroup "Export settings"
+    [ "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
+    , testGroup "Author"
+      [ "sets 'author' field" =:
+        "#+author: John /Emacs-Fanboy/ Doe" =?>
+        let author = toList . spcSep $ [ "John", emph "Emacs-Fanboy", "Doe" ]
+            meta = setMeta "author" (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
+      , "Multiple author lines" =:
+        T.unlines [ "#+author: James Dewey Watson,"
+                  , "#+author: Francis Harry Compton Crick"
+                  ] =?>
+        let watson = toList "James Dewey Watson,"
+            crick = toList "Francis Harry Compton Crick"
+            meta = setMeta "author"
+                           (MetaInlines (watson ++ SoftBreak : 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
+    , "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
+    , testGroup "Description"
+      [ "Single line" =:
+        "#+DESCRIPTION: Explanatory text" =?>
+        let description = [Str "Explanatory", Space, Str "text"]
+            meta = setMeta "description" (MetaInlines description) nullMeta
+        in Pandoc meta mempty
 
-  , "Properties drawer" =:
-      T.unlines [ "  :PROPERTIES:"
-                , "  :setting: foo"
-                , "  :END:"
+      , "Multiline" =:
+        T.unlines [ "#+DESCRIPTION: /Short/ introduction"
+                  , "#+DESCRIPTION: to Org-mode"
+                  ] =?>
+        let description = [ Emph [Str "Short"], Space, Str "introduction"
+                          , SoftBreak
+                          , Str "to", Space, Str "Org-mode"
+                          ]
+            meta = setMeta "description" (MetaInlines description) nullMeta
+        in Pandoc meta mempty
+      ]
+
+    , "Subtitle" =:
+      T.unlines [ "#+SUBTITLE: Your Life in"
+                , "#+SUBTITLE: /Plain/ Text"
                 ] =?>
-      (mempty::Blocks)
+      let subtitle = "Your Life in" <> softbreak <> emph "Plain" <> " Text"
+      in Pandoc (setMeta "subtitle" (toMetaValue subtitle) nullMeta) mempty
 
-  , "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
+    , "Keywords" =:
+      T.unlines [ "#+KEYWORDS: pandoc, testing,"
+                , "#+KEYWORDS: Org"
+                ] =?>
+      let keywords = toList $ "pandoc, testing," <> softbreak <> "Org"
+          meta = setMeta "keywords" (MetaInlines keywords) 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
+    , "Institute" =:
+      "#+INSTITUTE: ACME Inc." =?>
+      Pandoc (setMeta "institute" ("ACME Inc." :: Inlines) nullMeta) mempty
 
-  , "LaTeX_class_options is translated to classoption" =:
-      "#+LATEX_CLASS_OPTIONS: [a4paper]" =?>
-      let meta = setMeta "classoption" (MetaString "a4paper") nullMeta
-      in Pandoc meta mempty
+    , testGroup "LaTeX"
+      [ "LATEX_HEADER" =:
+        "#+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_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
+      , "LATEX_HEADER_EXTRA" =:
+        "#+LATEX_HEADER_EXTRA: \\usepackage{calc}" =?>
+        let latexInlines = rawInline "latex" "\\usepackage{calc}"
+            inclList = toMetaValue [latexInlines]
+        in Pandoc (setMeta "header-includes" inclList nullMeta) mempty
 
-  , "later meta definitions take precedence" =:
-      T.unlines [ "#+AUTHOR: this will not be used"
-                , "#+author: Max"
+      , testGroup "LaTeX_CLASS"
+        [ "stored as documentclass" =:
+          "#+LATEX_CLASS: article" =?>
+          let meta = setMeta "documentclass" (MetaString "article") nullMeta
+          in Pandoc meta mempty
+
+        , "last definition takes precedence" =:
+          T.unlines [ "#+LATEX_CLASS: this will not be used"
+                    , "#+LATEX_CLASS: report"
+                    ] =?>
+          let meta = setMeta "documentclass" (MetaString "report") nullMeta
+          in Pandoc meta mempty
+        ]
+
+      , "LATEX_CLASS_OPTIONS as classoption" =:
+        "#+LATEX_CLASS_OPTIONS: [a4paper]" =?>
+        let meta = setMeta "classoption" (MetaString "a4paper") nullMeta
+        in Pandoc meta mempty
+      ]
+
+    , testGroup "HTML"
+      [ "HTML_HEAD values are added to header-includes" =:
+        "#+html_head: <meta/>" =?>
+        let html = rawInline "html" "<meta/>"
+            inclList = MetaList [MetaInlines (toList html)]
+            meta = setMeta "header-includes" inclList nullMeta
+        in Pandoc meta mempty
+
+      , "HTML_HEAD_EXTRA behaves like HTML_HEAD" =:
+        T.unlines [ "#+HTML_HEAD: <meta name=\"generator\" content=\"pandoc\">"
+                  , "#+HTML_HEAD_EXTRA: <meta charset=\"utf-8\">"
+                  ] =?>
+        let generator = rawInline "html"
+                                  "<meta name=\"generator\" content=\"pandoc\">"
+            charset = rawInline "html" "<meta charset=\"utf-8\">"
+            inclList = toMetaValue [generator, charset]
+        in Pandoc (setMeta "header-includes" inclList nullMeta) mempty
+      ]
+    ]
+
+  , testGroup "Non-export keywords"
+    [ testGroup "#+LINK"
+      [ "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/]"
+      ]
+
+    , "Unknown keyword" =:
+      T.unlines [ "#+UNKNOWN_KEYWORD: Chumbawamba"
+                , "#+ANOTHER_UNKNOWN: Blur"
                 ] =?>
-      let author = MetaInlines [Str "Max"]
-          meta = setMeta "author" (MetaList [author]) nullMeta
-      in Pandoc meta mempty
+      rawBlock "org" "#+UNKNOWN_KEYWORD: Chumbawamba" <>
+      rawBlock "org" "#+ANOTHER_UNKNOWN: Blur"
+    ]
 
+  , "Properties drawer" =:
+      T.unlines [ "  :PROPERTIES:"
+                , "  :setting: foo"
+                , "  :END:"
+                ] =?>
+      (mempty::Blocks)
+
   , "Logbook drawer" =:
       T.unlines [ "  :LogBook:"
                 , "  - State \"DONE\"       from \"TODO\"       [2014-03-03 Mon 11:00]"
@@ -157,48 +275,4 @@
                 ] =?>
       (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/Txt2Tags.hs b/test/Tests/Readers/Txt2Tags.hs
--- a/test/Tests/Readers/Txt2Tags.hs
+++ b/test/Tests/Readers/Txt2Tags.hs
@@ -23,7 +23,6 @@
 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
@@ -44,8 +43,19 @@
              -> [Blocks]
              -> [[Blocks]]
              -> Blocks
-simpleTable' n = table "" (replicate n (AlignCenter, 0.0))
+simpleTable' n = simpleTable'' $ replicate n (AlignCenter, ColWidthDefault)
 
+simpleTable'' :: [ColSpec] -> [Blocks] -> [[Blocks]] -> Blocks
+simpleTable'' spec headers rows
+  = table emptyCaption
+          spec
+          (TableHead nullAttr $ toHeaderRow headers)
+          [TableBody nullAttr 0 [] $ map toRow rows]
+          (TableFoot nullAttr [])
+  where
+    toRow = Row nullAttr . map simpleCell
+    toHeaderRow l = if null l then [] else [toRow l]
+
 tests :: [TestTree]
 tests =
   [ testGroup "Inlines"
@@ -83,12 +93,12 @@
 
       , "Inline markup is greedy" =:
           "***** ///// _____ ----- ````` \"\"\"\"\" '''''" =?>
-          para (spcSep [strong "*", emph "/", underlineSpan "_"
+          para (spcSep [strong "*", emph "/", underline "_"
                        , strikeout "-", code "`", text "\""
                        , rawInline "html" "'"])
       , "Markup must be greedy" =:
           "**********    //////////    __________    ----------    ``````````   \"\"\"\"\"\"\"\"\"\"   ''''''''''" =?>
-                      para (spcSep [strong "******", emph "//////", underlineSpan "______"
+                      para (spcSep [strong "******", emph "//////", underline "______"
                        , strikeout "------", code "``````", text "\"\"\"\"\"\""
                        , rawInline "html" "''''''"])
       , "Inlines must be glued" =:
@@ -398,12 +408,15 @@
                   , "| 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"  ]
-                ]
+          simpleTable''
+            (zip
+              [AlignCenter, AlignRight, AlignDefault]
+              [ColWidthDefault, ColWidthDefault, ColWidthDefault])
+            []
+            [ [ 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 " =?>
@@ -415,11 +428,14 @@
                   , "| 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  ]
-                ]
+          simpleTable''
+            (zip
+              [AlignCenter, AlignLeft, AlignLeft]
+              [ColWidthDefault, ColWidthDefault, ColWidthDefault])
+            [ plain "Numbers", plain "Text" , plain mempty ]
+            [ [ plain "1"      , plain "One"  , plain "foo"  ]
+            , [ plain "2"      , plain mempty , plain mempty  ]
+            ]
 
       ]
 
diff --git a/test/Tests/Shared.hs b/test/Tests/Shared.hs
--- a/test/Tests/Shared.hs
+++ b/test/Tests/Shared.hs
@@ -20,6 +20,7 @@
 import Text.Pandoc.Arbitrary ()
 import Text.Pandoc.Builder
 import Text.Pandoc.Shared
+import Text.Pandoc.Writers.Shared (toLegacyTable)
 
 tests :: [TestTree]
 tests = [ testGroup "compactifyDL"
@@ -29,6 +30,7 @@
                in  compactifyDL x == x)
           ]
         , testGroup "collapseFilePath" testCollapse
+        , testGroup "toLegacyTable" testLegacyTable
         ]
 
 testCollapse :: [TestTree]
@@ -51,3 +53,62 @@
  ,  collapseFilePath (joinPath [ "parent","foo",".."]) @?= (joinPath [ "parent"])
  ,  collapseFilePath (joinPath [ "","parent","foo","..","..","bar"]) @?= (joinPath [ "","bar"])
  ,  collapseFilePath (joinPath [ "",".","parent","foo"]) @?= (joinPath [ "","parent","foo"])]
+
+testLegacyTable :: [TestTree]
+testLegacyTable =
+  [ testCase "decomposes a table with head" $ gen1 @?= expect1
+  , testCase "decomposes a table without head" $ gen2 @?= expect2
+  ]
+  where
+    pln = toList . plain . str
+    cl a h w = Cell ("", [], []) AlignDefault h w $ pln a
+    rws = map $ Row nullAttr
+    th = TableHead nullAttr . rws
+    tb n x y = TableBody nullAttr n (rws x) (rws y)
+    tf = TableFoot nullAttr . rws
+
+    headRows1 =
+      [[cl "a" 1 1, cl "b" 2 2]
+      ,[cl "c" 1 1]
+      ]
+    body1 = tb 1
+      [[cl "e" 3 1,cl "f" 3 2]
+      ,[]
+      ,[]
+      ]
+      [[emptyCell,emptyCell,emptyCell]
+      ,[cl "g" 1 1,emptyCell,emptyCell]
+      ]
+    footRows1 =
+      [[cl "h" 1 2,cl "i" 2 1]
+      ,[cl "j" 1 2]]
+    caption1 = simpleCaption $ plain "caption"
+    spec1 = replicate 2 (AlignDefault, ColWidth 0.5) ++ [(AlignRight, ColWidthDefault)]
+    expect1 = ( [Str "caption"]
+              , replicate 2 AlignDefault ++ [AlignRight]
+              , replicate 2 0.5 ++ [0]
+              , [pln "a", pln "b", mempty]
+              , [[pln "c", mempty, mempty]
+                ,[pln "e", pln "f", mempty]
+                ,[mempty, mempty, mempty]
+                ,[mempty, mempty, mempty]
+                ,[mempty, mempty, mempty]
+                ,[pln "g", mempty, mempty]
+                ,[pln "h", mempty, pln "i"]
+                ,[pln "j", mempty, mempty]]
+              )
+    gen1 = toLegacyTable caption1 spec1 (th headRows1) [body1] (tf footRows1)
+
+    expect2 = ( []
+              , replicate 2 AlignDefault ++ [AlignRight]
+              , replicate 2 0.5 ++ [0]
+              , []
+              , [[pln "e", pln "f", mempty]
+                ,[mempty, mempty, mempty]
+                ,[mempty, mempty, mempty]
+                ,[mempty, mempty, mempty]
+                ,[pln "g", mempty, mempty]
+                ,[pln "h", mempty, pln "i"]
+                ,[pln "j", mempty, mempty]]
+              )
+    gen2 = toLegacyTable emptyCaption spec1 (th []) [body1] (tf footRows1)
diff --git a/test/Tests/Writers/ConTeXt.hs b/test/Tests/Writers/ConTeXt.hs
--- a/test/Tests/Writers/ConTeXt.hs
+++ b/test/Tests/Writers/ConTeXt.hs
@@ -98,8 +98,8 @@
           ]
         , 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)]
+              let capt = text "Table 1"
+                  aligns = [(AlignRight, ColWidthDefault), (AlignLeft, ColWidthDefault), (AlignCenter, ColWidthDefault), (AlignDefault, ColWidthDefault)]
                   headers = [plain $ text "Right",
                              plain $ text "Left",
                              plain $ text "Center",
@@ -116,7 +116,12 @@
                            plain $ text "3.2",
                            plain $ text "3.3",
                            plain $ text "3.4"]]
-              in table caption aligns headers rows
+                  toRow = Row nullAttr . map simpleCell
+              in table (simpleCaption $ plain capt)
+                       aligns
+                       (TableHead nullAttr [toRow headers])
+                       [TableBody nullAttr 0 [] $ map toRow rows]
+                       (TableFoot nullAttr [])
               =?> unlines [ "\\startplacetable[title={Table 1}]"
                           , "\\startTABLE"
                           , "\\startTABLEhead"
diff --git a/test/Tests/Writers/Jira.hs b/test/Tests/Writers/Jira.hs
new file mode 100644
--- /dev/null
+++ b/test/Tests/Writers/Jira.hs
@@ -0,0 +1,65 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Tests.Writers.Jira (tests) where
+
+import Data.Text (unpack)
+import Test.Tasty
+import Tests.Helpers
+import Text.Pandoc
+import Text.Pandoc.Arbitrary ()
+import Text.Pandoc.Builder
+
+jira :: (ToPandoc a) => a -> String
+jira = unpack . purely (writeJira def) . toPandoc
+
+infix 4 =:
+(=:) :: (ToString a, ToPandoc a)
+     => String -> (a, String) -> TestTree
+(=:) = test jira
+
+tests :: [TestTree]
+tests =
+  [ testGroup "inlines"
+    [ "underlined text" =:
+      underline "underlined text" =?>
+      "+underlined text+"
+
+    , "image with attributes" =:
+      imageWith ("", [], [("align", "right"), ("height", "50")])
+                "image.png" "" mempty =?>
+      "!image.png|align=right, height=50!"
+
+    , testGroup "links"
+      [ "external link" =:
+        link "https://example.com/test.php" "" "test" =?>
+        "[test|https://example.com/test.php]"
+
+      , "external link without description" =:
+        link "https://example.com/tmp.js" "" "https://example.com/tmp.js" =?>
+        "[https://example.com/tmp.js]"
+
+      , "email link" =:
+        link "mailto:me@example.com" "" "Jane" =?>
+        "[Jane|mailto:me@example.com]"
+
+      , "email link without description" =:
+        link "mailto:me@example.com" "" "me@example.com" =?>
+        "[mailto:me@example.com]"
+
+      , "attachment link" =:
+        linkWith ("", ["attachment"], []) "foo.txt" "" "My file" =?>
+        "[My file^foo.txt]"
+
+      , "attachment link without description" =:
+        linkWith ("", ["attachment"], []) "foo.txt" "" "foo.txt" =?>
+        "[^foo.txt]"
+
+      , "user link" =:
+        linkWith ("", ["user-account"], []) "~johndoe" "" "John Doe" =?>
+        "[John Doe|~johndoe]"
+
+      , "user link with user as description" =:
+        linkWith ("", ["user-account"], []) "~johndoe" "" "~johndoe" =?>
+        "[~johndoe]"
+      ]
+    ]
+  ]
diff --git a/test/Tests/Writers/Muse.hs b/test/Tests/Writers/Muse.hs
--- a/test/Tests/Writers/Muse.hs
+++ b/test/Tests/Writers/Muse.hs
@@ -372,8 +372,12 @@
             [ "table without header" =:
               let rows = [[para "Para 1.1", para "Para 1.2"]
                          ,[para "Para 2.1", para "Para 2.2"]]
-              in table mempty [(AlignDefault,0.0),(AlignDefault,0.0)]
-                       [mempty, mempty] rows
+                  toRow = Row nullAttr . map simpleCell
+              in table emptyCaption
+                       [(AlignDefault,ColWidthDefault),(AlignDefault,ColWidthDefault)]
+                       (TableHead nullAttr [toRow [mempty, mempty]])
+                       [TableBody nullAttr 0 [] $ map toRow rows]
+                       (TableFoot nullAttr [])
               =?>
               unlines [ " Para 1.1 | Para 1.2"
                       , " Para 2.1 | Para 2.2"
@@ -389,12 +393,16 @@
                       , " Para 2.1 |  Para 2.2"
                       ]
             , "table with header and caption" =:
-              let caption = "Table 1"
-                  headers = [plain "header 1", plain "header 2"]
-                  rows = [[para "Para 1.1", para  "Para 1.2"]
-                         ,[para "Para 2.1", para  "Para 2.2"]]
-              in table caption [(AlignDefault,0.0),(AlignDefault,0.0)]
-                        headers rows
+              let capt = simpleCaption $ plain "Table 1"
+                  toRow = Row nullAttr . map simpleCell
+                  headers = [toRow [plain "header 1", plain "header 2"]]
+                  rows = map toRow [[para "Para 1.1", para  "Para 1.2"]
+                                   ,[para "Para 2.1", para  "Para 2.2"]]
+              in table capt
+                       [(AlignDefault,ColWidthDefault),(AlignDefault,ColWidthDefault)]
+                       (TableHead nullAttr headers)
+                       [TableBody nullAttr 0 [] rows]
+                       (TableFoot nullAttr [])
               =?> unlines [ " header 1 || header 2"
                           , " Para 1.1 |  Para 1.2"
                           , " Para 2.1 |  Para 2.2"
diff --git a/test/command/1592.md b/test/command/1592.md
--- a/test/command/1592.md
+++ b/test/command/1592.md
@@ -47,3 +47,24 @@
 [hi]{.smallcaps}
 ```
 
+```
+% pandoc -f html -t native
+<bdo dir="ltr">foo</bdo>
+^D
+[Plain [Span ("",[],[("dir","ltr")]) [Str "foo"]]]
+```
+
+```
+% pandoc -f html -t native
+<bdo dir="rtl">foo<bdo dir="ltr">bar</bdo>baz</bdo>
+^D
+[Plain [Span ("",[],[("dir","rtl")]) [Str "foo",Span ("",[],[("dir","ltr")]) [Str "bar"],Str "baz"]]]
+```
+
+```
+% pandoc -f html -t native
+<p><bdo dir="rtl">This text will go right
+to left.</bdo></p>
+^D
+[Para [Span ("",[],[("dir","rtl")]) [Str "This",Space,Str "text",Space,Str "will",Space,Str "go",Space,Str "right",SoftBreak,Str "to",Space,Str "left."]]]
+```
diff --git a/test/command/1881.md b/test/command/1881.md
--- a/test/command/1881.md
+++ b/test/command/1881.md
@@ -20,15 +20,35 @@
 </tbody>
 </table>
 ^D
-[Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] [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"]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [Plain [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."]])
+ [(AlignRight,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Center"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]])]
+ (TableFoot ("",[],[])
+ [])]
 ```
 
 ```
@@ -42,14 +62,26 @@
 </tr>
 </table>
 ^D
-[Table [] [AlignRight,AlignLeft,AlignCenter,AlignRight] [0.0,0.0,0.0,0.0]
- [[]
- ,[]
- ,[]
- ,[]]
- [[[Plain [Str "12"]]
-  ,[Plain [Str "12"]]
-  ,[Plain [Str "12"]]
-  ,[Plain [Str "12"]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignRight,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignRight,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]])]
+ (TableFoot ("",[],[])
+ [])]
 ```
 
diff --git a/test/command/3348.md b/test/command/3348.md
--- a/test/command/3348.md
+++ b/test/command/3348.md
@@ -7,11 +7,24 @@
         line of text
   ----- ------------------------------------------------
 ^D
-[Table [] [AlignRight,AlignLeft] [8.333333333333333e-2,0.6805555555555556]
- [[]
- ,[]]
- [[[Plain [Str "foo"]]
-  ,[Plain [Str "bar"]]]
- ,[[Plain [Str "foo"]]
-  ,[Plain [Str "this",Space,Str "is",Space,Str "a",Space,Str "long",SoftBreak,Str "line",Space,Str "of",Space,Str "text"]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignRight,ColWidth 8.333333333333333e-2)
+ ,(AlignLeft,ColWidth 0.6805555555555556)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "foo"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "bar"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "foo"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "this",Space,Str "is",Space,Str "a",Space,Str "long",SoftBreak,Str "line",Space,Str "of",Space,Str "text"]]]])]
+ (TableFoot ("",[],[])
+ [])]
 ```
diff --git a/test/command/3516.md b/test/command/3516.md
--- a/test/command/3516.md
+++ b/test/command/3516.md
@@ -24,24 +24,58 @@
 |   |   |
 +---+---+
 ^D
-[Table [] [AlignDefault,AlignDefault] [5.555555555555555e-2,5.555555555555555e-2]
- [[]
- ,[]]
- [[[Plain [Str "1"]]
-  ,[Plain [Str "2"]]]
- ,[[]
-  ,[]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidth 5.555555555555555e-2)
+ ,(AlignDefault,ColWidth 5.555555555555555e-2)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]])]
+ (TableFoot ("",[],[])
+ [])]
 ```
 
 ```
 % pandoc -f native -t rst
-[Table [] [AlignDefault,AlignDefault] [5.555555555555555e-2,5.555555555555555e-2]
- [[]
- ,[]]
- [[[Para [Str "1"]]
-  ,[Para [Str "2"]]]
- ,[[]
-  ,[]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidth 5.555555555555555e-2)
+ ,(AlignDefault,ColWidth 5.555555555555555e-2)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "2"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]])]
+ (TableFoot ("",[],[])
+ [])]
 ^D
 +---+---+
 | 1 | 2 |
diff --git a/test/command/3533-rst-csv-tables.md b/test/command/3533-rst-csv-tables.md
--- a/test/command/3533-rst-csv-tables.md
+++ b/test/command/3533-rst-csv-tables.md
@@ -5,16 +5,37 @@
    :header: Flavor,Price,Slogan
    :file: command/3533-rst-csv-tables.csv
 ^D
-[Table [Str "Test"] [AlignDefault,AlignDefault,AlignDefault] [0.4,0.2,0.4]
- [[Plain [Str "Flavor"]]
- ,[Plain [Str "Price"]]
- ,[Plain [Str "Slogan"]]]
- [[[Plain [Str "Albatross"]]
-  ,[Plain [Str "2.99"]]
-  ,[Plain [Str "On",Space,Str "a",Space,Str "stick!"]]]
- ,[[Plain [Str "Crunchy",Space,Str "Frog"]]
-  ,[Plain [Str "1.49"]]
-  ,[Plain [Str "If",Space,Str "we",Space,Str "took",Space,Str "the",Space,Str "bones",Space,Str "out,",Space,Str "it",Space,Str "wouldn't",Space,Str "be",SoftBreak,Str "crunchy,",Space,Str "now",Space,Str "would",Space,Str "it?"]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [Plain [Str "Test"]])
+ [(AlignDefault,ColWidth 0.4)
+ ,(AlignDefault,ColWidth 0.2)
+ ,(AlignDefault,ColWidth 0.4)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Flavor"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Price"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Slogan"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Albatross"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2.99"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "On",Space,Str "a",Space,Str "stick!"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Crunchy",Space,Str "Frog"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1.49"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "If",Space,Str "we",Space,Str "took",Space,Str "the",Space,Str "bones",Space,Str "out,",Space,Str "it",Space,Str "wouldn't",Space,Str "be",SoftBreak,Str "crunchy,",Space,Str "now",Space,Str "would",Space,Str "it?"]]]])]
+ (TableFoot ("",[],[])
+ [])]
 ```
 
 ```
@@ -28,16 +49,37 @@
    'cat''s' 3 4
    'dog''s' 2 3
 ^D
-[Table [Str "Test"] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[]
- ,[Plain [Str "a"]]
- ,[Plain [Str "b"]]]
- [[[Plain [Str "cat's"]]
-  ,[Plain [Str "3"]]
-  ,[Plain [Str "4"]]]
- ,[[Plain [Str "dog's"]]
-  ,[Plain [Str "2"]]
-  ,[Plain [Str "3"]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [Plain [Str "Test"]])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "a"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "b"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "cat's"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "dog's"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]]])]
+ (TableFoot ("",[],[])
+ [])]
 ```
 
 ```
@@ -47,10 +89,20 @@
 
    "1","\""
 ^D
-[Table [Str "Test"] [AlignDefault,AlignDefault] [0.0,0.0]
- [[]
- ,[]]
- [[[Plain [Str "1"]]
-  ,[Plain [Str "\""]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [Plain [Str "Test"]])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "\""]]]])]
+ (TableFoot ("",[],[])
+ [])]
 ```
 
diff --git a/test/command/3706.md b/test/command/3706.md
--- a/test/command/3706.md
+++ b/test/command/3706.md
@@ -16,15 +16,35 @@
 |  3 | La   |
 ^D
 [Div ("tab",[],[])
- [Table [Str "Lalelu."] [AlignDefault,AlignDefault] [0.0,0.0]
-  [[Plain [Str "Id"]]
-  ,[Plain [Str "Desc"]]]
-  [[[Plain [Str "1"]]
-   ,[Plain [Str "La"]]]
-  ,[[Plain [Str "2"]]
-   ,[Plain [Str "La"]]]
-  ,[[Plain [Str "3"]]
-   ,[Plain [Str "La"]]]]]]
+ [Table ("",[],[]) (Caption Nothing
+  [Plain [Str "Lalelu."]])
+  [(AlignDefault,ColWidthDefault)
+  ,(AlignDefault,ColWidthDefault)]
+  (TableHead ("",[],[])
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Id"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Desc"]]]])
+  [(TableBody ("",[],[]) (RowHeadColumns 0)
+   []
+   [Row ("",[],[])
+    [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+     [Plain [Str "1"]]
+    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+     [Plain [Str "La"]]]
+   ,Row ("",[],[])
+    [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+     [Plain [Str "2"]]
+    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+     [Plain [Str "La"]]]
+   ,Row ("",[],[])
+    [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+     [Plain [Str "3"]]
+    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+     [Plain [Str "La"]]]])]
+  (TableFoot ("",[],[])
+  [])]]
 ```
 
 ```
diff --git a/test/command/3708.md b/test/command/3708.md
--- a/test/command/3708.md
+++ b/test/command/3708.md
@@ -5,11 +5,24 @@
     C & D
 \end{tabular}
 ^D
-[Table [] [AlignCenter,AlignCenter] [0.0,0.0]
- [[]
- ,[]]
- [[[Plain [Str "A"]]
-  ,[Plain [Str "B&1"]]]
- ,[[Plain [Str "C"]]
-  ,[Plain [Str "D"]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "A"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "B&1"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "C"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "D"]]]])]
+ (TableFoot ("",[],[])
+ [])]
 ```
diff --git a/test/command/4056.md b/test/command/4056.md
--- a/test/command/4056.md
+++ b/test/command/4056.md
@@ -14,11 +14,22 @@
 Blah & Foo & Bar \\
 \end{tabular}
 ^D
-[Table [] [AlignLeft,AlignRight,AlignRight] [0.0,0.0,0.0]
- [[]
- ,[]
- ,[]]
- [[[Plain [Str "Blah"]]
-  ,[Plain [Str "Foo"]]
-  ,[Plain [Str "Bar"]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidthDefault)
+ ,(AlignRight,ColWidthDefault)
+ ,(AlignRight,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Blah"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Foo"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Bar"]]]])]
+ (TableFoot ("",[],[])
+ [])]
 ```
diff --git a/test/command/4119.md b/test/command/4119.md
--- a/test/command/4119.md
+++ b/test/command/4119.md
@@ -8,11 +8,25 @@
 not a caption!
 ::::::::::::::::
 ^D
-[Table [] [AlignDefault,AlignDefault] [0.0,0.0]
- [[Plain [Str "col1"]]
- ,[Plain [Str "col2"]]]
- [[[Plain [Str "1"]]
-  ,[Plain [Str "2"]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "col1"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "col2"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Div ("",["notes"],[])
  [Para [Str "not",Space,Str "a",Space,Str "caption!"]]]
 ```
diff --git a/test/command/4320.md b/test/command/4320.md
--- a/test/command/4320.md
+++ b/test/command/4320.md
@@ -1,11 +1,25 @@
 ```
 % pandoc -f native -t rst --wrap=none
-[Table [] [AlignDefault,AlignDefault] [0.3,0.3]
- [[Plain [Str "one"]]
- ,[Plain [Str "two"]]]
- [[[Plain [Str "ports"]]
-  ,[BlockQuote
-    [Para [Strong [Str "thisIsGoingToBeTooLongAnyway"]]]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidth 0.3)
+ ,(AlignDefault,ColWidth 0.3)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "one"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "two"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "ports"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [BlockQuote
+     [Para [Strong [Str "thisIsGoingToBeTooLongAnyway"]]]]]])]
+ (TableFoot ("",[],[])
+ [])]
 ^D
 +--------------------+-------------------------------------+
 | one                | two                                 |
diff --git a/test/command/4513.md b/test/command/4513.md
--- a/test/command/4513.md
+++ b/test/command/4513.md
@@ -2,8 +2,19 @@
 % 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"]]]
- []]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "heading",Space,Str "1"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "heading",Space,Str "2"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [])]
+ (TableFoot ("",[],[])
+ [])]
 ```
diff --git a/test/command/4579.md b/test/command/4579.md
--- a/test/command/4579.md
+++ b/test/command/4579.md
@@ -8,9 +8,23 @@
   * - spam
     - ham
 ^D
-[Table [] [AlignDefault,AlignDefault] [0.0,0.0]
- [[Plain [Str "Foo"]]
- ,[Plain [Str "Bar"]]]
- [[[Plain [Str "spam"]]
-  ,[Plain [Str "ham"]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Foo"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Bar"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "spam"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "ham"]]]])]
+ (TableFoot ("",[],[])
+ [])]
 ```
diff --git a/test/command/4805-beamer-columns-alignment.md b/test/command/4805-beamer-columns-alignment.md
new file mode 100644
--- /dev/null
+++ b/test/command/4805-beamer-columns-alignment.md
@@ -0,0 +1,40 @@
+```
+pandoc -t beamer
+:::: { .columns }                                
+::: { .column align=center }
+:::
+::: { .column align=bottom }
+:::
+::::
+
+:::: { .columns align=bottom .onlytextwidth }
+::: { .column align=top }
+:::
+::: { .column align=top-baseline }
+:::
+::::
+
+:::: { .columns totalwidth=7em } 
+::::
+^D
+\begin{frame}
+\begin{columns}[T]
+\begin{column}[c]{0.48\textwidth}
+\end{column}
+
+\begin{column}[b]{0.48\textwidth}
+\end{column}
+\end{columns}
+
+\begin{columns}[b,onlytextwidth]
+\begin{column}[T]{0.48\textwidth}
+\end{column}
+
+\begin{column}[t]{0.48\textwidth}
+\end{column}
+\end{columns}
+
+\begin{columns}[T,totalwidth=7em]
+\end{columns}
+\end{frame}
+```
diff --git a/test/command/5014.md b/test/command/5014.md
--- a/test/command/5014.md
+++ b/test/command/5014.md
@@ -13,7 +13,18 @@
     </tbody>
 </table>
 ^D
-[Table [] [AlignDefault] [0.0]
- [[Plain [Str "Name"]]]
- [[[Plain [Str "Accounts"]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Name"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Accounts"]]]])]
+ (TableFoot ("",[],[])
+ [])]
 ```
diff --git a/test/command/5079.md b/test/command/5079.md
--- a/test/command/5079.md
+++ b/test/command/5079.md
@@ -10,7 +10,16 @@
 </tbody>
 </table>
 ^D
-[Table [] [AlignDefault] [0.0]
- [[]]
- [[[Plain [Str "Cell"]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell"]]]])]
+ (TableFoot ("",[],[])
+ [])]
 ```
diff --git a/test/command/5627.md b/test/command/5627.md
--- a/test/command/5627.md
+++ b/test/command/5627.md
@@ -20,8 +20,8 @@
 <li>Two <code>--&gt;something&lt;!--</code></li>
 <li>Three</li>
 </ol>
-<div class="sourceCode" id="cb1"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb1-1"><a href="#cb1-1"></a>--&gt;<span class="co">&lt;!--&lt;script&gt;alert(&#39;Escaped!&#39;)&lt;/script&gt;</span></span></code></pre></div>
-<div class="sourceCode" id="cb2"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb2-1"><a href="#cb2-1"></a>Something</span></code></pre></div>
+<div class="sourceCode" id="cb1"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a>--&gt;<span class="co">&lt;!--&lt;script&gt;alert(&#39;Escaped!&#39;)&lt;/script&gt;</span></span></code></pre></div>
+<div class="sourceCode" id="cb2"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a>Something</span></code></pre></div>
 ```
 
 ```
@@ -46,8 +46,8 @@
 <li><code>--&gt;something&lt;!--</code></li>
 <li>bye <code>--&gt;something else&lt;!--</code></li>
 </ul>
-<div class="sourceCode" id="cb1"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb1-1"><a href="#cb1-1"></a>--&gt;<span class="co">&lt;!--&lt;script&gt;alert(&#39;Escaped!&#39;)&lt;/script&gt;</span></span></code></pre></div>
-<div class="sourceCode" id="cb2"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb2-1"><a href="#cb2-1"></a>Something</span></code></pre></div>
+<div class="sourceCode" id="cb1"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a>--&gt;<span class="co">&lt;!--&lt;script&gt;alert(&#39;Escaped!&#39;)&lt;/script&gt;</span></span></code></pre></div>
+<div class="sourceCode" id="cb2"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a>Something</span></code></pre></div>
 ```
 
 ```
diff --git a/test/command/5650.md b/test/command/5650.md
--- a/test/command/5650.md
+++ b/test/command/5650.md
@@ -5,8 +5,8 @@
 b
 ```
 ^D
-<div class="sourceCode" id="foocb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="foocb1-1"><a href="#foocb1-1"></a>a</span>
-<span id="foocb1-2"><a href="#foocb1-2"></a>b</span></code></pre></div>
+<div class="sourceCode" id="foocb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="foocb1-1"><a href="#foocb1-1" aria-hidden="true"></a>a</span>
+<span id="foocb1-2"><a href="#foocb1-2" aria-hidden="true"></a>b</span></code></pre></div>
 ````
 
 ````
@@ -16,7 +16,7 @@
 b
 ```
 ^D
-<div class="sourceCode" id="foobar"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="foobar-1"><a href="#foobar-1"></a>a</span>
-<span id="foobar-2"><a href="#foobar-2"></a>b</span></code></pre></div>
+<div class="sourceCode" id="foobar"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="foobar-1"><a href="#foobar-1" aria-hidden="true"></a>a</span>
+<span id="foobar-2"><a href="#foobar-2" aria-hidden="true"></a>b</span></code></pre></div>
 ````
 
diff --git a/test/command/5655.md b/test/command/5655.md
--- a/test/command/5655.md
+++ b/test/command/5655.md
@@ -2,13 +2,13 @@
 % pandoc --webtex
 $T_n={n+1 \choose 2}$
 ^D
-<p><img style="vertical-align:middle" src="https://latex.codecogs.com/png.latex?%5Ctextstyle%20T_n%3D%7Bn%2B1%20%5Cchoose%202%7D" alt="T_n={n+1 \choose 2}" title="T_n={n+1 \choose 2}" /></p>
+<p><img style="vertical-align:middle" src="https://latex.codecogs.com/png.latex?%5Ctextstyle%20T_n%3D%7Bn%2B1%20%5Cchoose%202%7D" alt="T_n={n+1 \choose 2}" title="T_n={n+1 \choose 2}" class="math inline" /></p>
 ````
 
 ````
 % pandoc --webtex
 $$T_n={n+1 \choose 2}$$
 ^D
-<p><br /><img style="vertical-align:middle" src="https://latex.codecogs.com/png.latex?%5Cdisplaystyle%20T_n%3D%7Bn%2B1%20%5Cchoose%202%7D" alt="T_n={n+1 \choose 2}" title="T_n={n+1 \choose 2}" /><br /></p>
+<p><img style="vertical-align:middle" src="https://latex.codecogs.com/png.latex?%5Cdisplaystyle%20T_n%3D%7Bn%2B1%20%5Cchoose%202%7D" alt="T_n={n+1 \choose 2}" title="T_n={n+1 \choose 2}" class="math display" /></p>
 ````
 
diff --git a/test/command/5708.md b/test/command/5708.md
--- a/test/command/5708.md
+++ b/test/command/5708.md
@@ -4,9 +4,23 @@
 | 123456 | :math:`a + b`  |
 +--------+----------------+
 ^D
-[Table [] [AlignDefault,AlignDefault] [0.125,0.2361111111111111]
- [[]
- ,[]]
- [[[Plain [Str "123456"]]
-  ,[Plain [Math InlineMath "a + b"]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidth 0.125)
+ ,(AlignDefault,ColWidth 0.2361111111111111)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123456"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Math InlineMath "a + b"]]]])]
+ (TableFoot ("",[],[])
+ [])]
 ```
diff --git a/test/command/5711.md b/test/command/5711.md
--- a/test/command/5711.md
+++ b/test/command/5711.md
@@ -7,7 +7,16 @@
 \end{tabular}
 \end{document}
 ^D
-[Table [] [AlignCenter] [0.0]
- [[]]
- [[[Plain [Str "d",LineBreak,Str "e"]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignCenter,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "d",LineBreak,Str "e"]]]])]
+ (TableFoot ("",[],[])
+ [])]
 ```
diff --git a/test/command/6137.md b/test/command/6137.md
--- a/test/command/6137.md
+++ b/test/command/6137.md
@@ -17,16 +17,31 @@
 ^D
 [Para [Str "This",Space,Str "reference",Space,Str "to",Space,Str "Table",Space,Link ("",[],[("reference-type","ref"),("reference","tbl:label")]) [Str "1"] ("#tbl:label",""),Space,Str "doesn\8217t",Space,Str "work."]
 ,Div ("tbl:label",[],[])
- [Table [Str "This",Space,Str "caption",Space,Str "has",Space,Str "no",Space,Str "number."] [AlignLeft,AlignCenter,AlignRight] [0.0,0.0,0.0]
-  [[]
-  ,[]
-  ,[]]
-  [[[Plain [Str "\8212\8212\8211"]]
-   ,[Plain [Str "\8212\8212\8211"]]
-   ,[Plain [Str "\8212\8212\8211"]]]
-  ,[[Plain [Str "\8212\8212\8211"]]
-   ,[Plain [Str "\8212\8212\8211"]]
-   ,[Plain [Str "\8212\8212\8211"]]]]]
+ [Table ("",[],[]) (Caption Nothing
+  [Plain [Str "This",Space,Str "caption",Space,Str "has",Space,Str "no",Space,Str "number."]])
+  [(AlignLeft,ColWidthDefault)
+  ,(AlignCenter,ColWidthDefault)
+  ,(AlignRight,ColWidthDefault)]
+  (TableHead ("",[],[])
+  [])
+  [(TableBody ("",[],[]) (RowHeadColumns 0)
+   []
+   [Row ("",[],[])
+    [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+     [Plain [Str "\8212\8212\8211"]]
+    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+     [Plain [Str "\8212\8212\8211"]]
+    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+     [Plain [Str "\8212\8212\8211"]]]
+   ,Row ("",[],[])
+    [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+     [Plain [Str "\8212\8212\8211"]]
+    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+     [Plain [Str "\8212\8212\8211"]]
+    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+     [Plain [Str "\8212\8212\8211"]]]])]
+  (TableFoot ("",[],[])
+  [])]
 ,Para [Str "This",Space,Str "reference",Space,Str "to",Space,Str "Figure",Space,Link ("",[],[("reference-type","ref"),("reference","fig:label")]) [Str "1"] ("#fig:label",""),Space,Str "works",Space,Str "fine."]
 ,Para [Image ("fig:label",[],[("width","\\textwidth")]) [Str "A",Space,Str "numbered",Space,Str "caption,",Space,Str "if",Space,Str "I",Space,Str "use",Space,Str "pandoc-crossref."] ("example.png","fig:")]]
 ```
diff --git a/test/command/6194.md b/test/command/6194.md
new file mode 100644
--- /dev/null
+++ b/test/command/6194.md
@@ -0,0 +1,14 @@
+```
+% pandoc -f markdown -t rst
+image1: ![foo](x.png)
+
+image2: ![foo](y.png)
+^D
+image1: |foo|
+
+image2: |image1|
+
+.. |foo| image:: x.png
+.. |image1| image:: y.png
+```
+
diff --git a/test/command/6265.md b/test/command/6265.md
new file mode 100644
--- /dev/null
+++ b/test/command/6265.md
@@ -0,0 +1,6 @@
+```
+% pandoc -f markdown -t latex -M csquotes=true
+"test"
+^D
+\enquote{test}
+```
diff --git a/test/command/6288.md b/test/command/6288.md
new file mode 100644
--- /dev/null
+++ b/test/command/6288.md
@@ -0,0 +1,8 @@
+```
+% pandoc -f jats -t native
+<sec>
+<label>I</label><title>Introduction</title>
+</sec>
+^D
+[Header 1 ("",[],[]) [Str "I.",Space,Str "Introduction"]]
+```
diff --git a/test/command/6296.md b/test/command/6296.md
new file mode 100644
--- /dev/null
+++ b/test/command/6296.md
@@ -0,0 +1,14 @@
+```
+% pandoc -f native -t markdown
+[Str "_hi_there"]
+^D
+\_hi_there
+```
+
+```
+% pandoc -f native -t markdown-intraword_underscores
+[Str "_hi_there"]
+^D
+\_hi\_there
+```
+
diff --git a/test/command/6308.md b/test/command/6308.md
new file mode 100644
--- /dev/null
+++ b/test/command/6308.md
@@ -0,0 +1,18 @@
+```
+% pandoc -f org -t asciidoc
+* Header
+#+begin_tip
+I'm a tip
+#+end_tip
+
+** Subheader
+^D
+== Header
+
+[TIP]
+====
+I'm a tip
+====
+
+=== Subheader
+```
diff --git a/test/command/6360.md b/test/command/6360.md
new file mode 100644
--- /dev/null
+++ b/test/command/6360.md
@@ -0,0 +1,6 @@
+```
+% pandoc -f native -t latex --wrap=none
+[Link ("test2",[],[]) [Str "link",Space,Str "to",Space,Str "text",Space,Str "test1"] ("#test1","")]
+^D
+\protect\hypertarget{test2}{\protect\hyperlink{test1}{link to text test1}}
+```
diff --git a/test/command/6385.md b/test/command/6385.md
new file mode 100644
--- /dev/null
+++ b/test/command/6385.md
@@ -0,0 +1,18 @@
+```
+% pandoc -f markdown -t html
+<details>
+<summary>Show me:</summary>
+details para 1
+
+details para 2
+
+</details>
+^D
+<details>
+<summary>
+Show me:
+</summary>
+<p>details para 1</p>
+<p>details para 2</p>
+</details>
+```
diff --git a/test/command/6481.md b/test/command/6481.md
new file mode 100644
--- /dev/null
+++ b/test/command/6481.md
@@ -0,0 +1,38 @@
+```
+% pandoc -t html5
+::: {.div-class}
++-------+-----+-----+-------------------------------------------------+
+| Col 1 | Col | Col | Col 4                                           |
+|       | 2   | 3   |                                                 |
++:=====:+:===:+:===:+:================================================+
+| High  | Med | Med | Some description of something.                  |
++-------+-----+-----+-------------------------------------------------+
+:::
+^D
+<div class="div-class">
+<table style="width:97%;">
+<colgroup>
+<col style="width: 11%" />
+<col style="width: 8%" />
+<col style="width: 8%" />
+<col style="width: 69%" />
+</colgroup>
+<thead>
+<tr class="header">
+<th style="text-align: center;">Col 1</th>
+<th style="text-align: center;">Col 2</th>
+<th style="text-align: center;">Col 3</th>
+<th style="text-align: left;">Col 4</th>
+</tr>
+</thead>
+<tbody>
+<tr class="odd">
+<td style="text-align: center;">High</td>
+<td style="text-align: center;">Med</td>
+<td style="text-align: center;">Med</td>
+<td style="text-align: left;">Some description of something.</td>
+</tr>
+</tbody>
+</table>
+</div>
+```
diff --git a/test/command/csv.md b/test/command/csv.md
--- a/test/command/csv.md
+++ b/test/command/csv.md
@@ -5,17 +5,42 @@
 """Navel"" Orange","35 cents",22
 ,,45
 ^D
-[Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[Plain [Str "Fruit"]]
- ,[Plain [Str "Price"]]
- ,[Plain [Str "Quantity"]]]
- [[[Plain [Str "Apple"]]
-  ,[Plain [Str "25",Space,Str "cents"]]
-  ,[Plain [Str "33"]]]
- ,[[Plain [Str "\"Navel\"",Space,Str "Orange"]]
-  ,[Plain [Str "35",Space,Str "cents"]]
-  ,[Plain [Str "22"]]]
- ,[[]
-  ,[]
-  ,[Plain [Str "45"]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Fruit"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Price"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Quantity"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Apple"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "25",Space,Str "cents"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "33"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "\"Navel\"",Space,Str "Orange"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "35",Space,Str "cents"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "22"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "45"]]]])]
+ (TableFoot ("",[],[])
+ [])]
 ```
diff --git a/test/command/gfm.md b/test/command/gfm.md
--- a/test/command/gfm.md
+++ b/test/command/gfm.md
@@ -7,13 +7,30 @@
 | apple | 0.13  |
 | orange|1.12|
 ^D
-[Table [] [AlignDefault,AlignRight] [0.0,0.0]
- [[Plain [Str "Fruit"]]
- ,[Plain [Str "Price"]]]
- [[[Plain [Str "apple"]]
-  ,[Plain [Str "0.13"]]]
- ,[[Plain [Str "orange"]]
-  ,[Plain [Str "1.12"]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignRight,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Fruit"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Price"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "apple"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "0.13"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "orange"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1.12"]]]])]
+ (TableFoot ("",[],[])
+ [])]
 ```
 
 ```
@@ -57,13 +74,30 @@
 
 ```
 % pandoc -t gfm -f native
-[Table [Str "The",Space,Str "caption."] [AlignDefault,AlignRight] [0.0,0.0]
- [[Plain [Str "Fruit"]]
- ,[Plain [Str "Price"]]]
- [[[Plain [Str "apple"]]
-  ,[Plain [Str "0.13"]]]
- ,[[Plain [Str "orange"]]
-  ,[Plain [Str "1.12"]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [Plain [Str "The",Space,Str "caption."]])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignRight,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Fruit"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Price"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "apple"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "0.13"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "orange"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1.12"]]]])]
+ (TableFoot ("",[],[])
+ [])]
 ^D
 | Fruit  | Price |
 | ------ | ----: |
diff --git a/test/command/latex-tabular-column-specs.md b/test/command/latex-tabular-column-specs.md
--- a/test/command/latex-tabular-column-specs.md
+++ b/test/command/latex-tabular-column-specs.md
@@ -11,14 +11,35 @@
 \bottomrule
 \end{tabular}
 ^D
-[Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
- [[Plain [Math InlineMath ""]]
- ,[Plain [Math InlineMath "f1"]]
- ,[Plain [Math InlineMath "f2"]]]
- [[[Plain [Math InlineMath "e"]]
-  ,[Plain [Math InlineMath "0.5"]]
-  ,[Plain [Math InlineMath "4"]]]
- ,[[Plain [Math InlineMath "f"]]
-  ,[Plain [Math InlineMath "0.5"]]
-  ,[Plain [Math InlineMath "5,5"]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Math InlineMath ""]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Math InlineMath "f1"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Math InlineMath "f2"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Math InlineMath "e"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Math InlineMath "0.5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Math InlineMath "4"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Math InlineMath "f"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Math InlineMath "0.5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Math InlineMath "5,5"]]]])]
+ (TableFoot ("",[],[])
+ [])]
 ```
diff --git a/test/command/lettrine.md b/test/command/lettrine.md
--- a/test/command/lettrine.md
+++ b/test/command/lettrine.md
@@ -4,6 +4,6 @@
 
 \lettrine[lhang=0.17]{A}{category} is
 ^D
-[Para [Span ("",["lettrine"],[]) [Str "A"],Span ("",[],[]) [Str "category"],Space,Str "is"]
-,Para [Span ("",["lettrine"],[]) [Str "A"],Span ("",[],[]) [Str "category"],Space,Str "is"]]
+[Para [Span ("",["lettrine"],[]) [Str "A"],SmallCaps [Str "category"],Space,Str "is"]
+,Para [Span ("",["lettrine"],[]) [Str "A"],SmallCaps [Str "category"],Space,Str "is"]]
 ```
diff --git a/test/command/tabularx.md b/test/command/tabularx.md
--- a/test/command/tabularx.md
+++ b/test/command/tabularx.md
@@ -6,33 +6,58 @@
   & Column Heading 2
   & Column Heading 3 \\
 \hline
-  Cell 1.1 
+  Cell 1.1
   & Cell 1.2
   & Cell 1.3 \\
 \hline
-  Cell 2.1 
+  Cell 2.1
   & Cell 2.2
   & Cell 2.3 \\
 \hline
-  Cell 3.1 
+  Cell 3.1
   & Cell 3.2
   & Cell 3.3 \\
 \hline
 \end{tabularx}
 ^D
-[Table [] [AlignCenter,AlignCenter,AlignCenter] [0.0,0.0,0.0]
- [[Plain [Str "Column",Space,Str "Heading",Space,Str "1"]]
- ,[Plain [Str "Column",Space,Str "Heading",Space,Str "2"]]
- ,[Plain [Str "Column",Space,Str "Heading",Space,Str "3"]]]
- [[[Plain [Str "Cell",Space,Str "1.1"]]
-  ,[Plain [Str "Cell",Space,Str "1.2"]]
-  ,[Plain [Str "Cell",Space,Str "1.3"]]]
- ,[[Plain [Str "Cell",Space,Str "2.1"]]
-  ,[Plain [Str "Cell",Space,Str "2.2"]]
-  ,[Plain [Str "Cell",Space,Str "2.3"]]]
- ,[[Plain [Str "Cell",Space,Str "3.1"]]
-  ,[Plain [Str "Cell",Space,Str "3.2"]]
-  ,[Plain [Str "Cell",Space,Str "3.3"]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Column",Space,Str "Heading",Space,Str "1"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Column",Space,Str "Heading",Space,Str "2"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Column",Space,Str "Heading",Space,Str "3"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "1.1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "1.2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "1.3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "2.1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "2.2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "2.3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "3.1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "3.2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "3.3"]]]])]
+ (TableFoot ("",[],[])
+ [])]
 ```
 
 ```
@@ -43,33 +68,58 @@
   & Column Heading 2
   & Column Heading 3 \\
 \hline
-  Cell 1.1 
+  Cell 1.1
   & Cell 1.2
   & Cell 1.3 \\
 \hline
-  Cell 2.1 
+  Cell 2.1
   & Cell 2.2
   & Cell 2.3 \\
 \hline
-  Cell 3.1 
+  Cell 3.1
   & Cell 3.2
   & Cell 3.3 \\
 \hline
 \end{tabularx}
 ^D
-[Table [] [AlignLeft,AlignCenter,AlignLeft] [0.0,0.0,0.25]
- [[Plain [Str "Column",Space,Str "Heading",Space,Str "1"]]
- ,[Plain [Str "Column",Space,Str "Heading",Space,Str "2"]]
- ,[Plain [Str "Column",Space,Str "Heading",Space,Str "3"]]]
- [[[Plain [Str "Cell",Space,Str "1.1"]]
-  ,[Plain [Str "Cell",Space,Str "1.2"]]
-  ,[Plain [Str "Cell",Space,Str "1.3"]]]
- ,[[Plain [Str "Cell",Space,Str "2.1"]]
-  ,[Plain [Str "Cell",Space,Str "2.2"]]
-  ,[Plain [Str "Cell",Space,Str "2.3"]]]
- ,[[Plain [Str "Cell",Space,Str "3.1"]]
-  ,[Plain [Str "Cell",Space,Str "3.2"]]
-  ,[Plain [Str "Cell",Space,Str "3.3"]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignLeft,ColWidth 0.25)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Column",Space,Str "Heading",Space,Str "1"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Column",Space,Str "Heading",Space,Str "2"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Column",Space,Str "Heading",Space,Str "3"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "1.1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "1.2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "1.3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "2.1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "2.2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "2.3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "3.1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "3.2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "3.3"]]]])]
+ (TableFoot ("",[],[])
+ [])]
 ```
 
 ```
@@ -80,31 +130,56 @@
   & Column Heading 2
   & Column Heading 3 \\
 \hline
-  Cell 1.1 
+  Cell 1.1
   & Cell 1.2
   & Cell 1.3 \\
 \hline
-  Cell 2.1 
+  Cell 2.1
   & Cell 2.2
   & Cell 2.3 \\
 \hline
-  Cell 3.1 
+  Cell 3.1
   & Cell 3.2
   & Cell 3.3 \\
 \hline
 \end{tabularx}
 ^D
-[Table [] [AlignLeft,AlignCenter,AlignLeft] [0.25,0.0,0.25]
- [[Plain [Str "Column",Space,Str "Heading",Space,Str "1"]]
- ,[Plain [Str "Column",Space,Str "Heading",Space,Str "2"]]
- ,[Plain [Str "Column",Space,Str "Heading",Space,Str "3"]]]
- [[[Plain [Str "Cell",Space,Str "1.1"]]
-  ,[Plain [Str "Cell",Space,Str "1.2"]]
-  ,[Plain [Str "Cell",Space,Str "1.3"]]]
- ,[[Plain [Str "Cell",Space,Str "2.1"]]
-  ,[Plain [Str "Cell",Space,Str "2.2"]]
-  ,[Plain [Str "Cell",Space,Str "2.3"]]]
- ,[[Plain [Str "Cell",Space,Str "3.1"]]
-  ,[Plain [Str "Cell",Space,Str "3.2"]]
-  ,[Plain [Str "Cell",Space,Str "3.3"]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidth 0.25)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignLeft,ColWidth 0.25)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Column",Space,Str "Heading",Space,Str "1"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Column",Space,Str "Heading",Space,Str "2"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Column",Space,Str "Heading",Space,Str "3"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "1.1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "1.2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "1.3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "2.1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "2.2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "2.3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "3.1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "3.2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "3.3"]]]])]
+ (TableFoot ("",[],[])
+ [])]
 ```
diff --git a/test/creole-reader.native b/test/creole-reader.native
--- a/test/creole-reader.native
+++ b/test/creole-reader.native
@@ -69,25 +69,62 @@
 ,Para [Image ("",[],[]) [Str "here is a red flower"] ("Red-Flower.jpg","")]
 ,Header 3 ("",[],[]) [Str "Creole 0.4"]
 ,Para [Str "Tables",Space,Str "are",Space,Str "done",Space,Str "like",Space,Str "this:"]
-,Table [] [AlignDefault,AlignDefault] [0.0,0.0]
- [[Plain [Str "header",Space,Str "col1"]]
- ,[Plain [Str "header",Space,Str "col2"]]]
- [[[Plain [Str "col1"]]
-  ,[Plain [Str "col2"]]]
- ,[[Plain [Str "you"]]
-  ,[Plain [Str "can"]]]
- ,[[Plain [Str "also"]]
-  ,[Plain [Str "align",LineBreak,Str "it."]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "header",Space,Str "col1"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "header",Space,Str "col2"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "col1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "col2"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "you"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "can"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "also"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "align",LineBreak,Str "it."]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "You",Space,Str "can",Space,Str "format",Space,Str "an",Space,Str "address",Space,Str "by",Space,Str "simply",Space,Str "forcing",Space,Str "linebreaks:"]
 ,Para [Str "My",Space,Str "contact",Space,Str "dates:",LineBreak,Str "Pone:",Space,Str "xyz",LineBreak,Str "Fax:",Space,Str "+45",LineBreak,Str "Mobile:",Space,Str "abc"]
 ,Header 3 ("",[],[]) [Str "Creole 0.5"]
-,Table [] [AlignDefault,AlignDefault] [0.0,0.0]
- [[Plain [Str "Header",Space,Str "title"]]
- ,[Plain [Str "Another",Space,Str "header",Space,Str "title"]]]
- [[[Plain [Code ("",[],[]) " //not italic text// "]]
-  ,[Plain [Code ("",[],[]) " **not bold text** "]]]
- ,[[Plain [Emph [Str "italic",Space,Str "text"]]]
-  ,[Plain [Strong [Space,Str "bold",Space,Str "text",Space]]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Header",Space,Str "title"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Another",Space,Str "header",Space,Str "title"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Code ("",[],[]) " //not italic text// "]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Code ("",[],[]) " **not bold text** "]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Emph [Str "italic",Space,Str "text"]]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Strong [Space,Str "bold",Space,Str "text",Space]]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Header 3 ("",[],[]) [Str "Creole 1.0"]
 ,Para [Str "If",Space,Str "interwiki",Space,Str "links",Space,Str "are",Space,Str "setup",Space,Str "in",Space,Str "your",Space,Str "wiki,",Space,Str "this",Space,Str "links",Space,Str "to",Space,Str "the",Space,Str "WikiCreole",Space,Str "page",Space,Str "about",Space,Str "Creole",Space,Str "1.0",Space,Str "test",Space,Str "cases:",Space,Link ("",[],[]) [Str "WikiCreole:Creole1.0TestCases"] ("WikiCreole:Creole1.0TestCases",""),Str "."]
 ,HorizontalRule
diff --git a/test/docbook-reader.docbook b/test/docbook-reader.docbook
--- a/test/docbook-reader.docbook
+++ b/test/docbook-reader.docbook
@@ -47,6 +47,12 @@
       <para>
         with no blank line
       </para>
+      <simplesect>
+        <title>Level 4</title>
+        <para>
+        An unnumbered section.
+        </para>
+      </simplesect>
     </sect3>
   </sect2>
   <sect2 id="level-2">
@@ -1557,5 +1563,29 @@
       </tbody>
     </tgroup>
   </informaltable>
+  <procedure><title>An Example Procedure</title>
+    <step>
+      <para>
+        A Step
+      </para>
+    </step>
+    <step>
+      <para>
+        Another Step
+      </para>
+      <substeps>
+        <step>
+          <para>
+            Substeps can be nested indefinitely deep.
+          </para>
+        </step>
+      </substeps>
+    </step>
+    <step>
+      <para>
+        A Final Step
+      </para>
+    </step>
+  </procedure>
 </sect1>
 </article>
diff --git a/test/docbook-reader.native b/test/docbook-reader.native
--- a/test/docbook-reader.native
+++ b/test/docbook-reader.native
@@ -10,6 +10,8 @@
 ,Header 2 ("level-2-with-emphasis",[],[]) [Str "Level",Space,Str "2",Space,Str "with",Space,Emph [Str "emphasis"]]
 ,Header 3 ("level-3",[],[]) [Str "Level",Space,Str "3"]
 ,Para [Str "with",Space,Str "no",Space,Str "blank",Space,Str "line"]
+,Header 4 ("",["unnumbered"],[]) [Str "Level",Space,Str "4"]
+,Para [Str "An",Space,Str "unnumbered",Space,Str "section."]
 ,Header 2 ("level-2",[],[]) [Str "Level",Space,Str "2"]
 ,Para [Str "with",Space,Str "no",Space,Str "blank",Space,Str "line"]
 ,Header 1 ("paragraphs",[],[]) [Str "Paragraphs"]
@@ -282,116 +284,300 @@
 ,Para [Str "This",Space,Str "paragraph",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "part",Space,Str "of",Space,Str "the",Space,Str "note,",Space,Str "as",Space,Str "it",Space,Str "is",Space,Str "not",Space,Str "indented."]
 ,Header 1 ("tables",[],[]) [Str "Tables"]
 ,Para [Str "Simple",Space,Str "table",Space,Str "with",Space,Str "caption:"]
-,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] [AlignRight,AlignLeft,AlignCenter,AlignLeft] [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 ("",[],[]) (Caption Nothing
+ [Plain [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."]])
+ [(AlignRight,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Center"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Simple",Space,Str "table",Space,Str "without",Space,Str "caption:"]
-,Table [] [AlignRight,AlignLeft,AlignCenter,AlignLeft] [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 ("",[],[]) (Caption Nothing
+ [])
+ [(AlignRight,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Center"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Simple",Space,Str "table",Space,Str "indented",Space,Str "two",Space,Str "spaces:"]
-,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] [AlignRight,AlignLeft,AlignCenter,AlignLeft] [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 ("",[],[]) (Caption Nothing
+ [Plain [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."]])
+ [(AlignRight,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Center"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Multiline",Space,Str "table",Space,Str "with",Space,Str "caption:"]
-,Table [Str "Here's",Space,Str "the",Space,Str "caption.",Space,Str "It",Space,Str "may",Space,Str "span",Space,Str "multiple",Space,Str "lines."] [AlignCenter,AlignLeft,AlignRight,AlignLeft] [0.2,0.2,0.3,0.3]
- [[Plain [Str "Centered",Space,Str "Header"]]
- ,[Plain [Str "Left",Space,Str "Aligned"]]
- ,[Plain [Str "Right",Space,Str "Aligned"]]
- ,[Plain [Str "Default",Space,Str "aligned"]]]
- [[[Plain [Str "First"]]
-  ,[Plain [Str "row"]]
-  ,[Plain [Str "12.0"]]
-  ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]]
- ,[[Plain [Str "Second"]]
-  ,[Plain [Str "row"]]
-  ,[Plain [Str "5.0"]]
-  ,[Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]]
+,Table ("",[],[]) (Caption Nothing
+ [Plain [Str "Here's",Space,Str "the",Space,Str "caption.",Space,Str "It",Space,Str "may",Space,Str "span",Space,Str "multiple",Space,Str "lines."]])
+ [(AlignCenter,ColWidth 0.2)
+ ,(AlignLeft,ColWidth 0.2)
+ ,(AlignRight,ColWidth 0.3)
+ ,(AlignLeft,ColWidth 0.3)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Centered",Space,Str "Header"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left",Space,Str "Aligned"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right",Space,Str "Aligned"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default",Space,Str "aligned"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "First"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "row"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12.0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Second"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "row"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5.0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "caption:"]
-,Table [] [AlignCenter,AlignLeft,AlignRight,AlignLeft] [0.1,0.2,0.3,0.4]
- [[Plain [Str "Centered",Space,Str "Header"]]
- ,[Plain [Str "Left",Space,Str "Aligned"]]
- ,[Plain [Str "Right",Space,Str "Aligned"]]
- ,[Plain [Str "Default",Space,Str "aligned"]]]
- [[[Plain [Str "First"]]
-  ,[Plain [Str "row"]]
-  ,[Plain [Str "12.0"]]
-  ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]]
- ,[[Plain [Str "Second"]]
-  ,[Plain [Str "row"]]
-  ,[Plain [Str "5.0"]]
-  ,[Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignCenter,ColWidth 0.1)
+ ,(AlignLeft,ColWidth 0.2)
+ ,(AlignRight,ColWidth 0.3)
+ ,(AlignLeft,ColWidth 0.4)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Centered",Space,Str "Header"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left",Space,Str "Aligned"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right",Space,Str "Aligned"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default",Space,Str "aligned"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "First"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "row"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12.0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Second"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "row"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5.0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Table",Space,Str "without",Space,Str "column",Space,Str "headers:"]
-,Table [] [AlignRight,AlignLeft,AlignCenter,AlignRight] [0.0,0.0,0.0,0.0]
- [[]
- ,[]
- ,[]
- ,[]]
- [[[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 ("",[],[]) (Caption Nothing
+ [])
+ [(AlignRight,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignRight,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "column",Space,Str "headers:"]
-,Table [] [AlignCenter,AlignLeft,AlignRight,AlignLeft] [0.25,0.25,0.25,0.25]
- [[]
- ,[]
- ,[]
- ,[]]
- [[[Plain [Str "First"]]
-  ,[Plain [Str "row"]]
-  ,[Plain [Str "12.0"]]
-  ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]]
- ,[[Plain [Str "Second"]]
-  ,[Plain [Str "row"]]
-  ,[Plain [Str "5.0"]]
-  ,[Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignCenter,ColWidth 0.25)
+ ,(AlignLeft,ColWidth 0.25)
+ ,(AlignRight,ColWidth 0.25)
+ ,(AlignLeft,ColWidth 0.25)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "First"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "row"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12.0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Second"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "row"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5.0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]])]
+ (TableFoot ("",[],[])
+ [])
+,BulletList
+ [[Para [Str "A",Space,Str "Step"]]
+ ,[Para [Str "Another",Space,Str "Step"]
+  ,Para [Str "Substeps",Space,Str "can",Space,Str "be",Space,Str "nested",Space,Str "indefinitely",Space,Str "deep."]]
+ ,[Para [Str "A",Space,Str "Final",Space,Str "Step"]]]]
diff --git a/test/docx/0_level_headers.native b/test/docx/0_level_headers.native
--- a/test/docx/0_level_headers.native
+++ b/test/docx/0_level_headers.native
@@ -1,15 +1,42 @@
-[Table [] [AlignDefault] [0.0]
- [[]]
- [[[]]
- ,[[Plain [Str "User\8217s",Space,Str "Guide"]]]
- ,[[]]
- ,[[]]
- ,[[]]
- ,[[Plain [Str "11",Space,Str "August",Space,Str "2017"]]]
- ,[[]]
- ,[[]]
- ,[[]]
- ,[[]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "User\8217s",Space,Str "Guide"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "11",Space,Str "August",Space,Str "2017"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "CONTENTS"]
 ,Para [Strong [Str "Section",Space,Str "Page"]]
 ,Para [Str "FIGURES",Space,Str "iv"]
diff --git a/test/docx/alternate_document_path.native b/test/docx/alternate_document_path.native
--- a/test/docx/alternate_document_path.native
+++ b/test/docx/alternate_document_path.native
@@ -1,2 +1,3 @@
+Pandoc (Meta {unMeta = fromList []})
 [Header 1 ("test",[],[]) [Str "Test"]
-,Para [Str "This",Space,Str "is",Space,Emph [Str "italic"],Str ",",Space,Strong [Str "bold"],Str ",",Space,Span ("",["underline"],[]) [Str "underlined"],Str ",",Space,Emph [Span ("",["underline"],[]) [Str "italic",Space,Str "underlined"]],Str ",",Space,Strong [Span ("",["underline"],[]) [Str "bold",Space,Str "underlined"]],Str ",",Space,Emph [Strong [Span ("",["underline"],[]) [Str "bold",Space,Str "italic",Space,Str "underlined"]]],Str "."]]
+,Para [Str "This",Space,Str "is",Space,Emph [Str "italic"],Str ",",Space,Strong [Str "bold"],Str ",",Space,Underline [Str "underlined"],Str ",",Space,Emph [Underline [Str "italic",Space,Str "underlined"]],Str ",",Space,Strong [Underline [Str "bold",Space,Str "underlined"]],Str ",",Space,Emph [Strong [Underline [Str "bold",Space,Str "italic",Space,Str "underlined"]]],Str "."]]
diff --git a/test/docx/golden/block_quotes.docx b/test/docx/golden/block_quotes.docx
Binary files a/test/docx/golden/block_quotes.docx and b/test/docx/golden/block_quotes.docx differ
diff --git a/test/docx/golden/codeblock.docx b/test/docx/golden/codeblock.docx
Binary files a/test/docx/golden/codeblock.docx and b/test/docx/golden/codeblock.docx differ
diff --git a/test/docx/golden/comments.docx b/test/docx/golden/comments.docx
Binary files a/test/docx/golden/comments.docx and b/test/docx/golden/comments.docx differ
diff --git a/test/docx/golden/custom_style_no_reference.docx b/test/docx/golden/custom_style_no_reference.docx
Binary files a/test/docx/golden/custom_style_no_reference.docx and b/test/docx/golden/custom_style_no_reference.docx differ
diff --git a/test/docx/golden/custom_style_preserve.docx b/test/docx/golden/custom_style_preserve.docx
Binary files a/test/docx/golden/custom_style_preserve.docx and b/test/docx/golden/custom_style_preserve.docx differ
diff --git a/test/docx/golden/definition_list.docx b/test/docx/golden/definition_list.docx
Binary files a/test/docx/golden/definition_list.docx and b/test/docx/golden/definition_list.docx differ
diff --git a/test/docx/golden/document-properties-short-desc.docx b/test/docx/golden/document-properties-short-desc.docx
Binary files a/test/docx/golden/document-properties-short-desc.docx and b/test/docx/golden/document-properties-short-desc.docx differ
diff --git a/test/docx/golden/document-properties.docx b/test/docx/golden/document-properties.docx
Binary files a/test/docx/golden/document-properties.docx and b/test/docx/golden/document-properties.docx differ
diff --git a/test/docx/golden/headers.docx b/test/docx/golden/headers.docx
Binary files a/test/docx/golden/headers.docx and b/test/docx/golden/headers.docx differ
diff --git a/test/docx/golden/image.docx b/test/docx/golden/image.docx
Binary files a/test/docx/golden/image.docx and b/test/docx/golden/image.docx differ
diff --git a/test/docx/golden/inline_code.docx b/test/docx/golden/inline_code.docx
Binary files a/test/docx/golden/inline_code.docx and b/test/docx/golden/inline_code.docx differ
diff --git a/test/docx/golden/inline_formatting.docx b/test/docx/golden/inline_formatting.docx
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
Binary files a/test/docx/golden/inline_images.docx and b/test/docx/golden/inline_images.docx differ
diff --git a/test/docx/golden/link_in_notes.docx b/test/docx/golden/link_in_notes.docx
Binary files a/test/docx/golden/link_in_notes.docx and b/test/docx/golden/link_in_notes.docx differ
diff --git a/test/docx/golden/links.docx b/test/docx/golden/links.docx
Binary files a/test/docx/golden/links.docx and b/test/docx/golden/links.docx differ
diff --git a/test/docx/golden/lists.docx b/test/docx/golden/lists.docx
Binary files a/test/docx/golden/lists.docx and b/test/docx/golden/lists.docx differ
diff --git a/test/docx/golden/lists_continuing.docx b/test/docx/golden/lists_continuing.docx
Binary files a/test/docx/golden/lists_continuing.docx and b/test/docx/golden/lists_continuing.docx differ
diff --git a/test/docx/golden/lists_restarting.docx b/test/docx/golden/lists_restarting.docx
Binary files a/test/docx/golden/lists_restarting.docx and b/test/docx/golden/lists_restarting.docx differ
diff --git a/test/docx/golden/nested_anchors_in_header.docx b/test/docx/golden/nested_anchors_in_header.docx
Binary files a/test/docx/golden/nested_anchors_in_header.docx and b/test/docx/golden/nested_anchors_in_header.docx differ
diff --git a/test/docx/golden/notes.docx b/test/docx/golden/notes.docx
Binary files a/test/docx/golden/notes.docx and b/test/docx/golden/notes.docx differ
diff --git a/test/docx/golden/table_one_row.docx b/test/docx/golden/table_one_row.docx
Binary files a/test/docx/golden/table_one_row.docx and b/test/docx/golden/table_one_row.docx differ
diff --git a/test/docx/golden/table_with_list_cell.docx b/test/docx/golden/table_with_list_cell.docx
Binary files a/test/docx/golden/table_with_list_cell.docx and b/test/docx/golden/table_with_list_cell.docx differ
diff --git a/test/docx/golden/tables.docx b/test/docx/golden/tables.docx
Binary files a/test/docx/golden/tables.docx and b/test/docx/golden/tables.docx differ
diff --git a/test/docx/golden/track_changes_deletion.docx b/test/docx/golden/track_changes_deletion.docx
Binary files a/test/docx/golden/track_changes_deletion.docx and b/test/docx/golden/track_changes_deletion.docx differ
diff --git a/test/docx/golden/track_changes_insertion.docx b/test/docx/golden/track_changes_insertion.docx
Binary files a/test/docx/golden/track_changes_insertion.docx and b/test/docx/golden/track_changes_insertion.docx differ
diff --git a/test/docx/golden/track_changes_move.docx b/test/docx/golden/track_changes_move.docx
Binary files a/test/docx/golden/track_changes_move.docx and b/test/docx/golden/track_changes_move.docx differ
diff --git a/test/docx/golden/unicode.docx b/test/docx/golden/unicode.docx
Binary files a/test/docx/golden/unicode.docx and b/test/docx/golden/unicode.docx differ
diff --git a/test/docx/golden/verbatim_subsuper.docx b/test/docx/golden/verbatim_subsuper.docx
Binary files a/test/docx/golden/verbatim_subsuper.docx and b/test/docx/golden/verbatim_subsuper.docx differ
diff --git a/test/docx/inline_formatting.native b/test/docx/inline_formatting.native
--- a/test/docx/inline_formatting.native
+++ b/test/docx/inline_formatting.native
@@ -1,5 +1,6 @@
+Pandoc (Meta {unMeta = fromList []})
 [Para [Str "Regular",Space,Str "text",Space,Emph [Str "italics"],Space,Strong [Str "bold",Space,Emph [Str "bold",Space,Str "italics"]],Str "."]
 ,Para [Str "This",Space,Str "is",Space,SmallCaps [Str "Small",Space,Str "Caps"],Str ",",Space,Str "and",Space,Str "this",Space,Str "is",Space,Strikeout [Str "strikethrough"],Str "."]
-,Para [Str "Some",Space,Str "people",Space,Str "use",Space,Span ("",["underline"],[]) [Str "single",Space,Str "underlines",Space,Str "for",Space,Emph [Str "emphasis"]],Str "."]
+,Para [Str "Some",Space,Str "people",Space,Str "use",Space,Underline [Str "single",Space,Str "underlines",Space,Str "for",Space],Emph [Underline [Str "emphasis"]],Str "."]
 ,Para [Str "Above",Space,Str "the",Space,Str "line",Space,Str "is",Space,Superscript [Str "superscript"],Space,Str "and",Space,Str "below",Space,Str "the",Space,Str "line",Space,Str "is",Space,Subscript [Str "subscript"],Str "."]
 ,Para [Str "A",Space,Str "line",LineBreak,Str "break."]]
diff --git a/test/docx/sdt_elements.native b/test/docx/sdt_elements.native
--- a/test/docx/sdt_elements.native
+++ b/test/docx/sdt_elements.native
@@ -1,10 +1,25 @@
-[Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[]
- ,[]
- ,[]]
- [[[Plain [Strong [Str "col1Header"]]]
-  ,[Plain [Strong [Str "col2Header"]]]
-  ,[Plain [Strong [Str "col3Header"]]]]
- ,[[Plain [Str "col1",Space,Str "content"]]
-  ,[Plain [Str "Body",Space,Str "copy"]]
-  ,[Plain [Str "col3",Space,Str "content"]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Strong [Str "col1Header"]]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Strong [Str "col2Header"]]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Strong [Str "col3Header"]]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "col1",Space,Str "content"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Body",Space,Str "copy"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "col3",Space,Str "content"]]]])]
+ (TableFoot ("",[],[])
+ [])]
diff --git a/test/docx/table_one_row.native b/test/docx/table_one_row.native
--- a/test/docx/table_one_row.native
+++ b/test/docx/table_one_row.native
@@ -1,7 +1,18 @@
-[Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[]
- ,[]
- ,[]]
- [[[Plain [Str "One"]]
-  ,[Plain [Str "Row"]]
-  ,[Plain [Str "Table"]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "One"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Row"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Table"]]]])]
+ (TableFoot ("",[],[])
+ [])]
diff --git a/test/docx/table_variable_width.native b/test/docx/table_variable_width.native
--- a/test/docx/table_variable_width.native
+++ b/test/docx/table_variable_width.native
@@ -1,16 +1,45 @@
-[Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0,0.0,0.0]
- [[]
- ,[]
- ,[Plain [Str "h3"]]
- ,[Plain [Str "h4"]]
- ,[Plain [Str "h5"]]]
- [[[Plain [Str "c11"]]
-  ,[]
-  ,[]
-  ,[]
-  ,[]]
- ,[[]
-  ,[Plain [Str "c22"]]
-  ,[Plain [Str "c23"]]
-  ,[]
-  ,[]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "h3"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "h4"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "h5"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "c11"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "c22"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "c23"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]])]
+ (TableFoot ("",[],[])
+ [])]
diff --git a/test/docx/table_with_list_cell.native b/test/docx/table_with_list_cell.native
--- a/test/docx/table_with_list_cell.native
+++ b/test/docx/table_with_list_cell.native
@@ -1,11 +1,25 @@
-[Table [] [AlignDefault,AlignDefault] [0.0,0.0]
- [[Plain [Str "Cell",Space,Str "with",Space,Str "text"]]
- ,[Plain [Str "Cell",Space,Str "with",Space,Str "text"]]]
- [[[BulletList
-    [[Para [Str "Cell",Space,Str "with"]]
-    ,[Para [Str "A"]]
-    ,[Para [Str "Bullet",Space,Str "list"]]]]
-  ,[OrderedList (1,Decimal,Period)
-    [[Para [Str "Cell",Space,Str "with"]]
-    ,[Para [Str "A"]]
-    ,[Para [Str "Numbered",Space,Str "list."]]]]]]]
+[Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Cell",Space,Str "with",Space,Str "text"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Cell",Space,Str "with",Space,Str "text"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [BulletList
+     [[Para [Str "Cell",Space,Str "with"]]
+     ,[Para [Str "A"]]
+     ,[Para [Str "Bullet",Space,Str "list"]]]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [OrderedList (1,Decimal,Period)
+     [[Para [Str "Cell",Space,Str "with"]]
+     ,[Para [Str "A"]]
+     ,[Para [Str "Numbered",Space,Str "list."]]]]]])]
+ (TableFoot ("",[],[])
+ [])]
diff --git a/test/docx/tables.native b/test/docx/tables.native
--- a/test/docx/tables.native
+++ b/test/docx/tables.native
@@ -1,36 +1,92 @@
 [Header 2 ("a-table-with-and-without-a-header-row",[],[]) [Str "A",Space,Str "table,",Space,Str "with",Space,Str "and",Space,Str "without",Space,Str "a",Space,Str "header",Space,Str "row"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0,0.0]
- [[Plain [Str "Name"]]
- ,[Plain [Str "Game"]]
- ,[Plain [Str "Fame"]]
- ,[Plain [Str "Blame"]]]
- [[[Plain [Str "Lebron",Space,Str "James"]]
-  ,[Plain [Str "Basketball"]]
-  ,[Plain [Str "Very",Space,Str "High"]]
-  ,[Plain [Str "Leaving",Space,Str "Cleveland"]]]
- ,[[Plain [Str "Ryan",Space,Str "Braun"]]
-  ,[Plain [Str "Baseball"]]
-  ,[Plain [Str "Moderate"]]
-  ,[Plain [Str "Steroids"]]]
- ,[[Plain [Str "Russell",Space,Str "Wilson"]]
-  ,[Plain [Str "Football"]]
-  ,[Plain [Str "High"]]
-  ,[Plain [Str "Tacky",Space,Str "uniform"]]]]
-,Table [] [AlignDefault,AlignDefault] [0.0,0.0]
- [[]
- ,[]]
- [[[Plain [Str "Sinple"]]
-  ,[Plain [Str "Table"]]]
- ,[[Plain [Str "Without"]]
-  ,[Plain [Str "Header"]]]]
-,Table [] [AlignDefault,AlignDefault] [0.0,0.0]
- [[]
- ,[]]
- [[[Para [Str "Simple"]
-   ,Para [Str "Multiparagraph"]]
-  ,[Para [Str "Table"]
-   ,Para [Str "Full"]]]
- ,[[Para [Str "Of"]
-   ,Para [Str "Paragraphs"]]
-  ,[Para [Str "In",Space,Str "each"]
-   ,Para [Str "Cell."]]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Name"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Game"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Fame"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Blame"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Lebron",Space,Str "James"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Basketball"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Very",Space,Str "High"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Leaving",Space,Str "Cleveland"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Ryan",Space,Str "Braun"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Baseball"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Moderate"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Steroids"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Russell",Space,Str "Wilson"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Football"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "High"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Tacky",Space,Str "uniform"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Sinple"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Table"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Without"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Header"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Simple"]
+    ,Para [Str "Multiparagraph"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Table"]
+    ,Para [Str "Full"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Of"]
+    ,Para [Str "Paragraphs"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "In",Space,Str "each"]
+    ,Para [Str "Cell."]]]])]
+ (TableFoot ("",[],[])
+ [])]
diff --git a/test/dokuwiki_multiblock_table.native b/test/dokuwiki_multiblock_table.native
--- a/test/dokuwiki_multiblock_table.native
+++ b/test/dokuwiki_multiblock_table.native
@@ -1,18 +1,41 @@
-[Table [Str "Sample",Space,Str "grid",Space,Str "table."] [AlignDefault,AlignDefault,AlignDefault] [0.2222222222222222,0.2222222222222222,0.2916666666666667]
- [[Plain [Str "Fruit"]]
- ,[Plain [Str "Price"]]
- ,[Plain [Str "Advantages"]]]
- [[[Para [Str "Bananas"]]
-  ,[Para [Str "$1.34"]]
-  ,[Para [Str "built-in",Space,Str "wrapper"]
-   ,Para [Str "potassium"]]]
- ,[[Para [Str "Oranges"]]
-  ,[Para [Str "$2.10"]]
-  ,[BulletList
-    [[Plain [Str "cures",Space,Str "scurvy"]]
-    ,[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"] 
-    ]]
- ]]
+[Table ("",[],[]) (Caption Nothing
+ [Para [Str "Sample",Space,Str "grid",Space,Str "table."]])
+ [(AlignDefault,ColWidth 0.2222222222222222)
+ ,(AlignDefault,ColWidth 0.2222222222222222)
+ ,(AlignDefault,ColWidth 0.2916666666666667)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Fruit"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Price"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Advantages"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Bananas"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "$1.34"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "built-in",Space,Str "wrapper"]
+    ,Para [Str "potassium"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Oranges"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "$2.10"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [BulletList
+     [[Plain [Str "cures",Space,Str "scurvy"]]
+     ,[Plain [Str "tasty"]]]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Apples"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "$1.10"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Some",Space,Str "text",LineBreak,LineBreak,Str "after",Space,Str "two",Space,Str "linebreaks"]]]])]
+ (TableFoot ("",[],[])
+ [])]
diff --git a/test/html-reader.native b/test/html-reader.native
--- a/test/html-reader.native
+++ b/test/html-reader.native
@@ -211,7 +211,7 @@
 ,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word."]
 ,Para [Str "This",Space,Str "is",Space,Str "code:",Space,Code ("",[],[]) ">",Str ",",Space,Code ("",[],[]) "$",Str ",",Space,Code ("",[],[]) "\\",Str ",",Space,Code ("",[],[]) "\\$",Str ",",Space,Code ("",[],[]) "<html>",Str "."]
 ,Para [Str "This",Space,Str "is",Space,SmallCaps [Str "small",Space,Str "caps"],Str "."]
-,Para [Str "These",Space,Str "are",Space,Str "all",Space,Str "underlined:",Space,Span ("",["underline"],[]) [Str "foo"],Space,Str "and",Space,Span ("",["underline"],[]) [Str "bar"],Str "."]
+,Para [Str "These",Space,Str "are",Space,Str "all",Space,Str "underlined:",Space,Underline [Str "foo"],Space,Str "and",Space,Underline [Str "bar"],Str "."]
 ,Para [Str "These",Space,Str "are",Space,Str "all",Space,Str "strikethrough:",Space,Strikeout [Str "foo"],Str ",",Space,Strikeout [Str "bar"],Str ",",Space,Str "and",Space,Strikeout [Str "baz"],Str "."]
 ,HorizontalRule
 ,Header 1 ("smart-quotes-ellipses-dashes",[],[]) [Str "Smart",Space,Str "quotes,",Space,Str "ellipses,",Space,Str "dashes"]
@@ -331,147 +331,396 @@
 ,Para [Emph [Str "Trailing",Space,Str "spaces"],Space,Str "text"]
 ,Header 1 ("tables",[],[]) [Str "Tables"]
 ,Header 2 ("tables-with-headers",[],[]) [Str "Tables",Space,Str "with",Space,Str "Headers"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[Plain [Str "X"]]
- ,[Plain [Str "Y"]]
- ,[Plain [Str "Z"]]]
- [[[Plain [Str "1"]]
-  ,[Plain [Str "2"]]
-  ,[Plain [Str "3"]]]
- ,[[Plain [Str "4"]]
-  ,[Plain [Str "5"]]
-  ,[Plain [Str "6"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "X"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Y"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Z"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,HorizontalRule
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[Plain [Str "X"]]
- ,[Plain [Str "Y"]]
- ,[Plain [Str "Z"]]]
- [[[Plain [Str "1"]]
-  ,[Plain [Str "2"]]
-  ,[Plain [Str "3"]]]
- ,[[Plain [Str "4"]]
-  ,[Plain [Str "5"]]
-  ,[Plain [Str "6"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "X"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Y"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Z"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,HorizontalRule
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[Plain [Str "X"]]
- ,[Plain [Str "Y"]]
- ,[Plain [Str "Z"]]]
- [[[Plain [Str "1"]]
-  ,[Plain [Str "2"]]
-  ,[Plain [Str "3"]]]
- ,[[Plain [Str "4"]]
-  ,[Plain [Str "5"]]
-  ,[Plain [Str "6"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "X"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Y"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Z"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,HorizontalRule
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[Plain [Str "X"]]
- ,[Plain [Str "Y"]]
- ,[Plain [Str "Z"]]]
- [[[Plain [Str "1"]]
-  ,[Plain [Str "2"]]
-  ,[Plain [Str "3"]]]
- ,[[Plain [Str "4"]]
-  ,[Plain [Str "5"]]
-  ,[Plain [Str "6"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "X"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Y"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Z"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,HorizontalRule
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[Plain [Str "X"]]
- ,[Plain [Str "Y"]]
- ,[Plain [Str "Z"]]]
- [[[Plain [Str "1"]]
-  ,[Plain [Str "2"]]
-  ,[Plain [Str "3"]]]
- ,[[Plain [Str "4"]]
-  ,[Plain [Str "5"]]
-  ,[Plain [Str "6"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "X"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Y"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Z"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,HorizontalRule
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[Plain [Str "X"]]
- ,[Plain [Str "Y"]]
- ,[Plain [Str "Z"]]]
- [[[Plain [Str "1"]]
-  ,[Plain [Str "2"]]
-  ,[Plain [Str "3"]]]
- ,[[Plain [Str "4"]]
-  ,[Plain [Str "5"]]
-  ,[Plain [Str "6"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "X"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Y"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Z"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,HorizontalRule
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[Plain [Str "X"]]
- ,[Plain [Str "Y"]]
- ,[Plain [Str "Z"]]]
- [[[Plain [Str "1"]]
-  ,[Plain [Str "2"]]
-  ,[Plain [Str "3"]]]
- ,[[Plain [Str "4"]]
-  ,[Plain [Str "5"]]
-  ,[Plain [Str "6"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "X"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Y"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Z"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,HorizontalRule
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[Plain [Str "X"]]
- ,[Plain [Str "Y"]]
- ,[Plain [Str "Z"]]]
- [[[Plain [Str "1"]]
-  ,[Plain [Str "2"]]
-  ,[Plain [Str "3"]]]
- ,[[Plain [Str "4"]]
-  ,[Plain [Str "5"]]
-  ,[Plain [Str "6"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "X"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Y"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Z"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,HorizontalRule
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[Plain [Str "X"]]
- ,[Plain [Str "Y"]]
- ,[Plain [Str "Z"]]]
- [[[Plain [Str "1"]]
-  ,[Para [Str "2"]]
-  ,[Plain [Str "3"]]]
- ,[[Plain [Str "4"]]
-  ,[Plain [Str "5"]]
-  ,[Plain [Str "6"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "X"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Y"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Z"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Header 2 ("tables-without-headers",[],[]) [Str "Tables",Space,Str "without",Space,Str "Headers"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[]
- ,[]
- ,[]]
- [[[Plain [Str "1"]]
-  ,[Plain [Str "2"]]
-  ,[Plain [Str "3"]]]
- ,[[Plain [Str "4"]]
-  ,[Plain [Str "5"]]
-  ,[Plain [Str "6"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,HorizontalRule
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[]
- ,[]
- ,[]]
- [[[Plain [Str "1"]]
-  ,[Plain [Str "2"]]
-  ,[Plain [Str "3"]]]
- ,[[Plain [Str "4"]]
-  ,[Plain [Str "5"]]
-  ,[Plain [Str "6"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,HorizontalRule
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[]
- ,[]
- ,[]]
- [[[Plain [Str "1"]]
-  ,[Plain [Str "2"]]
-  ,[Plain [Str "3"]]]
- ,[[Plain [Str "4"]]
-  ,[Plain [Str "5"]]
-  ,[Plain [Str "6"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,HorizontalRule
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[]
- ,[]
- ,[]]
- [[[Plain [Str "1"]]
-  ,[Plain [Str "2"]]
-  ,[Plain [Str "3"]]]
- ,[[Plain [Str "4"]]
-  ,[Plain [Str "5"]]
-  ,[Plain [Str "6"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Header 2 ("empty-tables",[],[]) [Str "Empty",Space,Str "Tables"]
 ,Para [Str "This",Space,Str "section",Space,Str "should",Space,Str "be",Space,Str "empty."]]
diff --git a/test/jats-reader.native b/test/jats-reader.native
--- a/test/jats-reader.native
+++ b/test/jats-reader.native
@@ -287,136 +287,385 @@
 ,Para [Emph [Str "Trailing",Space,Str "spaces"],Space,Str "text"]
 ,Header 1 ("tables",[],[]) [Str "Tables"]
 ,Header 2 ("tables-with-headers",[],[]) [Str "Tables",Space,Str "with",Space,Str "Headers"]
-,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
- [[Para [Str "X"]]
- ,[Para [Str "Y"]]
- ,[Para [Str "Z"]]]
- [[[Para [Str "1"]]
-  ,[Para [Str "2"]]
-  ,[Para [Str "3"]]]
- ,[[Para [Str "4"]]
-  ,[Para [Str "5"]]
-  ,[Para [Str "6"]]]]
-,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
- [[Para [Str "X"]]
- ,[Para [Str "Y"]]
- ,[Para [Str "Z"]]]
- [[[Para [Str "1"]]
-  ,[Para [Str "2"]]
-  ,[Para [Str "3"]]]
- ,[[Para [Str "4"]]
-  ,[Para [Str "5"]]
-  ,[Para [Str "6"]]]]
-,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
- [[Para [Str "X"]]
- ,[Para [Str "Y"]]
- ,[Para [Str "Z"]]]
- [[[Para [Str "1"]]
-  ,[Para [Str "2"]]
-  ,[Para [Str "3"]]]
- ,[[Para [Str "4"]]
-  ,[Para [Str "5"]]
-  ,[Para [Str "6"]]]]
-,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
- [[Para [Str "X"]]
- ,[Para [Str "Y"]]
- ,[Para [Str "Z"]]]
- [[[Para [Str "1"]]
-  ,[Para [Str "2"]]
-  ,[Para [Str "3"]]]
- ,[[Para [Str "4"]]
-  ,[Para [Str "5"]]
-  ,[Para [Str "6"]]]]
-,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
- [[Para [Str "X"]]
- ,[Para [Str "Y"]]
- ,[Para [Str "Z"]]]
- [[[Para [Str "1"]]
-  ,[Para [Str "2"]]
-  ,[Para [Str "3"]]]
- ,[[Para [Str "4"]]
-  ,[Para [Str "5"]]
-  ,[Para [Str "6"]]]]
-,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
- [[Para [Str "X"]]
- ,[Para [Str "Y"]]
- ,[Para [Str "Z"]]]
- [[[Para [Str "1"]]
-  ,[Para [Str "2"]]
-  ,[Para [Str "3"]]]
- ,[[Para [Str "4"]]
-  ,[Para [Str "5"]]
-  ,[Para [Str "6"]]]]
-,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
- [[Para [Str "X"]]
- ,[Para [Str "Y"]]
- ,[Para [Str "Z"]]]
- [[[Para [Str "1"]]
-  ,[Para [Str "2"]]
-  ,[Para [Str "3"]]]
- ,[[Para [Str "4"]]
-  ,[Para [Str "5"]]
-  ,[Para [Str "6"]]]]
-,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
- [[Para [Str "X"]]
- ,[Para [Str "Y"]]
- ,[Para [Str "Z"]]]
- [[[Para [Str "1"]]
-  ,[Para [Str "2"]]
-  ,[Para [Str "3"]]]
- ,[[Para [Str "4"]]
-  ,[Para [Str "5"]]
-  ,[Para [Str "6"]]]]
-,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
- [[Para [Str "X"]]
- ,[Para [Str "Y"]]
- ,[Para [Str "Z"]]]
- [[[Para [Str "1"]]
-  ,[Para [Str "2"]]
-  ,[Para [Str "3"]]]
- ,[[Para [Str "4"]]
-  ,[Para [Str "5"]]
-  ,[Para [Str "6"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "X"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Y"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Z"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "X"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Y"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Z"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "X"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Y"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Z"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "X"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Y"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Z"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "X"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Y"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Z"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "X"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Y"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Z"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "X"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Y"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Z"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "X"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Y"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Z"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "X"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Y"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Z"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Header 2 ("tables-without-headers",[],[]) [Str "Tables",Space,Str "without",Space,Str "Headers"]
-,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
- [[]
- ,[]
- ,[]]
- [[[Para [Str "1"]]
-  ,[Para [Str "2"]]
-  ,[Para [Str "3"]]]
- ,[[Para [Str "4"]]
-  ,[Para [Str "5"]]
-  ,[Para [Str "6"]]]]
-,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
- [[]
- ,[]
- ,[]]
- [[[Para [Str "1"]]
-  ,[Para [Str "2"]]
-  ,[Para [Str "3"]]]
- ,[[Para [Str "4"]]
-  ,[Para [Str "5"]]
-  ,[Para [Str "6"]]]]
-,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
- [[]
- ,[]
- ,[]]
- [[[Para [Str "1"]]
-  ,[Para [Str "2"]]
-  ,[Para [Str "3"]]]
- ,[[Para [Str "4"]]
-  ,[Para [Str "5"]]
-  ,[Para [Str "6"]]]]
-,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
- [[]
- ,[]
- ,[]]
- [[[Para [Str "1"]]
-  ,[Para [Str "2"]]
-  ,[Para [Str "3"]]]
- ,[[Para [Str "4"]]
-  ,[Para [Str "5"]]
-  ,[Para [Str "6"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "6"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Header 2 ("empty-tables",[],[]) [Str "Empty",Space,Str "Tables"]
 ,Para [Str "This",Space,Str "section",Space,Str "should",Space,Str "be",Space,Str "empty."]]
diff --git a/test/jira-reader.native b/test/jira-reader.native
--- a/test/jira-reader.native
+++ b/test/jira-reader.native
@@ -113,7 +113,7 @@
 ,HorizontalRule
 ,Header 1 ("",[],[]) [Str "Dashes,",Space,Str "and",Space,Str "emoticons"]
 ,Para [Str "Some",Space,Str "dashes:",Space,Str "one",Space,Str "\8211",Space,Str "two",Space,Str "\8212",Space,Str "three."]
-,Para [Str "Sure",Space,Str "\10003",LineBreak,Str "Nope",Space,Str "\127303"]
+,Para [Str "Sure",Space,Str "\10004",LineBreak,Str "Nope",Space,Str "\10060"]
 ,Para [Str "Nice",Space,Str "\128515"]
 ,Para [Str "Capital",Space,Str "d:D"]
 ,HorizontalRule
diff --git a/test/latex-reader.native b/test/latex-reader.native
--- a/test/latex-reader.native
+++ b/test/latex-reader.native
@@ -275,18 +275,46 @@
  ,[Para [Str "$22,000",Space,Str "is",Space,Str "a",Space,Emph [Str "lot"],Space,Str "of",Space,Str "money.",Space,Str "So",Space,Str "is",Space,Str "$34,000.",Space,Str "(It",Space,Str "worked",Space,Str "if",SoftBreak,Quoted DoubleQuote [Str "lot"],Space,Str "is",Space,Str "emphasized.)"]]
  ,[Para [Str "Escaped",Space,Code ("",[],[]) "$",Str ":",Space,Str "$73",Space,Emph [Str "this",Space,Str "should",Space,Str "be",Space,Str "emphasized"],Space,Str "23$."]]]
 ,Para [Str "Here\8217s",Space,Str "a",Space,Str "LaTeX",Space,Str "table:"]
-,Table [] [AlignLeft,AlignLeft] [0.0,0.0]
- [[Plain [Str "Animal"]]
- ,[Plain [Str "Number"]]]
- [[[Plain [Str "Dog"]]
-  ,[Plain [Str "2"]]]
- ,[[Plain [Str "Cat"]]
-  ,[Plain [Str "1"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Animal"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Number"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Dog"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cat"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "A",Space,Str "table",Space,Str "with",Space,Str "one",Space,Str "column:"]
-,Table [] [AlignCenter] [0.0]
- [[]]
- [[[Plain [Str "Animal"]]]
- ,[[Plain [Str "Vegetable"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignCenter,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Animal"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Vegetable"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,HorizontalRule
 ,Header 1 ("special-characters",[],[]) [Str "Special",Space,Str "Characters"]
 ,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Str "unicode:"]
diff --git a/test/lhs-test.html b/test/lhs-test.html
--- a/test/lhs-test.html
+++ b/test/lhs-test.html
@@ -74,6 +74,7 @@
     code span.va { color: #19177c; } /* Variable */
     code span.vs { color: #4070a0; } /* VerbatimString */
     code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
+    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
   </style>
   <!--[if lt IE 9]>
     <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
@@ -83,9 +84,9 @@
 <h1 id="lhs-test">lhs test</h1>
 <p><code>unsplit</code> is an arrow that takes a pair of values and combines them to
 return a single value:</p>
-<div class="sourceCode" id="cb1"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1"></a><span class="ot">unsplit ::</span> (<span class="dt">Arrow</span> a) <span class="ot">=&gt;</span> (b <span class="ot">-&gt;</span> c <span class="ot">-&gt;</span> d) <span class="ot">-&gt;</span> a (b, c) d</span>
-<span id="cb1-2"><a href="#cb1-2"></a>unsplit <span class="ot">=</span> arr <span class="op">.</span> <span class="fu">uncurry</span></span>
-<span id="cb1-3"><a href="#cb1-3"></a>          <span class="co">-- arr (\op (x,y) -&gt; x `op` y)</span></span></code></pre></div>
+<div class="sourceCode" id="cb1"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a><span class="ot">unsplit ::</span> (<span class="dt">Arrow</span> a) <span class="ot">=&gt;</span> (b <span class="ot">-&gt;</span> c <span class="ot">-&gt;</span> d) <span class="ot">-&gt;</span> a (b, c) d</span>
+<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a>unsplit <span class="ot">=</span> arr <span class="op">.</span> <span class="fu">uncurry</span></span>
+<span id="cb1-3"><a href="#cb1-3" aria-hidden="true"></a>          <span class="co">-- arr (\op (x,y) -&gt; x `op` y)</span></span></code></pre></div>
 <p><code>(***)</code> 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
 second item of the pair).</p>
diff --git a/test/lhs-test.html+lhs b/test/lhs-test.html+lhs
--- a/test/lhs-test.html+lhs
+++ b/test/lhs-test.html+lhs
@@ -74,6 +74,7 @@
     code span.va { color: #19177c; } /* Variable */
     code span.vs { color: #4070a0; } /* VerbatimString */
     code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
+    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
   </style>
   <!--[if lt IE 9]>
     <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
@@ -83,9 +84,9 @@
 <h1 id="lhs-test">lhs test</h1>
 <p><code>unsplit</code> is an arrow that takes a pair of values and combines them to
 return a single value:</p>
-<div class="sourceCode" id="cb1"><pre class="sourceCode literatehaskell literate"><code class="sourceCode literatehaskell"><span id="cb1-1"><a href="#cb1-1"></a><span class="ot">&gt; unsplit ::</span> (<span class="dt">Arrow</span> a) <span class="ot">=&gt;</span> (b <span class="ot">-&gt;</span> c <span class="ot">-&gt;</span> d) <span class="ot">-&gt;</span> a (b, c) d</span>
-<span id="cb1-2"><a href="#cb1-2"></a><span class="ot">&gt;</span> unsplit <span class="ot">=</span> arr <span class="op">.</span> <span class="fu">uncurry</span></span>
-<span id="cb1-3"><a href="#cb1-3"></a><span class="ot">&gt;</span>           <span class="co">-- arr (\op (x,y) -&gt; x `op` y)</span></span></code></pre></div>
+<div class="sourceCode" id="cb1"><pre class="sourceCode literatehaskell literate"><code class="sourceCode literatehaskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a><span class="ot">&gt; unsplit ::</span> (<span class="dt">Arrow</span> a) <span class="ot">=&gt;</span> (b <span class="ot">-&gt;</span> c <span class="ot">-&gt;</span> d) <span class="ot">-&gt;</span> a (b, c) d</span>
+<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a><span class="ot">&gt;</span> unsplit <span class="ot">=</span> arr <span class="op">.</span> <span class="fu">uncurry</span></span>
+<span id="cb1-3"><a href="#cb1-3" aria-hidden="true"></a><span class="ot">&gt;</span>           <span class="co">-- arr (\op (x,y) -&gt; x `op` y)</span></span></code></pre></div>
 <p><code>(***)</code> 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
 second item of the pair).</p>
diff --git a/test/lua/module/pandoc-types.lua b/test/lua/module/pandoc-types.lua
--- a/test/lua/module/pandoc-types.lua
+++ b/test/lua/module/pandoc-types.lua
@@ -26,10 +26,9 @@
         )
       end),
       test('non-version string is rejected', function ()
-        assert.error_matches(
-          function () Version '11friends' end,
-          '11friends'
-        )
+        local success, msg = pcall(function () Version '11friends' end)
+        assert.is_falsy(success)
+        assert.is_truthy(tostring(msg):match('11friends'))
       end)
     },
 
diff --git a/test/lua/require-file.lua b/test/lua/require-file.lua
new file mode 100644
--- /dev/null
+++ b/test/lua/require-file.lua
@@ -0,0 +1,2 @@
+package.path = package.path .. ';lua/?.lua'
+require 'script-name'
diff --git a/test/man-reader.native b/test/man-reader.native
--- a/test/man-reader.native
+++ b/test/man-reader.native
@@ -105,76 +105,196 @@
 ,Header 1 ("",[],[]) [Str "Macros"]
 ,Para [Strong [Str "Me",Space,Str "Myself"],Space,Str "and",Space,Str "I.",Space,Emph [Str "The",Space,Str "author",Space,Str "is",Space,Str "John",Space,Str "Jones."],Space,Str "It's",Space,Str "The",Space,Strong [Str "Author"],Str "."]
 ,Header 1 ("",[],[]) [Str "Tables"]
-,Table [] [AlignRight,AlignLeft,AlignCenter,AlignLeft] [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,AlignLeft] [0.0,0.0,0.0,0.0]
- [[Plain [Str "Right"]]
- ,[Plain [Str "Left"]]
- ,[Plain [Str "Center"]]
- ,[Plain [Str "Left",Space,Emph [Str "more"]]]]
- [[[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 [] [AlignCenter,AlignLeft,AlignRight,AlignLeft] [0.0,0.0,0.0,0.0]
- [[Plain [Str "Centered",Space,Str "Header"]]
- ,[Plain [Str "Left",Space,Str "Aligned"]]
- ,[Plain [Str "Right",Space,Str "Aligned"]]
- ,[Plain [Str "Default",Space,Str "aligned"]]]
- [[[Plain [Str "First"]]
-  ,[Plain [Str "row"]]
-  ,[Plain [Str "12.0"]]
-  ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]]
- ,[[Plain [Str "Second"]]
-  ,[Plain [Str "row"]]
-  ,[Plain [Str "5.0"]]
-  ,[Plain [Str "Here\8217s",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignRight,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Center"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignRight,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Center"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left",Space,Emph [Str "more"]]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignCenter,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignRight,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Centered",Space,Str "Header"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left",Space,Str "Aligned"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right",Space,Str "Aligned"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default",Space,Str "aligned"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "First"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "row"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12.0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Second"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "row"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5.0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Here\8217s",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Table",Space,Str "without",Space,Str "column",Space,Str "headers:"]
-,Table [] [AlignRight,AlignLeft,AlignCenter,AlignRight] [0.0,0.0,0.0,0.0]
- [[]
- ,[]
- ,[]
- ,[]]
- [[[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] [0.5,0.5]
- [[]
- ,[]]
- [[[Plain [Str "a"]]
-  ,[Plain [Str "b"]]]
- ,[[Para [Str "one"]
-   ,Para [Str "two"]]
-  ,[CodeBlock ("",[],[]) "some\n   code"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignRight,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignRight,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignRight,ColWidth 0.5)
+ ,(AlignLeft,ColWidth 0.5)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "a"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "b"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "one"]
+    ,Para [Str "two"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [CodeBlock ("",[],[]) "some\n   code"]]])]
+ (TableFoot ("",[],[])
+ [])]
diff --git a/test/markdown-reader-more.native b/test/markdown-reader-more.native
--- a/test/markdown-reader-more.native
+++ b/test/markdown-reader-more.native
@@ -96,84 +96,224 @@
  ,[Str "Continuation",Space,Str "line"]
  ,[Str "\160\160and",Space,Str "another"]]
 ,Header 2 ("grid-tables",[],[]) [Str "Grid",Space,Str "Tables"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.2638888888888889,0.16666666666666666,0.18055555555555555]
- [[Plain [Str "col",Space,Str "1"]]
- ,[Plain [Str "col",Space,Str "2"]]
- ,[Plain [Str "col",Space,Str "3"]]]
- [[[Plain [Str "r1",Space,Str "a",SoftBreak,Str "r1",Space,Str "bis"]]
-  ,[Plain [Str "b",SoftBreak,Str "b",Space,Str "2"]]
-  ,[Plain [Str "c",SoftBreak,Str "c",Space,Str "2"]]]
- ,[[Plain [Str "r2",Space,Str "d"]]
-  ,[Plain [Str "e"]]
-  ,[Plain [Str "f"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidth 0.2638888888888889)
+ ,(AlignDefault,ColWidth 0.16666666666666666)
+ ,(AlignDefault,ColWidth 0.18055555555555555)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "col",Space,Str "1"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "col",Space,Str "2"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "col",Space,Str "3"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "r1",Space,Str "a",SoftBreak,Str "r1",Space,Str "bis"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "b",SoftBreak,Str "b",Space,Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "c",SoftBreak,Str "c",Space,Str "2"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "r2",Space,Str "d"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "e"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "f"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Headless"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.2638888888888889,0.16666666666666666,0.18055555555555555]
- [[]
- ,[]
- ,[]]
- [[[Plain [Str "r1",Space,Str "a",SoftBreak,Str "r1",Space,Str "bis"]]
-  ,[Plain [Str "b",SoftBreak,Str "b",Space,Str "2"]]
-  ,[Plain [Str "c",SoftBreak,Str "c",Space,Str "2"]]]
- ,[[Plain [Str "r2",Space,Str "d"]]
-  ,[Plain [Str "e"]]
-  ,[Plain [Str "f"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidth 0.2638888888888889)
+ ,(AlignDefault,ColWidth 0.16666666666666666)
+ ,(AlignDefault,ColWidth 0.18055555555555555)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "r1",Space,Str "a",SoftBreak,Str "r1",Space,Str "bis"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "b",SoftBreak,Str "b",Space,Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "c",SoftBreak,Str "c",Space,Str "2"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "r2",Space,Str "d"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "e"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "f"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "With",Space,Str "alignments"]
-,Table [] [AlignRight,AlignLeft,AlignCenter] [0.2638888888888889,0.16666666666666666,0.18055555555555555]
- [[Plain [Str "col",Space,Str "1"]]
- ,[Plain [Str "col",Space,Str "2"]]
- ,[Plain [Str "col",Space,Str "3"]]]
- [[[Plain [Str "r1",Space,Str "a",SoftBreak,Str "r1",Space,Str "bis"]]
-  ,[Plain [Str "b",SoftBreak,Str "b",Space,Str "2"]]
-  ,[Plain [Str "c",SoftBreak,Str "c",Space,Str "2"]]]
- ,[[Plain [Str "r2",Space,Str "d"]]
-  ,[Plain [Str "e"]]
-  ,[Plain [Str "f"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignRight,ColWidth 0.2638888888888889)
+ ,(AlignLeft,ColWidth 0.16666666666666666)
+ ,(AlignCenter,ColWidth 0.18055555555555555)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "col",Space,Str "1"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "col",Space,Str "2"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "col",Space,Str "3"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "r1",Space,Str "a",SoftBreak,Str "r1",Space,Str "bis"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "b",SoftBreak,Str "b",Space,Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "c",SoftBreak,Str "c",Space,Str "2"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "r2",Space,Str "d"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "e"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "f"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Headless",Space,Str "with",Space,Str "alignments"]
-,Table [] [AlignRight,AlignLeft,AlignCenter] [0.2638888888888889,0.16666666666666666,0.18055555555555555]
- [[]
- ,[]
- ,[]]
- [[[Plain [Str "r1",Space,Str "a",SoftBreak,Str "r1",Space,Str "bis"]]
-  ,[Plain [Str "b",SoftBreak,Str "b",Space,Str "2"]]
-  ,[Plain [Str "c",SoftBreak,Str "c",Space,Str "2"]]]
- ,[[Plain [Str "r2",Space,Str "d"]]
-  ,[Plain [Str "e"]]
-  ,[Plain [Str "f"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignRight,ColWidth 0.2638888888888889)
+ ,(AlignLeft,ColWidth 0.16666666666666666)
+ ,(AlignCenter,ColWidth 0.18055555555555555)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "r1",Space,Str "a",SoftBreak,Str "r1",Space,Str "bis"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "b",SoftBreak,Str "b",Space,Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "c",SoftBreak,Str "c",Space,Str "2"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "r2",Space,Str "d"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "e"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "f"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Spaces",Space,Str "at",Space,Str "ends",Space,Str "of",Space,Str "lines"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.2638888888888889,0.16666666666666666,0.18055555555555555]
- [[]
- ,[]
- ,[]]
- [[[Plain [Str "r1",Space,Str "a",SoftBreak,Str "r1",Space,Str "bis"]]
-  ,[Plain [Str "b",SoftBreak,Str "b",Space,Str "2"]]
-  ,[Plain [Str "c",SoftBreak,Str "c",Space,Str "2"]]]
- ,[[Plain [Str "r2",Space,Str "d"]]
-  ,[Plain [Str "e"]]
-  ,[Plain [Str "f"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidth 0.2638888888888889)
+ ,(AlignDefault,ColWidth 0.16666666666666666)
+ ,(AlignDefault,ColWidth 0.18055555555555555)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "r1",Space,Str "a",SoftBreak,Str "r1",Space,Str "bis"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "b",SoftBreak,Str "b",Space,Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "c",SoftBreak,Str "c",Space,Str "2"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "r2",Space,Str "d"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "e"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "f"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Multiple",Space,Str "blocks",Space,Str "in",Space,Str "a",Space,Str "cell"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.2638888888888889,0.16666666666666666,0.18055555555555555]
- [[]
- ,[]
- ,[]]
- [[[Header 1 ("col-1",[],[]) [Str "col",Space,Str "1"]
-   ,Plain [Str "col",Space,Str "1"]]
-  ,[Header 1 ("col-2",[],[]) [Str "col",Space,Str "2"]
-   ,Plain [Str "col",Space,Str "2"]]
-  ,[Header 1 ("col-3",[],[]) [Str "col",Space,Str "3"]
-   ,Plain [Str "col",Space,Str "3"]]]
- ,[[Para [Str "r1",Space,Str "a"]
-   ,Para [Str "r1",Space,Str "bis"]]
-  ,[BulletList
-    [[Plain [Str "b"]]
-    ,[Plain [Str "b",Space,Str "2"]]
-    ,[Plain [Str "b",Space,Str "2"]]]]
-  ,[Plain [Str "c",SoftBreak,Str "c",Space,Str "2",SoftBreak,Str "c",Space,Str "2"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidth 0.2638888888888889)
+ ,(AlignDefault,ColWidth 0.16666666666666666)
+ ,(AlignDefault,ColWidth 0.18055555555555555)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Header 1 ("col-1",[],[]) [Str "col",Space,Str "1"]
+    ,Plain [Str "col",Space,Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Header 1 ("col-2",[],[]) [Str "col",Space,Str "2"]
+    ,Plain [Str "col",Space,Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Header 1 ("col-3",[],[]) [Str "col",Space,Str "3"]
+    ,Plain [Str "col",Space,Str "3"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "r1",Space,Str "a"]
+    ,Para [Str "r1",Space,Str "bis"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [BulletList
+     [[Plain [Str "b"]]
+     ,[Plain [Str "b",Space,Str "2"]]
+     ,[Plain [Str "b",Space,Str "2"]]]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "c",SoftBreak,Str "c",Space,Str "2",SoftBreak,Str "c",Space,Str "2"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Empty",Space,Str "cells"]
-,Table [] [AlignDefault,AlignDefault] [5.555555555555555e-2,5.555555555555555e-2]
- [[]
- ,[]]
- [[[]
-  ,[]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidth 5.555555555555555e-2)
+ ,(AlignDefault,ColWidth 5.555555555555555e-2)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]])]
+ (TableFoot ("",[],[])
+ [])
 ,Header 2 ("entities-in-links-and-titles",[],[]) [Str "Entities",Space,Str "in",Space,Str "links",Space,Str "and",Space,Str "titles"]
 ,Para [Link ("",[],[]) [Str "link"] ("/\252rl","\246\246!")]
 ,Para [Link ("",["uri"],[]) [Str "http://g\246\246gle.com"] ("http://g\246\246gle.com","")]
diff --git a/test/mediawiki-reader.native b/test/mediawiki-reader.native
--- a/test/mediawiki-reader.native
+++ b/test/mediawiki-reader.native
@@ -187,76 +187,232 @@
 ,RawBlock (Format "mediawiki") "{{Thankyou|all your effort|Me}}"
 ,Para [Str "Written",Space,RawInline (Format "mediawiki") "{{{date}}}",Space,Str "by",Space,RawInline (Format "mediawiki") "{{{name}}}",Str "."]
 ,Header 2 ("tables",[],[]) [Str "tables"]
-,Table [] [AlignDefault,AlignDefault] [0.0,0.0]
- [[]
- ,[]]
- [[[Para [Str "Orange"]]
-  ,[Para [Str "Apple"]]]
- ,[[Para [Str "Bread"]]
-  ,[Para [Str "Pie"]]]
- ,[[Para [Str "Butter"]]
-  ,[Para [Str "Ice",Space,Str "cream"]]]]
-,Table [Str "Food",Space,Str "complements"] [AlignDefault,AlignDefault] [0.0,0.0]
- [[Para [Str "Orange"]]
- ,[Para [Str "Apple"]]]
- [[[Para [Str "Bread"]]
-  ,[Para [Str "Pie"]]]
- ,[[Para [Str "Butter"]]
-  ,[Para [Str "Ice",Space,Str "cream"]]]]
-,Table [Str "Food",Space,Str "complements"] [AlignDefault,AlignDefault] [0.0,0.0]
- [[Para [Str "Orange"]]
- ,[Para [Str "Apple"]]]
- [[[Para [Str "Bread"]
-   ,Para [Str "and",Space,Str "cheese"]]
-  ,[Para [Str "Pie"]
-   ,OrderedList (1,DefaultStyle,DefaultDelim)
-    [[Plain [Str "apple"]]
-    ,[Plain [Str "carrot"]]]]]]
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[]
- ,[]
- ,[]]
- [[[Para [Str "Orange"]]
-  ,[Para [Str "Apple"]]
-  ,[Para [Str "more"]]]
- ,[[Para [Str "Bread"]]
-  ,[Para [Str "Pie"]]
-  ,[Para [Str "more"]]]
- ,[[Para [Str "Butter"]]
-  ,[Para [Str "Ice",Space,Str "cream"]]
-  ,[Para [Str "and",Space,Str "more"]]]]
-,Table [] [AlignLeft,AlignRight,AlignCenter] [0.25,0.125,0.125]
- [[Para [Str "Left"]]
- ,[Para [Str "Right"]]
- ,[Para [Str "Center"]]]
- [[[Para [Str "left"]]
-  ,[Para [Str "15.00"]]
-  ,[Para [Str "centered"]]]
- ,[[Para [Str "more"]]
-  ,[Para [Str "2.0"]]
-  ,[Para [Str "more"]]]]
-,Table [] [AlignDefault,AlignDefault] [0.0,0.0]
- [[]
- ,[]]
- [[[Para [Str "Orange"]]
-  ,[Para [Str "Apple"]]]
- ,[[Para [Str "Bread"]]
-  ,[Table [] [AlignDefault,AlignDefault] [0.0,0.0]
-    [[Para [Str "fruit"]]
-    ,[Para [Str "topping"]]]
-    [[[Para [Str "apple"]]
-     ,[Para [Str "ice",Space,Str "cream"]]]]]]
- ,[[Para [Str "Butter"]]
-  ,[Para [Str "Ice",Space,Str "cream"]]]]
-,Table [] [AlignDefault] [0.0]
- [[]]
- [[[Para [Str "Orange"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Orange"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Apple"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Bread"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Pie"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Butter"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Ice",Space,Str "cream"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [Plain [Str "Food",Space,Str "complements"]])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Orange"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Apple"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Bread"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Pie"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Butter"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Ice",Space,Str "cream"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [Plain [Str "Food",Space,Str "complements"]])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Orange"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Apple"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Bread"]
+    ,Para [Str "and",Space,Str "cheese"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Pie"]
+    ,OrderedList (1,DefaultStyle,DefaultDelim)
+     [[Plain [Str "apple"]]
+     ,[Plain [Str "carrot"]]]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Orange"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Apple"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "more"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Bread"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Pie"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "more"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Butter"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Ice",Space,Str "cream"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "and",Space,Str "more"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidth 0.25)
+ ,(AlignRight,ColWidth 0.125)
+ ,(AlignCenter,ColWidth 0.125)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Left"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Right"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "Center"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "left"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "15.00"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "centered"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "more"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "2.0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "more"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Orange"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Apple"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Bread"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Table ("",[],[]) (Caption Nothing
+     [])
+     [(AlignDefault,ColWidthDefault)
+     ,(AlignDefault,ColWidthDefault)]
+     (TableHead ("",[],[])
+     [Row ("",[],[])
+      [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+       [Para [Str "fruit"]]
+      ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+       [Para [Str "topping"]]]])
+     [(TableBody ("",[],[]) (RowHeadColumns 0)
+      []
+      [Row ("",[],[])
+       [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+        [Para [Str "apple"]]
+       ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+        [Para [Str "ice",Space,Str "cream"]]]])]
+     (TableFoot ("",[],[])
+     [])]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Butter"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Ice",Space,Str "cream"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "Orange"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Paragraph",Space,Str "after",Space,Str "the",Space,Str "table."]
-,Table [] [AlignDefault,AlignDefault] [0.0,0.0]
- [[Para [Str "fruit"]]
- ,[Para [Str "topping"]]]
- [[[Para [Str "apple"]]
-  ,[Para [Str "ice",Space,Str "cream"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "fruit"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Para [Str "topping"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "apple"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "ice",Space,Str "cream"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Header 2 ("notes",[],[]) [Str "notes"]
 ,Para [Str "My",Space,Str "note!",Note [Plain [Str "This."]]]
 ,Para [Str "URL",Space,Str "note.",Note [Plain [Link ("",[],[]) [Str "http://docs.python.org/library/functions.html#range"] ("http://docs.python.org/library/functions.html#range","")]]]]
diff --git a/test/odt/native/simpleTable.native b/test/odt/native/simpleTable.native
--- a/test/odt/native/simpleTable.native
+++ b/test/odt/native/simpleTable.native
@@ -1,1 +1,1 @@
-[Table [] [AlignDefault,AlignDefault] [0.0,0.0] [[],[]] [[[Plain [Str "Content"]],[Plain [Str "More",Space,Str "content"]]]],Para []]
+[Table ("",[],[]) (Caption Nothing []) [(AlignDefault,ColWidthDefault),(AlignDefault,ColWidthDefault)] (TableHead ("",[],[]) [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) []]]) [TableBody ("",[],[]) (RowHeadColumns 0) [] [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Content"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "More",Space,Str "content"]]]]] (TableFoot ("",[],[]) []),Para []]
diff --git a/test/odt/native/simpleTableWithCaption.native b/test/odt/native/simpleTableWithCaption.native
--- a/test/odt/native/simpleTableWithCaption.native
+++ b/test/odt/native/simpleTableWithCaption.native
@@ -1,1 +1,1 @@
-[Table [Str "Table",Space,Str "1:",Space,Str "Some",Space,Str "caption",Space,Str "for",Space,Str "a",Space,Str "table"] [AlignDefault,AlignDefault] [0.0,0.0] [[],[]] [[[Plain [Str "Content"]],[Plain [Str "More",Space,Str "content"]]]],Para []]
+[Table ("",[],[]) (Caption Nothing [Para [Str "Table",Space,Str "1:",Space,Str "Some",Space,Str "caption",Space,Str "for",Space,Str "a",Space,Str "table"]]) [(AlignDefault,ColWidthDefault),(AlignDefault,ColWidthDefault)] (TableHead ("",[],[]) [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) []]]) [TableBody ("",[],[]) (RowHeadColumns 0) [] [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Content"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "More",Space,Str "content"]]]]] (TableFoot ("",[],[]) []),Para []]
diff --git a/test/odt/native/tableWithContents.native b/test/odt/native/tableWithContents.native
--- a/test/odt/native/tableWithContents.native
+++ b/test/odt/native/tableWithContents.native
@@ -1,1 +1,1 @@
-[Table [] [AlignDefault,AlignDefault] [0.0,0.0] [[],[]]  [[[Plain [Str "A"]],[Plain [Str "B"]]],[[Plain [Str "C"]],[Plain [Str "D"]]]],Para []]
+[Table ("",[],[]) (Caption Nothing []) [(AlignDefault,ColWidthDefault),(AlignDefault,ColWidthDefault)] (TableHead ("",[],[]) [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) []]]) [TableBody ("",[],[]) (RowHeadColumns 0) [] [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "A"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "B"]]],Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "C"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "D"]]]]] (TableFoot ("",[],[]) []),Para []]
diff --git a/test/pipe-tables.native b/test/pipe-tables.native
--- a/test/pipe-tables.native
+++ b/test/pipe-tables.native
@@ -1,115 +1,334 @@
 [Para [Str "Simplest",Space,Str "table",Space,Str "without",Space,Str "caption:"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[Plain [Str "Default1"]]
- ,[Plain [Str "Default2"]]
- ,[Plain [Str "Default3"]]]
- [[[Plain [Str "12"]]
-  ,[Plain [Str "12"]]
-  ,[Plain [Str "12"]]]
- ,[[Plain [Str "123"]]
-  ,[Plain [Str "123"]]
-  ,[Plain [Str "123"]]]
- ,[[Plain [Str "1"]]
-  ,[Plain [Str "1"]]
-  ,[Plain [Str "1"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default1"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default2"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default3"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Simple",Space,Str "table",Space,Str "with",Space,Str "caption:"]
-,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] [AlignRight,AlignLeft,AlignDefault,AlignCenter] [0.0,0.0,0.0,0.0]
- [[Plain [Str "Right"]]
- ,[Plain [Str "Left"]]
- ,[Plain [Str "Default"]]
- ,[Plain [Str "Center"]]]
- [[[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 ("",[],[]) (Caption Nothing
+ [Plain [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."]])
+ [(AlignRight,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Center"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Simple",Space,Str "table",Space,Str "without",Space,Str "caption:"]
-,Table [] [AlignRight,AlignLeft,AlignCenter] [0.0,0.0,0.0]
- [[Plain [Str "Right"]]
- ,[Plain [Str "Left"]]
- ,[Plain [Str "Center"]]]
- [[[Plain [Str "12"]]
-  ,[Plain [Str "12"]]
-  ,[Plain [Str "12"]]]
- ,[[Plain [Str "123"]]
-  ,[Plain [Str "123"]]
-  ,[Plain [Str "123"]]]
- ,[[Plain [Str "1"]]
-  ,[Plain [Str "1"]]
-  ,[Plain [Str "1"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignRight,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Center"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Headerless",Space,Str "table",Space,Str "without",Space,Str "caption:"]
-,Table [] [AlignRight,AlignLeft,AlignCenter] [0.0,0.0,0.0]
- [[]
- ,[]
- ,[]]
- [[[Plain [Str "12"]]
-  ,[Plain [Str "12"]]
-  ,[Plain [Str "12"]]]
- ,[[Plain [Str "123"]]
-  ,[Plain [Str "123"]]
-  ,[Plain [Str "123"]]]
- ,[[Plain [Str "1"]]
-  ,[Plain [Str "1"]]
-  ,[Plain [Str "1"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignRight,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Table",Space,Str "without",Space,Str "sides:"]
-,Table [] [AlignDefault,AlignRight] [0.0,0.0]
- [[Plain [Str "Fruit"]]
- ,[Plain [Str "Quantity"]]]
- [[[Plain [Str "apple"]]
-  ,[Plain [Str "5"]]]
- ,[[Plain [Str "orange"]]
-  ,[Plain [Str "17"]]]
- ,[[Plain [Str "pear"]]
-  ,[Plain [Str "302"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignRight,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Fruit"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Quantity"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "apple"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "orange"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "17"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "pear"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "302"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "One-column:"]
-,Table [] [AlignDefault] [0.0]
- [[Plain [Str "hi"]]]
- [[[Plain [Str "lo"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "hi"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "lo"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Header-less",Space,Str "one-column:"]
-,Table [] [AlignCenter] [0.0]
- [[]]
- [[[Plain [Str "hi"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignCenter,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "hi"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Indented",Space,Str "left",Space,Str "column:"]
-,Table [] [AlignRight,AlignLeft] [0.0,0.0]
- [[Plain [Str "Number",Space,Str "of",Space,Str "siblings"]]
- ,[Plain [Str "Salary"]]]
- [[[Plain [Str "3"]]
-  ,[Plain [Str "33"]]]
- ,[[Plain [Str "4"]]
-  ,[Plain [Str "44"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignRight,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Number",Space,Str "of",Space,Str "siblings"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Salary"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "33"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "44"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Long",Space,Str "pipe",Space,Str "table",Space,Str "with",Space,Str "relative",Space,Str "widths:"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.15517241379310345,0.1724137931034483,0.6724137931034483]
- [[Plain [Str "Default1"]]
- ,[Plain [Str "Default2"]]
- ,[Plain [Str "Default3"]]]
- [[[Plain [Str "123"]]
-  ,[Plain [Str "this",Space,Str "is",Space,Str "a",Space,Str "table",Space,Str "cell"]]
-  ,[Plain [Str "and",Space,Str "this",Space,Str "is",Space,Str "a",Space,Str "really",Space,Str "long",Space,Str "table",Space,Str "cell",Space,Str "that",Space,Str "will",Space,Str "probably",Space,Str "need",Space,Str "wrapping"]]]
- ,[[Plain [Str "123"]]
-  ,[Plain [Str "123"]]
-  ,[Plain [Str "123"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidth 0.15517241379310345)
+ ,(AlignDefault,ColWidth 0.1724137931034483)
+ ,(AlignDefault,ColWidth 0.6724137931034483)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default1"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default2"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default3"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "this",Space,Str "is",Space,Str "a",Space,Str "table",Space,Str "cell"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "and",Space,Str "this",Space,Str "is",Space,Str "a",Space,Str "really",Space,Str "long",Space,Str "table",Space,Str "cell",Space,Str "that",Space,Str "will",Space,Str "probably",Space,Str "need",Space,Str "wrapping"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Pipe",Space,Str "table",Space,Str "with",Space,Str "no",Space,Str "body:"]
-,Table [] [AlignDefault] [0.0]
- [[Plain [Str "Header"]]]
- []
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Header"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Pipe",Space,Str "table",Space,Str "with",Space,Str "tricky",Space,Str "cell",Space,Str "contents",Space,Str "(see",Space,Str "#2765):"]
-,Table [] [AlignLeft,AlignRight,AlignRight] [0.0,0.0,0.0]
- [[]
- ,[Plain [Str "IP_gene8-_1st"]]
- ,[Plain [Str "IP_gene8+_1st"]]]
- [[[Plain [Str "IP_gene8-_1st"]]
-  ,[Plain [Str "1.0000000"]]
-  ,[Plain [Str "0.4357325"]]]
- ,[[Plain [Str "IP_gene8+_1st"]]
-  ,[Plain [Str "0.4357325"]]
-  ,[Plain [Str "1.0000000"]]]
- ,[[Plain [Str "foo",Code ("",[],[]) "bar|baz"]]
-  ,[Plain [Str "and|escaped"]]
-  ,[Plain [Str "3.0000000"]]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidthDefault)
+ ,(AlignRight,ColWidthDefault)
+ ,(AlignRight,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "IP_gene8-_1st"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "IP_gene8+_1st"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "IP_gene8-_1st"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1.0000000"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "0.4357325"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "IP_gene8+_1st"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "0.4357325"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1.0000000"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "foo",Code ("",[],[]) "bar|baz"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "and|escaped"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3.0000000"]]]])]
+ (TableFoot ("",[],[])
+ [])]
diff --git a/test/pptx/inline_formatting.pptx b/test/pptx/inline_formatting.pptx
Binary files a/test/pptx/inline_formatting.pptx and b/test/pptx/inline_formatting.pptx differ
diff --git a/test/pptx/inline_formatting_templated.pptx b/test/pptx/inline_formatting_templated.pptx
Binary files a/test/pptx/inline_formatting_templated.pptx and b/test/pptx/inline_formatting_templated.pptx differ
diff --git a/test/pptx/speaker_notes_afterseps.native b/test/pptx/speaker_notes_afterseps.native
--- a/test/pptx/speaker_notes_afterseps.native
+++ b/test/pptx/speaker_notes_afterseps.native
@@ -1,23 +1,53 @@
 [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"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [Para [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax,",Space,Str "with",Space,Str "alignment"]])
+ [(AlignRight,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Center"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Div ("",["notes"],[])
  [Para [Str "foo",Space,Str "bar"]]
 ,Div ("",["columns"],[])
diff --git a/test/pptx/tables.native b/test/pptx/tables.native
--- a/test/pptx/tables.native
+++ b/test/pptx/tables.native
@@ -1,35 +1,95 @@
 [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"]]]]]
+,Table ("",[],[]) (Caption Nothing
+ [Para [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax,",Space,Str "with",Space,Str "alignment"]])
+ [(AlignRight,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Center"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignRight,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Center"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])]
diff --git a/test/rst-reader.native b/test/rst-reader.native
--- a/test/rst-reader.native
+++ b/test/rst-reader.native
@@ -244,72 +244,194 @@
  ,[Str "Continuation",Space,Str "line"]
  ,[Str "\160\160and",Space,Str "another"]]
 ,Header 1 ("simple-tables",[],[]) [Str "Simple",Space,Str "Tables"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[Plain [Str "col",Space,Str "1"]]
- ,[Plain [Str "col",Space,Str "2"]]
- ,[Plain [Str "col",Space,Str "3"]]]
- [[[Plain [Str "r1",Space,Str "a"]]
-  ,[Plain [Str "b"]]
-  ,[Plain [Str "c"]]]
- ,[[Plain [Str "r2",Space,Str "d"]]
-  ,[Plain [Str "e"]]
-  ,[Plain [Str "f"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "col",Space,Str "1"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "col",Space,Str "2"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "col",Space,Str "3"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "r1",Space,Str "a"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "b"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "c"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "r2",Space,Str "d"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "e"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "f"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Headless"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[]
- ,[]
- ,[]]
- [[[Plain [Str "r1",Space,Str "a"]]
-  ,[Plain [Str "b"]]
-  ,[Plain [Str "c"]]]
- ,[[Plain [Str "r2",Space,Str "d"]]
-  ,[Plain [Str "e"]]
-  ,[Plain [Str "f"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "r1",Space,Str "a"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "b"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "c"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "r2",Space,Str "d"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "e"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "f"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Header 1 ("grid-tables",[],[]) [Str "Grid",Space,Str "Tables"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.2375,0.15,0.1625]
- [[Plain [Str "col",Space,Str "1"]]
- ,[Plain [Str "col",Space,Str "2"]]
- ,[Plain [Str "col",Space,Str "3"]]]
- [[[Plain [Str "r1",Space,Str "a",SoftBreak,Str "r1",Space,Str "bis"]]
-  ,[Plain [Str "b",SoftBreak,Str "b",Space,Str "2"]]
-  ,[Plain [Str "c",SoftBreak,Str "c",Space,Str "2"]]]
- ,[[Plain [Str "r2",Space,Str "d"]]
-  ,[Plain [Str "e"]]
-  ,[Plain [Str "f"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidth 0.2375)
+ ,(AlignDefault,ColWidth 0.15)
+ ,(AlignDefault,ColWidth 0.1625)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "col",Space,Str "1"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "col",Space,Str "2"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "col",Space,Str "3"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "r1",Space,Str "a",SoftBreak,Str "r1",Space,Str "bis"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "b",SoftBreak,Str "b",Space,Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "c",SoftBreak,Str "c",Space,Str "2"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "r2",Space,Str "d"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "e"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "f"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Headless"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.2375,0.15,0.1625]
- [[]
- ,[]
- ,[]]
- [[[Plain [Str "r1",Space,Str "a",SoftBreak,Str "r1",Space,Str "bis"]]
-  ,[Plain [Str "b",SoftBreak,Str "b",Space,Str "2"]]
-  ,[Plain [Str "c",SoftBreak,Str "c",Space,Str "2"]]]
- ,[[Plain [Str "r2",Space,Str "d"]]
-  ,[Plain [Str "e"]]
-  ,[Plain [Str "f"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidth 0.2375)
+ ,(AlignDefault,ColWidth 0.15)
+ ,(AlignDefault,ColWidth 0.1625)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "r1",Space,Str "a",SoftBreak,Str "r1",Space,Str "bis"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "b",SoftBreak,Str "b",Space,Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "c",SoftBreak,Str "c",Space,Str "2"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "r2",Space,Str "d"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "e"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "f"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Spaces",Space,Str "at",Space,Str "ends",Space,Str "of",Space,Str "lines"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.2375,0.15,0.1625]
- [[]
- ,[]
- ,[]]
- [[[Plain [Str "r1",Space,Str "a",SoftBreak,Str "r1",Space,Str "bis"]]
-  ,[Plain [Str "b",SoftBreak,Str "b",Space,Str "2"]]
-  ,[Plain [Str "c",SoftBreak,Str "c",Space,Str "2"]]]
- ,[[Plain [Str "r2",Space,Str "d"]]
-  ,[Plain [Str "e"]]
-  ,[Plain [Str "f"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidth 0.2375)
+ ,(AlignDefault,ColWidth 0.15)
+ ,(AlignDefault,ColWidth 0.1625)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "r1",Space,Str "a",SoftBreak,Str "r1",Space,Str "bis"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "b",SoftBreak,Str "b",Space,Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "c",SoftBreak,Str "c",Space,Str "2"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "r2",Space,Str "d"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "e"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "f"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Multiple",Space,Str "blocks",Space,Str "in",Space,Str "a",Space,Str "cell"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.2375,0.15,0.1625]
- [[]
- ,[]
- ,[]]
- [[[Para [Str "r1",Space,Str "a"]
-   ,Para [Str "r1",Space,Str "bis"]]
-  ,[BulletList
-    [[Plain [Str "b"]]
-    ,[Plain [Str "b",Space,Str "2"]]
-    ,[Plain [Str "b",Space,Str "2"]]]]
-  ,[Plain [Str "c",SoftBreak,Str "c",Space,Str "2",SoftBreak,Str "c",Space,Str "2"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidth 0.2375)
+ ,(AlignDefault,ColWidth 0.15)
+ ,(AlignDefault,ColWidth 0.1625)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Para [Str "r1",Space,Str "a"]
+    ,Para [Str "r1",Space,Str "bis"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [BulletList
+     [[Plain [Str "b"]]
+     ,[Plain [Str "b",Space,Str "2"]]
+     ,[Plain [Str "b",Space,Str "2"]]]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "c",SoftBreak,Str "c",Space,Str "2",SoftBreak,Str "c",Space,Str "2"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Header 1 ("footnotes",[],[]) [Str "Footnotes"]
 ,Para [Note [Para [Str "Note",Space,Str "with",Space,Str "one",Space,Str "line."]]]
 ,Para [Note [Para [Str "Note",Space,Str "with",SoftBreak,Str "continuation",Space,Str "line."]]]
diff --git a/test/s5-basic.html b/test/s5-basic.html
--- a/test/s5-basic.html
+++ b/test/s5-basic.html
@@ -17,6 +17,7 @@
     div.column{display: inline-block; vertical-align: top; width: 50%;}
     div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
     ul.task-list{list-style: none;}
+    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
   </style>
   <!-- configuration parameters -->
   <meta name="defaultView" content="slideshow" />
diff --git a/test/s5-inserts.html b/test/s5-inserts.html
--- a/test/s5-inserts.html
+++ b/test/s5-inserts.html
@@ -15,6 +15,7 @@
     div.column{display: inline-block; vertical-align: top; width: 50%;}
     div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
     ul.task-list{list-style: none;}
+    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
   </style>
   <link rel="stylesheet" href="main.css" type="text/css" />
   STUFF INSERTED
diff --git a/test/tables-rstsubset.native b/test/tables-rstsubset.native
--- a/test/tables-rstsubset.native
+++ b/test/tables-rstsubset.native
@@ -1,114 +1,309 @@
 [Para [Str "Simple",Space,Str "table",Space,Str "with",Space,Str "caption:"]
-,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] [AlignDefault,AlignDefault,AlignDefault,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 ("",[],[]) (Caption Nothing
+ [Plain [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."]])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Center"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Simple",Space,Str "table",Space,Str "without",Space,Str "caption:"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault,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 ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Center"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Simple",Space,Str "table",Space,Str "indented",Space,Str "two",Space,Str "spaces:"]
-,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] [AlignDefault,AlignDefault,AlignDefault,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 ("",[],[]) (Caption Nothing
+ [Plain [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."]])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Center"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,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.3375]
- [[Plain [Str "Centered",SoftBreak,Str "Header"]]
- ,[Plain [Str "Left",SoftBreak,Str "Aligned"]]
- ,[Plain [Str "Right",SoftBreak,Str "Aligned"]]
- ,[Plain [Str "Default",Space,Str "aligned"]]]
- [[[Plain [Str "First"]]
-  ,[Plain [Str "row"]]
-  ,[Plain [Str "12.0"]]
-  ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",SoftBreak,Str "spans",Space,Str "multiple",Space,Str "lines."]]]
- ,[[Plain [Str "Second"]]
-  ,[Plain [Str "row"]]
-  ,[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",SoftBreak,Str "rows."]]]]
+,Table ("",[],[]) (Caption Nothing
+ [Plain [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,ColWidth 0.1375)
+ ,(AlignDefault,ColWidth 0.125)
+ ,(AlignDefault,ColWidth 0.15)
+ ,(AlignDefault,ColWidth 0.3375)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Centered",SoftBreak,Str "Header"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left",SoftBreak,Str "Aligned"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right",SoftBreak,Str "Aligned"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default",Space,Str "aligned"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "First"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "row"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12.0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",SoftBreak,Str "spans",Space,Str "multiple",Space,Str "lines."]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Second"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "row"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5.0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [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."]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "caption:"]
-,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"]]
- ,[Plain [Str "Default",Space,Str "aligned"]]]
- [[[Plain [Str "First"]]
-  ,[Plain [Str "row"]]
-  ,[Plain [Str "12.0"]]
-  ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",SoftBreak,Str "spans",Space,Str "multiple",Space,Str "lines."]]]
- ,[[Plain [Str "Second"]]
-  ,[Plain [Str "row"]]
-  ,[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",SoftBreak,Str "rows."]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidth 0.1375)
+ ,(AlignDefault,ColWidth 0.125)
+ ,(AlignDefault,ColWidth 0.15)
+ ,(AlignDefault,ColWidth 0.3375)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Centered",SoftBreak,Str "Header"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left",SoftBreak,Str "Aligned"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right",SoftBreak,Str "Aligned"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default",Space,Str "aligned"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "First"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "row"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12.0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",SoftBreak,Str "spans",Space,Str "multiple",Space,Str "lines."]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Second"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "row"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5.0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [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."]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Table",Space,Str "without",Space,Str "column",Space,Str "headers:"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0,0.0]
- [[]
- ,[]
- ,[]
- ,[]]
- [[[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 ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,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.3375]
- [[]
- ,[]
- ,[]
- ,[]]
- [[[Plain [Str "First"]]
-  ,[Plain [Str "row"]]
-  ,[Plain [Str "12.0"]]
-  ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",SoftBreak,Str "spans",Space,Str "multiple",Space,Str "lines."]]]
- ,[[Plain [Str "Second"]]
-  ,[Plain [Str "row"]]
-  ,[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",SoftBreak,Str "rows."]]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidth 0.1375)
+ ,(AlignDefault,ColWidth 0.125)
+ ,(AlignDefault,ColWidth 0.15)
+ ,(AlignDefault,ColWidth 0.3375)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "First"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "row"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12.0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",SoftBreak,Str "spans",Space,Str "multiple",Space,Str "lines."]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Second"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "row"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5.0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [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."]]]])]
+ (TableFoot ("",[],[])
+ [])]
diff --git a/test/tables.fb2 b/test/tables.fb2
--- a/test/tables.fb2
+++ b/test/tables.fb2
@@ -10,6 +10,6 @@
 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
+the blank line between rows.</td></tr></table><p><emphasis /></p><p>Table without column headers:</p><table><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><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
--- a/test/tables.haddock
+++ b/test/tables.haddock
@@ -1,90 +1,90 @@
 Simple table with caption:
 
-> +-------+------+--------+---------+
-> | Right | Left | Center | Default |
-> +=======+======+========+=========+
-> | 12    | 12   | 12     | 12      |
-> +-------+------+--------+---------+
-> | 123   | 123  | 123    | 123     |
-> +-------+------+--------+---------+
-> | 1     | 1    | 1      | 1       |
-> +-------+------+--------+---------+
->
-> Demonstration of simple table syntax.
++-------+------+--------+---------+
+| Right | Left | Center | Default |
++=======+======+========+=========+
+| 12    | 12   | 12     | 12      |
++-------+------+--------+---------+
+| 123   | 123  | 123    | 123     |
++-------+------+--------+---------+
+| 1     | 1    | 1      | 1       |
++-------+------+--------+---------+
 
+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       |
-> +-------+------+--------+---------+
->
-> Demonstration of simple table syntax.
++-------+------+--------+---------+
+| Right | Left | Center | Default |
++=======+======+========+=========+
+| 12    | 12   | 12     | 12      |
++-------+------+--------+---------+
+| 123   | 123  | 123    | 123     |
++-------+------+--------+---------+
+| 1     | 1    | 1      | 1       |
++-------+------+--------+---------+
 
+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.    |
-> +----------+---------+-----------+--------------------------+
-> | Second   | row     | 5.0       | Here’s another one. Note |
-> |          |         |           | the blank line between   |
-> |          |         |           | rows.                    |
-> +----------+---------+-----------+--------------------------+
->
-> 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.                    |
++----------+---------+-----------+--------------------------+
 
+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.native b/test/tables.native
--- a/test/tables.native
+++ b/test/tables.native
@@ -1,114 +1,293 @@
 [Para [Str "Simple",Space,Str "table",Space,Str "with",Space,Str "caption:"]
-,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] [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 ("",[],[]) (Caption Nothing
+ [Plain [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."]])
+ [(AlignRight,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Center"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Simple",Space,Str "table",Space,Str "without",Space,Str "caption:"]
-,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"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignRight,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Center"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Simple",Space,Str "table",Space,Str "indented",Space,Str "two",Space,Str "spaces:"]
-,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] [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 ("",[],[]) (Caption Nothing
+ [Plain [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."]])
+ [(AlignRight,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Center"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,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.35]
- [[Plain [Str "Centered",SoftBreak,Str "Header"]]
- ,[Plain [Str "Left",SoftBreak,Str "Aligned"]]
- ,[Plain [Str "Right",SoftBreak,Str "Aligned"]]
- ,[Plain [Str "Default",Space,Str "aligned"]]]
- [[[Plain [Str "First"]]
-  ,[Plain [Str "row"]]
-  ,[Plain [Str "12.0"]]
-  ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",SoftBreak,Str "multiple",Space,Str "lines."]]]
- ,[[Plain [Str "Second"]]
-  ,[Plain [Str "row"]]
-  ,[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."]]]]
+,Table ("",[],[]) (Caption Nothing
+ [Plain [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,ColWidth 0.15)
+ ,(AlignLeft,ColWidth 0.1375)
+ ,(AlignRight,ColWidth 0.1625)
+ ,(AlignLeft,ColWidth 0.35)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Centered",SoftBreak,Str "Header"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left",SoftBreak,Str "Aligned"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right",SoftBreak,Str "Aligned"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default",Space,Str "aligned"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "First"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "row"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12.0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",SoftBreak,Str "multiple",Space,Str "lines."]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Second"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "row"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5.0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [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."]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "caption:"]
-,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"]]
- ,[Plain [Str "Default",Space,Str "aligned"]]]
- [[[Plain [Str "First"]]
-  ,[Plain [Str "row"]]
-  ,[Plain [Str "12.0"]]
-  ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",SoftBreak,Str "multiple",Space,Str "lines."]]]
- ,[[Plain [Str "Second"]]
-  ,[Plain [Str "row"]]
-  ,[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."]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignCenter,ColWidth 0.15)
+ ,(AlignLeft,ColWidth 0.1375)
+ ,(AlignRight,ColWidth 0.1625)
+ ,(AlignLeft,ColWidth 0.35)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Centered",SoftBreak,Str "Header"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Left",SoftBreak,Str "Aligned"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Right",SoftBreak,Str "Aligned"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Default",Space,Str "aligned"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "First"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "row"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12.0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",SoftBreak,Str "multiple",Space,Str "lines."]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Second"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "row"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5.0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [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."]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "Table",Space,Str "without",Space,Str "column",Space,Str "headers:"]
-,Table [] [AlignRight,AlignLeft,AlignCenter,AlignRight] [0.0,0.0,0.0,0.0]
- [[]
- ,[]
- ,[]
- ,[]]
- [[[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 ("",[],[]) (Caption Nothing
+ [])
+ [(AlignRight,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignRight,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "123"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,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.35]
- [[]
- ,[]
- ,[]
- ,[]]
- [[[Plain [Str "First"]]
-  ,[Plain [Str "row"]]
-  ,[Plain [Str "12.0"]]
-  ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",SoftBreak,Str "multiple",Space,Str "lines."]]]
- ,[[Plain [Str "Second"]]
-  ,[Plain [Str "row"]]
-  ,[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."]]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignCenter,ColWidth 0.15)
+ ,(AlignLeft,ColWidth 0.1375)
+ ,(AlignRight,ColWidth 0.1625)
+ ,(AlignDefault,ColWidth 0.35)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "First"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "row"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "12.0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",SoftBreak,Str "multiple",Space,Str "lines."]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Second"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "row"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5.0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [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."]]]])]
+ (TableFoot ("",[],[])
+ [])]
diff --git a/test/tables.tei b/test/tables.tei
--- a/test/tables.tei
+++ b/test/tables.tei
@@ -123,12 +123,6 @@
 </table>
 <p>Table without column headers:</p>
 <table>
-  <row role="label">
-    <cell></cell>
-    <cell></cell>
-    <cell></cell>
-    <cell></cell>
-  </row>
   <row>
     <cell><p>12</p></cell>
     <cell><p>12</p></cell>
@@ -150,12 +144,6 @@
 </table>
 <p>Multiline table without column headers:</p>
 <table>
-  <row role="label">
-    <cell></cell>
-    <cell></cell>
-    <cell></cell>
-    <cell></cell>
-  </row>
   <row>
     <cell><p>First</p></cell>
     <cell><p>row</p></cell>
diff --git a/test/test-pandoc.hs b/test/test-pandoc.hs
--- a/test/test-pandoc.hs
+++ b/test/test-pandoc.hs
@@ -34,6 +34,7 @@
 import qualified Tests.Writers.FB2
 import qualified Tests.Writers.HTML
 import qualified Tests.Writers.JATS
+import qualified Tests.Writers.Jira
 import qualified Tests.Writers.LaTeX
 import qualified Tests.Writers.Markdown
 import qualified Tests.Writers.Muse
@@ -57,6 +58,7 @@
           , testGroup "LaTeX" Tests.Writers.LaTeX.tests
           , testGroup "HTML" Tests.Writers.HTML.tests
           , testGroup "JATS" Tests.Writers.JATS.tests
+          , testGroup "Jira" Tests.Writers.Jira.tests
           , testGroup "Docbook" Tests.Writers.Docbook.tests
           , testGroup "Markdown" Tests.Writers.Markdown.tests
           , testGroup "Org" Tests.Writers.Org.tests
@@ -87,7 +89,7 @@
           , testGroup "FB2" Tests.Readers.FB2.tests
           , testGroup "DokuWiki" Tests.Readers.DokuWiki.tests
           ]
-        , testGroup "Lua"
+        ,  testGroup "Lua"
           [ testGroup "Lua filters" Tests.Lua.tests
           , testGroup "Lua modules" Tests.Lua.Module.tests
           ]
diff --git a/test/textile-reader.native b/test/textile-reader.native
--- a/test/textile-reader.native
+++ b/test/textile-reader.native
@@ -86,7 +86,7 @@
  ,([Str "beer"],
    [[Plain [Str "fresh",Space,Str "and",Space,Str "bitter"]]])]
 ,Header 1 ("inline-markup",[],[]) [Str "Inline",Space,Str "Markup"]
-,Para [Str "This",Space,Str "is",Space,Emph [Str "emphasized"],Str ",",Space,Str "and",Space,Str "so",Space,Emph [Str "is",Space,Str "this"],Str ".",LineBreak,Str "This",Space,Str "is",Space,Strong [Str "strong"],Str ",",Space,Str "and",Space,Str "so",Space,Strong [Str "is",Space,Str "this"],Str ".",LineBreak,Str "This",Space,Str "is",Space,Span ("",["underline"],[]) [Str "inserted"],Str ",",Space,Str "and",Space,Str "this",Space,Str "is",Space,Strikeout [Str "deleted"],Str ".",LineBreak,Str "Hyphenated-words-are-ok,",Space,Str "as",Space,Str "well",Space,Str "as",Space,Str "strange_underscore_notation.",LineBreak,Str "A",Space,Link ("",[],[]) [Strong [Str "strong",Space,Str "link"]] ("http://www.foobar.com",""),Str "."]
+,Para [Str "This",Space,Str "is",Space,Emph [Str "emphasized"],Str ",",Space,Str "and",Space,Str "so",Space,Emph [Str "is",Space,Str "this"],Str ".",LineBreak,Str "This",Space,Str "is",Space,Strong [Str "strong"],Str ",",Space,Str "and",Space,Str "so",Space,Strong [Str "is",Space,Str "this"],Str ".",LineBreak,Str "This",Space,Str "is",Space,Underline [Str "inserted"],Str ",",Space,Str "and",Space,Str "this",Space,Str "is",Space,Strikeout [Str "deleted"],Str ".",LineBreak,Str "Hyphenated-words-are-ok,",Space,Str "as",Space,Str "well",Space,Str "as",Space,Str "strange_underscore_notation.",LineBreak,Str "A",Space,Link ("",[],[]) [Strong [Str "strong",Space,Str "link"]] ("http://www.foobar.com",""),Str "."]
 ,Para [Emph [Strong [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em."]],LineBreak,Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word",Space,Str "and",Space,Emph [Strong [Str "that",Space,Str "one"]],Str ".",LineBreak,Strikeout [Str "This",Space,Str "is",Space,Str "strikeout",Space,Str "and",Space,Strong [Str "strong"]]]
 ,Para [Str "Superscripts:",Space,Str "a",Superscript [Str "bc"],Str "d",Space,Str "a",Space,Superscript [Strong [Str "hello"]],Space,Str "a",Superscript [Str "hello",Space,Str "there"],Str ".",LineBreak,Str "Subscripts:",Space,Subscript [Str "here"],Space,Str "H",Space,Subscript [Str "2"],Str "O,",Space,Str "H",Space,Subscript [Str "23"],Str "O,",Space,Str "H",Space,Subscript [Str "many",Space,Str "of",Space,Str "them"],Str "O."]
 ,Para [Str "Dashes",Space,Str ":",Space,Str "How",Space,Str "cool",Space,Str "\8212",Space,Str "automatic",Space,Str "dashes."]
@@ -103,37 +103,85 @@
 ,Header 1 ("tables",[],[]) [Str "Tables"]
 ,Para [Str "Textile",Space,Str "allows",Space,Str "tables",Space,Str "with",Space,Str "and",Space,Str "without",Space,Str "headers",Space,Str ":"]
 ,Header 2 ("without-headers",[],[]) [Str "Without",Space,Str "headers"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[]
- ,[]
- ,[]]
- [[[Plain [Str "name"]]
-  ,[Plain [Str "age"]]
-  ,[Plain [Str "sex"]]]
- ,[[Plain [Str "joan"]]
-  ,[Plain [Str "24"]]
-  ,[Plain [Str "f"]]]
- ,[[Plain [Str "archie"]]
-  ,[Plain [Str "29"]]
-  ,[Plain [Str "m"]]]
- ,[[Plain [Str "bella"]]
-  ,[Plain [Str "45"]]
-  ,[Plain [Str "f"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "name"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "age"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "sex"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "joan"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "24"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "f"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "archie"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "29"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "m"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "bella"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "45"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "f"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "and",Space,Str "some",Space,Str "text",Space,Str "following",Space,Str "\8230"]
 ,Header 2 ("with-headers",[],[]) [Str "With",Space,Str "headers"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[Plain [Str "name"]]
- ,[Plain [Str "age"]]
- ,[Plain [Str "sex"]]]
- [[[Plain [Str "joan"]]
-  ,[Plain [Str "24"]]
-  ,[Plain [Str "f"]]]
- ,[[Plain [Str "archie"]]
-  ,[Plain [Str "29"]]
-  ,[Plain [Str "m"]]]
- ,[[Plain [Str "bella"]]
-  ,[Plain [Str "45"]]
-  ,[Plain [Str "f"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "name"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "age"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "sex"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "joan"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "24"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "f"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "archie"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "29"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "m"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "bella"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "45"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "f"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Header 1 ("images",[],[]) [Str "Images"]
 ,Para [Str "Textile",Space,Str "inline",Space,Str "image",Space,Str "syntax,",Space,Str "like",LineBreak,Str "here",Space,Image ("",[],[]) [Str "this is the alt text"] ("this_is_an_image.png","this is the alt text"),LineBreak,Str "and",Space,Str "here",Space,Image ("",[],[]) [Str ""] ("this_is_an_image.png",""),Str "."]
 ,Header 1 ("attributes",[],[]) [Str "Attributes"]
@@ -143,16 +191,31 @@
 ,Header 2 ("justified",[],[("lang","en"),("style","color:blue;text-align:justify;")]) [Str "Justified"]
 ,Para [Str "as",Space,Str "well",Space,Str "as",Space,Strong [Span ("",["foo"],[]) [Str "inline",Space,Str "attributes"]],Space,Str "of",Space,Span ("",[],[("style","color:red;")]) [Str "all",Space,Str "kind"]]
 ,Para [Str "and",Space,Str "paragraph",Space,Str "attributes,",Space,Str "and",Space,Str "table",Space,Str "attributes."]
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[]
- ,[]
- ,[]]
- [[[Plain [Str "name"]]
-  ,[Plain [Str "age"]]
-  ,[Plain [Str "sex"]]]
- ,[[Plain [Str "joan"]]
-  ,[Plain [Str "24"]]
-  ,[Plain [Str "f"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "name"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "age"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "sex"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "joan"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "24"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "f"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Emph [Str "(class#id)",Space,Str "emph"]]
 ,Para [Emph [Str "(no",Space,Str "class#id)",Space,Str "emph"]]
 ,Header 1 ("entities",[],[]) [Str "Entities"]
diff --git a/test/tikiwiki-reader.native b/test/tikiwiki-reader.native
--- a/test/tikiwiki-reader.native
+++ b/test/tikiwiki-reader.native
@@ -90,41 +90,123 @@
      [[Plain [Str "five",Space,Str "sub",Space,Str "1",Space,Str "sub",Space,Str "1"]]]]
    ,[Plain [Str "five",Space,Str "sub",Space,Str "2"]]]]]
 ,Header 1 ("tables",[],[]) [Str "tables"]
-,Table [] [AlignDefault,AlignDefault] [0.0,0.0]
- [[Plain [Str ""]]
- ,[Plain [Str ""]]]
- [[[Plain [Str "Orange"]]
-  ,[Plain [Str "Apple"]]]
- ,[[Plain [Str "Bread"]]
-  ,[Plain [Str "Pie"]]]
- ,[[Plain [Str "Butter"]]
-  ,[Plain [Str "Ice",Space,Str "cream"]]]]
-,Table [] [AlignDefault,AlignDefault] [0.0,0.0]
- [[Plain [Str ""]]
- ,[Plain [Str ""]]]
- [[[Plain [Str "Orange"]]
-  ,[Plain [Str "Apple"]]]
- ,[[Plain [Str "Bread"]]
-  ,[Plain [Str "Pie"]]]
- ,[[Plain [Strong [Str "Butter"]]]
-  ,[Plain [Str "Ice",Space,Str "cream"]]]]
-,Table [] [AlignDefault,AlignDefault] [0.0,0.0]
- [[Plain [Str ""]]
- ,[Plain [Str ""]]]
- [[[Plain [Str "Orange"]]
-  ,[Plain [Str "Apple"]]]
- ,[[Plain [Str "Bread",LineBreak,LineBreak,Str "and",Space,Str "cheese"]]
-  ,[Plain [Str "Pie",LineBreak,LineBreak,Strong [Str "apple"],Space,Str "and",Space,Emph [Str "carrot"],Space]]]]
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[Plain [Str ""]]
- ,[Plain [Str ""]]
- ,[Plain [Str ""]]]
- [[[Plain [Space,Str "Orange",Space]]
-  ,[Plain [Space,Str "Apple",Space]]
-  ,[Plain [Space,Str "more"]]]
- ,[[Plain [Space,Str "Bread",Space]]
-  ,[Plain [Space,Str "Pie",Space]]
-  ,[Plain [Space,Str "more"]]]
- ,[[Plain [Space,Str "Butter",Space]]
-  ,[Plain [Space,Str "Ice",Space,Str "cream",Space]]
-  ,[Plain [Space,Str "and",Space,Str "more",Space]]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str ""]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str ""]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Orange"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Apple"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Bread"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Pie"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Butter"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Ice",Space,Str "cream"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str ""]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str ""]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Orange"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Apple"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Bread"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Pie"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Strong [Str "Butter"]]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Ice",Space,Str "cream"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str ""]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str ""]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Orange"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Apple"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Bread",LineBreak,LineBreak,Str "and",Space,Str "cheese"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Pie",LineBreak,LineBreak,Strong [Str "apple"],Space,Str "and",Space,Emph [Str "carrot"],Space]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str ""]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str ""]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str ""]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Space,Str "Orange",Space]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Space,Str "Apple",Space]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Space,Str "more"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Space,Str "Bread",Space]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Space,Str "Pie",Space]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Space,Str "more"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Space,Str "Butter",Space]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Space,Str "Ice",Space,Str "cream",Space]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Space,Str "and",Space,Str "more",Space]]]])]
+ (TableFoot ("",[],[])
+ [])]
diff --git a/test/twiki-reader.native b/test/twiki-reader.native
--- a/test/twiki-reader.native
+++ b/test/twiki-reader.native
@@ -127,40 +127,116 @@
    ,[Plain [Str "and"]]
    ,[Plain [Str "supported"]]]]]
 ,Header 1 ("tables",[],[]) [Str "tables"]
-,Table [] [AlignDefault,AlignDefault] [0.0,0.0]
- [[]
- ,[]]
- [[[Plain [Str "Orange"]]
-  ,[Plain [Str "Apple"]]]
- ,[[Plain [Str "Bread"]]
-  ,[Plain [Str "Pie"]]]
- ,[[Plain [Str "Butter"]]
-  ,[Plain [Str "Ice",Space,Str "cream"]]]]
-,Table [] [AlignLeft,AlignLeft] [0.0,0.0]
- [[Plain [Str "Orange"]]
- ,[Plain [Str "Apple"]]]
- [[[Plain [Str "Bread"]]
-  ,[Plain [Str "Pie"]]]
- ,[[Plain [Strong [Str "Butter"]]]
-  ,[Plain [Str "Ice",Space,Str "cream"]]]]
-,Table [] [AlignLeft,AlignLeft] [0.0,0.0]
- [[Plain [Str "Orange"]]
- ,[Plain [Str "Apple"]]]
- [[[Plain [Str "Bread",LineBreak,LineBreak,Str "and",Space,Str "cheese"]]
-  ,[Plain [Str "Pie",LineBreak,LineBreak,Strong [Str "apple"],Space,Str "and",Space,Emph [Str "carrot"]]]]]
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[]
- ,[]
- ,[]]
- [[[Plain [Str "Orange"]]
-  ,[Plain [Str "Apple"]]
-  ,[Plain [Str "more"]]]
- ,[[Plain [Str "Bread"]]
-  ,[Plain [Str "Pie"]]
-  ,[Plain [Str "more"]]]
- ,[[Plain [Str "Butter"]]
-  ,[Plain [Str "Ice",Space,Str "cream"]]
-  ,[Plain [Str "and",Space,Str "more"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Orange"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Apple"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Bread"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Pie"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Butter"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Ice",Space,Str "cream"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Orange"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Apple"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Bread"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Pie"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Strong [Str "Butter"]]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Ice",Space,Str "cream"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignLeft,ColWidthDefault)
+ ,(AlignLeft,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Orange"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Apple"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Bread",LineBreak,LineBreak,Str "and",Space,Str "cheese"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Pie",LineBreak,LineBreak,Strong [Str "apple"],Space,Str "and",Space,Emph [Str "carrot"]]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Orange"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Apple"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "more"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Bread"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Pie"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "more"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Butter"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Ice",Space,Str "cream"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "and",Space,Str "more"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Header 1 ("macros",[],[]) [Str "macros"]
 ,Para [Span ("",["twiki-macro","TEST"],[]) []]
 ,Para [Span ("",["twiki-macro","TEST"],[]) [Str ""]]
diff --git a/test/txt2tags.native b/test/txt2tags.native
--- a/test/txt2tags.native
+++ b/test/txt2tags.native
@@ -29,8 +29,8 @@
 ,Para [Strikeout [Str "-------+--------"]]
 ,Para [Str "(",Space,Strikeout [Str "----------------"],Space,Str ")"]
 ,Header 1 ("inline",[],[]) [Str "Inline"]
-,Para [Str "i)",Space,Strong [Str "b"],Space,Emph [Str "i"],Space,Span ("",["underline"],[]) [Str "u"],Space,Strikeout [Str "s"],Space,Code ("",[],[]) "m",Space,Str "r",Space,RawInline (Format "html") "t",SoftBreak,Str "i)",Space,Strong [Str "bo"],Space,Emph [Str "it"],Space,Span ("",["underline"],[]) [Str "un"],Space,Strikeout [Str "st"],Space,Code ("",[],[]) "mo",Space,Str "ra",Space,RawInline (Format "html") "tg",SoftBreak,Str "i)",Space,Strong [Str "bold"],Space,Emph [Str "ital"],Space,Span ("",["underline"],[]) [Str "undr"],Space,Strikeout [Str "strk"],Space,Code ("",[],[]) "mono",Space,Str "raw",Space,RawInline (Format "html") "tggd",SoftBreak,Str "i)",Space,Strong [Str "bo",Space,Str "ld"],Space,Emph [Str "it",Space,Str "al"],Space,Span ("",["underline"],[]) [Str "un",Space,Str "dr"],Space,Strikeout [Str "st",Space,Str "rk"],Space,Code ("",[],[]) "mo no",Space,Str "r",Space,Str "aw",Space,RawInline (Format "html") "tg gd",SoftBreak,Str "i)",Space,Strong [Str "bo",Space,Str "*",Space,Str "ld"],Space,Emph [Str "it",Space,Str "/",Space,Str "al"],Space,Span ("",["underline"],[]) [Str "un",Space,Str "_",Space,Str "dr"],Space,Strikeout [Str "st",Space,Str "-",Space,Str "rk"],Space,Code ("",[],[]) "mo ` no",Space,Str "r",Space,Str "\"",Space,Str "aw",Space,RawInline (Format "html") "tg ' gd",SoftBreak,Str "i)",Space,Strong [Str "bo",Space,Str "**ld"],Space,Emph [Str "it",Space,Str "//al"],Space,Span ("",["underline"],[]) [Str "un",Space,Str "__dr"],Space,Strikeout [Str "st",Space,Str "--rk"],Space,Code ("",[],[]) "mo ``no",Space,Str "r",Space,Str "\"\"aw",Space,RawInline (Format "html") "tg ''gd",SoftBreak,Str "i)",Space,Strong [Str "bo",Space,Str "**",Space,Str "ld"],Space,Emph [Str "it",Space,Str "//",Space,Str "al"],Space,Span ("",["underline"],[]) [Str "un",Space,Str "__",Space,Str "dr"],Space,Strikeout [Str "st",Space,Str "--",Space,Str "rk"],Space,Code ("",[],[]) "mo `` no",Space,Str "r",Space,Str "\"\"",Space,Str "aw",Space,RawInline (Format "html") "tg '' gd",SoftBreak,Str "i)",Space,Strong [Str "**bold**"],Space,Emph [Str "//ital//"],Space,Span ("",["underline"],[]) [Str "__undr__"],Space,Strikeout [Str "--strk--"],Space,Code ("",[],[]) "``mono``",Space,Str "\"\"raw\"\"",Space,RawInline (Format "html") "''tggd''",SoftBreak,Str "i)",Space,Strong [Str "*bold*"],Space,Emph [Str "/ital/"],Space,Span ("",["underline"],[]) [Str "_undr_"],Space,Strikeout [Str "-strk-"],Space,Code ("",[],[]) "`mono`",Space,Str "\"raw\"",Space,RawInline (Format "html") "'tggd'"]
-,Para [Str "i)",Space,Strong [Str "*"],Space,Emph [Str "/"],Space,Span ("",["underline"],[]) [Str "_"],Space,Strikeout [Str "-"],Space,Code ("",[],[]) "`",Space,Str "\"",Space,RawInline (Format "html") "'",SoftBreak,Str "i)",Space,Strong [Str "**"],Space,Emph [Str "//"],Space,Span ("",["underline"],[]) [Str "__"],Space,Strikeout [Str "--"],Space,Code ("",[],[]) "``",Space,Str "\"\"",Space,RawInline (Format "html") "''",SoftBreak,Str "i)",Space,Strong [Str "***"],Space,Emph [Str "///"],Space,Span ("",["underline"],[]) [Str "___"],Space,Strikeout [Str "---"],Space,Code ("",[],[]) "```",Space,Str "\"\"\"",Space,RawInline (Format "html") "'''",SoftBreak,Str "i)",Space,Strong [Str "****"],Space,Emph [Str "////"],Space,Span ("",["underline"],[]) [Str "____"],Space,Strikeout [Str "----"],Space,Code ("",[],[]) "````",Space,Str "\"\"\"\"",Space,RawInline (Format "html") "''''",SoftBreak,Str "i)",Space,Strong [Str "*****"],Space,Emph [Str "/////"],Space,Span ("",["underline"],[]) [Str "_____"],Space,Strikeout [Str "-----"],Space,Code ("",[],[]) "`````",Space,Str "\"\"\"\"\"",Space,RawInline (Format "html") "'''''",SoftBreak,Str "i)",Space,Strong [Str "******"],Space,Emph [Str "//////"],Space,Span ("",["underline"],[]) [Str "______"],Space,Strikeout [Str "------"],Space,Code ("",[],[]) "``````",Space,Str "\"\"\"\"\"\"",Space,RawInline (Format "html") "''''''"]
+,Para [Str "i)",Space,Strong [Str "b"],Space,Emph [Str "i"],Space,Underline [Str "u"],Space,Strikeout [Str "s"],Space,Code ("",[],[]) "m",Space,Str "r",Space,RawInline (Format "html") "t",SoftBreak,Str "i)",Space,Strong [Str "bo"],Space,Emph [Str "it"],Space,Underline [Str "un"],Space,Strikeout [Str "st"],Space,Code ("",[],[]) "mo",Space,Str "ra",Space,RawInline (Format "html") "tg",SoftBreak,Str "i)",Space,Strong [Str "bold"],Space,Emph [Str "ital"],Space,Underline [Str "undr"],Space,Strikeout [Str "strk"],Space,Code ("",[],[]) "mono",Space,Str "raw",Space,RawInline (Format "html") "tggd",SoftBreak,Str "i)",Space,Strong [Str "bo",Space,Str "ld"],Space,Emph [Str "it",Space,Str "al"],Space,Underline [Str "un",Space,Str "dr"],Space,Strikeout [Str "st",Space,Str "rk"],Space,Code ("",[],[]) "mo no",Space,Str "r",Space,Str "aw",Space,RawInline (Format "html") "tg gd",SoftBreak,Str "i)",Space,Strong [Str "bo",Space,Str "*",Space,Str "ld"],Space,Emph [Str "it",Space,Str "/",Space,Str "al"],Space,Underline [Str "un",Space,Str "_",Space,Str "dr"],Space,Strikeout [Str "st",Space,Str "-",Space,Str "rk"],Space,Code ("",[],[]) "mo ` no",Space,Str "r",Space,Str "\"",Space,Str "aw",Space,RawInline (Format "html") "tg ' gd",SoftBreak,Str "i)",Space,Strong [Str "bo",Space,Str "**ld"],Space,Emph [Str "it",Space,Str "//al"],Space,Underline [Str "un",Space,Str "__dr"],Space,Strikeout [Str "st",Space,Str "--rk"],Space,Code ("",[],[]) "mo ``no",Space,Str "r",Space,Str "\"\"aw",Space,RawInline (Format "html") "tg ''gd",SoftBreak,Str "i)",Space,Strong [Str "bo",Space,Str "**",Space,Str "ld"],Space,Emph [Str "it",Space,Str "//",Space,Str "al"],Space,Underline [Str "un",Space,Str "__",Space,Str "dr"],Space,Strikeout [Str "st",Space,Str "--",Space,Str "rk"],Space,Code ("",[],[]) "mo `` no",Space,Str "r",Space,Str "\"\"",Space,Str "aw",Space,RawInline (Format "html") "tg '' gd",SoftBreak,Str "i)",Space,Strong [Str "**bold**"],Space,Emph [Str "//ital//"],Space,Underline [Str "__undr__"],Space,Strikeout [Str "--strk--"],Space,Code ("",[],[]) "``mono``",Space,Str "\"\"raw\"\"",Space,RawInline (Format "html") "''tggd''",SoftBreak,Str "i)",Space,Strong [Str "*bold*"],Space,Emph [Str "/ital/"],Space,Underline [Str "_undr_"],Space,Strikeout [Str "-strk-"],Space,Code ("",[],[]) "`mono`",Space,Str "\"raw\"",Space,RawInline (Format "html") "'tggd'"]
+,Para [Str "i)",Space,Strong [Str "*"],Space,Emph [Str "/"],Space,Underline [Str "_"],Space,Strikeout [Str "-"],Space,Code ("",[],[]) "`",Space,Str "\"",Space,RawInline (Format "html") "'",SoftBreak,Str "i)",Space,Strong [Str "**"],Space,Emph [Str "//"],Space,Underline [Str "__"],Space,Strikeout [Str "--"],Space,Code ("",[],[]) "``",Space,Str "\"\"",Space,RawInline (Format "html") "''",SoftBreak,Str "i)",Space,Strong [Str "***"],Space,Emph [Str "///"],Space,Underline [Str "___"],Space,Strikeout [Str "---"],Space,Code ("",[],[]) "```",Space,Str "\"\"\"",Space,RawInline (Format "html") "'''",SoftBreak,Str "i)",Space,Strong [Str "****"],Space,Emph [Str "////"],Space,Underline [Str "____"],Space,Strikeout [Str "----"],Space,Code ("",[],[]) "````",Space,Str "\"\"\"\"",Space,RawInline (Format "html") "''''",SoftBreak,Str "i)",Space,Strong [Str "*****"],Space,Emph [Str "/////"],Space,Underline [Str "_____"],Space,Strikeout [Str "-----"],Space,Code ("",[],[]) "`````",Space,Str "\"\"\"\"\"",Space,RawInline (Format "html") "'''''",SoftBreak,Str "i)",Space,Strong [Str "******"],Space,Emph [Str "//////"],Space,Underline [Str "______"],Space,Strikeout [Str "------"],Space,Code ("",[],[]) "``````",Space,Str "\"\"\"\"\"\"",Space,RawInline (Format "html") "''''''"]
 ,Para [Str "i)",Space,Str "****",Space,Str "////",Space,Str "____",Space,Str "----",Space,Str "````",Space,Str "\"\"\"\"",Space,Str "''''",SoftBreak,Str "i)",Space,Str "**",Space,Str "**",Space,Str "//",Space,Str "//",Space,Str "__",Space,Str "__",Space,Str "--",Space,Str "--",Space,Str "``",Space,Str "``",Space,Str "\"\"",Space,Str "\"\"",Space,Str "''",Space,Str "''"]
 ,Para [Str "i)",Space,Str "**",Space,Str "bold**",Space,Str "//",Space,Str "ital//",Space,Str "__",Space,Str "undr__",Space,Str "--",Space,Str "strk--",Space,Str "``",Space,Str "mono``",Space,Str "\"\"",Space,Str "raw\"\"",Space,Str "''",Space,Str "tggd''",SoftBreak,Str "i)",Space,Str "**bold",Space,Str "**",Space,Str "//ital",Space,Str "//",Space,Str "__undr",Space,Str "__",Space,Str "--strk",Space,Str "--",Space,Str "``mono",Space,Str "``",Space,Str "\"\"raw",Space,Str "\"\"",Space,Str "''tggd",Space,Str "''",SoftBreak,Str "i)",Space,Str "**",Space,Str "bold",Space,Str "**",Space,Str "//",Space,Str "ital",Space,Str "//",Space,Str "__",Space,Str "undr",Space,Str "__",Space,Str "--",Space,Str "strk",Space,Str "--",Space,Str "``",Space,Str "mono",Space,Str "``",Space,Str "\"\"",Space,Str "raw",Space,Str "\"\"",Space,Str "''",Space,Str "tggd",Space,Str "''"]
 ,Header 1 ("link",[],[]) [Str "Link"]
@@ -301,308 +301,665 @@
     ,BulletList
      [[Plain [Str "just",Space,Str "like",Space,Str "when",Space,Str "using",Space,Str "the",Space,Str "two",Space,Str "blank",Space,Str "lines."]]]]]]]
 ,Header 1 ("table",[],[]) [Str "Table"]
-,Table [] [AlignRight] [0.0]
- [[]]
- [[[Plain [Str "Cell",Space,Str "1"]]]]
-,Table [] [AlignCenter,AlignCenter,AlignRight] [0.0,0.0,0.0]
- [[]
- ,[]
- ,[]]
- [[[Plain [Str "Cell",Space,Str "1"]]
-  ,[Plain [Str "Cell",Space,Str "2"]]
-  ,[Plain [Str "Cell",Space,Str "3"]]]]
-,Table [] [AlignCenter,AlignCenter,AlignCenter] [0.0,0.0,0.0]
- [[]
- ,[]
- ,[]]
- [[[Plain [Str "Cell",Space,Str "1"]]
-  ,[Plain [Str "Cell",Space,Str "2"]]
-  ,[Plain [Str "Cell",Space,Str "3"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignRight,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "1"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignRight,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "3"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "3"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "||",Space,Str "Cell",Space,Str "1",Space,Str "|",Space,Str "Cell",Space,Str "2",Space,Str "|",Space,Str "Cell",Space,Str "3",Space,Str "|"]
-,Table [] [AlignCenter,AlignCenter,AlignCenter] [0.0,0.0,0.0]
- [[]
- ,[]
- ,[]]
- [[[Plain [Str "Cell",Space,Str "1"]]
-  ,[Plain [Str "Cell",Space,Str "2"]]
-  ,[Plain [Str "Cell",Space,Str "3"]]]]
-,Table [] [AlignDefault,AlignCenter,AlignDefault] [0.0,0.0,0.0]
- [[Plain [Str "Heading"]]
- ,[Plain [Str "Heading"]]
- ,[Plain [Str "Heading"]]]
- [[[Plain [Str "<-"]]
-  ,[Plain [Str "--"]]
-  ,[Plain [Str "->"]]]
- ,[[Plain [Str "--"]]
-  ,[Plain [Str "--"]]
-  ,[Plain [Str "--"]]]
- ,[[Plain [Str "->"]]
-  ,[Plain [Str "--"]]
-  ,[Plain [Str "<-"]]]]
-,Table [] [AlignDefault,AlignDefault,AlignCenter,AlignCenter] [0.0,0.0,0.0,0.0]
- [[Plain [Str "1"]]
- ,[Plain [Str "2"]]
- ,[Plain [Str "3+4"]]
- ,[]]
- [[[Plain [Str "1"]]
-  ,[Plain [Str "2"]]
-  ,[Plain [Str "3"]]
-  ,[Plain [Str "4"]]]
- ,[[Plain [Str "1+2+3"]]
-  ,[Plain [Str "4"]]
-  ,[]
-  ,[]]
- ,[[Plain [Str "1"]]
-  ,[Plain [Str "2+3"]]
-  ,[Plain [Str "4"]]
-  ,[]]
- ,[[Plain [Str "1+2+3+4"]]
-  ,[]
-  ,[]
-  ,[]]]
-,Table [] [AlignCenter,AlignCenter,AlignCenter,AlignCenter] [0.0,0.0,0.0,0.0]
- [[]
- ,[]
- ,[]
- ,[]]
- [[[Plain [Str "0"]]
-  ,[Plain [Str "1"]]
-  ,[Plain [Str "2"]]
-  ,[]]
- ,[[Plain [Str "4"]]
-  ,[Plain [Str "5"]]
-  ,[]
-  ,[Plain [Str "7"]]]
- ,[[Plain [Str "8"]]
-  ,[]
-  ,[Plain [Str "A"]]
-  ,[Plain [Str "B"]]]
- ,[[]
-  ,[Plain [Str "D"]]
-  ,[Plain [Str "E"]]
-  ,[Plain [Str "F"]]]]
-,Table [] [AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter] [0.0,0.0,0.0,0.0,0.0]
- [[]
- ,[]
- ,[]
- ,[]
- ,[]]
- [[[Plain [Str "1"]]
-  ,[]
-  ,[]
-  ,[]
-  ,[]]
- ,[[Plain [Str "1"]]
-  ,[Plain [Str "2"]]
-  ,[]
-  ,[]
-  ,[]]
- ,[[Plain [Str "1"]]
-  ,[Plain [Str "2"]]
-  ,[Plain [Str "3"]]
-  ,[]
-  ,[]]
- ,[[Plain [Str "1"]]
-  ,[Plain [Str "2"]]
-  ,[Plain [Str "3"]]
-  ,[Plain [Str "4"]]
-  ,[]]
- ,[[Plain [Str "1"]]
-  ,[Plain [Str "2"]]
-  ,[Plain [Str "3"]]
-  ,[Plain [Str "4"]]
-  ,[Plain [Str "5"]]]]
-,Table [] [AlignDefault,AlignCenter,AlignCenter,AlignCenter,AlignCenter] [0.0,0.0,0.0,0.0,0.0]
- [[]
- ,[]
- ,[]
- ,[]
- ,[]]
- [[[Plain [Str "Jan"]]
-  ,[]
-  ,[]
-  ,[]
-  ,[]]
- ,[[Plain [Str "Fev"]]
-  ,[]
-  ,[]
-  ,[]
-  ,[]]
- ,[[Plain [Str "Mar"]]
-  ,[]
-  ,[]
-  ,[]
-  ,[]]
- ,[[Plain [Str "Apr"]]
-  ,[]
-  ,[]
-  ,[]
-  ,[]]
- ,[[Plain [Str "May"]]
-  ,[]
-  ,[]
-  ,[]
-  ,[]]
- ,[[Plain [Str "20%"]]
-  ,[Plain [Str "40%"]]
-  ,[Plain [Str "60%"]]
-  ,[Plain [Str "80%"]]
-  ,[Plain [Str "100%"]]]]
-,Table [] [AlignCenter,AlignDefault,AlignDefault,AlignCenter,AlignCenter] [0.0,0.0,0.0,0.0,0.0]
- [[]
- ,[]
- ,[]
- ,[]
- ,[]]
- [[[]
-  ,[]
-  ,[Plain [Str "/"]]
-  ,[]
-  ,[]]
- ,[[]
-  ,[Plain [Str "/",Space,Str "/",Space,Str "/",Space,Str "/",Space,Str "/"]]
-  ,[]
-  ,[]
-  ,[]]
- ,[[Plain [Str "/",Space,Str "/",Space,Str "/",Space,Str "/",Space,Str "/",Space,Str "/",Space,Str "/",Space,Str "/",Space,Str "/"]]
-  ,[]
-  ,[]
-  ,[]
-  ,[]]
- ,[[]
-  ,[Plain [Str "o"]]
-  ,[]
-  ,[Plain [Str "o"]]
-  ,[]]
- ,[[]
-  ,[]
-  ,[Plain [Str "."]]
-  ,[]
-  ,[]]
- ,[[]
-  ,[Plain [Str "=",Space,Str "=",Space,Str "=",Space,Str "="]]
-  ,[]
-  ,[]
-  ,[]]]
-,Table [] [AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter] [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0]
- [[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]]
- [[[Plain [Str "01"]]
-  ,[Plain [Str "02"]]
-  ,[]
-  ,[]
-  ,[Plain [Str "05"]]
-  ,[]
-  ,[Plain [Str "07"]]
-  ,[]]
- ,[[]
-  ,[]
-  ,[Plain [Str "11"]]
-  ,[]
-  ,[Plain [Str "13"]]
-  ,[]
-  ,[]
-  ,[Plain [Str "16"]]]
- ,[[Plain [Str "17"]]
-  ,[]
-  ,[Plain [Str "19"]]
-  ,[Plain [Str "20"]]
-  ,[]
-  ,[]
-  ,[Plain [Str "23"]]
-  ,[]]
- ,[[Plain [Str "25"]]
-  ,[Plain [Str "26"]]
-  ,[]
-  ,[]
-  ,[Plain [Str "29"]]
-  ,[Plain [Str "30"]]
-  ,[]
-  ,[Plain [Str "32"]]]
- ,[[]
-  ,[]
-  ,[Plain [Str "35"]]
-  ,[]
-  ,[Plain [Str "37"]]
-  ,[]
-  ,[Plain [Str "39"]]
-  ,[Plain [Str "40"]]]]
-,Table [] [AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter,AlignCenter] [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0]
- [[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]
- ,[]]
- [[[Plain [Str "0"]]
-  ,[Plain [Str "1"]]
-  ,[Plain [Str "2"]]
-  ,[Plain [Str "3"]]
-  ,[Plain [Str "4"]]
-  ,[Plain [Str "5"]]
-  ,[Plain [Str "6"]]
-  ,[Plain [Str "7"]]
-  ,[Plain [Str "8"]]
-  ,[Plain [Str "9"]]
-  ,[Plain [Str "A"]]
-  ,[Plain [Str "B"]]
-  ,[Plain [Str "C"]]
-  ,[Plain [Str "D"]]
-  ,[Plain [Str "E"]]
-  ,[Plain [Str "F"]]
-  ,[Plain [Str "0"]]
-  ,[Plain [Str "1"]]
-  ,[Plain [Str "2"]]
-  ,[Plain [Str "3"]]
-  ,[Plain [Str "4"]]
-  ,[Plain [Str "5"]]
-  ,[Plain [Str "6"]]
-  ,[Plain [Str "7"]]
-  ,[Plain [Str "8"]]
-  ,[Plain [Str "9"]]
-  ,[Plain [Str "A"]]
-  ,[Plain [Str "B"]]
-  ,[Plain [Str "C"]]
-  ,[Plain [Str "D"]]
-  ,[Plain [Str "E"]]
-  ,[Plain [Str "F"]]]]
-,Table [] [AlignCenter] [0.0]
- [[]]
- [[[]]
- ,[[]]
- ,[[]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Cell",Space,Str "3"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Heading"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Heading"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Heading"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "<-"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "--"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "->"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "--"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "--"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "--"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "->"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "--"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "<-"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "1"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "2"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "3+4"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1+2+3"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2+3"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1+2+3+4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "7"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "8"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "A"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "B"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "D"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "E"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "F"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Jan"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Fev"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Mar"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "Apr"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "May"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "20%"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "40%"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "60%"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "80%"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "100%"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignCenter,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "/"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "/",Space,Str "/",Space,Str "/",Space,Str "/",Space,Str "/"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "/",Space,Str "/",Space,Str "/",Space,Str "/",Space,Str "/",Space,Str "/",Space,Str "/",Space,Str "/",Space,Str "/"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "o"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "o"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "."]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "=",Space,Str "=",Space,Str "=",Space,Str "="]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "01"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "02"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "05"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "07"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "11"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "13"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "16"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "17"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "19"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "20"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "23"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "25"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "26"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "29"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "30"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "32"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "35"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "37"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "39"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "40"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)
+ ,(AlignCenter,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "6"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "7"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "8"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "9"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "A"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "B"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "C"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "D"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "E"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "F"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "0"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "3"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "4"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "5"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "6"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "7"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "8"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "9"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "A"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "B"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "C"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "D"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "E"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "F"]]]])]
+ (TableFoot ("",[],[])
+ [])
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignCenter,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]])]
+ (TableFoot ("",[],[])
+ [])
 ,Para [Str "|this|is|not|a|table|"]
 ,Para [Str "|this|",Space,Str "is|",Space,Str "not|",Space,Str "a|",Space,Str "table|"]
 ,Para [Str "|this",Space,Str "|is",Space,Str "|not",Space,Str "|a",Space,Str "|table",Space,Str "|"]
diff --git a/test/vimwiki-reader.native b/test/vimwiki-reader.native
--- a/test/vimwiki-reader.native
+++ b/test/vimwiki-reader.native
@@ -49,6 +49,8 @@
 ,CodeBlock ("",[],[]) "  Tyger! Tyger! burning bright\n   In the forests of the night,\n    What immortal hand or eye\n     Could frame thy fearful symmetry?\n  In what distant deeps or skies\n   Burnt the fire of thine eyes?\n    On what wings dare he aspire?\n     What the hand dare sieze the fire?"
 ,Header 3 ("preformatted text with attributes",[],[]) [Str "preformatted",Space,Str "text",Space,Str "with",Space,Str "attributes"]
 ,CodeBlock ("",[],[("class","python"),("style","color:blue")]) " for i in range(1, 5):\n     print(i)"
+,Header 3 ("preformatted text with nested syntax",[],[]) [Str "preformatted",Space,Str "text",Space,Str "with",Space,Str "nested",Space,Str "syntax"]
+,CodeBlock ("",["sql"],[]) "SELECT * FROM table"
 ,Header 3 ("empty preformatted text",[],[]) [Str "empty",Space,Str "preformatted",Space,Str "text"]
 ,CodeBlock ("",[],[]) ""
 ,Header 2 ("block quotes",[],[]) [Str "block",Space,Str "quotes"]
@@ -86,13 +88,30 @@
   ,Para [Math DisplayMath "a^2 + b^2 = c^2"]
   ,Plain [Str "and",Space,Str "some",Space,Str "preformatted",Space,Str "and",Space,Str "tables",Space,Str "belonging",Space,Str "to",Space,Str "item",Space,Str "1",Space,Str "as",Space,Str "well"]
   ,CodeBlock ("",[],[]) "I'm part of item 1."
-  ,Table [] [AlignDefault,AlignDefault] [0.0,0.0]
-   [[]
-   ,[]]
-   [[[Plain [Str "this",Space,Str "table"]]
-    ,[Plain [Str "is"]]]
-   ,[[Plain [Str "also",Space,Str "a",Space,Str "part"]]
-    ,[Plain [Str "of",Space,Str "item",Space,Str "1"]]]]
+  ,Table ("",[],[]) (Caption Nothing
+   [])
+   [(AlignDefault,ColWidthDefault)
+   ,(AlignDefault,ColWidthDefault)]
+   (TableHead ("",[],[])
+   [Row ("",[],[])
+    [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+     []
+    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+     []]])
+   [(TableBody ("",[],[]) (RowHeadColumns 0)
+    []
+    [Row ("",[],[])
+     [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+      [Plain [Str "this",Space,Str "table"]]
+     ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+      [Plain [Str "is"]]]
+    ,Row ("",[],[])
+     [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+      [Plain [Str "also",Space,Str "a",Space,Str "part"]]
+     ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+      [Plain [Str "of",Space,Str "item",Space,Str "1"]]]])]
+   (TableFoot ("",[],[])
+   [])
   ,Plain [Str "and",Space,Str "some",Space,Str "more",Space,Str "text",Space,Str "belonging",Space,Str "to",Space,Str "item",Space,Str "1."]]
  ,[Plain [Str "ordered",Space,Str "list",Space,Str "item",Space,Str "2"]]]
 ,BulletList
@@ -179,11 +198,25 @@
   ,OrderedList (1,DefaultStyle,DefaultDelim)
    [[Plain [Span ("",["done3"],[]) [],Str "4",SoftBreak,Str "5"]]
    ,[Plain [Span ("",["done4"],[]) []]
-    ,Table [] [AlignDefault,AlignDefault] [0.0,0.0]
-     [[]
-     ,[]]
-     [[[Plain [Str "a"]]
-      ,[Plain [Str "b"]]]]]]]
+    ,Table ("",[],[]) (Caption Nothing
+     [])
+     [(AlignDefault,ColWidthDefault)
+     ,(AlignDefault,ColWidthDefault)]
+     (TableHead ("",[],[])
+     [Row ("",[],[])
+      [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+       []
+      ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+       []]])
+     [(TableBody ("",[],[]) (RowHeadColumns 0)
+      []
+      [Row ("",[],[])
+       [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+        [Plain [Str "a"]]
+       ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+        [Plain [Str "b"]]]])]
+     (TableFoot ("",[],[])
+     [])]]]
  ,[Plain [Span ("",["done4"],[]) [],Str "task",Space,Str "2"]]]
 ,Header 2 ("math",[],[]) [Str "math"]
 ,Para [Math InlineMath " \\sum_i a_i^2 = 1 "]
@@ -198,34 +231,84 @@
 ,Header 2 ("tags",[],[]) [Str "tags"]
 ,Para [Span ("-tag-one",[],[]) [Str ""],Span ("tag-one",["tag"],[]) [Str "tag-one"],Space,Span ("-tag-two",[],[]) [Str ""],Span ("tag-two",["tag"],[]) [Str "tag-two"]]
 ,Header 2 ("tables",[],[]) [Str "tables"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
- [[Plain [Str "Year"]]
- ,[Plain [Str "Temperature",Space,Str "(low)"]]
- ,[Plain [Str "Temperature",Space,Str "(high)"]]]
- [[[Plain [Str "1900"]]
-  ,[Plain [Str "-10"]]
-  ,[Plain [Str "25"]]]
- ,[[Plain [Str "1910"]]
-  ,[Plain [Str "-15"]]
-  ,[Plain [Str "30"]]]
- ,[[Plain [Str "1920"]]
-  ,[Plain [Str "-10"]]
-  ,[Plain [Str "32"]]]
- ,[[Plain [Str "1930"]]
-  ,[Plain [Emph [Str "N/A"]]]
-  ,[Plain [Emph [Str "N/A"]]]]
- ,[[Plain [Str "1940"]]
-  ,[Plain [Str "-2"]]
-  ,[Plain [Str "40"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Year"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Temperature",Space,Str "(low)"]]
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   [Plain [Str "Temperature",Space,Str "(high)"]]]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1900"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "-10"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "25"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1910"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "-15"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "30"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1920"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "-10"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "32"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1930"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Emph [Str "N/A"]]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Emph [Str "N/A"]]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "1940"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "-2"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "40"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Header 3 ("centered headerless tables",[],[]) [Str "centered",Space,Str "headerless",Space,Str "tables"]
 ,Div ("",["center"],[])
- [Table [] [AlignDefault,AlignDefault] [0.0,0.0]
-  [[]
-  ,[]]
-  [[[Plain [Str "a"]]
-   ,[Plain [Str "b"]]]
-  ,[[Plain [Str "c"]]
-   ,[Plain [Str "d"]]]]]
+ [Table ("",[],[]) (Caption Nothing
+  [])
+  [(AlignDefault,ColWidthDefault)
+  ,(AlignDefault,ColWidthDefault)]
+  (TableHead ("",[],[])
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    []]])
+  [(TableBody ("",[],[]) (RowHeadColumns 0)
+   []
+   [Row ("",[],[])
+    [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+     [Plain [Str "a"]]
+    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+     [Plain [Str "b"]]]
+   ,Row ("",[],[])
+    [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+     [Plain [Str "c"]]
+    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+     [Plain [Str "d"]]]])]
+  (TableFoot ("",[],[])
+  [])]
 ,Header 2 ("paragraphs",[],[]) [Str "paragraphs"]
 ,Para [Str "This",Space,Str "is",Space,Str "first",Space,Str "paragraph",SoftBreak,Str "with",Space,Str "two",Space,Str "lines."]
 ,Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "second",Space,Str "paragraph",Space,Str "with",SoftBreak,Str "two",Space,Str "lines",Space,Str "after",Space,Str "many",Space,Str "blank",Space,Str "lines."]
@@ -275,37 +358,92 @@
 ,Para [Span ("",["todo"],[]) [Str "TODO:"]]
 ,Header 1 ("not implemented yet",[],[]) [Emph [Span ("not implemented yet",[],[]) [],Strong [Str "not",Space,Str "implemented",Space,Str "yet"]]]
 ,Header 2 ("tables with spans",[],[]) [Str "tables",Space,Str "with",Space,Str "spans"]
-,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0,0.0]
- [[]
- ,[]
- ,[]
- ,[]]
- [[[Plain [Str "a"]]
-  ,[Plain [Str "b"]]
-  ,[Plain [Str "c"]]
-  ,[Plain [Str "d"]]]
- ,[[Plain [Str "\\/"]]
-  ,[Plain [Str "e"]]
-  ,[Plain [Str ">"]]
-  ,[Plain [Str "f"]]]
- ,[[Plain [Str "\\/"]]
-  ,[Plain [Str "\\/"]]
-  ,[Plain [Str ">"]]
-  ,[Plain [Str "g"]]]
- ,[[Plain [Str "h"]]
-  ,[Plain [Str ">"]]
-  ,[Plain [Str ">"]]
-  ,[Plain [Str ">"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "a"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "b"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "c"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "d"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "\\/"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "e"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str ">"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "f"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "\\/"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "\\/"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str ">"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "g"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "h"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str ">"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str ">"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str ">"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Header 2 ("tables with multiple lines of headers",[],[]) [Str "tables",Space,Str "with",Space,Str "multiple",Space,Str "lines",Space,Str "of",Space,Str "headers"]
-,Table [] [AlignDefault,AlignDefault] [0.0,0.0]
- [[]
- ,[]]
- [[[Plain [Str "a"]]
-  ,[Plain [Str "b"]]]
- ,[[Plain [Str "c"]]
-  ,[Plain [Str "d"]]]
- ,[[Plain [Str "---"]]
-  ,[Plain [Str "---"]]]]
+,Table ("",[],[]) (Caption Nothing
+ [])
+ [(AlignDefault,ColWidthDefault)
+ ,(AlignDefault,ColWidthDefault)]
+ (TableHead ("",[],[])
+ [Row ("",[],[])
+  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []
+  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+   []]])
+ [(TableBody ("",[],[]) (RowHeadColumns 0)
+  []
+  [Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "a"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "b"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "c"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "d"]]]
+  ,Row ("",[],[])
+   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "---"]]
+   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
+    [Plain [Str "---"]]]])]
+ (TableFoot ("",[],[])
+ [])
 ,Header 2 ("some other placeholders",[],[]) [Str "some",Space,Str "other",Space,Str "placeholders"]
 ,Para [Code ("",[],[]) "template",Space,Str "placeholder",Space,Str "is",Space,Str "ignored."]
 ,Para [Code ("",[],[]) "nohtml",Space,Str "placeholder",Space,Str "is",Space,Str "ignored."]]
diff --git a/test/vimwiki-reader.wiki b/test/vimwiki-reader.wiki
--- a/test/vimwiki-reader.wiki
+++ b/test/vimwiki-reader.wiki
@@ -117,6 +117,12 @@
      print(i)
  }}}
 
+=== preformatted text with nested syntax ===
+
+{{{sql
+SELECT * FROM table
+}}}
+
 === empty preformatted text ===
 
 {{{
diff --git a/test/writer.docbook4 b/test/writer.docbook4
--- a/test/writer.docbook4
+++ b/test/writer.docbook4
@@ -6,12 +6,16 @@
     <title>Pandoc Test Suite</title>
     <authorgroup>
       <author>
-        <firstname>John</firstname>
-        <surname>MacFarlane</surname>
+        <personname>
+          <firstname>John</firstname>
+          <surname>MacFarlane</surname>
+        </personname>
       </author>
       <author>
-        <firstname></firstname>
-        <surname>Anonymous</surname>
+        <personname>
+          <firstname></firstname>
+          <surname>Anonymous</surname>
+        </personname>
       </author>
     </authorgroup>
     <date>July 17, 2006</date>
diff --git a/test/writer.docbook5 b/test/writer.docbook5
--- a/test/writer.docbook5
+++ b/test/writer.docbook5
@@ -7,12 +7,16 @@
     <title>Pandoc Test Suite</title>
     <authorgroup>
       <author>
-        <firstname>John</firstname>
-        <surname>MacFarlane</surname>
+        <personname>
+          <firstname>John</firstname>
+          <surname>MacFarlane</surname>
+        </personname>
       </author>
       <author>
-        <firstname></firstname>
-        <surname>Anonymous</surname>
+        <personname>
+          <firstname></firstname>
+          <surname>Anonymous</surname>
+        </personname>
       </author>
     </authorgroup>
     <date>July 17, 2006</date>
diff --git a/test/writer.html4 b/test/writer.html4
--- a/test/writer.html4
+++ b/test/writer.html4
@@ -15,6 +15,7 @@
     div.column{display: inline-block; vertical-align: top; width: 50%;}
     div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
     ul.task-list{list-style: none;}
+    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
   </style>
 </head>
 <body>
@@ -432,7 +433,7 @@
 <li><span class="math inline"><em>α</em> ∧ <em>ω</em></span></li>
 <li><span class="math inline">223</span></li>
 <li><span class="math inline"><em>p</em></span>-Tree</li>
-<li>Here’s some display math: <br /><span class="math display">$$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$</span><br /></li>
+<li>Here’s some display math: <span class="math display">$$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$</span></li>
 <li>Here’s one that has a line break in it: <span class="math inline"><em>α</em> + <em>ω</em> × <em>x</em><sup>2</sup></span>.</li>
 </ul>
 <p>These shouldn’t be math:</p>
diff --git a/test/writer.html5 b/test/writer.html5
--- a/test/writer.html5
+++ b/test/writer.html5
@@ -15,6 +15,7 @@
     div.column{display: inline-block; vertical-align: top; width: 50%;}
     div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
     ul.task-list{list-style: none;}
+    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
   </style>
   <!--[if lt IE 9]>
     <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
@@ -435,7 +436,7 @@
 <li><span class="math inline"><em>α</em> ∧ <em>ω</em></span></li>
 <li><span class="math inline">223</span></li>
 <li><span class="math inline"><em>p</em></span>-Tree</li>
-<li>Here’s some display math: <br /><span class="math display">$$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$</span><br /></li>
+<li>Here’s some display math: <span class="math display">$$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$</span></li>
 <li>Here’s one that has a line break in it: <span class="math inline"><em>α</em> + <em>ω</em> × <em>x</em><sup>2</sup></span>.</li>
 </ul>
 <p>These shouldn’t be math:</p>
diff --git a/test/writer.jira b/test/writer.jira
--- a/test/writer.jira
+++ b/test/writer.jira
@@ -377,7 +377,7 @@
 * 223
 * _p_\-Tree
 * Here’s some display math: 
-$$\frac{d\}\{dx}f\(x)=\lim\_\{h\to 0\}&bsol;frac{f(x+h)-f\(x)\}\{h}$$
+$$\frac\{d\}\{dx\}f\(x)=\lim\_\{h\to 0\}&bsol;frac\{f(x+h)-f\(x)\}\{h\}$$
 
 * Here’s one that has a line break in it: _α_ + {_}ω{_} × {_}x{_}^2^.
 
@@ -495,15 +495,15 @@
 Here’s an [inline link in pointy braces|/script?foo=1&bar=2].
 
 h2. {anchor:autolinks}Autolinks
-With an ampersand: [http://example.com/?foo=1&bar=2|http://example.com/?foo=1&bar=2]
+With an ampersand: [http://example.com/?foo=1&bar=2]
 
 * In a list?
-* [http://example.com/|http://example.com/]
+* [http://example.com/]
 * It should.
 
-An e-mail address: [nobody@nowhere.net|mailto:nobody@nowhere.net]
+An e-mail address: [mailto:nobody@nowhere.net]
 
-bq. Blockquoted: [http://example.com/|http://example.com/]
+bq. Blockquoted: [http://example.com/]
 Auto-links should not occur here: {{<http://example.com/>}}
 
 {code:java}
@@ -513,7 +513,7 @@
 h1. {anchor:images}Images
 From "Voyage dans la Lune" by Georges Melies \(1902):
 
-!lalune.jpg!
+!lalune.jpg|title=fig:Voyage dans la Lune!
 
 Here is a movie !movie.jpg! icon.
 
diff --git a/test/writer.markdown b/test/writer.markdown
--- a/test/writer.markdown
+++ b/test/writer.markdown
@@ -683,7 +683,7 @@
 
 [URL and title](/url/ "title with single quotes")
 
-[with\_underscore](/url/with_underscore)
+[with_underscore](/url/with_underscore)
 
 [Email link](mailto:nobody@nowhere.net)
 
diff --git a/trypandoc/index.html b/trypandoc/index.html
--- a/trypandoc/index.html
+++ b/trypandoc/index.html
@@ -9,9 +9,9 @@
        <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
        <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
        <![endif]-->
-  <script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
-  <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet">
-  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
+  <script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
+  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
+  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
   <script>
 "use strict";
 (function($) { // http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values
@@ -44,14 +44,17 @@
     $("#from").val(from);
     var to = $.QueryString["to"] || "html";
     $("#to").val(to);
-    var standalone = ($.QueryString["standalone"] === "1") ? "1" : "0"
+    var standalone = ($.QueryString["standalone"] === "1") ? "1" : "0";
     $("#standalone").prop('checked', (standalone === "1"));
     if (text && text != "") {
        $.getJSON("/cgi-bin/trypandoc", { from: from, to: to, text: text, standalone: standalone },
          function(res) {
           $("#results").text(res.html);
           $("#version").text(res.version);
-          $("#command").text("pandoc --from " + from + " --to " + to);
+          var commandString = "pandoc"
+            + ((standalone === "1") ? " --standalone" : "")
+            + " --from " + from + " --to " + to;
+          $("#command").text(commandString);
          });
     };
     $("#convert").click(newpage);
