diff --git a/AUTHORS.md b/AUTHORS.md
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -342,6 +342,7 @@
 - R. N. West
 - Ralf Stephan
 - Raniere Silva
+- Raymond Berger
 - Raymond Ehlers
 - Recai Oktaş
 - Repetitive
@@ -490,6 +491,7 @@
 - priiduonu
 - qerub
 - quasicomputational
+- reptee
 - ricnorr
 - robabla
 - roblabla
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: 2025-09-06
+date: 2025-09-29
 ---
 
 # Synopsis
@@ -361,6 +361,7 @@
     - `s5` ([S5] HTML and JavaScript slide show)
     - `tei` ([TEI Simple])
     - `typst` ([typst])
+    - `vimdoc` ([Vimdoc])
     - `xml` (XML version of native AST)
     - `xwiki` ([XWiki markup])
     - `zimwiki` ([ZimWiki markup])
@@ -511,6 +512,7 @@
 [DokuWiki markup]: https://www.dokuwiki.org/dokuwiki
 [ZimWiki markup]: https://zim-wiki.org/manual/Help/Wiki_Syntax.html
 [XWiki markup]: https://www.xwiki.org/xwiki/bin/view/Documentation/UserGuide/Features/XWikiSyntax/
+[Vimdoc]: https://vimhelp.org/helphelp.txt.html#help-writing
 [TWiki markup]: https://twiki.org/cgi-bin/view/TWiki/TextFormattingRules
 [TikiWiki markup]: https://doc.tiki.org/Wiki-Syntax-Text#The_Markup_Language_Wiki-Syntax
 [Haddock markup]: https://www.haskell.org/haddock/doc/html/ch03s08.html
@@ -3054,6 +3056,11 @@
         - heightrounded
         ...
 
+`shorthands`
+:   Enable language-specific shorthands when loading `babel`.
+    (By default, pandoc includes `shorthands=off` when loading
+    `babel`, disabling language-specific shorthands.)
+
 `hyperrefoptions`
 :   option for [`hyperref`] package, e.g. `linktoc=all`;
     repeat for multiple options:
@@ -7416,12 +7423,112 @@
 cause Setext-style headings to be used; and `--preserve-tabs` will
 prevent tabs from being turned to spaces.
 
+# Vimdoc
+
+Vimdoc writer generates Vim help files and makes use of the following metadata
+variables:
+
+``` yaml
+abstract: "A short description"
+author: Author
+title: Title
+
+# Vimdoc-specific
+filename: "definition-lists.txt"
+vimdoc-prefix: pandoc
+```
+
+Complete header requires `abstract`, `author`, `title` and `filename` to
+be set. Compiling file with such metadata produces the following file
+(assumes `--standalone`, see [Templates]):
+
+``` vimdoc
+*definition-lists.txt*  A short description
+
+                            Title by Author
+
+
+                                 Type |gO| to see the table of contents.
+
+[...]
+
+ vim:tw=72:sw=4:ts=4:ft=help:norl:et:
+```
+
+If `vimdoc-prefix` is set, all non-command tags are prefixed with its
+value, it is used to prevent tag collision: all headers have a tag
+(either inferred or explicit) and multiple help pages can have the same
+header names, therefore collision is to be expected. Let our input be
+the following markdown file:
+
+``` markdown
+## Header
+
+`:[range]Fnl {expr}`{#:Fnl}
+:   Evaluates {expr} or range
+
+`vim.b`{#vim.b}
+:   Buffer-scoped (`:h b:`) variables for the current buffer. Invalid or unset
+    key returns `nil`. Can be indexed with an integer to access variables for a
+    specific buffer.
+
+[Span]{#span}
+:   generic inline container for phrasing content, which does not inherently
+    represent anything.
+```
+
+Convert it to vimdoc:
+
+``` vimdoc
+------------------------------------------------------------------------
+Header                                                            *header*
+
+:[range]Fnl {expr}                                                  *:Fnl*
+    Evaluates {expr} or range
+`vim.b`                                                            *vim.b*
+    Buffer-scoped (|b:|) variables for the current buffer. Invalid or
+    unset key returns `nil`. Can be indexed with an integer to access
+    variables for a specific buffer.
+Span                                                                *span*
+    generic inline container for phrasing content, which does not
+    inherently represent anything.
+```
+
+Convert it to vimdoc with metadata variable set (e.g. with
+`-M vimdoc-prefix=pandoc`)
+
+``` vimdoc
+------------------------------------------------------------------------
+Header                                                     *pandoc-header*
+
+:[range]Fnl {expr}                                                  *:Fnl*
+    Evaluates {expr} or range
+`vim.b`                                                     *pandoc-vim.b*
+    Buffer-scoped (|b:|) variables for the current buffer. Invalid or
+    unset key returns `nil`. Can be indexed with an integer to access
+    variables for a specific buffer.
+Span                                                         *pandoc-span*
+    generic inline container for phrasing content, which does not
+    inherently represent anything.
+```
+
+`vim.b` and `Span` got their prefixes but not `:Fnl` because ex-commands
+(those starting with `:`) don't get a prefix, since they are considered
+unique across help pages.
+
+In both cases `:help b:` became reference `|b:|` (also works with
+`:h b:`). Links pointing to either <https://vimhelp.org/> or
+<https://neovim.io/doc/user> become references too.
+
+Vim traditionally wraps at 78, but Pandoc defaults to 72. Use
+`--columns 78` to match Vim.
+
 # Syntax highlighting
 
 Pandoc will automatically highlight syntax in [fenced code blocks] that
 are marked with a language name.  The Haskell library [skylighting] is
 used for highlighting. Currently highlighting is supported only for
-HTML, EPUB, Docx, Ms, Man, and LaTeX/PDF output. To see a list
+HTML, EPUB, Docx, Ms, Man, Typst, and LaTeX/PDF output. To see a list
 of language names that pandoc will recognize, type `pandoc
 --list-highlight-languages`.
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -217,6 +217,8 @@
   slide show)
 - `tei` ([TEI Simple](https://github.com/TEIC/TEI-Simple))
 - `typst` ([typst](https://typst.app))
+- `vimdoc`
+  ([Vimdoc](https://vimhelp.org/helphelp.txt.html#help-writing))
 - `xml` (XML version of native AST)
 - `xwiki` ([XWiki
   markup](https://www.xwiki.org/xwiki/bin/view/Documentation/UserGuide/Features/XWikiSyntax/))
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,156 @@
 # Revision history for pandoc
 
+## pandoc 3.8.1 (2025-09-29)
+
+  * New output format `vimdoc` (Vim documentation format) (#11132, reptee).
+
+    + [API change] Added module Text.Pandoc.Writers.Vimdoc, exporting
+      `writeVimdoc`.
+
+  * Markdown reader:
+
+    + Improve superscript/subscript/inline note parsing (#8652).
+      We do not allow inline notes to be followed by `(` or `[`.
+      Otherwise, we parse inline notes before superscripts.
+      Also, the sub/superscript parsers have been adjusted so that they
+      really exclude unescaped spaces (as they did not before, when the
+      spaces occurred in nested inlines).
+    + Fix simple table alignment (#11136, Tuong Nguyen Manh). Take wide
+      characters into account when determining the alignment.
+
+  * LaTeX reader:
+
+    + Ignore `\pandocbounded` (#11140).
+
+  * XML reader:
+
+    + Parse `<MetaString>` (#11137, massifrg).
+
+  * Typst reader:
+
+    + Add support for reading typst pagebreak (#11101, Raymond Berger).
+      The pagebreak is parsed as a HorizontalRule inside a wrapper Div
+      with class `page-break`.
+
+  * Docx reader:
+
+    + Handle figures in indented paragraphs (#11028).
+    + Change default for textwidth. This should only be used if `sectPr`
+      is not found.
+    + Properly calculate table column widths (#9837, #11147).
+      Previously we assumed that every table took up the full text
+      width. Now we read the text width from the document's `sectPr`.
+    + Use Tasty.Golden for Docx reader tests. This way we can update
+      them with `--accept`.
+
+  * RST reader:
+
+    + Fix regression in simple table parsing (#11150).
+    + SkippedContent warning if table directive contains
+      non-tabular content.
+    + Simple tables: leading space in a cell should not cause the contents
+      to be parsed as a block quote (#11146).
+    + Parse `:alt:` on figure (#11140). Also give a better default if
+      `alt` is not specified, using the stringified caption rather
+      than the filename.
+    + Support col spans for simple tables (Tuong Nguyen Manh).
+
+  * Markdown writer:
+
+    + Improve handling of implicit figures (#11140).
+      Allow implicit figures when alt text differs from caption
+      (in this case, we use an image attribute to add the alt).
+    + Use approximate pipe tables when it's the only option (#11128).
+      If we have a table with row/colspans that can rendered as an
+      approximate pipe table (without row/colspans), and no other table
+      format is enabled that could render the table, we fall back to
+      an "approximate" pipe table, with no row/colspans.
+
+  * RST writer:
+
+    + Ensure blank line before directives (#11162).
+    + Add col spans for simple tables (#10127, Tuong Nguyen Manh).
+
+  * OpenDocument writer:
+
+    + Add missing table elements (#10002, Tuong Nguyen Manh).
+      Add missing header rows after the first one,
+      footer rows as well as TableBody header rows.
+
+  * Docx writer:
+
+    + Fix regression (from 3.8) in highlighted code (#11156).
+
+  * Powerpoint writer:
+
+    + Handle single column (Tuong Nguyen Manh).
+
+  * Typst writer:
+
+    + Fix syntax highlighting (#11171, completes #10525).
+      Previously the native typst highlighting was always used, regardless
+      of the setting of `--syntax-highlighting`. With this change,
+      `--syntax-highlighting=none` and `--syntax-highlighting=<stylename>`
+      (with skylighting style) will work.
+
+  * LaTeX writer:
+
+    + Make beamer footnotes compatible with pauses (#5954).
+      Previously they would appear before the content to which
+      the note was attached, when there were pauses in a slide.
+    + Avoid `\_` in bibliography variable (#11152).
+    + Ensure that unlabelled tables don't increment counter (#11141).
+    + Protect VERB in caption (#11139, Tuong Nguyen Manh).
+    + Don't add links to TOC (#11124, Albert Krewinkel).
+    + Fix strikeouts in beamer title (#11168, Tuong Nguyen Manh).
+
+  * LaTeX template: Add `shorthands` variable for LaTeX output
+    (#11160). If true, pandoc will allow language-specific shorthands
+    when loading babel. (This is helpful, for example, in getting
+    proper spacing around French punctuation.)
+
+  * epub.css: Remove coloring for `a, a:visiting` (#11174).
+    This was causing links in iOS books app not to be distinguished in
+    any way (since underlining is not used there).
+
+  * Text.Pandoc.Parsing:
+
+    + [API chage] (Tuong Nguyen Manh). New functions `tableWithSpans`,
+      `tableWithSpans'`, `toTableComponentsWithSpans` and
+      `toTableComponentsWithSpans'` take a list of lists of
+      (Blocks, RowSpan, ColSpan) to parse a Table with different RowSpan and
+      ColSpan values accordingly. New helper functions `singleRowSpans` and
+      `singleColumnSpans` help set all RowSpans or ColSpans to be 1 in case
+      the table format only allows setting one or the other.
+
+  * Text.Pandoc.Class:
+
+    + Let `fetchItem` fail if the HTTP request is not
+      successful (Albert Krewinkel). HTTP requests that don't return a 200
+      error code are now treated as an error. This ensures that a warning is
+      triggered when using `--embed-resources` or `--extract-media`.
+
+  * Text.Pandoc.Writers.Shared:
+
+    + Add new function `removeLinks` [API change] (Albert Krewinkel).
+      The function converts links to spans. It is used, for example, to avoid
+      nested links. The HTML writer used to put the description of nested links
+      into small caps, but uses a simple *span* now.
+
+  * Text.Pandoc.Highlighting: export typst functions
+    [API change]. New exported functions `formatTypstBlock`,
+    `formatTypstInline`, `styleToTypst`.
+
+  * Text.Pandoc.XML:
+
+    + Add `fetchpriority` to list of HTML attributes (#11176).
+
+  * Allow unicode-data 0.7.
+
+  * Use released djot 0.1.2.3. Fixes a bug in which indentation
+    was swallowed in a code block inside a blockquote.
+
+
 ## pandoc 3.8 (2025-09-06)
 
   * Add a new input and output format `xml`, exactly representing a Pandoc
@@ -319,13 +470,15 @@
       parameter in a defaults file.
     + Add type `HighlightMethod` and patterns [API Change] (Albert Krewinkel).
     + The `writerListings` and `writerHighlightStyle` fields of the
-      `WriterOptions` type are replaced with `writerHighlightStyle`
+      `WriterOptions` type are replaced with `writerHighlightMethod`
       [API change] (Albert Krewinkel, #10525).
 
   * Text.Pandoc.Extensions:
 
     + Remove `Ext_compact_definition_lists` constructor for
       `Extension` [API change].
+    + Add `Ext_smart_quotes` and `Ext_special_strings` constructors.
+      [API change].
 
   * Text.Pandoc.SelfContained:
 
diff --git a/data/epub.css b/data/epub.css
--- a/data/epub.css
+++ b/data/epub.css
@@ -26,9 +26,6 @@
   widows: 2;
   orphans: 2;
 }
-a, a:visited {
-  color: #1a1a1a;
-}
 img {
   max-width: 100%;
 }
diff --git a/data/templates/common.latex b/data/templates/common.latex
--- a/data/templates/common.latex
+++ b/data/templates/common.latex
@@ -183,9 +183,9 @@
 $--
 $if(lang)$
 \ifLuaTeX
-\usepackage[bidi=basic,shorthands=off,$for(babeloptions)$,$babeloptions$$endfor$]{babel}
+\usepackage[bidi=basic$if(shorthands)$$else$,shorthands=off$endif$$for(babeloptions)$,$babeloptions$$endfor$]{babel}
 \else
-\usepackage[bidi=default,shorthands=off,$for(babeloptions)$,$babeloptions$$endfor$]{babel}
+\usepackage[bidi=default$if(shorthands)$$else$,shorthands=off$endif$$for(babeloptions)$,$babeloptions$$endfor$]{babel}
 \fi
 $if(babel-lang)$
 $if(mainfont)$
diff --git a/data/templates/default.beamer b/data/templates/default.beamer
--- a/data/templates/default.beamer
+++ b/data/templates/default.beamer
@@ -108,12 +108,12 @@
 $hypersetup.latex()$
 
 $if(title)$
-\title$if(shorttitle)$[$shorttitle$]$endif${$title$$if(thanks)$\thanks{$thanks$}$endif$}
+\title$if(shorttitle)$[$shorttitle$]$endif${\texorpdfstring{$title$}{$title-meta$}$if(thanks)$\thanks{$thanks$}$endif$}
 $endif$
 $if(subtitle)$
-\subtitle$if(shortsubtitle)$[$shortsubtitle$]$endif${$subtitle$}
+\subtitle$if(shortsubtitle)$[$shortsubtitle$]$endif${\texorpdfstring{$subtitle$}{$subtitle-meta$}}
 $endif$
-\author$if(shortauthor)$[$shortauthor$]$endif${$for(author)$$author$$sep$ \and $endfor$}
+\author$if(shortauthor)$[$shortauthor$]$endif${\texorpdfstring{$for(author)$$author$$sep$ \and $endfor$}{$author-meta$}}
 \date$if(shortdate)$[$shortdate$]$endif${$date$}
 $if(institute)$
 \institute$if(shortinstitute)$[$shortinstitute$]$endif${$for(institute)$$institute$$sep$ \and $endfor$}
diff --git a/data/templates/default.typst b/data/templates/default.typst
--- a/data/templates/default.typst
+++ b/data/templates/default.typst
@@ -22,6 +22,11 @@
   kind: image
 ): set figure.caption(position: $if(figure-caption-position)$$figure-caption-position$$else$bottom$endif$)
 
+$if(highlighting-definitions)$
+// syntax highlighting functions from skylighting:
+$highlighting-definitions$
+
+$endif$
 $if(template)$
 #import "$template$": conf
 $else$
diff --git a/data/templates/default.vimdoc b/data/templates/default.vimdoc
new file mode 100644
--- /dev/null
+++ b/data/templates/default.vimdoc
@@ -0,0 +1,16 @@
+$if(filename)$*${filename}*	$endif$$if(abstract)$${abstract}$endif$$if(filename)$
+
+
+$endif$$if(combined-title)$${combined-title}
+
+
+$endif$$toc-reminder$
+
+$if(toc)$
+$toc$
+
+$endif$
+
+$body$
+
+ $modeline$
diff --git a/pandoc.cabal b/pandoc.cabal
--- a/pandoc.cabal
+++ b/pandoc.cabal
@@ -1,6 +1,6 @@
 cabal-version:   2.4
 name:            pandoc
-version:         3.8
+version:         3.8.1
 build-type:      Simple
 license:         GPL-2.0-or-later
 license-file:    COPYING.md
@@ -23,7 +23,7 @@
                    txt2tags, djot)
                  - HTML formats (HTML 4 and 5)
                  - Ebook formats (EPUB v2 and v3, FB2)
-                 - Documentation formats (GNU TexInfo, Haddock)
+                 - Documentation formats (GNU TexInfo, Haddock, Vimdoc)
                  - Roff formats (man, ms)
                  - TeX formats (LaTeX, ConTeXt)
                  - Typst
@@ -110,6 +110,7 @@
                  data/templates/fonts.latex
                  data/templates/font-settings.latex
                  data/templates/after-header-includes.latex
+                 data/templates/default.vimdoc
 
                  -- translations
                  data/translations/*.yaml
@@ -340,6 +341,7 @@
                  test/tables.txt
                  test/tables.fb2
                  test/tables.muse
+                 test/tables.vimdoc
                  test/tables.xwiki
                  test/tables/*.html4
                  test/tables/*.html5
@@ -386,6 +388,7 @@
                  test/writer.zimwiki
                  test/writer.xwiki
                  test/writer.muse
+                 test/writer.vimdoc
                  test/ansi-test.ansi
                  test/writers-lang-and-dir.latex
                  test/writers-lang-and-dir.context
@@ -433,6 +436,8 @@
                  test/odt/markdown/*.md
                  test/odt/native/*.native
                  test/pod-reader.pod
+                 test/vimdoc/*.markdown
+                 test/vimdoc/*.vimdoc
 source-repository head
   type:          git
   location:      https://github.com/jgm/pandoc.git
@@ -544,7 +549,7 @@
                  text-conversions      >= 0.3      && < 0.4,
                  time                  >= 1.5      && < 1.16,
                  unicode-collation     >= 0.1.1    && < 0.2,
-                 unicode-data          >= 0.6      && < 0.7,
+                 unicode-data          >= 0.6      && < 0.8,
                  unicode-transforms    >= 0.3      && < 0.5,
                  yaml                  >= 0.11     && < 0.12,
                  libyaml               >= 0.1.4    && < 0.2,
@@ -553,7 +558,7 @@
                  xml                   >= 1.3.12   && < 1.4,
                  typst                 >= 0.8.0.2  && < 0.9,
                  vector                >= 0.12     && < 0.14,
-                 djot                  >= 0.1.2.2  && < 0.2,
+                 djot                  >= 0.1.2.3  && < 0.2,
                  tls                   >= 2.0.1    && < 2.2,
                  crypton-x509-system   >= 1.6.7    && < 1.7
 
@@ -660,6 +665,7 @@
                    Text.Pandoc.Writers.AnnotatedTable,
                    Text.Pandoc.Writers.BibTeX,
                    Text.Pandoc.Writers.ANSI,
+                   Text.Pandoc.Writers.Vimdoc,
                    Text.Pandoc.PDF,
                    Text.Pandoc.UTF8,
                    Text.Pandoc.Scripting,
diff --git a/src/Text/Pandoc/Class/IO.hs b/src/Text/Pandoc/Class/IO.hs
--- a/src/Text/Pandoc/Class/IO.hs
+++ b/src/Text/Pandoc/Class/IO.hs
@@ -46,7 +46,7 @@
 import qualified Network.TLS.Extra as TLS
 import Network.HTTP.Client
        (httpLbs, Manager, responseBody, responseHeaders,
-        Request(port, host, requestHeaders), parseRequest, newManager)
+        Request(port, host, requestHeaders), parseUrlThrow, newManager)
 import Network.HTTP.Client.Internal (addProxy)
 import Network.HTTP.Client.TLS (mkManagerSettings)
 import Network.HTTP.Types.Header ( hContentType )
@@ -168,9 +168,9 @@
        proxy <- tryIOError (getEnv "http_proxy")
        let addProxy' x = case proxy of
                             Left _ -> return x
-                            Right pr -> parseRequest pr >>= \r ->
+                            Right pr -> parseUrlThrow pr >>= \r ->
                                 return (addProxy (host r) (port r) x)
-       req <- parseRequest (unpack u) >>= addProxy'
+       req <- parseUrlThrow (unpack u) >>= addProxy'
        let req' = req{requestHeaders = customHeaders ++ requestHeaders req}
        resp <- httpLbs req' manager
        return (B.concat $ toChunks $ responseBody resp,
diff --git a/src/Text/Pandoc/Highlighting.hs b/src/Text/Pandoc/Highlighting.hs
--- a/src/Text/Pandoc/Highlighting.hs
+++ b/src/Text/Pandoc/Highlighting.hs
@@ -30,6 +30,10 @@
                                 , formatConTeXtBlock
                                 , styleToConTeXt
                                 , formatANSI
+                                -- ** Typst
+                                , formatTypstBlock
+                                , formatTypstInline
+                                , styleToTypst
                                 -- * Styles
                                 , defaultStyle
                                 , pygments
@@ -45,12 +49,47 @@
                                 , fromListingsLanguage
                                 , toListingsLanguage
                                 ) where
-import Control.Monad
+import Control.Monad ( msum )
 import qualified Data.Map as M
 import Data.Maybe (fromMaybe)
 import qualified Data.Text as T
 import Skylighting
-import Text.Pandoc.Definition
+    ( SyntaxMap,
+      breezeDark,
+      espresso,
+      haddock,
+      kate,
+      monochrome,
+      pygments,
+      tango,
+      zenburn,
+      formatHtml4Block,
+      formatHtmlBlock,
+      formatHtmlInline,
+      styleToCss,
+      formatConTeXtBlock,
+      formatConTeXtInline,
+      styleToConTeXt,
+      formatLaTeXBlock,
+      formatLaTeXInline,
+      styleToLaTeX,
+      formatTypstBlock,
+      formatTypstInline,
+      styleToTypst,
+      formatANSI,
+      Style,
+      FormatOptions(containerClasses, startNumber, lineAnchors,
+                    numberLines, lineIdPrefix, codeClasses),
+      SourceLine,
+      lookupSyntax,
+      syntaxesByExtension,
+      parseTheme,
+      tokenize,
+      defaultFormatOpts,
+      TokenizerConfig(traceOutput, TokenizerConfig, syntaxMap),
+      Syntax(sShortname, sName),
+      TokenType(NormalTok) )
+import Text.Pandoc.Definition ( Attr )
 import Text.Pandoc.Class (PandocMonad, readFileLazy)
 import Text.Pandoc.Error (PandocError(..))
 import Control.Monad.Except (throwError)
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
@@ -61,6 +61,8 @@
                              lineBlockLines,
                              tableWith,
                              tableWith',
+                             tableWithSpans,
+                             tableWithSpans',
                              widthsFromIndices,
                              gridTableWith,
                              gridTableWith',
@@ -68,6 +70,10 @@
                              TableNormalization (..),
                              toTableComponents,
                              toTableComponents',
+                             toTableComponentsWithSpans,
+                             toTableComponentsWithSpans',
+                             singleRowSpans,
+                             singleColumnSpans,
                              readWith,
                              readWithM,
                              testStringWith,
@@ -303,8 +309,14 @@
       gridTableWith',
       tableWith,
       tableWith',
+      tableWithSpans,
+      tableWithSpans',
       toTableComponents,
       toTableComponents',
+      toTableComponentsWithSpans,
+      toTableComponentsWithSpans',
+      singleRowSpans,
+      singleColumnSpans,
       widthsFromIndices,
       TableComponents(..),
       TableNormalization(..) )
diff --git a/src/Text/Pandoc/Parsing/GridTable.hs b/src/Text/Pandoc/Parsing/GridTable.hs
--- a/src/Text/Pandoc/Parsing/GridTable.hs
+++ b/src/Text/Pandoc/Parsing/GridTable.hs
@@ -14,12 +14,18 @@
   , gridTableWith'
   , tableWith
   , tableWith'
+  , tableWithSpans
+  , tableWithSpans'
   , widthsFromIndices
     -- * Components of a plain-text table
   , TableComponents (..)
   , TableNormalization (..)
   , toTableComponents
   , toTableComponents'
+  , toTableComponentsWithSpans
+  , toTableComponentsWithSpans'
+  , singleRowSpans
+  , singleColumnSpans
   )
 where
 
@@ -65,6 +71,19 @@
                    -> [Alignment] -> [Double] -> [[Blocks]] -> [[Blocks]]
                    -> TableComponents
 toTableComponents' normalization aligns widths heads rows =
+  toTableComponentsWithSpans' normalization aligns widths (singleSpansBlocks heads) (singleSpansBlocks rows)
+
+-- | Bundles basic table components with span information into a single value.
+toTableComponentsWithSpans :: [Alignment] -> [Double] -> [[(Blocks, RowSpan, ColSpan)]] -> [[(Blocks, RowSpan, ColSpan)]]
+                           -> TableComponents
+toTableComponentsWithSpans = toTableComponentsWithSpans' NoNormalization
+
+-- | Bundles basic table components with span information into a single value,
+-- performing normalizations as necessary.
+toTableComponentsWithSpans' :: TableNormalization
+                            -> [Alignment] -> [Double] -> [[(Blocks, RowSpan, ColSpan)]] -> [[(Blocks, RowSpan, ColSpan)]]
+                            -> TableComponents
+toTableComponentsWithSpans' normalization aligns widths heads rows =
   let th = TableHead nullAttr (mapMaybe (toHeaderRow normalization) heads)
       tb = TableBody nullAttr 0 [] (map toRow rows)
       tf = TableFoot nullAttr []
@@ -208,7 +227,31 @@
            -> ParsecT s st m sep                       -- ^ line parser
            -> ParsecT s st m end                       -- ^ footer parser
            -> ParsecT s st m (mf TableComponents)
-tableWith' n11n headerParser rowParser lineParser footerParser = try $ do
+tableWith' n11n headerParser rowParser lineParser footerParser =
+  tableWithSpans' n11n headerParser' rowParser' lineParser footerParser
+    where
+      headerParser' = fmap (\(heads, aligns, indices) -> (fmap singleSpansBlocks heads, aligns, indices)) headerParser
+      rowParser' indices = fmap (\row -> zip3 row (repeat 1) (repeat 1)) <$> rowParser indices
+
+tableWithSpans :: (Stream s m Char, UpdateSourcePos s Char,
+              HasReaderOptions st, Monad mf)
+               => ParsecT s st m (mf [[(Blocks, RowSpan, ColSpan)]], [Alignment], [Int]) -- ^ header parser
+               -> ([Int] -> ParsecT s st m (mf [(Blocks, RowSpan, ColSpan)]))  -- ^ row parser
+               -> ParsecT s st m sep                       -- ^ line parser
+               -> ParsecT s st m end                       -- ^ footer parser
+               -> ParsecT s st m (mf Blocks)
+tableWithSpans hp rp lp fp = fmap tableFromComponents <$>
+  tableWithSpans' NoNormalization hp rp lp fp
+
+tableWithSpans' :: (Stream s m Char, UpdateSourcePos s Char,
+               HasReaderOptions st, Monad mf)
+                => TableNormalization
+                -> ParsecT s st m (mf [[(Blocks, RowSpan, ColSpan)]], [Alignment], [Int]) -- ^ header parser
+                -> ([Int] -> ParsecT s st m (mf [(Blocks, RowSpan, ColSpan)]))  -- ^ row parser
+                -> ParsecT s st m sep                       -- ^ line parser
+                -> ParsecT s st m end                       -- ^ footer parser
+                -> ParsecT s st m (mf TableComponents)
+tableWithSpans' n11n headerParser rowParser lineParser footerParser = try $ do
   (heads, aligns, indices) <- headerParser
   lines' <- sequence <$> rowParser indices `sepEndBy1` lineParser
   footerParser
@@ -216,15 +259,17 @@
   let widths = if null indices
                then replicate (length aligns) 0.0
                else widthsFromIndices numColumns indices
-  return $ toTableComponents' n11n aligns widths <$> heads <*> lines'
+  return $ toTableComponentsWithSpans' n11n aligns widths <$> heads <*> lines'
 
-toRow :: [Blocks] -> Row
-toRow =  Row nullAttr . map B.simpleCell
+toRow :: [(Blocks, RowSpan, ColSpan)] -> Row
+toRow =  Row nullAttr . map (\(blocks, rowSpan, columnSpan) -> B.cell AlignDefault rowSpan columnSpan blocks)
 
-toHeaderRow :: TableNormalization -> [Blocks] -> Maybe Row
+toHeaderRow :: TableNormalization -> [(Blocks, RowSpan, ColSpan)] -> Maybe Row
 toHeaderRow = \case
   NoNormalization -> \l -> if not (null l) then Just (toRow l) else Nothing
-  NormalizeHeader -> \l -> if not (all null l) then Just (toRow l) else Nothing
+  NormalizeHeader -> \l -> if not (all nullHeaderRow l) then Just (toRow l) else Nothing
+  where
+    nullHeaderRow (l, _, _) = null l
 
 -- | Calculate relative widths of table columns, based on indices
 widthsFromIndices :: Int      -- Number of columns on terminal
@@ -250,3 +295,14 @@
                    else fromIntegral numColumns
       fracs = map (\l -> fromIntegral l / quotient) lengths in
   drop 1 fracs
+
+-- | List of lists of `RowSpan` of 1.
+singleRowSpans :: [[RowSpan]]
+singleRowSpans = repeat $ repeat 1
+
+-- | List of lists of `ColsSpan` of 1.
+singleColumnSpans :: [[ColSpan]]
+singleColumnSpans = repeat $ repeat 1
+
+singleSpansBlocks :: [[Blocks]] -> [[(Blocks, RowSpan, ColSpan)]]
+singleSpansBlocks blocks = zipWith3 zip3 blocks singleRowSpans singleColumnSpans
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
@@ -810,6 +810,8 @@
           -> singleton $ Figure attr' capt [Plain im]
         [Div attr bls']
           -> toCaptioned (attr <> attr') bls'
+        [BlockQuote bls']
+          -> toCaptioned attr' bls'
         _ -> captContents
   pure $ toCaptioned nullAttr (toList bs)
 bodyPartToBlocks (Tbl _ _ _ _ []) =
@@ -833,8 +835,7 @@
       alignments = case rows of
                      [] -> replicate width Pandoc.AlignDefault
                      Docx.Row _ cs : _ -> concatMap getAlignment cs
-      totalWidth = sum grid
-      widths = (\w -> ColWidth (fromInteger w / fromInteger totalWidth)) <$> grid
+      widths = map ColWidth grid
 
   extStylesEnabled <- asks (isEnabled Ext_styles . docxOptions)
   let attr = case mbsty of
diff --git a/src/Text/Pandoc/Readers/Docx/Parse.hs b/src/Text/Pandoc/Readers/Docx/Parse.hs
--- a/src/Text/Pandoc/Readers/Docx/Parse.hs
+++ b/src/Text/Pandoc/Readers/Docx/Parse.hs
@@ -110,6 +110,7 @@
                            , envParStyles     :: ParStyleMap
                            , envLocation      :: DocumentLocation
                            , envDocXmlPath    :: FilePath
+                           , envTextWidth     :: Int
                            }
                deriving Show
 
@@ -272,7 +273,7 @@
               | HRule
               deriving Show
 
-type TblGrid = [Integer]
+type TblGrid = [Double]
 
 newtype TblLook = TblLook {firstRowFormatting::Bool}
               deriving Show
@@ -403,6 +404,7 @@
       rels      = archiveToRelationships archive docXmlPath
       media     = filteredFilesFromArchive archive filePathIsMedia
       (styles, parstyles) = archiveToStyles archive
+      textWidth = archiveToTextWidth archive
       rEnv = ReaderEnv { envNotes = notes
                        , envComments = comments
                        , envNumbering = numbering
@@ -413,6 +415,7 @@
                        , envParStyles = parstyles
                        , envLocation = InDocument
                        , envDocXmlPath = docXmlPath
+                       , envTextWidth = fromMaybe 9360 textWidth
                        }
       rState = ReaderState { stateWarnings = []
                            , stateFldCharState = []
@@ -636,6 +639,20 @@
 archiveToNumbering archive =
   fromMaybe (Numbering mempty [] []) (archiveToNumbering' archive)
 
+archiveToTextWidth :: Archive -> Maybe Int
+archiveToTextWidth zf = do
+  entry <- findEntryByPath "word/document.xml" zf
+  docElem <- parseXMLFromEntry entry
+  let ns = elemToNameSpaces docElem
+  sectElem <- findChildByName ns "w" "body" docElem >>= findChildByName ns "w" "sectPr"
+  pgWidth <- findChildByName ns "w" "pgSz" sectElem
+               >>= findAttrByName ns "w" "w" >>= safeRead
+  pgMar <- findChildByName ns "w" "pgMar" sectElem
+  leftMargin <- findAttrByName ns "w" "left" pgMar >>= safeRead
+  rightMargin <- findAttrByName ns "w" "right" pgMar >>= safeRead
+  gutter <- findAttrByName ns "w" "gutter" pgMar >>= safeRead
+  return $ pgWidth - (leftMargin + rightMargin + gutter)
+
 elemToNotes :: NameSpaces -> Text -> Element -> Maybe (M.Map T.Text Element)
 elemToNotes ns notetype element
   | isElem ns "w" (notetype <> "s") element =
@@ -664,11 +681,20 @@
 ---------------------------------------------
 
 elemToTblGrid :: NameSpaces -> Element -> D TblGrid
-elemToTblGrid ns element | isElem ns "w" "tblGrid" element =
+elemToTblGrid ns element | isElem ns "w" "tblGrid" element = do
   let cols = findChildrenByName ns "w" "gridCol" element
-  in
-   mapD (\e -> maybeToD (findAttrByName ns "w" "w" e >>= stringToInteger))
-   cols
+  textWidth <- asks envTextWidth
+  -- space between cols is 10 twips, so we subtract this:
+  let totalWidth = textWidth - (10 * (length cols - 1))
+  let toFraction :: Int -> Double
+      toFraction x = fromIntegral x / fromIntegral totalWidth
+  let normalizeFractions xs =
+        case sum xs of
+          tot | tot > 1.0 -> map (/ tot) xs
+          _ -> xs
+  normalizeFractions <$>
+    mapD (\e -> maybeToD (findAttrByName ns "w" "w" e >>=
+                          fmap toFraction . safeRead)) cols
 elemToTblGrid _ _ = throwError WrongElem
 
 elemToTblLook :: NameSpaces -> Element -> D TblLook
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
@@ -444,6 +444,9 @@
     , ("ifdim", ifdim)
     -- generally only used in \date
     , ("today", today)
+    -- this is used internally by pandoc but the definition is too complicated
+    -- for pandoc to handle (see #11140):
+    , ("pandocbounded", tok)
     ]
 
 bracedFilename :: PandocMonad m => LP m Text
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
@@ -190,6 +190,27 @@
        <|> T.singleton <$> noneOf "\n"
        <|> try (newline >> notFollowedBy blankline >> return " ")
 
+litBetween :: PandocMonad m => Char -> Char -> MarkdownParser m Text
+litBetween op cl = try $ do
+  char op
+  mconcat <$> (manyTill litChar (char cl))
+
+litCharNoSpace :: PandocMonad m => MarkdownParser m Text
+litCharNoSpace = T.singleton <$> escapedChar''
+       <|> characterReference
+       <|> T.singleton <$> noneOf "\n \r\t"
+ where
+   escapedChar'' = do
+     c <- escapedChar'
+     pure $ case c of
+       ' ' -> '\160'
+       _ -> c
+
+litBetweenNoSpace :: PandocMonad m => Char -> Char -> MarkdownParser m Text
+litBetweenNoSpace op cl = try $ do
+  char op
+  mconcat <$> (manyTill litCharNoSpace (char cl))
+
 -- | Parse a sequence of elements between square brackets,
 -- including between balanced pairs of square brackets.
 -- Skip brackets in standard inline escapes, code, raw HTML or LaTeX.
@@ -356,11 +377,9 @@
                                      try (spnl <* keyValAttr)
                     notFollowedBy' (() <$ reference)
                     mconcat <$> many1 (notFollowedBy space *> litChar)
-  let betweenAngles = try $ char '<' >>
-                             mconcat <$> (manyTill litChar (char '>'))
   rebase <- option False (True <$ guardEnabled Ext_rebase_relative_paths)
   src <- (if rebase then rebasePath pos else id) <$>
-             (try betweenAngles <|> sourceURL)
+             (try (litBetween '<' '>') <|> sourceURL)
   tit <- option "" referenceTitle
   attr   <- option nullAttr $ try $
               do guardEnabled Ext_link_attributes
@@ -1243,7 +1262,7 @@
   let nonempties = filter (not . T.null) $ map trimr strLst
       (leftSpace, rightSpace) =
            case sortOn T.length nonempties of
-                 (x:_) -> (T.head x `elem` [' ', '\t'], T.length x < len)
+                 (x:_) -> (T.head x `elem` [' ', '\t'], realLength x < len)
                  []    -> (False, False)
   in  case (leftSpace, rightSpace) of
         (True,  False) -> AlignRight
@@ -1496,7 +1515,7 @@
      '`'     -> code
      '_'     -> strongOrEmph
      '*'     -> strongOrEmph
-     '^'     -> superscript <|> inlineNote -- in this order bc ^[link](/foo)^
+     '^'     -> inlineNote <|> superscript
      '['     -> note <|> cite <|> bracketedSpan <|> wikilink B.linkWith <|> link
      '!'     -> image
      '$'     -> math
@@ -1702,29 +1721,29 @@
 
 superscript :: PandocMonad m => MarkdownParser m (F Inlines)
 superscript = do
-  fmap B.superscript <$> try (do
-    char '^'
-    mconcat <$> (try regularSuperscript <|> try mmdShortSuperscript))
-      where regularSuperscript = many1Till (do guardEnabled Ext_superscript
-                                               notFollowedBy spaceChar
-                                               notFollowedBy newline
-                                               inline) (char '^')
-            mmdShortSuperscript = do guardEnabled Ext_short_subsuperscripts
-                                     result <- T.pack <$> many1 alphaNum
-                                     return $ return $ return $ B.str result
+  fmap B.superscript <$> (regularSuperscript <|> mmdShortSuperscript)
+      where
+        regularSuperscript = do
+          guardEnabled Ext_superscript
+          litBetweenNoSpace '^' '^' >>= parseFromString inlines
+        mmdShortSuperscript = try $ do
+          guardEnabled Ext_short_subsuperscripts
+          char '^'
+          result <- T.pack <$> many1 alphaNum
+          return $ return $ B.str result
 
 subscript :: PandocMonad m => MarkdownParser m (F Inlines)
 subscript = do
-  fmap B.subscript <$> try (do
-    char '~'
-    mconcat <$> (try regularSubscript <|> mmdShortSubscript))
-      where regularSubscript = many1Till (do guardEnabled Ext_subscript
-                                             notFollowedBy spaceChar
-                                             notFollowedBy newline
-                                             inline) (char '~')
-            mmdShortSubscript = do guardEnabled Ext_short_subsuperscripts
-                                   result <- T.pack <$> many1 alphaNum
-                                   return $ return $ return $ B.str result
+  fmap B.subscript <$> (regularSubscript <|> mmdShortSubscript)
+      where
+        regularSubscript = do
+          guardEnabled Ext_subscript
+          litBetweenNoSpace '~' '~' >>= parseFromString inlines
+        mmdShortSubscript = try $ do
+          guardEnabled Ext_short_subsuperscripts
+          char '~'
+          result <- T.pack <$> many1 alphaNum
+          return $ return $ B.str result
 
 whitespace :: PandocMonad m => MarkdownParser m (F Inlines)
 whitespace = spaceChar >> return <$> (lb <|> regsp) <?> "whitespace"
@@ -1804,9 +1823,7 @@
           <|> (notFollowedBy (oneOf " )") >> litChar)
           <|> try (many1Char spaceChar <* notFollowedBy (oneOf "\"')"))
   let sourceURL = T.unwords . T.words . T.concat <$> many urlChunk
-  let betweenAngles = try $
-         char '<' >> mconcat <$> (manyTill litChar (char '>'))
-  src <- try betweenAngles <|> try base64DataURI <|> sourceURL
+  src <- try (litBetween '<' '>') <|> try base64DataURI <|> sourceURL
   tit <- option "" linkTitle'
   skipSpaces
   char ')'
@@ -2047,6 +2064,7 @@
     updateState $ \st -> st{ stateInNote = True
                            , stateNoteNumber = stateNoteNumber st + 1 }
     contents <- inBalancedBrackets inlines
+    notFollowedBy (char '(' <|> char '[') -- ^[link](foo)^ is superscript
     updateState $ \st -> st{ stateInNote = False }
     return $ B.note . B.para <$> contents
 
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
@@ -15,7 +15,7 @@
 -}
 module Text.Pandoc.Readers.RST ( readRST ) where
 import Control.Arrow (second)
-import Control.Monad (forM_, guard, liftM, mplus, mzero, when, unless)
+import Control.Monad (forM_, guard, liftM, mplus, mzero, when, unless, void)
 import Control.Monad.Except (throwError)
 import Control.Monad.Identity (Identity (..))
 import Data.Char (isHexDigit, isSpace, toUpper, isAlphaNum, generalCategory,
@@ -23,7 +23,7 @@
                                   DashPunctuation, OtherSymbol))
 import Data.List (deleteFirstsBy, elemIndex, nub, partition, sort, transpose)
 import qualified Data.Map as M
-import Data.Maybe (fromMaybe, maybeToList, isJust)
+import Data.Maybe (fromMaybe, maybeToList, isJust, isNothing, catMaybes)
 import Data.Sequence (ViewR (..), viewr)
 import Data.Text (Text)
 import qualified Data.Text as T
@@ -288,7 +288,7 @@
   guard $ indent >= minIndent
   char ':'
   name <- many1TillChar (noneOf "\n") (char ':')
-  (() <$ lookAhead newline) <|> skipMany1 spaceChar
+  (void (lookAhead newline)) <|> skipMany1 spaceChar
   first <- anyLine
   rest <- option "" $ try $ do lookAhead (count indent (char ' ') >> spaceChar)
                                indentedBlock
@@ -343,7 +343,7 @@
 optArg = do
   c <- letter <|> char '<'
   if c == '<'
-     then () <$ manyTill (noneOf "<>") (char '>')
+     then void $ manyTill (noneOf "<>") (char '>')
      else skipMany (alphaNum <|> char '_' <|> char '-')
 
 longOpt :: PandocMonad m => RSTParser m ()
@@ -672,7 +672,7 @@
 listItem start = try $ do
   (markerLength, first) <- rawListItem start
   rest <- many (listContinuation markerLength)
-  skipMany1 blankline <|> () <$ lookAhead start
+  skipMany1 blankline <|> void (lookAhead start)
   -- parsing with ListItemState forces markers at beginning of lines to
   -- count as list item markers, even if not separated by blank space.
   -- see definition of "endline"
@@ -710,7 +710,7 @@
 comment :: Monad m => RSTParser m Blocks
 comment = try $ do
   string ".."
-  skipMany1 spaceChar <|> (() <$ lookAhead newline)
+  skipMany1 spaceChar <|> void (lookAhead newline)
   -- notFollowedBy' directiveLabel -- comment comes after directive so unnec.
   _ <- anyLine
   optional indentedBlock
@@ -855,8 +855,9 @@
            let figcls = concatMap (T.words . snd) figclasskv
            let figattr = ("", figcls ++ aligncls, [])
            let capt = B.caption Nothing (B.plain caption <> legend)
+           let alt = maybe caption (B.text . trim) (lookup "alt" fields)
            return $ B.figureWith figattr capt $
-             B.plain (B.imageWith (imgident, imgcls, imgkvs) src "" (B.text src))
+             B.plain (B.imageWith (imgident, imgcls, imgkvs) src "" alt)
         "image" -> do
            let src = escapeURI $ trim top
            let alt = B.str $ maybe "image" trim $ lookup "alt" fields
@@ -911,7 +912,10 @@
          let tspecs = zip aligns' widths
          return $ B.singleton $ Table attr (B.caption Nothing (B.plain title))
                                   tspecs thead tbody tfoot
-       _ -> return mempty
+       _ -> do
+         pos <- getPosition
+         logMessage $ SkippedContent body pos
+         return mempty
   where
     -- only valid on the very first row of a table section
     rowLength (Row _ rb) = sum $ cellLength <$> rb
@@ -1037,7 +1041,7 @@
 
 parseCell :: PandocMonad m => Text -> RSTParser m Blocks
 parseCell t = singleParaToPlain
-   <$> parseFromString' parseBlocks (t <> "\n\n")
+   <$> parseFromString' parseBlocks (trim t <> "\n\n")
 
 
 -- TODO:
@@ -1358,7 +1362,6 @@
 --    support for them
 --
 -- Simple tables TODO:
---  - column spans
 --  - multiline support
 --  - ensure that rightmost column span does not need to reach end
 --  - require at least 2 columns
@@ -1367,67 +1370,105 @@
 dashedLine ch = do
   dashes <- many1 (char ch)
   sp     <- many (char ' ')
-  return (length dashes, length $ dashes ++ sp)
+  return (length dashes, length sp)
 
 simpleDashedLines :: Monad m => Char -> ParsecT Sources st m [(Int,Int)]
-simpleDashedLines ch = try $ many1 (dashedLine ch)
+simpleDashedLines ch = try $ do
+  lines' <- many1 (dashedLine ch)
+  skipMany spaceChar
+  newline
+  return $ addSpaces lines'
+ where
+  addSpaces [] = []
+  addSpaces [(dashes, _)] = [(dashes, dashes)] -- Don't count trailing whitespaces
+  addSpaces ((dashes, sp) : moreLines) =
+    (dashes, dashes + sp) : addSpaces moreLines
 
 -- Parse a table row separator
-simpleTableSep :: Monad m => Char -> RSTParser m Char
-simpleTableSep ch = try $ simpleDashedLines ch >> newline
+simpleTableSep :: Monad m => Char -> RSTParser m ()
+simpleTableSep ch = void (simpleDashedLines ch)
 
 -- Parse a table footer
-simpleTableFooter :: Monad m => RSTParser m Text
-simpleTableFooter = try $ simpleTableSep '=' >> blanklines
+simpleTableFooter :: Monad m => RSTParser m ()
+simpleTableFooter = try $ simpleTableSep '=' >> void blanklines
 
 -- Parse a raw line and split it into chunks by indices.
-simpleTableRawLine :: Monad m => [Int] -> RSTParser m [Text]
-simpleTableRawLine indices = simpleTableSplitLine indices <$> anyLine
+simpleTableRawLine :: Monad m => [Int] -> RSTParser m [(Text, ColSpan)]
+simpleTableRawLine indices = do
+  row <- rowWithOptionalColSpan
 
-simpleTableRawLineWithInitialEmptyCell :: Monad m => [Int] -> RSTParser m [Text]
+  case simpleTableSplitLine indices row of
+    Just rowLine -> return rowLine
+    Nothing -> Prelude.fail "col spans don't match"
+
+simpleTableRawLineWithInitialEmptyCell :: Monad m => [Int] -> RSTParser m [(Text, ColSpan)]
 simpleTableRawLineWithInitialEmptyCell indices = try $ do
   cs <- simpleTableRawLine indices
   let isEmptyCell = T.all (\c -> c == ' ' || c == '\t')
   case cs of
-    c:_ | isEmptyCell c -> return cs
+    c:_ | isEmptyCell (fst c) -> return cs
     _ -> mzero
 
 -- Parse a table row and return a list of blocks (columns).
-simpleTableRow :: PandocMonad m => [Int] -> RSTParser m [Blocks]
+simpleTableRow :: PandocMonad m => [Int] -> RSTParser m [(Blocks, RowSpan, ColSpan)]
 simpleTableRow indices = do
-  notFollowedBy' (blanklines <|> simpleTableFooter)
+  notFollowedBy' (void blanklines <|> simpleTableFooter)
   firstLine <- simpleTableRawLine indices
   conLines  <- many $ simpleTableRawLineWithInitialEmptyCell indices
-  let cols = map T.unlines . transpose $ firstLine : conLines ++
+  let cols = map T.unlines . transpose $ (map fst firstLine) : (map (map fst) conLines) ++
                                   [replicate (length indices) ""
                                     | not (null conLines)]
-  mapM parseCell cols
+  let rowParser = mapM parseCell cols
+  fmap (\blocks -> zip3 blocks (repeat 1) (map snd firstLine)) rowParser
 
-simpleTableSplitLine :: [Int] -> Text -> [Text]
-simpleTableSplitLine indices line =
-  map trimr $ drop 1 $ splitTextByIndices (init indices) line
+simpleTableSplitLine :: [Int] -> (Text, Maybe [Int]) -> Maybe [(Text, ColSpan)]
+simpleTableSplitLine indices (line, maybeColspanIndices) =
+  fmap (zip tableLines) columnSpans
+ where
+  splitTableLines lineIndices = map trimr $ drop 1 $ splitTextByIndices (init lineIndices) line
+  (tableLines, columnSpans) = case maybeColspanIndices of
+      Nothing -> (splitTableLines indices, Just $ repeat 1)
+      Just colSpanIndices -> (splitTableLines colSpanIndices, colSpans indices colSpanIndices)
 
 simpleTableHeader :: PandocMonad m
                   => Bool  -- ^ Headerless table
-                  -> RSTParser m ([[Blocks]], [Alignment], [Int])
+                  -> RSTParser m ([[(Blocks, RowSpan, ColSpan)]], [Alignment], [Int])
 simpleTableHeader headless = try $ do
   optional blanklines
+  dashes <- simpleDashedLines '='
+
   rawContent  <- if headless
-                    then return [""]
-                    else simpleTableSep '=' >> many1 (notFollowedBy (simpleDashedLines '=') >> anyLine)
-  dashes      <- if headless
-                    then simpleDashedLines '='
-                    else simpleDashedLines '=' <|> simpleDashedLines '-'
-  newline
-  let lines'   = map snd dashes
-  let indices  = scanl (+) 0 lines'
+                    then return [("", Nothing)]
+                    else many1 $ notFollowedBy (simpleDashedLines '=') >> rowWithOptionalColSpan
+
+  unless headless $ simpleTableSep '='
+
+  let (lines', indices) = dashedLinesToLinesWithIndices dashes
   let aligns   = replicate (length lines') AlignDefault
   let rawHeads = if headless
                     then []
                     else map (simpleTableSplitLine indices) rawContent
-  heads <- mapM ( mapM $ parseFromString' (mconcat <$> many plain) . trim) rawHeads
-  return (heads, aligns, indices)
 
+  when (any isNothing rawHeads) $ Prelude.fail "col spans don't match"
+
+  let justRawHeads  = catMaybes rawHeads
+  let rawHeads'     = map fst <$> justRawHeads
+  let columnSpans   = map snd <$> justRawHeads
+  heads <- mapM (mapM $ parseFromString' (mconcat <$> many plain) . trim) rawHeads'
+  let headsWithSpans = zipWith3 zip3 heads singleRowSpans columnSpans
+  return (headsWithSpans, aligns, indices)
+
+rowWithOptionalColSpan :: Monad m
+                       => RSTParser m (Text, Maybe [Int])
+rowWithOptionalColSpan = do
+  line <- anyLine
+  colSpanHyphens <- optionMaybe $ simpleDashedLines '-'
+
+  let colSpan = fmap colSpanFromHyphens colSpanHyphens
+  return (line, colSpan)
+ where
+  colSpanFromHyphens colSpanHyphens = snd $ dashedLinesToLinesWithIndices colSpanHyphens
+
 -- Parse a simple table.
 simpleTable :: PandocMonad m
             => Bool  -- ^ Headerless table
@@ -1435,7 +1476,7 @@
 simpleTable headless = do
   let wrapIdFst (a, b, c) = (Identity a, b, c)
       wrapId = fmap Identity
-  tbl <- runIdentity <$> tableWith
+  tbl <- runIdentity <$> tableWithSpans
            (wrapIdFst <$> simpleTableHeader headless)
            (wrapId <$> simpleTableRow)
            sep simpleTableFooter
@@ -1658,7 +1699,7 @@
       <|> (char '\\' >> ((\c -> ['\\',c]) <$> noneOf "\n"))
       <|> (string "\n" <* notFollowedBy blankline)
       <|> try (string "`" <*
-                notFollowedBy (() <$ roleMarker) <*
+                notFollowedBy (void roleMarker) <*
                 lookAhead (satisfy isAlphaNum))
        )
   char '`'
@@ -1806,3 +1847,37 @@
     s{ stateKeys = M.insert (toKey name) (("#" <> ident, ""), nullAttr)
                     (stateKeys s) }
   pure $ B.spanWith (ident,[],[]) (B.text name)
+
+dashedLinesToLinesWithIndices :: [(Int, Int)] -> ([Int], [Int])
+dashedLinesToLinesWithIndices dashes =
+  let lines'  = map snd dashes
+      indices = scanl (+) 0 lines'
+  in  (lines', indices)
+
+-- | Determines column spans by appying indices of a table border with column span indices.
+--
+-- The indices need to align.
+colSpans :: [Int] -> [Int] -> Maybe [ColSpan]
+colSpans [] []  = Just []
+colSpans [] _   = Nothing
+colSpans _ []   = Nothing
+colSpans (index : indices) colSpanIndices@(colIndex : colSpanIndicesTail)
+    | index /= colIndex = colSpans indices colSpanIndices
+    | otherwise =
+        -- For a matching index start counting the column spans.
+        let (spanCount, remainingIndices, remainingColSpanindices) = colSpanCount indices colSpanIndicesTail 1
+        in  (:) spanCount <$> colSpans remainingIndices remainingColSpanindices
+
+-- | Counts column spans by consuming all non-matching indices until a matching one is encountered.
+--
+-- If the indices match, the end of a column span has been encountered and the
+-- column count can be returned. Otherwise, if the indices don't match, add to
+-- the span count until a matching index is found.
+colSpanCount :: [Int] -> [Int] -> ColSpan -> (ColSpan, [Int], [Int])
+colSpanCount [] colSpanIndices spanCount = (spanCount, [], colSpanIndices)
+colSpanCount _ [] spanCount = (spanCount, [], [])
+colSpanCount indices@(index : indicesTail) colSpanIndices@(colIndex : colSpanIndicesTail) spanCount
+    | index == colIndex = case colSpanIndicesTail of
+        [] -> (spanCount, indicesTail, colSpanIndicesTail)
+        _ -> (spanCount, indices, colSpanIndices)
+    | otherwise = colSpanCount indicesTail colSpanIndices $ spanCount + 1
diff --git a/src/Text/Pandoc/Readers/Typst.hs b/src/Text/Pandoc/Readers/Typst.hs
--- a/src/Text/Pandoc/Readers/Typst.hs
+++ b/src/Text/Pandoc/Readers/Typst.hs
@@ -396,6 +396,7 @@
       getField "body" fields >>= pWithContents pBlocks)
   ,("pad", \_ _ fields ->  -- ignore paddingy
       getField "body" fields >>= pWithContents pBlocks)
+  ,("pagebreak", \_ _ _ -> pure $ B.divWith ("", ["page-break"], [("wrapper", "1")]) B.horizontalRule)
   ]
 
 inlineHandlers :: PandocMonad m =>
diff --git a/src/Text/Pandoc/Readers/XML.hs b/src/Text/Pandoc/Readers/XML.hs
--- a/src/Text/Pandoc/Readers/XML.hs
+++ b/src/Text/Pandoc/Readers/XML.hs
@@ -500,6 +500,9 @@
 parseMetaMapEntryContents :: (PandocMonad m) => [Content] -> XMLReader m (Maybe MetaValue)
 parseMetaMapEntryContents cs = msum <$> mapM parseMeta cs
 
+getElementText :: Element -> T.Text
+getElementText el = T.concat [cdData c | Text c <- elContent el]
+
 parseMeta :: (PandocMonad m) => Content -> XMLReader m (Maybe MetaValue)
 parseMeta (Text (CData CDataRaw _ _)) = return Nothing
 parseMeta (Text (CData _ s _)) =
@@ -515,7 +518,7 @@
         "MetaBool" -> case (attrValue atNameMetaBoolValue e) of
           "true" -> return $ Just $ MetaBool True
           _ -> return $ Just $ MetaBool False
-        "MetaString" -> pure Nothing
+        "MetaString" -> return $ Just $ MetaString (getElementText e)
         "MetaInlines" -> do
           inlines <- getInlines (elContent e)
           return $ Just $ MetaInlines $ toList inlines
diff --git a/src/Text/Pandoc/Writers.hs b/src/Text/Pandoc/Writers.hs
--- a/src/Text/Pandoc/Writers.hs
+++ b/src/Text/Pandoc/Writers.hs
@@ -79,6 +79,7 @@
     , writeXML
     , writeXWiki
     , writeZimWiki
+    , writeVimdoc
     , getWriter
     ) where
 
@@ -132,6 +133,7 @@
 import Text.Pandoc.Writers.XML
 import Text.Pandoc.Writers.XWiki
 import Text.Pandoc.Writers.ZimWiki
+import Text.Pandoc.Writers.Vimdoc
 
 data Writer m = TextWriter (WriterOptions -> Pandoc -> m Text)
               | ByteStringWriter (WriterOptions -> Pandoc -> m BL.ByteString)
@@ -206,6 +208,7 @@
   ,("djot"         , TextWriter writeDjot)
   ,("ansi"         , TextWriter writeANSI)
   ,("xml"          , TextWriter writeXML)
+  ,("vimdoc"       , TextWriter writeVimdoc)
   ]
 
 -- | Retrieve writer, extensions based on formatSpec (format+extensions).
diff --git a/src/Text/Pandoc/Writers/Docx/OpenXML.hs b/src/Text/Pandoc/Writers/Docx/OpenXML.hs
--- a/src/Text/Pandoc/Writers/Docx/OpenXML.hs
+++ b/src/Text/Pandoc/Writers/Docx/OpenXML.hs
@@ -888,14 +888,16 @@
           [ mknode "w:rPr" [] $
             maybeToList (lookup toktype tokTypesMap)
             , mknode "w:t" [("xml:space","preserve")] tok ]
-  withTextPropM (rStyleM "Verbatim Char")
-    $ case writerHighlightMethod opts of
-        Skylighting _ ->
-          case highlight (writerSyntaxMap opts) formatOpenXML attrs str of
+  let highlighted =
+        case highlight (writerSyntaxMap opts) formatOpenXML attrs str of
             Right h  -> return (map Elem h)
             Left msg -> do
               unless (T.null msg) $ report $ CouldNotHighlight msg
               unhighlighted
+  withTextPropM (rStyleM "Verbatim Char")
+    $ case writerHighlightMethod opts of
+        DefaultHighlighting -> highlighted
+        Skylighting _ -> highlighted
         _ -> unhighlighted
 inlineToOpenXML' opts (Note bs) = do
   notes <- gets stFootnotes
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
@@ -1548,6 +1548,9 @@
              _ -> do report $ InlineNotRendered inline
                      return mempty
     (Link attr txt (s,_)) | "mailto:" `T.isPrefixOf` s -> do
+                        -- We need to remove links from link text, because an
+                        -- <a> element is not allowed inside another <a>
+                        -- element.
                         linkText <- inlineListToHtml opts (removeLinks txt)
                         obfuscateLink opts attr linkText s
     (Link (ident,classes,kvs) txt (s,tit)) -> do
@@ -1767,15 +1770,6 @@
 isSlideVariant :: Format -> Bool
 isSlideVariant f = f `elem` [Format "s5", Format "slidy", Format "slideous",
                              Format "dzslides", Format "revealjs"]
-
-
--- We need to remove links from link text, because an <a> element is
--- not allowed inside another <a> element.
-removeLinks :: [Inline] -> [Inline]
-removeLinks = walk go
- where
-  go (Link attr ils _) = Span attr ils
-  go x = x
 
 toURI :: Bool -> Text -> Text
 toURI isHtml5 t = if isHtml5 then t else escapeURI t
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
@@ -32,7 +32,7 @@
       unless )
 import Crypto.Hash (hashWith, MD5(MD5))
 import Data.Containers.ListUtils (nubOrd)
-import Data.Char (isDigit, isAscii)
+import Data.Char (isDigit, isAscii, isLetter)
 import Data.List (intersperse, (\\))
 import Data.Maybe (catMaybes, fromMaybe, isJust, mapMaybe, isNothing)
 import Data.Monoid (Any (..))
@@ -68,7 +68,6 @@
 import qualified Data.Attoparsec.Text as A
 import qualified Text.Pandoc.UTF8 as UTF8
 import qualified Text.Pandoc.Writers.AnnotatedTable as Ann
-import Data.Char (isLetter)
 import Control.Applicative ((<|>))
 
 -- Work around problems with notes inside emphasis (see #8982)
@@ -184,6 +183,7 @@
   st <- get
   titleMeta <- escapeCommas <$> -- see #10501
                 stringToLaTeX TextString (stringify $ docTitle meta)
+  subtitleMeta <- stringToLaTeX TextString (stringify $ lookupMetaInlines "subtitle" meta)
   authorsMeta <- mapM (stringToLaTeX TextString . stringify) $ docAuthors meta
   -- The trailer ID is as hash used to identify the PDF. Taking control of its
   -- value is important when aiming for reproducible PDF generation. Setting
@@ -216,7 +216,15 @@
                            _         -> [])
                     $ lookupMetaInlines "nocite" meta
 
-  let context  =  defField "toc" (writerTableOfContents options) $
+   -- see #7414, avoid escaped underscores
+  let unescapeUnderscore = T.replace "\\_" "_"
+  let bibliography' = map unescapeUnderscore <$>
+                        getField "bibliography" metadata
+
+  let context  =  (case bibliography' of
+                     Nothing -> id
+                     Just xs -> resetField "bibliography" xs) $
+                  defField "toc" (writerTableOfContents options) $
                   defField "lof" (writerListOfFigures options) $
                   defField "lot" (writerListOfTables options) $
                   defField "toc-depth" (tshow
@@ -226,6 +234,7 @@
                                                  else 0)) $
                   defField "body" main $
                   defField "title-meta" titleMeta $
+                  defField "subtitle-meta" subtitleMeta $
                   defField "author-meta"
                         (T.intercalate "; " authorsMeta) $
                   defField "documentclass" documentClass $
@@ -536,7 +545,7 @@
                Right h -> do
                   when inNote $ modify (\s -> s{ stVerbInNote = True })
                   modify (\s -> s{ stHighlighting = True })
-                  return (flush $ linkAnchor $$ text (T.unpack h))
+                  return (flush $ linkAnchor $$ literal h)
   case () of
      _ | isEnabled Ext_literate_haskell opts && "haskell" `elem` classes &&
          "literate" `elem` classes           -> lhsCodeBlock
@@ -677,7 +686,7 @@
       , stSubfigure = stSubfigure st || isSubfigure
       }
 
-  let containsTable = getAny . (query $ \case
+  let containsTable = getAny . query (\case
         Table {}  -> Any True
         _         -> Any False)
   st <- get
@@ -785,6 +794,7 @@
       removeInvalidInline x                    = [x]
   let lstNoNotes = foldr (mappend . (\x -> walkM removeInvalidInline x)) mempty lst
   txtNoNotes <- inlineListToLaTeX lstNoNotes
+  txtNoLinksNoNotes <- inlineListToLaTeX (removeLinks lstNoNotes)
   -- footnotes in sections don't work (except for starred variants)
   -- unless you specify an optional argument:
   -- \section[mysec]{mysec\footnote{blah}}
@@ -837,7 +847,7 @@
                    $$ if unnumbered && not unlisted
                          then "\\addcontentsline{toc}" <>
                                 braces (text sectionType) <>
-                                braces txtNoNotes
+                                braces txtNoLinksNoNotes
                          else empty
 
 -- | Convert list of inline elements to LaTeX.
@@ -947,6 +957,7 @@
   inHeading <- gets stInHeading
   inItem <- gets stInItem
   inSoul <- gets stInSoulCommand
+  inCaption <- gets stInCaption
   let listingsCode = do
         let listingsopts = (case getListingsLanguage classes of
                                 Just l  -> (("language", mbBraced l):)
@@ -999,7 +1010,14 @@
   -- (see #1294). with regular texttt we don't get an error, but we get
   -- incorrect results if there is a space (see #5529).
   let inMbox x = "\\mbox" <> braces x
-  (if inSoul then inMbox else id) <$>
+
+  -- for captions we need to protect VERB with \protect (see #6821)
+  let protect x = "\\protect" <> x
+
+  let optionalProtect = case () of _ | inSoul -> inMbox
+                                     | inCaption -> protect
+                                     | otherwise -> id
+  optionalProtect <$>
    case writerHighlightMethod opts of
      _ | inHeading || inItem  -> rawCode  -- see #5574
      IdiomaticHighlighting    -> listingsCode
@@ -1196,9 +1214,12 @@
   let noteContents = nest 2 contents' <> optnl
   beamer <- gets stBeamer
   -- in beamer slides, display footnote from current overlay forward
-  -- and ensure that the note is on the frame, not e.g. the column (#5769)
+  -- and ensure that the note is on the frame, not e.g. the column (#5769, #5954)
+  incremental <- gets stIncremental
   let beamerMark = if beamer
-                      then text "<.->[frame]"
+                      then if incremental
+                           then text "<.->[frame]"
+                           else text "<\\value{beamerpauses}->[frame]"
                       else empty
   if externalNotes
      then do
diff --git a/src/Text/Pandoc/Writers/LaTeX/Caption.hs b/src/Text/Pandoc/Writers/LaTeX/Caption.hs
--- a/src/Text/Pandoc/Writers/LaTeX/Caption.hs
+++ b/src/Text/Pandoc/Writers/LaTeX/Caption.hs
@@ -23,7 +23,7 @@
 import Text.Pandoc.Walk
 import Text.Pandoc.Writers.LaTeX.Notes (notesToLaTeX)
 import Text.Pandoc.Writers.LaTeX.Types
-  ( LW, WriterState (stExternalNotes, stNotes) )
+  ( LW, WriterState (stExternalNotes, stNotes, stInCaption) )
 
 
 -- | Produces the components of a LaTeX 'caption' command. Returns a triple
@@ -35,6 +35,7 @@
            -> Caption
            -> LW m (Doc Text, Doc Text, Doc Text)
 getCaption inlineListToLaTeX externalNotes (Caption maybeShort long) = do
+  modify $ \st -> st{ stInCaption = True }
   let long' = blocksToInlines long
   oldExternalNotes <- gets stExternalNotes
   modify $ \st -> st{ stExternalNotes = externalNotes, stNotes = [] }
@@ -53,4 +54,5 @@
                              then toShortCapt long'
                              else return empty
                   Just short -> toShortCapt short
+  modify $ \st -> st{ stInCaption = False }
   return (capt, captForLof, footnotes)
diff --git a/src/Text/Pandoc/Writers/LaTeX/Table.hs b/src/Text/Pandoc/Writers/LaTeX/Table.hs
--- a/src/Text/Pandoc/Writers/LaTeX/Table.hs
+++ b/src/Text/Pandoc/Writers/LaTeX/Table.hs
@@ -98,8 +98,10 @@
   modify $ \s -> s{ stTable = True }
   notes <- notesToLaTeX <$> gets stNotes
   beamer <- gets stBeamer
+  let makeUnnumbered x = "{\\def\\LTcaptype{} % do not increment counter" $$ x $$ "}"
   return
-    $  "\\begin{longtable}[]" <>
+    $ (if null capt then makeUnnumbered else id)
+    $ "\\begin{longtable}[]" <>
           braces ("@{}" <> colDescriptors isSimpleTable tbl <> "@{}")
           -- the @{} removes extra space at beginning and end
     $$ head'
diff --git a/src/Text/Pandoc/Writers/LaTeX/Types.hs b/src/Text/Pandoc/Writers/LaTeX/Types.hs
--- a/src/Text/Pandoc/Writers/LaTeX/Types.hs
+++ b/src/Text/Pandoc/Writers/LaTeX/Types.hs
@@ -54,6 +54,7 @@
   , stLang          :: Maybe Lang    -- ^ lang specified in metadata
   , stInSoulCommand :: Bool          -- ^ in a soul command like ul
   , stCancel        :: Bool          -- ^ true if document uses \cancel
+  , stInCaption     :: Bool          -- ^ true if in a caption
   }
 
 startingState :: WriterOptions -> WriterState
@@ -95,4 +96,5 @@
   , stLang = Nothing
   , stInSoulCommand = False
   , stCancel = False
+  , stInCaption = False
   }
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
@@ -643,30 +643,22 @@
   let widths' = case numcols - length widths of
                      x | x > 0 -> widths ++ replicate x 0.0
                        | otherwise -> widths
+  let mkTable f = do
+       rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers
+       rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts)) rows
+       f (all null headers) aligns' widths' rawHeaders rawRows
   case True of
      _ | isSimple &&
          isEnabled Ext_simple_tables opts -> do
-           rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers
-           rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts))
-                      rows
-           tbl <- pandocTable opts False (all null headers)
-                      aligns' widths' rawHeaders rawRows
+           tbl <- mkTable (pandocTable opts False)
            return $ nest 2 (tbl $$ caption''') $$ blankline
        | isSimple &&
          isEnabled Ext_pipe_tables opts -> do
-           rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers
-           rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts))
-                      rows
-           tbl <- pipeTable opts (all null headers) aligns' widths'
-                     rawHeaders rawRows
+           tbl <- mkTable (pipeTable opts)
            return $ (tbl $$ caption''') $$ blankline
        | not (hasBlocks || hasColRowSpans) &&
          isEnabled Ext_multiline_tables opts -> do
-           rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers
-           rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts))
-                      rows
-           tbl <- pandocTable opts True (all null headers)
-                     aligns' widths' rawHeaders rawRows
+           tbl <- mkTable (pandocTable opts True)
            return $ nest 2 (tbl $$ caption''') $$ blankline
        | isEnabled Ext_grid_tables opts &&
           (hasColRowSpans || writerColumns opts >= 8 * numcols) -> do
@@ -676,17 +668,21 @@
        | hasSimpleCells,
          not hasColRowSpans,
          isEnabled Ext_pipe_tables opts -> do
-           rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers
-           rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts))
-                      rows
-           tbl <- pipeTable opts (all null headers) aligns' widths'
-                    rawHeaders rawRows
+           tbl <- mkTable (pipeTable opts)
            return $ (tbl $$ caption''') $$ blankline
        | isEnabled Ext_raw_html opts -> do -- HTML fallback
            tbl <- literal . removeBlankLinesInHTML <$>
                      writeHtml5String opts{ writerTemplate = Nothing }
                      (Pandoc nullMeta [t])
            return $ tbl $$ blankline  -- caption is in the HTML table
+       | hasSimpleCells,
+         hasColRowSpans,
+         isEnabled Ext_pipe_tables opts -> do
+           -- In this case an approximate pipe table will be rendered,
+           -- without col/row spans. This is better than nothing, since
+           -- we have no other way to render the table correctly (#11128).
+           tbl <- mkTable (pipeTable opts)
+           return $ (tbl $$ caption''') $$ blankline
        | otherwise
          -> do
            report (BlockNotRendered t)
@@ -724,30 +720,32 @@
   return $ mconcat contents <> blankline
 blockToMarkdown' opts (Figure figattr capt body) = do
   let combinedAttr imgattr = case imgattr of
-        ("", cls, kv)
-          | (figid, [], []) <- figattr -> Just (figid, cls, kv)
-        _ -> Nothing
-  let combinedAlt alt = case capt of
-        Caption Nothing [] -> if null alt
-                              then Just [Str "image"]
-                              else Just alt
-        Caption Nothing [Plain captInlines]
-          | null alt || stringify captInlines == stringify alt
-            -> Just captInlines
-        Caption Nothing [Para captInlines]
-          | null alt || stringify captInlines == stringify alt
-            -> Just captInlines
+        ("", cls, kvs)
+          | (figid, [], []) <- figattr
+            -> Just (figid, cls, [(k,v) | (k,v) <- kvs
+                                        , k /= "alt" ||
+                                          v /= "" && v /= trim (stringify capt)])
         _ -> Nothing
   case body of
     [Plain [Image imgAttr alt (src, ttl)]]
       | isEnabled Ext_implicit_figures opts
-      , Just descr    <- combinedAlt alt
       , Just imgAttr' <- combinedAttr imgAttr
       , isEnabled Ext_link_attributes opts || imgAttr' == nullAttr
         -> do
           -- use implicit figures if possible
           let tgt' = (src, fromMaybe ttl $ T.stripPrefix "fig:" ttl)
-          contents <- inlineListToMarkdown opts [Image imgAttr' descr tgt']
+          let descr = case capt of
+                        Caption _ bs -> blocksToInlines bs
+          -- add alt attribute if image description different from caption,
+          -- so this won't be lost:
+          let imgAttr'' = case imgAttr' of
+                            (i,c,kv)
+                              | not (null alt)
+                              , Nothing <- lookup "alt" kv
+                              , stringify descr /= stringify alt ->
+                                 (i, c, ("alt", stringify alt) : kv)
+                            _ -> imgAttr'
+          contents <- inlineListToMarkdown opts [Image imgAttr'' descr tgt']
           return $ contents <> blankline
     _ ->
       -- fallback to raw html if possible or div otherwise
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
@@ -26,7 +26,6 @@
 import Text.Pandoc.ImageSize
 import Text.Pandoc.Logging
 import Text.Pandoc.Options
-import Text.Pandoc.Walk
 import Text.DocLayout (render, literal)
 import Text.Pandoc.Shared
 import Text.Pandoc.URI
@@ -484,6 +483,8 @@
 inlineToMediaWiki Space = return " "
 
 inlineToMediaWiki (Link _ txt (src, _)) = do
+  -- We need to remove links from link text, because an <a> element is
+  -- not allowed inside another <a> element.
   label <- inlineListToMediaWiki (removeLinks txt)
   case txt of
      [Str s] | isURI src && escapeURI s == src -> return src
@@ -517,14 +518,6 @@
   modify (\s -> s { stNotes = True })
   return $ "<ref>" <> stripTrailingNewlines contents' <> "</ref>"
   -- note - does not work for notes with multiple blocks
-
--- We need to remove links from link text, because an <a> element is
--- not allowed inside another <a> element.
-removeLinks :: [Inline] -> [Inline]
-removeLinks = walk go
- where
-  go (Link _ ils _) = SmallCaps ils
-  go x = x
 
 highlightingLangs :: Set.Set Text
 highlightingLangs = Set.fromList [
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
@@ -21,7 +21,7 @@
 import Data.Foldable (find)
 import Data.List (sortOn, sortBy, foldl')
 import qualified Data.Map as Map
-import Data.Ord (comparing)
+import Data.Ord (comparing, Down (Down))
 import qualified Data.Set as Set
 import Data.Text (Text)
 import qualified Data.Text as T
@@ -260,7 +260,7 @@
            b <- blocksToOpenDocument opts blocks
            return (b, m)
   let styles   = stTableStyles s ++ stParaStyles s ++ formulaStyles ++
-                     map snd (sortBy (flip (comparing fst)) (
+                     map snd (sortBy (comparing (Down . fst)) (
                         Map.elems (stTextStyles s)))
       listStyle (n,l) = inTags True "text:list-style"
                           [("style:name", "L" <> tshow n)] (vcat l)
@@ -413,7 +413,7 @@
                            setInDefinitionList False
                            return r
       unhighlighted s = flush . vcat <$>
-            (mapM (inPreformattedTags . (:[])) (map preformatted (T.lines s)))
+            (mapM ((inPreformattedTags . (:[])) . preformatted) (T.lines s))
       mkDiv    attr s = do
         let (ident,_,kvs) = attr
             i = withLangFromAttr attr $
@@ -433,7 +433,7 @@
                                       <$> orderedListToOpenDocument o pn b
       table :: PandocMonad m => WriterOptions -> Ann.Table -> OD m (Doc Text)
       table opts
-          (Ann.Table (ident, _, _) (Caption _ c) colspecs thead tbodies _) = do
+          (Ann.Table (ident, _, _) (Caption _ c) colspecs thead tbodies tfoot) = do
         tn <- length <$> gets stTableStyles
         pn <- length <$> gets stParaStyles
         let  genIds      = map chr [65..]
@@ -459,10 +459,11 @@
                                 else unNumberedCaption "TableCaption"
         th <- colHeadsToOpenDocument o (map fst paraHStyles) thead
         tr <- mapM (tableBodyToOpenDocument o (map fst paraHStyles) (map fst paraStyles)) tbodies
+        tf <- tableFootToOpenDocument o (map fst paraStyles) tfoot
         let tableDoc = inTags True "table:table" [
                             ("table:name"      , name)
                           , ("table:style-name", name)
-                          ] (vcat columns $$ th $$ vcat tr)
+                          ] (vcat columns $$ th $$ vcat tr $$ tf)
         return $
           case writerTableCaptionPosition opts of
             CaptionAbove -> captionDoc $$ tableDoc
@@ -521,18 +522,33 @@
 colHeadsToOpenDocument o ns (Ann.TableHead _ hs) =
   case hs of
     [] -> return empty
-    (x:_) ->
-        let (Ann.HeaderRow _ _ c) = x
-        in inTagsIndented "table:table-header-rows" .
-        inTagsIndented "table:table-row" .
-        vcat <$> mapM (tableItemToOpenDocument o "TableHeaderRowCell") (zip ns c)
+    xs -> inTagsIndented "table:table-header-rows" <$>
+      tableHeaderRowsToOpenDocument o ns "TableHeaderRowCell" xs
 
+tableHeaderRowsToOpenDocument :: PandocMonad m
+                              => WriterOptions -> [Text] -> Text -> [Ann.HeaderRow]
+                              -> OD m (Doc Text)
+tableHeaderRowsToOpenDocument o ns s headerRows =
+  vcat <$> mapM headerRowToOpenDocument headerRows
+  where
+    headerRowToOpenDocument (Ann.HeaderRow _ _ c) =
+      inTagsIndented "table:table-row" .
+      vcat <$> mapM (tableItemToOpenDocument o s) (zip ns c)
+
 tableBodyToOpenDocument:: PandocMonad m
                        => WriterOptions -> [Text] -> [Text] -> Ann.TableBody
                        -> OD m (Doc Text)
-tableBodyToOpenDocument o headns bodyns tb =
-    let (Ann.TableBody _ _ _ r) = tb
-    in vcat <$> mapM (tableRowToOpenDocument o headns bodyns) r
+tableBodyToOpenDocument o headns bodyns tb = do
+    let (Ann.TableBody _ _ hs r) = tb
+    tableRowHeaders <- tableHeaderRowsToOpenDocument o headns "TableRowCell" hs
+    tableRows <- mapM (tableRowToOpenDocument o headns bodyns) r
+    return $ tableRowHeaders $$ vcat tableRows
+
+tableFootToOpenDocument :: PandocMonad m
+                        => WriterOptions -> [Text] -> Ann.TableFoot
+                        -> OD m (Doc Text)
+tableFootToOpenDocument o ns (Ann.TableFoot _ r) =
+  tableHeaderRowsToOpenDocument o ns "TableRowCell" r
 
 tableRowToOpenDocument :: PandocMonad m
                        => WriterOptions -> [Text] -> [Text] -> Ann.BodyRow
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
@@ -727,6 +727,7 @@
   , "columns" `elem` classes
   , Div (_, clsL, _) blksL : Div (_, clsR, _) blksR : remaining <- divBlks
   , "column" `elem` clsL, "column" `elem` clsR = do
+      -- At least 2 column elements
       mapM_ (addLogMessage . BlockNotRendered) (blks ++ remaining)
       let mkTwoColumn left right = do
             blksL' <- join . take 1 <$> splitBlocks left
@@ -755,6 +756,16 @@
       if (any null [blksL1, blksL2]) && (any null [blksR1, blksR2])
       then mkTwoColumn blksL blksR
       else mkComparison blksL1 blksL2 blksR1 blksR2
+  | Div (_, classes, _) divBlks <- blk
+  , "columns" `elem` classes
+  , Div (_, cls, _) columnBlks : remaining <- divBlks
+  , "column" `elem` cls = do
+      -- Only 1 column element.
+      mapM_ (addLogMessage . BlockNotRendered) (blks ++ remaining)
+      clBlks' <- join . take 1 <$> splitBlocks columnBlks
+      shapes <- blocksToShapes clBlks'
+      sldId <- asks envCurSlideId
+      return $ Slide sldId (ContentSlide [] shapes) spkNotes Nothing
 bodyBlocksToSlide _ (blk : blks) spkNotes = do
       sldId <- asks envCurSlideId
       inNoteSlide <- asks envInNoteSlide
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
@@ -251,8 +251,8 @@
   let admonition = case classes of
                         (cl:_)
                           | cl `elem` admonitions
-                          -> ".. " <> literal cl <> "::"
-                        cls -> ".. container::" <> space <>
+                          -> blankline <> ".. " <> literal cl <> "::"
+                        cls -> blankline <> ".. container::" <> space <>
                                    literal (T.unwords (filter (/= "container") cls))
   -- if contents start with block quote, we need to insert
   -- an empty comment to fix the indentation point (#10236)
@@ -323,7 +323,7 @@
                      c `notElem` ["sourceCode","literate","numberLines",
                                   "number-lines","example"]] of
              []       -> "::"
-             (lang:_) -> (".. code:: " <> literal lang) $$ numberlines)
+             (lang:_) -> (blankline <> ".. code:: " <> literal lang) $$ numberlines)
           $+$ nest 3 (literal str) $$ blankline
 blockToRST (BlockQuote blocks) = do
   contents <- blockListToRST blocks
@@ -343,7 +343,7 @@
       renderGrid = gridTable opts blocksToDoc specs' thead tbody tfoot
       isSimple = all (== 0) widths && length widths > 1
       renderSimple = do
-        tbl' <- simpleTable opts blocksToDoc headers rows
+        tbl' <- simpleTable opts blocksToDoc thead tbody tfoot
         if offset tbl' > writerColumns opts
           then renderGrid
           else return tbl'
@@ -358,7 +358,7 @@
   return $ blankline $$
            (if null caption || isList
                then tbl
-               else (".. table:: " <> caption') $$ blankline $$ nest 3 tbl) $$
+               else (blankline <> ".. table:: " <> caption') $$ blankline $$ nest 3 tbl) $$
            blankline
 blockToRST (BulletList items) = do
   contents <- mapM bulletListItemToRST items
@@ -918,25 +918,76 @@
 simpleTable :: PandocMonad m
             => WriterOptions
             -> (WriterOptions -> [Block] -> m (Doc Text))
-            -> [[Block]]
-            -> [[[Block]]]
+            -> TableHead
+            -> [TableBody]
+            -> TableFoot
             -> m (Doc Text)
-simpleTable opts blocksToDoc headers rows = do
-  -- can't have empty cells in first column:
-  let fixEmpties (d:ds) = if isEmpty d
-                             then literal "\\ " : ds
-                             else d : ds
-      fixEmpties [] = []
-  headerDocs <- if all null headers
+simpleTable opts blocksToDoc (TableHead _ headers) tbody (TableFoot _ footers) = do
+  headerDocs <- if all isEmptyRow headers
                    then return []
-                   else fixEmpties <$> mapM (blocksToDoc opts) headers
-  rowDocs <- mapM (fmap fixEmpties . mapM (blocksToDoc opts)) rows
-  let numChars = maybe 0 maximum . NE.nonEmpty . map offset
-  let colWidths = map numChars $ transpose (headerDocs : rowDocs)
-  let toRow = mconcat . intersperse (lblock 1 " ") . zipWith lblock colWidths
+                   else fixEmpties <$> mapM rowToDoc headers
+  rowDocs <- fixEmpties <$> mapM rowToDoc ((concatMap tableBodyToRows tbody) ++ footers)
+  let numChars = maybe 0 maximum . NE.nonEmpty . map (offset . fst)
+  let colWidths = map numChars $ transpose (headerDocs ++ rowDocs)
   let hline = nowrap $ hsep (map (\n -> literal (T.replicate n "=")) colWidths)
-  let hdr = if all null headers
+  let hdr = if all isEmptyRow headers
                then mempty
-               else hline $$ toRow headerDocs
-  let bdy = vcat $ map toRow rowDocs
+               else hline $$ mapToRow colWidths headerDocs
+  let bdy = mapToRow colWidths rowDocs
   return $ hdr $$ hline $$ bdy $$ hline
+  where
+    isEmptyRow (Row _ cells) = all isEmptyCell cells
+
+    isEmptyCell (Cell _ _ _ _ blocks) = null blocks
+
+    -- can't have empty cells in first column:
+    fixEmpties (d:ds) = fixEmpties' d : ds
+    fixEmpties [] = []
+
+    fixEmpties' ((d, colSpan):ds) = if isEmpty d
+                                     then (literal "\\ ", colSpan) : ds
+                                     else (d, colSpan) : ds
+    fixEmpties' [] = []
+
+    rowToDoc (Row _ cells) = concat <$> mapM cellToDocs cells
+
+    cellToDocs (Cell _ _ _ colSpan blocks) = applyColSpan colSpan <$> (blocksToDoc opts) blocks
+
+    tableBodyToRows (TableBody _ _ headerRows bodyRows) = headerRows ++ bodyRows
+
+    applyColSpan col@(ColSpan colSpan) doc
+      | colSpan > 1 =
+          -- Fill up columns for the col spans by adding empty docs without a ColSpan.
+          let emptyDoc = (literal "", Nothing)
+          in  (doc, Just col) : replicate (colSpan - 1) emptyDoc
+      | otherwise = [(doc, Just col)]
+
+    mapToRow colWidths = vcat . concatMap (toRow colWidths)
+
+    toRow colWidths rowDocsWithColSpans =
+      let (rowDocs, colSpans) = unzip rowDocsWithColSpans
+          row = intersperseDivider $ zipWith lblock colWidths rowDocs
+          colSpanRow = intersperseDivider $ writeColSpans colSpans colWidths
+      in  if any (maybe False (> 1)) colSpans
+           then [row, colSpanRow]
+           else [row] -- Don't write out col spans if they are all just 1.
+
+    intersperseDivider = mconcat . intersperse (lblock 1 " ")
+
+    -- Write col span dashes to match the length of the col widths.
+    writeColSpans [] _ = []
+    writeColSpans _ [] = []
+    writeColSpans (Nothing : remainingColSpans) colWidths = writeColSpans remainingColSpans colWidths
+    writeColSpans (Just (ColSpan colSpan) : remainingColSpans) colWidths =
+      let (colWidths', remainingColWidths) = splitAt colSpan colWidths
+      in  writeColSpanDashes colWidths' : writeColSpans remainingColSpans remainingColWidths
+
+    writeColSpanDashes colWidths =
+      let colWidthsLength = length colWidths
+          colWidthsSum = sum colWidths
+          dashLength = if colWidthsLength > 1
+            -- Offset by 1 for the white spaces between columns so that the col
+            -- span dashes align with the end of the columns correctly.
+            then colWidthsSum + colWidthsLength - 1
+            else colWidthsSum
+      in  literal $ T.replicate dashLength "-"
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
@@ -45,6 +45,7 @@
                      , toLegacyTable
                      , splitSentences
                      , ensureValidXmlIdentifiers
+                     , removeLinks
                      , setupTranslations
                      , isOrderedListMarker
                      , toTaskListItem
@@ -804,6 +805,14 @@
     Table (f attr) cap colspecs thead tbodies tfoot
   goBlock (Div attr bs) = Div (f attr) bs
   goBlock x = x
+
+-- | Convert links to spans; most useful when writing elements that must not
+-- contain links, e.g. to avoid nested links.
+removeLinks :: [Inline] -> [Inline]
+removeLinks = walk go
+ where
+  go (Link attr ils _) = Span attr ils
+  go x = x
 
 -- | Set translations based on the `lang` in metadata.
 setupTranslations :: PandocMonad m => Meta -> m ()
diff --git a/src/Text/Pandoc/Writers/Typst.hs b/src/Text/Pandoc/Writers/Typst.hs
--- a/src/Text/Pandoc/Writers/Typst.hs
+++ b/src/Text/Pandoc/Writers/Typst.hs
@@ -18,21 +18,24 @@
     writeTypst
   ) where
 import Text.Pandoc.Definition
-import Text.Pandoc.Class ( PandocMonad)
+import Text.Pandoc.Class ( PandocMonad, report )
 import Text.Pandoc.ImageSize ( dimension, Dimension(Pixel), Direction(..),
                                showInInch )
 import Text.Pandoc.Options ( WriterOptions(..), WrapOption(..), isEnabled,
-                             CaptionPosition(..) )
+                             CaptionPosition(..), HighlightMethod(..) )
 import Data.Text (Text)
 import Data.List (intercalate, intersperse)
 import Data.Bifunctor (first, second)
 import Network.URI (unEscapeString)
 import qualified Data.Text as T
+import Control.Monad (unless)
 import Control.Monad.State ( StateT, evalStateT, gets, modify )
 import Text.Pandoc.Writers.Shared ( lookupMetaInlines, lookupMetaString,
                                     metaToContext, defField, resetField,
                                     setupTranslations )
 import Text.Pandoc.Shared (isTightList, orderedListMarkers, tshow)
+import Text.Pandoc.Highlighting (highlight, formatTypstBlock, formatTypstInline,
+                                 styleToTypst)
 import Text.Pandoc.Translations (Term(Abstract), translateTerm)
 import Text.Pandoc.Walk (query)
 import Text.Pandoc.Writers.Math (convertMath)
@@ -40,6 +43,7 @@
 import Text.DocLayout
 import Text.DocTemplates (renderTemplate)
 import Text.Pandoc.Extensions (Extension(..))
+import Text.Pandoc.Logging (LogMessage(..))
 import Text.Collate.Lang (Lang(..), parseLang)
 import Text.Printf (printf)
 import Data.Char (isDigit)
@@ -51,7 +55,8 @@
 writeTypst options document =
   evalStateT (pandocToTypst options document)
     WriterState{ stOptions = options,
-                 stEscapeContext = NormalContext }
+                 stEscapeContext = NormalContext,
+                 stHighlighting = False }
 
 data EscapeContext = NormalContext | TermContext
   deriving (Show, Eq)
@@ -59,7 +64,9 @@
 data WriterState =
   WriterState {
     stOptions :: WriterOptions,
-    stEscapeContext :: EscapeContext }
+    stEscapeContext :: EscapeContext,
+    stHighlighting :: Bool
+    }
 
 type TW m = StateT WriterState m
 
@@ -83,6 +90,7 @@
                            Cite cs _ -> map citationId cs
                            _         -> [])
                   $ lookupMetaInlines "nocite" meta
+  hasHighlighting <- gets stHighlighting
 
   let context = defField "body" main
               $ defField "toc" (writerTableOfContents options)
@@ -103,6 +111,13 @@
               $ defField "smart" (isEnabled Ext_smart options)
               $ defField "abstract-title" abstractTitle
               $ defField "toc-depth" (tshow $ writerTOCDepth options)
+              $ (if hasHighlighting
+                    then case writerHighlightMethod options of
+                           Skylighting sty ->
+                              defField "highlighting-definitions"
+                                (T.stripEnd $ styleToTypst sty)
+                           _ -> id
+                    else id)
               $ defField "figure-caption-position"
                    (toPosition $ writerFigureCaptionPosition options)
               $ defField "table-caption-position"
@@ -184,7 +199,7 @@
       case fmt of
         Format "typst" -> return $ literal str
         _ -> return mempty
-    CodeBlock (_,cls,_) code -> do
+    CodeBlock (ident,cls,kvs) code -> do
       let go :: Char -> (Int, Int) -> (Int, Int)
           go '`' (longest, current) =
             let !new = current + 1 in (max longest new, new)
@@ -194,7 +209,19 @@
       let lang = case cls of
                    (cl:_) -> literal cl
                    _ -> mempty
-      return $ fence <> lang <> cr <> literal code <> cr <> fence <> blankline
+      opts <-  gets stOptions
+      case writerHighlightMethod opts of
+        Skylighting _ ->
+          case highlight (writerSyntaxMap opts) formatTypstBlock
+                (ident,cls ++ ["default"],kvs) code of
+            Left msg -> do
+              unless (T.null msg) $ report $ CouldNotHighlight msg
+              return $ fence <> lang <> cr <> literal code <> cr <> fence <> blankline
+            Right h -> do
+              modify (\s -> s{ stHighlighting = True })
+              return (literal h)
+        NoHighlighting -> return $ fence <> cr <> literal code <> cr <> fence <> blankline
+        _ -> return $ fence <> lang <> cr <> literal code <> cr <> fence <> blankline
     LineBlock lns -> do
       contents <- inlinesToTypst (intercalate [LineBreak] lns)
       return $ contents <> blankline
@@ -410,13 +437,27 @@
              case mathType of
                InlineMath -> return $ "$" <> literal r <> "$"
                DisplayMath -> return $ "$ " <> literal r <> " $"
-    Code (_,cls,_) code -> return $
-      case cls of
-        (lang:_) -> "#raw(lang:" <> doubleQuoted lang <>
-                        ", " <> doubleQuoted code <> ")" <> endCode
-        _ | T.any (=='`') code -> "#raw(" <> doubleQuoted code <> ")"
-                                     <> endCode
-          | otherwise -> "`" <> literal code <> "`"
+    Code (ident,cls,kvs) code -> do
+      opts <- gets stOptions
+      let defaultHighlightedCode =
+            case cls of
+              (lang:_) | writerHighlightMethod opts /= NoHighlighting
+                       -> "#raw(lang:" <> doubleQuoted lang <>
+                              ", " <> doubleQuoted code <> ")" <> endCode
+              _ | T.any (=='`') code -> "#raw(" <> doubleQuoted code <> ")"
+                                           <> endCode
+                | otherwise -> "`" <> literal code <> "`"
+      case writerHighlightMethod opts of
+        Skylighting _ ->
+          case highlight (writerSyntaxMap opts) formatTypstInline
+                (ident,cls ++ ["default"],kvs) code of
+            Left msg -> do
+              unless (T.null msg) $ report $ CouldNotHighlight msg
+              return defaultHighlightedCode
+            Right h -> do
+              modify (\s -> s{ stHighlighting = True })
+              return (literal h)
+        _ -> return defaultHighlightedCode
     RawInline fmt str ->
       case fmt of
         Format "typst" -> return $ literal str
diff --git a/src/Text/Pandoc/Writers/Vimdoc.hs b/src/Text/Pandoc/Writers/Vimdoc.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/Writers/Vimdoc.hs
@@ -0,0 +1,615 @@
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE MultiWayIf #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE Strict #-}
+
+module Text.Pandoc.Writers.Vimdoc (writeVimdoc) where
+
+import Control.Applicative (optional, (<|>))
+import Control.Monad (forM)
+import Control.Monad.Reader (MonadReader (..), ReaderT (..), asks)
+import Control.Monad.State (MonadState (..), StateT, evalStateT, gets, modify)
+import Data.Default (Default (..))
+import Data.List (intercalate, intersperse, transpose)
+import Data.List.NonEmpty (NonEmpty (..), nonEmpty)
+import Data.Maybe (fromMaybe)
+import Data.Text (Text)
+import qualified Data.Text as T
+import Text.DocLayout hiding (char, link, text)
+import Text.Pandoc.Class.PandocMonad ( report, PandocMonad )
+import Text.Pandoc.Definition
+import Text.Pandoc.Error (PandocError)
+import Text.Pandoc.Logging (LogMessage (..))
+import Text.Pandoc.Options (WrapOption (..), WriterOptions (..))
+import Text.Pandoc.Parsing.General (many1Till, many1TillChar, readWith)
+import Text.Pandoc.Shared (capitalize, onlySimpleTableCells, orderedListMarkers, isTightList, makeSections, removeFormatting, tshow)
+import Text.Pandoc.Templates (renderTemplate)
+import Text.Pandoc.URI (escapeURI, isURI)
+import Text.Pandoc.Writers.Shared (defField, metaToContext, toLegacyTable)
+import Text.Parsec (anyChar, char, eof, string, try)
+import Text.Read (readMaybe)
+import Text.Pandoc.Chunks (toTOCTree, SecInfo (..))
+import Data.Tree (Tree(..))
+import Data.Functor ((<&>))
+import Data.Sequence (Seq, (|>), (<|))
+import qualified Data.Sequence as Seq
+import Data.Foldable (toList)
+
+data WriterState = WriterState
+  { indentLevel :: Int -- How much to indent the block. Inlines shouldn't
+                       -- be concerned with indent level (I guess?)
+  , shiftWidth :: Int -- spaces per indentation level
+  , writerOptions :: WriterOptions
+  , vimdocPrefix :: Maybe Text
+  }
+
+instance Default WriterState where
+  def =
+    WriterState
+      { indentLevel = 0
+      , shiftWidth = 4
+      , writerOptions = def
+      , vimdocPrefix = Nothing
+      }
+
+indent :: (Monad m) => Int -> (VW m a) -> (VW m a)
+indent n = local (\s -> s{indentLevel = indentLevel s + n})
+
+type VW m = StateT (Seq (Doc Text)) (ReaderT WriterState m)
+
+runRR :: (Monad m) => Seq (Doc Text) -> WriterState -> VW m a -> m a
+runRR footnotes opts action = runReaderT (evalStateT action footnotes) opts
+
+docShiftWidth :: Meta -> Maybe Int
+docShiftWidth meta = case lookupMeta "shiftwidth" meta of
+  Just (MetaInlines [Str sw]) -> readMaybe (T.unpack sw)
+  Just (MetaString sw) -> readMaybe (T.unpack sw)
+  _ -> Nothing
+
+docVimdocPrefix :: Meta -> Maybe Text
+docVimdocPrefix meta = case lookupMeta "vimdoc-prefix" meta of
+  Just (MetaInlines [Str pref]) -> Just pref
+  Just (MetaString pref) -> Just pref
+  _ -> Nothing
+
+{- | Build a vim modeline
+>>> makeModeLine def
+"vim:tw=72:sw=4:ts=4:ft=help:norl:et:"
+-}
+makeModeLine :: WriterState -> Text
+makeModeLine ws =
+  T.pack . intercalate ":" $
+    [ "vim"
+    , "tw=" <> show tw
+    , "sw=" <> show sw
+    , "ts=" <> show sw
+    , "ft=help"
+    , "norl" -- left-to-right text
+    , "et:" -- expandtab and finishing ":"
+    ]
+ where
+  tw = writerColumns . writerOptions $ ws
+  sw = shiftWidth ws
+
+-- | Build a single formatted TOC line
+tocEntryToLine :: (PandocMonad m) => SecInfo -> VW m Text
+tocEntryToLine secinfo = do
+  rightRef <- mkVimdocRef (secId secinfo)
+  let numberStr = case secNumber secinfo of
+        Nothing -> ""
+        Just x | '.' `T.elem` x -> x <> " "
+        Just x -> x <> ". "
+  title <- inlineListToVimdoc $ removeFormatting (secTitle secinfo)
+  let titlePlain = render Nothing (title <> " ")
+
+  -- length sub 2 because vertical bars are concealed
+  let rightRefLen = max 0 (T.length rightRef - 2)
+  let numberLen = T.length numberStr
+  let leftLen = numberLen + T.length titlePlain
+  let padForRight = 1
+  textWidth <- asks (writerColumns . writerOptions)
+  il <- asks indentLevel
+
+  -- positive when we lack space (i.e. content is too long)
+  let lack = (il + leftLen + padForRight + rightRefLen) - textWidth
+
+  -- when lacking, truncate title reserving 3+ chars for ellipsis
+  let finalTitle =
+        if lack >= 0
+          then
+            let trunc = T.dropEnd (lack + 3) titlePlain
+                stripped = T.stripEnd trunc
+                ellipsis =
+                  T.replicate (3 + T.length trunc - T.length stripped) "."
+             in stripped <> ellipsis
+          else titlePlain
+
+  -- Negative lack means we have an excess of space, so we fill it with dots
+  let dots = T.replicate (negate lack) "."
+
+  pure . T.concat $ [numberStr, finalTitle, dots, " ", rightRef]
+
+vimdocTOC :: (PandocMonad m) => WriterState -> [Block] -> VW m (Doc Text)
+vimdocTOC (WriterState{writerOptions = opts}) blocks = do
+  let (Node _ subtrees) =
+        toTOCTree $ makeSections (writerNumberSections opts) Nothing blocks
+  let tocDepth = writerTOCDepth opts
+  let isBelowTocDepth (Node sec _) = secLevel sec <= tocDepth
+
+  let makeItem :: (PandocMonad m) => Tree SecInfo -> VW m (Doc Text)
+      makeItem (Node secinfo xs) = do
+        line <- tocEntryToLine secinfo
+        -- When unnumbered, indent constantly by two,
+        -- otherwise indent by (length of marker + 1)
+        let markerLen = 1 + maybe 1 T.length (secNumber secinfo)
+        childItems <-
+          indent markerLen $
+            traverse makeItem (filter isBelowTocDepth xs)
+        pure (literal line $$ nest markerLen (vcat childItems))
+
+  items <- traverse makeItem (filter isBelowTocDepth subtrees)
+  pure $ vcat items
+
+writeVimdoc :: (PandocMonad m) => WriterOptions -> Pandoc -> m Text
+writeVimdoc opts document@(Pandoc meta _) =
+  let
+    sw = fromMaybe (shiftWidth def) $ docShiftWidth meta
+    vp = docVimdocPrefix meta
+    footnotes = Seq.empty
+    initialEnv = def{shiftWidth = sw, writerOptions = opts, vimdocPrefix = vp}
+   in
+    runRR footnotes initialEnv $ pandocToVimdoc document
+
+pandocToVimdoc :: (PandocMonad m) => Pandoc -> VW m Text
+pandocToVimdoc (Pandoc meta body) = do
+  st <- ask
+  let opts = writerOptions st
+
+  metadata <- metaToContext opts blockListToVimdoc inlineListToVimdoc meta
+  main <- do
+    body' <- blockListToVimdoc body
+    footnotes <- get
+    rule <- blockToVimdoc HorizontalRule
+    let footnotes' = if Seq.null footnotes
+          then Empty
+          else vsep (toList $ rule <| footnotes)
+    pure $ body' <> blankline <> footnotes'
+
+  title <- inlineListToVimdoc $ docTitle meta
+  authors <- traverse inlineListToVimdoc $ docAuthors meta
+  let authors' = mconcat $ intersperse ("," <> space) (fmap nowrap authors)
+  let tw = writerColumns . writerOptions $ st
+
+  let combinedTitle =
+        render (Just tw) . cblock tw $
+            (title <> space)
+              <> (if null authors' then "" else "by" <> space <> authors')
+
+  -- This is placed here because I couldn't find a way to right-align text
+  -- inside template to the width specified by a variable
+  let toc_reminder =
+        render Nothing . rblock tw $
+          ("Type |gO| to see the table of contents." :: Doc Text)
+
+  toc <- render (Just tw) <$> vimdocTOC st body
+
+  let modeline = makeModeLine st
+  let context =
+        defField "body" main
+          . defField "toc" (if writerTableOfContents opts then toc else "")
+          . defField "modeline" modeline
+          . defField "combined-title" combinedTitle
+          . defField "toc-reminder" toc_reminder
+          $ metadata
+
+  pure $
+    case writerTemplate opts of
+      Just tpl -> render (Just tw) $ renderTemplate tpl context
+      Nothing -> render (Just tw) main
+
+blockListToVimdoc :: (PandocMonad m) => [Block] -> VW m (Doc Text)
+blockListToVimdoc blocks = vcat <$> mapM blockToVimdoc blocks
+
+blockToVimdoc :: (PandocMonad m) => Block -> VW m (Doc Text)
+
+blockToVimdoc (Plain inlines) = inlineListToVimdoc inlines
+
+blockToVimdoc (Para inlines) = do
+  contents <- inlineListToVimdoc inlines
+  pure $ contents <> blankline
+
+blockToVimdoc (LineBlock inliness) = vcat <$> mapM inlineListToVimdoc inliness
+
+blockToVimdoc (CodeBlock (_, cls, _) code) = do
+  sw <- asks shiftWidth
+  let lang = case cls of
+        (lang' : _) -> lang'
+        _ -> ""
+  -- NOTE: No blankline after the codeblock because closing `<` is concealed
+  pure . vcat $
+    [ ">" <> literal lang
+    , nest sw (literal code)
+    , flush "<"
+    ]
+
+blockToVimdoc block@(RawBlock format raw) = case format of
+  "vimdoc" -> pure $ literal raw
+  _ -> "" <$ report (BlockNotRendered block)
+
+blockToVimdoc (BlockQuote blocks) = do
+  content <- blockListToVimdoc blocks
+  pure $ nest 2 content <> blankline
+
+blockToVimdoc (OrderedList listAttr items) = do
+  let itemSpacer = if isTightList items then empty else blankline
+  let itemsWithMarkers = zip (orderedListMarkers listAttr) items
+  items' <- forM itemsWithMarkers $ \(marker, blocks) -> do
+    let markerLen = T.length marker
+
+    item' <- indent (markerLen + 1) $ blockListToVimdoc blocks
+    pure $ literal marker <> space <> nest (markerLen + 1) item' <> itemSpacer
+  pure $ vcat items' <> blankline
+
+blockToVimdoc (BulletList items) = do
+  let itemSpacer = if isTightList items then empty else blankline
+  items' <- forM items $ \blocks -> do
+    let marker = "-"
+    item <- indent 2 $ blockListToVimdoc blocks
+    pure $ marker <> " " <> nest 2 item <> itemSpacer
+  pure $ vcat items' <> blankline
+
+blockToVimdoc (DefinitionList items) = do
+  sw <- asks shiftWidth
+  let sepAll = if all (isTightList . snd) items then vcat else vsep
+  items' <- forM items $ \(term, definitions) -> do
+    let sepCur = if isTightList definitions then vcat else vsep
+    labeledTerm <- mkVimdocDefinitionTerm term
+    definitions' <- indent sw $ traverse blockListToVimdoc definitions
+    pure $ labeledTerm <> cr <> nest sw (sepCur definitions')
+  pure $ sepAll items' <> blankline
+
+blockToVimdoc (Header level (ref, _, _) inlines) = do
+  tw <- asks (writerColumns . writerOptions)
+  let rule = case level of
+        1 -> T.replicate tw "="
+        2 -> T.replicate tw "-"
+        _ -> ""
+  title <- fmap (render Nothing) . inlineListToVimdoc $ case level of
+    3 -> capitalize inlines
+    _ -> inlines
+
+  label <- mkVimdocTag ref
+  -- One manual space that ensures that even if spaceLeft is 0, title and ref
+  -- don't touch each other
+  let label' = " " <> label
+  -- (+ 2) due to stars concealment
+  let spaceLeft = tw - T.length title + 2
+
+  pure $ vcat
+      [ blankline
+      , literal rule
+      , literal $ title <> T.justifyRight spaceLeft ' ' label'
+      , blankline
+      ]
+
+blockToVimdoc HorizontalRule = do
+  tw <- asks (writerColumns . writerOptions)
+  pure $ literal (T.replicate (tw `div` 2) " *") <> blankline
+
+-- Based on blockToMarkdown' from Text.Pandoc.Writers.Markdown
+blockToVimdoc t@(Table (_, _, _) blkCapt specs thead tbody tfoot) = do
+  let isColRowSpans (Cell _ _ rs cs _) = rs > 1 || cs > 1
+  let rowHasColRowSpans (Row _ cs) = any isColRowSpans cs
+  let tbodyHasColRowSpans (TableBody _ _ rhs rs) =
+        any rowHasColRowSpans rhs || any rowHasColRowSpans rs
+  let theadHasColRowSpans (TableHead _ rs) = any rowHasColRowSpans rs
+  let tfootHasColRowSpans (TableFoot _ rs) = any rowHasColRowSpans rs
+  let hasColRowSpans =
+        theadHasColRowSpans thead
+          || any tbodyHasColRowSpans tbody
+          || tfootHasColRowSpans tfoot
+  let (caption, aligns, widths, headers, rows) =
+        toLegacyTable blkCapt specs thead tbody tfoot
+  let numcols =
+        maximum $
+          length aligns :| length widths : map length (headers : rows)
+  caption' <- inlineListToVimdoc caption
+  let caption''
+        | null caption = blankline
+        | otherwise = blankline $$ caption' $$ blankline
+  let hasSimpleCells = onlySimpleTableCells $ headers : rows
+  let isSimple = hasSimpleCells && all (== 0) widths && not hasColRowSpans
+  let isPlainBlock (Plain _) = True
+      isPlainBlock _ = False
+  let hasBlocks = not (all (all (all isPlainBlock)) $ headers : rows)
+  let padRow r = r ++ replicate x empty
+       where
+        x = numcols - length r
+  let aligns' = aligns ++ replicate x AlignDefault
+       where
+        x = numcols - length aligns
+  let widths' = widths ++ replicate x 0.0
+       where
+        x = numcols - length widths
+  sw <- asks shiftWidth
+  rawHeaders <- padRow <$> mapM blockListToVimdoc headers
+  rawRows <- mapM (fmap padRow . mapM blockListToVimdoc) rows
+  let hasHeader = all null headers
+  if
+    | isSimple -> do
+        -- Simple table
+        tbl <-
+          indent sw $
+            vimdocTable False hasHeader aligns' widths' rawHeaders rawRows
+        pure $ nest sw (tbl $$ caption'') $$ blankline
+    | not (hasBlocks || hasColRowSpans) -> do
+        -- Multiline table
+        tbl <-
+          indent sw $
+            vimdocTable True hasHeader aligns' widths' rawHeaders rawRows
+        pure $ nest sw (tbl $$ caption'') $$ blankline
+    | otherwise -> ("[TABLE]" $$ caption'') <$ report (BlockNotRendered t)
+
+blockToVimdoc (Figure _ _ blocks) = blockListToVimdoc blocks
+
+blockToVimdoc (Div _ blocks) = blockListToVimdoc blocks
+
+{- | Create a vimdoc tag. Tag is prefixed with "$vimdocPrefix-" if vimdocPrefix
+is a Just value.
+>>> runReader (mkVimdocTag "abc") def
+"*abc*"
+>>> runReader (mkVimdocTag "abc") (def{vimdocPrefix = Just "myCoolProject"})
+"*myCoolProject-abc*"
+-}
+mkVimdocTag :: (Monad m) => Text -> VW m Text
+mkVimdocTag tag = do
+  asks vimdocPrefix <&> \case
+    _ | T.null tag -> ""
+    Nothing -> "*" <> tag <> "*"
+    Just pref' -> "*" <> pref' <> "-" <> tag <> "*"
+
+{- | Create a hotlink for a tag, ie. a followable vimdoc link. Tag is prefixed
+ - with "$vimdocPrefix-" if vimdocPrefix is a Just value
+>>> runReader (mkVimdocRef "abc") def
+"|abc|"
+>>> runReader (mkVimdocRef "abc") (def{vimdocPrefix = Just "myCoolProject"})
+"|myCoolProject-abc|"
+-}
+mkVimdocRef :: (Monad m) => Text -> VW m Text
+mkVimdocRef ref =
+  asks vimdocPrefix <&> \case
+    _ | T.null ref -> ""
+    Nothing -> "|" <> ref <> "|"
+    Just pref' -> "|" <> pref' <> "-" <> ref <> "|"
+
+mkVimdocDefinitionTerm ::
+  (PandocMonad m) =>
+  [Inline] ->
+  VW m (Doc Text)
+mkVimdocDefinitionTerm inlines = do
+  il <- asks indentLevel
+  tw <- asks (writerColumns . writerOptions)
+  label <- case inlines of
+    -- NOTE: commands in vim are unique, so they get no prefix
+    [Code (ref, _, _) code]
+      | T.isPrefixOf ":" code ->
+          pure . Just $ "*" <> ref <> "*"
+    [Code (ref, _, _) _] | not (T.null ref) -> Just <$> mkVimdocTag ref
+    [Span (ref, _, _) _] | not (T.null ref) -> Just <$> mkVimdocTag ref
+    _ -> pure Nothing
+
+  term <- case inlines of
+    [Code _ code] | T.isPrefixOf ":" code -> pure $ literal code
+    _ -> inlineListToVimdoc inlines
+  let termLen = offset term
+  let labelLen = maybe 0 T.length label
+
+  if il + termLen + labelLen > tw
+    then
+      pure . mconcat $
+        [ case label of
+            Nothing -> empty
+            -- (+2) due to stars concealment
+            Just l -> flush (rblock (tw + 2) $ literal l) <> cr
+        , term
+        ]
+    else
+      pure . mconcat $
+        [ -- Since we calculated that label fits on the same line as
+          -- term and since label actually must exceed textwidth to align
+          -- properly, we disable wrapping.
+          -- vvvvvvvv
+          nowrap term
+        , case label of
+            Nothing -> empty
+            -- (+2) due to stars concealment
+            Just l -> rblock (tw - termLen - il + 2) (literal l)
+        ]
+
+-- | Write a vimdoc table
+vimdocTable ::
+  (Monad m) =>
+  -- | whether this is a multiline table
+  Bool ->
+  -- | whether the table has a header
+  Bool ->
+  -- | column alignments
+  [Alignment] ->
+  -- | column widths
+  [Double] ->
+  -- | table header cells
+  [Doc Text] ->
+  -- | table body rows
+  [[Doc Text]] ->
+  VW m (Doc Text)
+vimdocTable multiline headless aligns widths rawHeaders rawRows = do
+  let isSimple = all (== 0) widths
+  let alignHeader alignment = case alignment of
+        AlignLeft -> lblock
+        AlignCenter -> cblock
+        AlignRight -> rblock
+        AlignDefault -> lblock
+  -- Number of characters per column necessary to output every cell
+  -- without requiring a line break.
+  -- The @+2@ is needed for specifying the alignment.
+  let numChars = (+ 2) . maybe 0 maximum . nonEmpty . map offset
+  -- Number of characters per column necessary to output every cell
+  -- without requiring a line break *inside a word*.
+  -- The @+2@ is needed for specifying the alignment.
+  let minNumChars = (+ 2) . maybe 0 maximum . nonEmpty . map minOffset
+  let columns = transpose (rawHeaders : rawRows)
+
+  il <- asks indentLevel
+
+  -- x = (2 * length columns)         -- spaces for specifying the alignment
+  -- y = (length columns - 1)         -- spaces between the columns
+  -- x + y = (3 * length columns - 1) -- total needed correction
+  tw <- asks (writerColumns . writerOptions)
+  let tw' = tw - il - 3 * length columns + 1
+  wrap <- asks (writerWrapText . writerOptions)
+
+  -- minimal column width without wrapping a single word
+  let relWidth w col =
+        max
+          (floor $ fromIntegral (tw' - 1) * w)
+          ( if wrap == WrapAuto
+              then minNumChars col
+              else numChars col
+          )
+  let widthsInChars
+        | isSimple = map numChars columns
+        | otherwise = zipWith relWidth widths columns
+  let makeRow =
+        hcat
+          . intersperse (lblock 1 (literal " "))
+          . zipWith3 alignHeader aligns widthsInChars
+  let rows' = map makeRow rawRows
+  -- TODO: reduce tw in case head is not empty
+  let head' = makeRow rawHeaders <> " ~"
+  let head'' =
+        if headless
+          then empty
+          else head'
+  let body =
+        if multiline
+          then
+            vsep rows'
+              $$ if length rows' < 2
+                then blankline
+                else empty
+          else vcat rows'
+  return $
+    blankline
+      $$ head''
+      $$ (if multiline then blankline else empty)
+      $$ body
+
+-- | Replace Unicode characters with their ASCII representation
+replaceSpecialStrings :: Text -> Text
+replaceSpecialStrings =
+  let expand c = case c of
+        '\x00ad' -> ""
+        '\x2013' -> "--"
+        '\x2014' -> "---"
+        '\x2019' -> "'"
+        '\x2026' -> "..."
+        _        -> T.singleton c
+  in T.concatMap expand
+
+inlineListToVimdoc :: (PandocMonad m) => [Inline] -> VW m (Doc Text)
+inlineListToVimdoc inlines = hcat <$> mapM inlineToVimdoc inlines
+
+inlineToVimdoc :: (PandocMonad m) => Inline -> VW m (Doc Text)
+
+inlineToVimdoc (Str str) = pure . literal $ replaceSpecialStrings str
+
+-- Neither `:h help-writing`, nor neovim's grammar.js for vimdoc and
+-- highlights.scm say anything about styling text, so we strip all the
+-- formatting
+inlineToVimdoc (Emph inlines) = inlineListToVimdoc inlines
+inlineToVimdoc (Underline inlines) = inlineListToVimdoc inlines
+inlineToVimdoc (Strong inlines) = inlineListToVimdoc inlines
+inlineToVimdoc (Strikeout inlines) = inlineListToVimdoc inlines
+inlineToVimdoc (Superscript inlines) = inlineListToVimdoc inlines
+inlineToVimdoc (Subscript inlines) = inlineListToVimdoc inlines
+inlineToVimdoc (SmallCaps inlines) = inlineListToVimdoc inlines
+
+inlineToVimdoc (Quoted typ inlines) =
+  let quote = case typ of SingleQuote -> "'"; DoubleQuote -> "\""
+   in inlineListToVimdoc inlines >>= \text -> pure (quote <> text <> quote)
+
+inlineToVimdoc (Cite _citations inlines) = inlineListToVimdoc inlines
+
+inlineToVimdoc (Code (_, cls, _) code) = do
+  let hasNoLang = null cls
+  pure . literal $ case T.words code of
+    [":help", ref] | hasNoLang -> "|" <> ref <> "|"
+    [":h", ref]    | hasNoLang -> "|" <> ref <> "|"
+    _                          -> "`" <> code <> "`"
+
+inlineToVimdoc Space = pure space
+inlineToVimdoc SoftBreak =
+  asks (writerWrapText . writerOptions) >>= \case
+    WrapAuto -> pure space
+    WrapNone -> pure " "
+    WrapPreserve -> pure "\n"
+
+inlineToVimdoc LineBreak = pure "\n"
+
+inlineToVimdoc (Math _ math) = pure . literal $ "`$" <> math <> "$`"
+
+inlineToVimdoc inline@(RawInline (Format format) text) = case format of
+  "vimdoc" -> pure $ literal text
+  _ -> "" <$ report (InlineNotRendered inline)
+
+inlineToVimdoc (Link _ txt (src, _)) = do
+  let srcSuffix = fromMaybe src (T.stripPrefix "mailto:" src)
+  linkText <- render Nothing <$> inlineListToVimdoc txt
+
+  let isAutolink = case txt of
+        [Str x] | escapeURI x `elem` [src, srcSuffix] -> True
+        _ -> False
+
+  pure $ case refdocLinkToLink src of
+    Right link | isAutolink -> "|" <> literal link <> "|"
+    Right link ->
+      literal (T.stripEnd linkText) <> space <> "|" <> literal link <> "|"
+    Left _ | isURI src, isAutolink -> literal srcSuffix
+    Left _ -> literal (T.stripEnd linkText) <> space <> literal srcSuffix
+
+inlineToVimdoc (Image {}) = pure ""
+
+inlineToVimdoc (Note blocks) = do
+  newN <- gets (succ . Seq.length)
+  contents <- blockListToVimdoc blocks
+  tag <- mkVimdocTag ("footnote" <> tshow newN)
+  tw <- asks (writerColumns . writerOptions)
+
+  -- (+2) due to concealment of stars
+  --                     vvvvvvvv
+  let taggedContents = rblock (tw + 2) (literal tag) $$ contents
+  modify (|> taggedContents)
+
+  ref <- mkVimdocRef ("footnote" <> tshow newN)
+  pure $ space <> literal ref
+
+inlineToVimdoc (Span _ inlines) = inlineListToVimdoc inlines
+
+
+refdocLinkToLink :: Text -> Either PandocError Text
+refdocLinkToLink x = (\parser -> readWith parser Nothing x) $ do
+  string "http" >> optional (char 's') >> string "://"
+
+  let vimhelpP = do
+        try (string "vimhelp.org/") <|> string "neo.vimhelp.org/"
+
+        try (many1Till anyChar (char '#') >> many1TillChar anyChar eof)
+          <|> many1TillChar anyChar (try $ string ".html" >> eof)
+
+  let neovimP = do
+        string "neovim.io/doc/user/"
+        try (many1Till anyChar (char '#') >> many1TillChar anyChar eof)
+          <|> do base <- many1TillChar anyChar (try $ string ".html" >> eof)
+                 pure $ base <> ".txt"
+
+  try vimhelpP <|> neovimP
diff --git a/src/Text/Pandoc/XML.hs b/src/Text/Pandoc/XML.hs
--- a/src/Text/Pandoc/XML.hs
+++ b/src/Text/Pandoc/XML.hs
@@ -208,6 +208,7 @@
   , "draggable"
   , "enctype"
   , "enterkeyhint"
+  , "fetchpriority"
   , "for"
   , "form"
   , "formaction"
diff --git a/test/Tests/Old.hs b/test/Tests/Old.hs
--- a/test/Tests/Old.hs
+++ b/test/Tests/Old.hs
@@ -257,6 +257,24 @@
       [ test' "pod" ["-f", "pod", "-t", "native"]
         "pod-reader.pod" "pod-reader.native"
       ]
+  , testGroup "vimdoc" [ testGroup "writer" $
+      writerTests' "vimdoc" ++
+        [ test' "vimdoc-specific definition lists"
+            ["-s", "-r", "markdown", "-w", "vimdoc", "--toc", "--columns=78"]
+            "vimdoc/definition-lists.markdown" "vimdoc/definition-lists.vimdoc"
+        , test' "linking to docs"
+            ["-s", "-r", "markdown", "-w", "vimdoc", "--toc", "--columns=78"]
+            "vimdoc/vim-online-doc.markdown" "vimdoc/vim-online-doc.vimdoc"
+        , test' "unnumbered TOC up to level 2 headers"
+            ["-s", "-r", "markdown", "-w", "vimdoc", "--toc", "--columns=78",
+             "--toc-depth=2"]
+            "vimdoc/headers.markdown" "vimdoc/headers.vimdoc"
+        , test' "numbered TOC"
+            ["-s", "-r", "markdown", "-w", "vimdoc", "--toc", "--columns=78",
+             "-N"]
+            "vimdoc/headers.markdown" "vimdoc/headers-numbered.vimdoc"
+        ]
+    ]
   ]
  where
     test'           = test pandocPath
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
@@ -12,14 +12,15 @@
 -}
 module Tests.Readers.Docx (tests) where
 
+import Data.Algorithm.Diff (getDiff)
 import Codec.Archive.Zip
 import qualified Data.ByteString as BS
 import qualified Data.ByteString.Lazy as B
-import qualified Data.Map as M
 import qualified Data.Text as T
 import Data.Maybe
 import System.IO.Unsafe
 import Test.Tasty
+import Test.Tasty.Golden.Advanced
 import Test.Tasty.HUnit
 import Tests.Helpers
 import Text.Pandoc
@@ -27,51 +28,36 @@
 import qualified Text.Pandoc.MediaBag as MB
 import Text.Pandoc.UTF8 as UTF8
 
--- We define a wrapper around pandoc that doesn't normalize in the
--- tests. Since we do our own normalization, we want to make sure
--- we're doing it right.
-
-newtype NoNormPandoc = NoNormPandoc {unNoNorm :: Pandoc}
-                 deriving Show
-
-noNorm :: Pandoc -> NoNormPandoc
-noNorm = NoNormPandoc
-
 defopts :: ReaderOptions
 defopts = def{ readerExtensions = getDefaultExtensions "docx" }
 
-instance ToString NoNormPandoc where
-  toString d = T.unpack $ purely (writeNative def{ writerTemplate = s }) $ toPandoc d
-   where s = case d of
-                  NoNormPandoc (Pandoc (Meta m) _)
-                    | M.null m  -> Nothing
-                    | otherwise -> Just mempty -- need this to get meta output
+testCompare :: String -> FilePath -> FilePath -> TestTree
+testCompare = testCompareWithOpts defopts
 
-instance ToPandoc NoNormPandoc where
-  toPandoc = unNoNorm
 
-compareOutput :: ReaderOptions
-                 -> FilePath
-                 -> FilePath
-                 -> IO (NoNormPandoc, NoNormPandoc)
-compareOutput opts docxFile nativeFile = do
-  df <- B.readFile docxFile
-  nf <- UTF8.toText <$> BS.readFile nativeFile
-  p <- runIOorExplode $ readDocx opts df
-  df' <- runIOorExplode $ readNative def nf
-  return (noNorm p, noNorm df')
-
-testCompareWithOptsIO :: ReaderOptions -> String -> FilePath -> FilePath -> IO TestTree
-testCompareWithOptsIO opts name docxFile nativeFile = do
-  (dp, np) <- compareOutput opts docxFile nativeFile
-  return $ test id name (dp, np)
+nativeDiff :: FilePath -> Pandoc -> Pandoc -> IO (Maybe String)
+nativeDiff normPath expectedNative actualNative
+  | expectedNative == actualNative = return Nothing
+  | otherwise = Just <$> do
+      expected <- T.unpack <$> runIOorExplode (writeNative def expectedNative)
+      actual <- T.unpack <$> runIOorExplode (writeNative def actualNative)
+      let dash = replicate 72 '-'
+      let diff = getDiff (lines actual) (lines expected)
+      return $ '\n' : dash ++
+               "\n--- " ++ normPath ++
+               "\n+++ " ++ "test" ++ "\n" ++
+               showDiff (1,1) diff ++ dash
 
 testCompareWithOpts :: ReaderOptions -> String -> FilePath -> FilePath -> TestTree
-testCompareWithOpts opts name docxFile nativeFile =
-  unsafePerformIO $ testCompareWithOptsIO opts name docxFile nativeFile
-
-testCompare :: String -> FilePath -> FilePath -> TestTree
-testCompare = testCompareWithOpts defopts
+testCompareWithOpts opts testName docxFP nativeFP =
+  goldenTest
+  testName
+  (do nf <- UTF8.toText <$> BS.readFile nativeFP
+      runIOorExplode (readNative def nf))
+  (do df <- B.readFile docxFP
+      runIOorExplode (readDocx opts df))
+  (nativeDiff nativeFP)
+  (\a -> runIOorExplode (writeNative def a) >>= BS.writeFile nativeFP . UTF8.fromText)
 
 testForWarningsWithOptsIO :: ReaderOptions -> String -> FilePath -> [String] -> IO TestTree
 testForWarningsWithOptsIO opts name docxFile expected = do
diff --git a/test/Tests/Writers/Powerpoint.hs b/test/Tests/Writers/Powerpoint.hs
--- a/test/Tests/Writers/Powerpoint.hs
+++ b/test/Tests/Writers/Powerpoint.hs
@@ -102,6 +102,14 @@
       def
       "pptx/two-column/text-and-image/input.native"
       "pptx/two-column/text-and-image/output.pptx"
+    , pptxTests "single column text"
+      def
+      "pptx/single-column/text/input.native"
+      "pptx/single-column/text/output.pptx"
+    , pptxTests "single column image"
+      def
+      "pptx/single-column/image/input.native"
+      "pptx/single-column/image/output.pptx"
     , pptxTests "speaker notes"
       def
       "pptx/speaker-notes/input.native"
diff --git a/test/command/10002.md b/test/command/10002.md
new file mode 100644
--- /dev/null
+++ b/test/command/10002.md
@@ -0,0 +1,203 @@
+````
+% pandoc -f native -t opendocument
+[ Table
+    ( "" , [] , [] )
+    (Caption Nothing [])
+    [ ( AlignDefault , ColWidthDefault )
+    , ( AlignDefault , ColWidthDefault )
+    , ( AlignDefault , ColWidthDefault )
+    ]
+    (TableHead
+       ( "" , [] , [] )
+       [ Row
+           ( "" , [] , [] )
+           [ Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 3)
+               [ Plain
+                   [ Str "First"
+                   , Space
+                   , Str "Header"
+                   , Space
+                   , Str "Row"
+                   ]
+               ]
+           ]
+       , Row
+           ( "" , [] , [] )
+           [ Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "Second" ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "Header" ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "Row" ] ]
+           ]
+       ])
+    [ TableBody
+        ( "" , [] , [] )
+        (RowHeadColumns 0)
+        [ Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "Header - Table" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "Header - Body" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "Header - Row" ] ]
+            ]
+        ]
+        [ Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "Table" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "Body" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "Row" ] ]
+            ]
+        ]
+    ]
+    (TableFoot
+        ( "" , [] , [] )
+        [ Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 3)
+                [ Plain
+                    [ Str "First"
+                    , Space
+                    , Str "Footer"
+                    , Space
+                    , Str "Row"
+                    ]
+                ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "Second" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "Footer" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "Row" ] ]
+            ]
+        ])
+]
+^D
+<table:table table:name="Table1" table:style-name="Table1">
+  <table:table-column table:style-name="Table1.A" />
+  <table:table-column table:style-name="Table1.B" />
+  <table:table-column table:style-name="Table1.C" />
+  <table:table-header-rows>
+    <table:table-row>
+      <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string" table:number-columns-spanned="3">
+        <text:p text:style-name="Table_20_Heading">First Header
+        Row</text:p>
+      </table:table-cell>
+    </table:table-row>
+    <table:table-row>
+      <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
+        <text:p text:style-name="Table_20_Heading">Second</text:p>
+      </table:table-cell>
+      <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
+        <text:p text:style-name="Table_20_Heading">Header</text:p>
+      </table:table-cell>
+      <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">
+        <text:p text:style-name="Table_20_Heading">Row</text:p>
+      </table:table-cell>
+    </table:table-row>
+  </table:table-header-rows>
+  <table:table-row>
+    <table:table-cell table:style-name="TableRowCell" office:value-type="string">
+      <text:p text:style-name="Table_20_Heading">Header - Table</text:p>
+    </table:table-cell>
+    <table:table-cell table:style-name="TableRowCell" office:value-type="string">
+      <text:p text:style-name="Table_20_Heading">Header - Body</text:p>
+    </table:table-cell>
+    <table:table-cell table:style-name="TableRowCell" office:value-type="string">
+      <text:p text:style-name="Table_20_Heading">Header - Row</text:p>
+    </table:table-cell>
+  </table:table-row>
+  <table:table-row>
+    <table:table-cell table:style-name="TableRowCell" office:value-type="string">
+      <text:p text:style-name="Table_20_Contents">Table</text:p>
+    </table:table-cell>
+    <table:table-cell table:style-name="TableRowCell" office:value-type="string">
+      <text:p text:style-name="Table_20_Contents">Body</text:p>
+    </table:table-cell>
+    <table:table-cell table:style-name="TableRowCell" office:value-type="string">
+      <text:p text:style-name="Table_20_Contents">Row</text:p>
+    </table:table-cell>
+  </table:table-row>
+  <table:table-row>
+    <table:table-cell table:style-name="TableRowCell" office:value-type="string" table:number-columns-spanned="3">
+      <text:p text:style-name="Table_20_Contents">First Footer
+      Row</text:p>
+    </table:table-cell>
+  </table:table-row>
+  <table:table-row>
+    <table:table-cell table:style-name="TableRowCell" office:value-type="string">
+      <text:p text:style-name="Table_20_Contents">Second</text:p>
+    </table:table-cell>
+    <table:table-cell table:style-name="TableRowCell" office:value-type="string">
+      <text:p text:style-name="Table_20_Contents">Footer</text:p>
+    </table:table-cell>
+    <table:table-cell table:style-name="TableRowCell" office:value-type="string">
+      <text:p text:style-name="Table_20_Contents">Row</text:p>
+    </table:table-cell>
+  </table:table-row>
+</table:table>
+````
diff --git a/test/command/10127.md b/test/command/10127.md
new file mode 100644
--- /dev/null
+++ b/test/command/10127.md
@@ -0,0 +1,713 @@
+RST Reader
+
+```
+% pandoc -f rst -t native
+=====  =====  ======
+   Inputs     Output
+------------  ------
+  A      B    A or B
+=====  =====  ======
+False  False  False
+True   False  True
+False  True   True
+True   True   True
+=====  =====  ======
+
+Table with trailing whitespaces to ensure they don't interfere with col span parsing.
+
+===============  ============  =====================  
+Full column header
+---------------------------------------------------- 
+Header One       Header Two    Header 3
+===============  ============  =====================   
+Row              With col span 2 on the right
+---------------  -----------------------------------   
+Full column row
+----------------------------------------------------
+Row with         Col spans     For visual separation
+---------------  ------------  ---------------------  
+Row with col span 2            On the left
+-----------------------------  ---------------------
+Final row
+===============  ============  =====================
+^D
+[ Table
+    ( "" , [] , [] )
+    (Caption Nothing [])
+    [ ( AlignDefault , ColWidthDefault )
+    , ( AlignDefault , ColWidthDefault )
+    , ( AlignDefault , ColWidthDefault )
+    ]
+    (TableHead
+       ( "" , [] , [] )
+       [ Row
+           ( "" , [] , [] )
+           [ Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 2)
+               [ Plain [ Str "Inputs" ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "Output" ] ]
+           ]
+       , 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 "A" , Space , Str "or" , Space , Str "B" ]
+               ]
+           ]
+       ])
+    [ TableBody
+        ( "" , [] , [] )
+        (RowHeadColumns 0)
+        []
+        [ Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "False" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "False" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "False" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "True" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "False" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "True" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "False" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "True" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "True" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "True" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "True" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "True" ] ]
+            ]
+        ]
+    ]
+    (TableFoot ( "" , [] , [] ) [])
+, Para
+    [ Str "Table"
+    , Space
+    , Str "with"
+    , Space
+    , Str "trailing"
+    , Space
+    , Str "whitespaces"
+    , Space
+    , Str "to"
+    , Space
+    , Str "ensure"
+    , Space
+    , Str "they"
+    , Space
+    , Str "don't"
+    , Space
+    , Str "interfere"
+    , Space
+    , Str "with"
+    , Space
+    , Str "col"
+    , Space
+    , Str "span"
+    , Space
+    , Str "parsing."
+    ]
+, Table
+    ( "" , [] , [] )
+    (Caption Nothing [])
+    [ ( AlignDefault , ColWidthDefault )
+    , ( AlignDefault , ColWidthDefault )
+    , ( AlignDefault , ColWidthDefault )
+    ]
+    (TableHead
+       ( "" , [] , [] )
+       [ Row
+           ( "" , [] , [] )
+           [ Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 3)
+               [ Plain
+                   [ Str "Full"
+                   , Space
+                   , Str "column"
+                   , Space
+                   , Str "header"
+                   ]
+               ]
+           ]
+       , Row
+           ( "" , [] , [] )
+           [ Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "Header" , Space , Str "One" ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "Header" , Space , Str "Two" ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "Header" , Space , Str "3" ] ]
+           ]
+       ])
+    [ TableBody
+        ( "" , [] , [] )
+        (RowHeadColumns 0)
+        []
+        [ Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "Row" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 2)
+                [ Plain
+                    [ Str "With"
+                    , Space
+                    , Str "col"
+                    , Space
+                    , Str "span"
+                    , Space
+                    , Str "2"
+                    , Space
+                    , Str "on"
+                    , Space
+                    , Str "the"
+                    , Space
+                    , Str "right"
+                    ]
+                ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 3)
+                [ Plain
+                    [ Str "Full"
+                    , Space
+                    , Str "column"
+                    , Space
+                    , Str "row"
+                    ]
+                ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "Row" , Space , Str "with" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "Col" , Space , Str "spans" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain
+                    [ Str "For"
+                    , Space
+                    , Str "visual"
+                    , Space
+                    , Str "separation"
+                    ]
+                ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 2)
+                [ Plain
+                    [ Str "Row"
+                    , Space
+                    , Str "with"
+                    , Space
+                    , Str "col"
+                    , Space
+                    , Str "span"
+                    , Space
+                    , Str "2"
+                    ]
+                ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain
+                    [ Str "On"
+                    , Space
+                    , Str "the"
+                    , Space
+                    , Str "left"
+                    ]
+                ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "Final" , Space , Str "row" ] ]
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            ]
+        ]
+    ]
+    (TableFoot ( "" , [] , [] ) [])
+]
+```
+
+RST Writer
+```
+% pandoc -f native -t rst
+[ Table
+    ( "" , [] , [] )
+    (Caption Nothing [])
+    [ ( AlignDefault , ColWidthDefault )
+    , ( AlignDefault , ColWidthDefault )
+    , ( AlignDefault , ColWidthDefault )
+    ]
+    (TableHead
+       ( "" , [] , [] )
+       [ Row
+           ( "" , [] , [] )
+           [ Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 2)
+               [ Plain [ Str "Inputs" ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "Output" ] ]
+           ]
+       , 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 "A" , Space , Str "or" , Space , Str "B" ]
+               ]
+           ]
+       ])
+    [ TableBody
+        ( "" , [] , [] )
+        (RowHeadColumns 0)
+        []
+        [ Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "False" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "False" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "False" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "True" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "False" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "True" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "False" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "True" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "True" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "True" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "True" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "True" ] ]
+            ]
+        ]
+    ]
+    (TableFoot ( "" , [] , [] ) [])
+, Table
+    ( "" , [] , [] )
+    (Caption Nothing [])
+    [ ( AlignDefault , ColWidthDefault )
+    , ( AlignDefault , ColWidthDefault )
+    , ( AlignDefault , ColWidthDefault )
+    ]
+    (TableHead
+       ( "" , [] , [] )
+       [ Row
+           ( "" , [] , [] )
+           [ Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 3)
+               [ Plain
+                   [ Str "Full"
+                   , Space
+                   , Str "column"
+                   , Space
+                   , Str "header"
+                   ]
+               ]
+           ]
+       , Row
+           ( "" , [] , [] )
+           [ Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "Header" , Space , Str "One" ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "Header" , Space , Str "Two" ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "Header" , Space , Str "3" ] ]
+           ]
+       ])
+    [ TableBody
+        ( "" , [] , [] )
+        (RowHeadColumns 0)
+        []
+        [ Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "Row" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 2)
+                [ Plain
+                    [ Str "With"
+                    , Space
+                    , Str "col"
+                    , Space
+                    , Str "span"
+                    , Space
+                    , Str "2"
+                    , Space
+                    , Str "on"
+                    , Space
+                    , Str "the"
+                    , Space
+                    , Str "right"
+                    ]
+                ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 3)
+                [ Plain
+                    [ Str "Full"
+                    , Space
+                    , Str "column"
+                    , Space
+                    , Str "row"
+                    ]
+                ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 2)
+                [ Plain
+                    [ Str "Row"
+                    , Space
+                    , Str "with"
+                    , Space
+                    , Str "col"
+                    , Space
+                    , Str "span"
+                    , Space
+                    , Str "2"
+                    ]
+                ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain
+                    [ Str "On"
+                    , Space
+                    , Str "the"
+                    , Space
+                    , Str "left"
+                    ]
+                ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "Final" , Space , Str "row" ] ]
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            ]
+        ]
+    ]
+    (TableFoot
+      ( "" , [] , [] ) 
+      [ Row
+          ( "" , [] , [] )
+          [ Cell
+              ( "" , [] , [] )
+              AlignDefault
+              (RowSpan 1)
+              (ColSpan 1)
+              [ Plain [ Str "Footer" , Space , Str "Row" ] ]
+          , Cell
+              ( "" , [] , [] )
+              AlignDefault
+              (RowSpan 1)
+              (ColSpan 1)
+              [ Plain [ Str "at" , Space , Str "the" ] ]
+          , Cell
+              ( "" , [] , [] )
+              AlignDefault
+              (RowSpan 1)
+              (ColSpan 1)
+              [ Plain [ Str "bottom" ] ]
+          ]
+      ])
+]
+^D
+====== ===== ======
+Inputs       Output
+------------ ------
+A      B     A or B
+====== ===== ======
+False  False False
+True   False True
+False  True  True
+True   True  True
+====== ===== ======
+
+=================== ============================ ===========
+Full column header                               
+------------------------------------------------------------
+Header One          Header Two                   Header 3
+=================== ============================ ===========
+Row                 With col span 2 on the right 
+------------------- ----------------------------------------
+Full column row                                  
+------------------------------------------------------------
+Row with col span 2                              On the left
+------------------------------------------------ -----------
+Final row                                        
+Footer Row          at the                       bottom
+=================== ============================ ===========
+```
diff --git a/test/command/11101.md b/test/command/11101.md
new file mode 100644
--- /dev/null
+++ b/test/command/11101.md
@@ -0,0 +1,15 @@
+```
+% pandoc -f typst -t native
+First paragraph.
+
+#pagebreak()
+
+Second paragraph.
+^D
+[ Para [ Str "First" , Space , Str "paragraph." ]
+, Div
+    ( "" , [ "page-break" ] , [ ( "wrapper" , "1" ) ] )
+    [ HorizontalRule ]
+, Para [ Str "Second" , Space , Str "paragraph." ]
+]
+```
diff --git a/test/command/11124.md b/test/command/11124.md
new file mode 100644
--- /dev/null
+++ b/test/command/11124.md
@@ -0,0 +1,10 @@
+The heading is "unlinked" before adding it to the TOC.
+
+```
+% pandoc --to=latex
+<http://example.com/> {-}
+=========================
+^D
+\section*{\texorpdfstring{\url{http://example.com/}}{http://example.com/}}\label{httpexample.com}
+\addcontentsline{toc}{section}{{http://example.com/}}
+```
diff --git a/test/command/11128.md b/test/command/11128.md
new file mode 100644
--- /dev/null
+++ b/test/command/11128.md
@@ -0,0 +1,23 @@
+```
+% pandoc -f html -t markdown_strict+pipe_tables-raw_html
+<table>
+<tr>
+<th class="" colspan="2" rowspan="1"><b>Subject</b></th>
+<th class=""><b>Grade</b></th>
+</tr>
+<tr>
+<td class="" colspan="1" rowspan="2">Physics</td>
+<td class="">Practical</td>
+<td class="">A</td>
+</tr>
+<tr>
+<td class="">Theory</td>
+<td class="">B+</td>
+</tr>
+</table>
+^D
+| **Subject** |           | **Grade** |
+|-------------|-----------|-----------|
+| Physics     | Practical | A         |
+|             | Theory    | B+        |
+```
diff --git a/test/command/11140.md b/test/command/11140.md
new file mode 100644
--- /dev/null
+++ b/test/command/11140.md
@@ -0,0 +1,71 @@
+```
+% pandoc -f rst -t native
+.. figure:: image.png
+   :alt: my alt
+
+   Caption
+^D
+[ Figure
+    ( "" , [] , [] )
+    (Caption Nothing [ Plain [ Str "Caption" ] ])
+    [ Plain
+        [ Image
+            ( "" , [] , [] )
+            [ Str "my" , Space , Str "alt" ]
+            ( "image.png" , "" )
+        ]
+    ]
+]
+```
+
+```
+% pandoc -f rst -t native
+.. figure:: image.png
+
+   Caption
+^D
+[ Figure
+    ( "" , [] , [] )
+    (Caption Nothing [ Plain [ Str "Caption" ] ])
+    [ Plain
+        [ Image
+            ( "" , [] , [] ) [ Str "Caption" ] ( "image.png" , "" )
+        ]
+    ]
+]
+```
+
+```
+% pandoc -f native -t markdown
+[ Figure
+    ( "" , [] , [] )
+    (Caption
+       Nothing [ Plain [ Str "Caption" ] ])
+    [ Plain
+        [ Image ( "" , [] , [] ) [ Str "my", Space, Str "alt" ] ( "image.png" , "" )
+        ]
+    ]
+]
+^D
+![Caption](image.png){alt="my alt"}
+```
+
+Ignore `\pandocbounded`:
+```
+% pandoc -f latex -t native
+\begin{figure}
+\centering
+\pandocbounded{\includegraphics[keepaspectratio,alt={Caption}]{image.png}}
+\caption{Caption}
+\end{figure}
+^D
+[ Figure
+    ( "" , [] , [] )
+    (Caption Nothing [ Plain [ Str "Caption" ] ])
+    [ Para
+        [ Image
+            ( "" , [] , [] ) [ Str "Caption" ] ( "image.png" , "" )
+        ]
+    ]
+]
+```
diff --git a/test/command/11150.md b/test/command/11150.md
new file mode 100644
--- /dev/null
+++ b/test/command/11150.md
@@ -0,0 +1,29 @@
+```
+% pandoc -f rst
+===  =====
+int  float
+===  =====
+10   9.90
+-10  9.90
+===  =====
+^D
+<table>
+<thead>
+<tr>
+<th>int</th>
+<th>float</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>10</td>
+<td>9.90</td>
+</tr>
+<tr>
+<td>-10</td>
+<td>9.90</td>
+</tr>
+</tbody>
+</table>
+
+```
diff --git a/test/command/11162.md b/test/command/11162.md
new file mode 100644
--- /dev/null
+++ b/test/command/11162.md
@@ -0,0 +1,19 @@
+```
+% pandoc -f native -t rst
+[ BulletList
+    [ [ Plain [ Str "list" ]
+      , CodeBlock ( "" , [ "ruby" ] , [] ) "code = 7 # comment"
+      ]
+    , [ Plain [ Str "second" , Space , Str "item" ] ]
+    ]
+]
+^D
+- list
+
+  .. code:: ruby
+
+     code = 7 # comment
+
+- second item
+
+```
diff --git a/test/command/5619.md b/test/command/5619.md
--- a/test/command/5619.md
+++ b/test/command/5619.md
@@ -37,7 +37,28 @@
     [ Plain
         [ Image
             ( "test" , [] , [ ( "width" , "1in" ) ] )
-            [ Str "img1.jpg" ]
+            [ Str "The"
+            , Space
+            , Str "caption."
+            , Space
+            , Str "Here's"
+            , Space
+            , Str "what"
+            , Space
+            , Str "piggybacking"
+            , Space
+            , Str "on"
+            , Space
+            , Str "caption"
+            , Space
+            , Str "would"
+            , Space
+            , Str "look"
+            , Space
+            , Str "like"
+            , Space
+            , Str "{#fig:1}"
+            ]
             ( "img1.jpg" , "" )
         ]
     ]
diff --git a/test/command/6021.md b/test/command/6021.md
new file mode 100644
--- /dev/null
+++ b/test/command/6021.md
@@ -0,0 +1,54 @@
+```
+% pandoc -t native
+Oxide      石英
+-------  ------
+SiO2        100
+^D
+[ Table
+    ( "" , [] , [] )
+    (Caption Nothing [])
+    [ ( AlignLeft , ColWidthDefault )
+    , ( AlignRight , ColWidthDefault )
+    ]
+    (TableHead
+       ( "" , [] , [] )
+       [ Row
+           ( "" , [] , [] )
+           [ Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "Oxide" ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "\30707\33521" ] ]
+           ]
+       ])
+    [ TableBody
+        ( "" , [] , [] )
+        (RowHeadColumns 0)
+        []
+        [ Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "SiO2" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "100" ] ]
+            ]
+        ]
+    ]
+    (TableFoot ( "" , [] , [] ) [])
+]
+```
diff --git a/test/command/6821.md b/test/command/6821.md
new file mode 100644
--- /dev/null
+++ b/test/command/6821.md
@@ -0,0 +1,80 @@
+```
+% pandoc -f native -t latex
+[ Para [ Code ( "" , [ "python" ] , [] ) "x = 5" ]
+, Figure
+    ( "" , [] , [] )
+    (Caption
+       Nothing
+       [ Plain
+           [ Str "This"
+           , Space
+           , Str "is"
+           , Space
+           , Str "a"
+           , Space
+           , Str "test"
+           , Space
+           , Code ( "" , [ "python" ] , [] ) "x = 5"
+           ]
+       ])
+    [ Plain
+        [ Image
+            ( "" , [] , [] )
+            [ Str "This"
+            , Space
+            , Str "is"
+            , Space
+            , Str "a"
+            , Space
+            , Str "test"
+            , Space
+            , Code ( "" , [ "python" ] , [] ) "x = 5"
+            ]
+            ( "test.png" , "" )
+        ]
+    ]
+, Table
+    ( "" , [] , [] )
+    (Caption
+       Nothing
+       [ Plain [ Code ( "" , [ "cpp" ] , [] ) "caption" ] ])
+    [ ( AlignDefault , ColWidthDefault ) ]
+    (TableHead ( "" , [] , [] ) [])
+    [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]
+    (TableFoot
+       ( "" , [] , [] )
+       [ Row
+           ( "" , [] , [] )
+           [ Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "A" ] ]
+           ]
+       ])
+, Para [ Code ( "" , [ "cpp" ] , [] ) "caption" ]
+]
+^D
+\VERB|\NormalTok{x }\OperatorTok{=} \DecValTok{5}|
+
+\begin{figure}
+\centering
+\pandocbounded{\includegraphics[keepaspectratio,alt={This is a test x = 5}]{test.png}}
+\caption{This is a test
+\protect\VERB|\NormalTok{x }\OperatorTok{=} \DecValTok{5}|}
+\end{figure}
+
+\begin{longtable}[]{@{}l@{}}
+\caption{\protect\VERB|\NormalTok{caption}|}\tabularnewline
+\toprule\noalign{}
+\endfirsthead
+\endhead
+\midrule\noalign{}
+A \\
+\bottomrule\noalign{}
+\endlastfoot
+\end{longtable}
+
+\VERB|\NormalTok{caption}|
+```
diff --git a/test/command/6925.md b/test/command/6925.md
--- a/test/command/6925.md
+++ b/test/command/6925.md
@@ -23,12 +23,12 @@
 ::: thm
 **Theorem 1**. *a*
 
-![image](1.png)
+![](1.png)
 :::
 
 ::: thm2
 **Theorem 1**. a
 
-![image](1.png)
+![](1.png)
 :::
 ```
diff --git a/test/command/7272.md b/test/command/7272.md
--- a/test/command/7272.md
+++ b/test/command/7272.md
@@ -14,6 +14,7 @@
   </tbody>
 </table>
 ^D
+{\def\LTcaptype{} % do not increment counter
 \begin{longtable}[]{@{}
   >{\raggedright\arraybackslash}p{(\linewidth - 0\tabcolsep) * \real{1.0000}}@{}}
 \toprule\noalign{}
@@ -25,4 +26,5 @@
 text2 }\strut
 \end{minipage} \\
 \end{longtable}
+}
 ```
diff --git a/test/command/7473.md b/test/command/7473.md
--- a/test/command/7473.md
+++ b/test/command/7473.md
@@ -24,7 +24,14 @@
     [ Plain
         [ Image
             ( "" , [] , [ ( "width" , "1in" ) ] )
-            [ Str "example.png" ]
+            [ Str "This"
+            , Space
+            , Str "is"
+            , Space
+            , Str "a"
+            , Space
+            , Str "caption."
+            ]
             ( "example.png" , "" )
         ]
     ]
diff --git a/test/command/8638.md b/test/command/8638.md
--- a/test/command/8638.md
+++ b/test/command/8638.md
@@ -7,6 +7,7 @@
 | oranges | 4.25  |
 ^D
 \begin{frame}
+{\def\LTcaptype{} % do not increment counter
 \begin{longtable}[]{@{}lr@{}}
 \toprule\noalign{}
 fruit & price \\
@@ -16,5 +17,6 @@
 oranges & 4.25 \\
 \bottomrule\noalign{}
 \end{longtable}
+}
 \end{frame}
 ```
diff --git a/test/command/8652.md b/test/command/8652.md
new file mode 100644
--- /dev/null
+++ b/test/command/8652.md
@@ -0,0 +1,28 @@
+```
+% pandoc -t native
+My text^[My note]isnot^[Text]
+^D
+[ Para
+    [ Str "My"
+    , Space
+    , Str "text"
+    , Note [ Para [ Str "My" , Space , Str "note" ] ]
+    , Str "isnot"
+    , Note [ Para [ Str "Text" ] ]
+    ]
+]
+
+```
+
+```
+% pandoc -t native
+^[note1]test^[note2]
+^D
+[ Para
+    [ Note [ Para [ Str "note1" ] ]
+    , Str "test"
+    , Note [ Para [ Str "note2" ] ]
+    ]
+]
+
+```
diff --git a/test/command/8738.md b/test/command/8738.md
--- a/test/command/8738.md
+++ b/test/command/8738.md
@@ -2,5 +2,5 @@
 % pandoc -f native -t mediawiki
 [Link ("",[],[]) [Link ("",[],[]) [Str "test"] ("https://bar.example.com",""),Str "Test"] ("https://foo.example.com","")]
 ^D
-[https://foo.example.com testTest]
+[https://foo.example.com <span>test</span>Test]
 ```
diff --git a/test/command/9002.md b/test/command/9002.md
--- a/test/command/9002.md
+++ b/test/command/9002.md
@@ -1,11 +1,11 @@
 ```
 % pandoc command/9002.docx -t html
 ^D
-<table>
+<table style="width:40%;">
 <caption><p>This is my table!</p></caption>
 <colgroup>
-<col style="width: 50%" />
-<col style="width: 50%" />
+<col style="width: 20%" />
+<col style="width: 20%" />
 </colgroup>
 <thead>
 <tr>
diff --git a/test/command/9350.md b/test/command/9350.md
--- a/test/command/9350.md
+++ b/test/command/9350.md
@@ -2,6 +2,7 @@
 % pandoc -f html -t latex
 <table><tbody><tr></tr></tbody></table>
 ^D
+{\def\LTcaptype{} % do not increment counter
 \begin{longtable}[]{@{}l@{}}
 \toprule\noalign{}
 \endhead
@@ -9,4 +10,5 @@
 \endlastfoot
  \\
 \end{longtable}
+}
 ```
diff --git a/test/command/9472.md b/test/command/9472.md
--- a/test/command/9472.md
+++ b/test/command/9472.md
@@ -49,9 +49,9 @@
   \KOMAoptions{parskip=half}}
 \makeatother
 \ifLuaTeX
-\usepackage[bidi=basic,shorthands=off,]{babel}
+\usepackage[bidi=basic,shorthands=off]{babel}
 \else
-\usepackage[bidi=default,shorthands=off,]{babel}
+\usepackage[bidi=default,shorthands=off]{babel}
 \fi
 \ifLuaTeX
   \usepackage{selnolig} % disable illegal ligatures
diff --git a/test/command/rst_block_subst.md b/test/command/rst_block_subst.md
--- a/test/command/rst_block_subst.md
+++ b/test/command/rst_block_subst.md
@@ -11,9 +11,7 @@
     (Caption Nothing [ Plain [ Str "capt" ] ])
     [ Plain
         [ Image
-            ( "" , [] , [] )
-            [ Str "img/dummy.png" ]
-            ( "img/dummy.png" , "" )
+            ( "" , [] , [] ) [ Str "capt" ] ( "img/dummy.png" , "" )
         ]
     ]
 ]
diff --git a/test/djot-reader.native b/test/djot-reader.native
--- a/test/djot-reader.native
+++ b/test/djot-reader.native
@@ -98,7 +98,7 @@
           [ Para [ Str "Code in a block quote:" ]
           , CodeBlock
               ( "" , [ "" ] , [] )
-              "sub status {\nprint \"working\";\n}\n"
+              "sub status {\n    print \"working\";\n}\n"
           , Para [ Str "A list:" ]
           , OrderedList
               ( 1 , Decimal , Period )
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,52 +1,146 @@
-[Table ("",[],[]) (Caption Nothing
- [])
- [(AlignDefault,ColWidth 1.0)]
- (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,Link ("",[],[]) [Str "iv"] ("#figures","")]
-,Para [Str "TABLES",Space,Link ("",[],[]) [Str "v"] ("#tables","")]
-,Para [Str "SECTION",Space,Str "1",Space,Str "Introduction",Space,Link ("",[],[]) [Str "2"] ("#introduction","")]
-,Header 1 ("figures",["Heading-0"],[]) [Str "FIGURES"]
-,Para [Strong [Str "Figure",Space,Str "Page"]]
-,Para [Strong [Str "No",Space,Str "table",Space,Str "of",Space,Str "figures",Space,Str "entries",Space,Str "found."]]
-,Header 1 ("tables",["Heading-0"],[]) [Str "TABLES"]
-,Para [Strong [Str "Table",Space,Str "Page"]]
-,Para [Strong [Str "No",Space,Str "table",Space,Str "of",Space,Str "figures",Space,Str "entries",Space,Str "found."]]
-,Header 1 ("introduction",[],[]) [Str "Introduction"]
-,Para [Str "Nothing",Space,Str "to",Space,Str "introduce,",Space,Str "yet."]]
+[ Table
+    ( "" , [] , [] )
+    (Caption Nothing [])
+    [ ( AlignDefault , ColWidth 0.8615384615384616 ) ]
+    (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
+    , Link ( "" , [] , [] ) [ Str "iv" ] ( "#figures" , "" )
+    ]
+, Para
+    [ Str "TABLES"
+    , Space
+    , Link ( "" , [] , [] ) [ Str "v" ] ( "#tables" , "" )
+    ]
+, Para
+    [ Str "SECTION"
+    , Space
+    , Str "1"
+    , Space
+    , Str "Introduction"
+    , Space
+    , Link ( "" , [] , [] ) [ Str "2" ] ( "#introduction" , "" )
+    ]
+, Header
+    1 ( "figures" , [ "Heading-0" ] , [] ) [ Str "FIGURES" ]
+, Para [ Strong [ Str "Figure" , Space , Str "Page" ] ]
+, Para
+    [ Strong
+        [ Str "No"
+        , Space
+        , Str "table"
+        , Space
+        , Str "of"
+        , Space
+        , Str "figures"
+        , Space
+        , Str "entries"
+        , Space
+        , Str "found."
+        ]
+    ]
+, Header
+    1 ( "tables" , [ "Heading-0" ] , [] ) [ Str "TABLES" ]
+, Para [ Strong [ Str "Table" , Space , Str "Page" ] ]
+, Para
+    [ Strong
+        [ Str "No"
+        , Space
+        , Str "table"
+        , Space
+        , Str "of"
+        , Space
+        , Str "figures"
+        , Space
+        , Str "entries"
+        , Space
+        , Str "found."
+        ]
+    ]
+, Header
+    1 ( "introduction" , [] , [] ) [ Str "Introduction" ]
+, Para
+    [ Str "Nothing"
+    , Space
+    , Str "to"
+    , Space
+    , Str "introduce,"
+    , Space
+    , Str "yet."
+    ]
+]
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/sdt_elements.native b/test/docx/sdt_elements.native
--- a/test/docx/sdt_elements.native
+++ b/test/docx/sdt_elements.native
@@ -1,24 +1,60 @@
-[Table ("",[],[]) (Caption Nothing
- [])
- [(AlignDefault,ColWidth 0.22069570301081556)
- ,(AlignDefault,ColWidth 0.22069570301081556)
- ,(AlignDefault,ColWidth 0.5586085939783689)]
- (TableHead ("",[],[])
- [Row ("",[],[])
-   [Cell ("",[],[]) AlignCenter (RowSpan 1) (ColSpan 1)
-    [Plain [Strong [Str "col1Header"]]]
-   ,Cell ("",[],[]) AlignCenter (RowSpan 1) (ColSpan 1)
-    [Plain [Strong [Str "col2Header"]]]
-   ,Cell ("",[],[]) AlignCenter (RowSpan 1) (ColSpan 1)
-    [Plain [Strong [Str "col3Header"]]]]])
- [(TableBody ("",[],[]) (RowHeadColumns 0)
-  []
-  [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 ("",[],[])
- [])]
+[ Table
+    ( "" , [] , [] )
+    (Caption Nothing [])
+    [ ( AlignDefault , ColWidth 0.16167023554603854 )
+    , ( AlignDefault , ColWidth 0.16167023554603854 )
+    , ( AlignDefault , ColWidth 0.40920770877944324 )
+    ]
+    (TableHead
+       ( "" , [] , [] )
+       [ Row
+           ( "" , [] , [] )
+           [ Cell
+               ( "" , [] , [] )
+               AlignCenter
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Strong [ Str "col1Header" ] ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignCenter
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Strong [ Str "col2Header" ] ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignCenter
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Strong [ Str "col3Header" ] ] ]
+           ]
+       ])
+    [ TableBody
+        ( "" , [] , [] )
+        (RowHeadColumns 0)
+        []
+        [ 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_captions_no_field.native b/test/docx/table_captions_no_field.native
--- a/test/docx/table_captions_no_field.native
+++ b/test/docx/table_captions_no_field.native
@@ -1,33 +1,81 @@
-[Para [Str "See",Space,Str "Table",Space,Str "5.1."]
-,Table ("",[],[])
- (Caption Nothing [ Para [ Str "Table" , Space , Str "5.1" ] ])
- [(AlignDefault,ColWidth 0.7605739372523825)
- ,(AlignDefault,ColWidth 0.11971303137380876)
- ,(AlignDefault,ColWidth 0.11971303137380876)]
- (TableHead ("",[],[])
-[Row ("",[],[])
- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-  []
- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-  [Plain [Str "Count"]]
- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-  [Plain [Str "%"]]]])
- [(TableBody ("",[],[]) (RowHeadColumns 0)
-  []
-  [Row ("",[],[])
- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-  [Plain [Str "First",Space,Str "option"]]
- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-  [Plain [Str "242"]]
- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-  [Plain [Str "45"]]]
-,Row ("",[],[])
- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-  [Plain [Str "Second",Space,Str "option"]]
- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-  [Plain [Str "99"]]
- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-  [Plain [Str "18"]]]])]
- (TableFoot ("",[],[])
- [])
-,Header 2 ("section", [], []) []]
+[ Para
+    [ Str "See" , Space , Str "Table" , Space , Str "5.1." ]
+, Table
+    ( "" , [] , [] )
+    (Caption
+       Nothing [ Para [ Str "Table" , Space , Str "5.1" ] ])
+    [ ( AlignDefault , ColWidth 0.7605739372523824 )
+    , ( AlignDefault , ColWidth 0.11971303137380876 )
+    , ( AlignDefault , ColWidth 0.11971303137380876 )
+    ]
+    (TableHead
+       ( "" , [] , [] )
+       [ Row
+           ( "" , [] , [] )
+           [ Cell
+               ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "Count" ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "%" ] ]
+           ]
+       ])
+    [ TableBody
+        ( "" , [] , [] )
+        (RowHeadColumns 0)
+        []
+        [ Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "First" , Space , Str "option" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "242" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "45" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "Second" , Space , Str "option" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "99" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "18" ] ]
+            ]
+        ]
+    ]
+    (TableFoot ( "" , [] , [] ) [])
+, Header 2 ( "section" , [] , [] ) []
+]
diff --git a/test/docx/table_captions_with_field.native b/test/docx/table_captions_with_field.native
--- a/test/docx/table_captions_with_field.native
+++ b/test/docx/table_captions_with_field.native
@@ -1,52 +1,115 @@
-[Para [Str "See",Space,Str "Table",Space,Str "1."]
-,Table ("",[],[])
- (Caption Nothing [ Para [ Str "Table" , Space , Str "1" ] ])
- [(AlignDefault,ColWidth 0.7605739372523825)
- ,(AlignDefault,ColWidth 0.11971303137380876)
- ,(AlignDefault,ColWidth 0.11971303137380876)]
- (TableHead ("",[],[])
-[Row ("",[],[])
- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-  []
- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-  [Plain [Str "Count"]]
- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-  [Plain [Str "%"]]]])
- [(TableBody ("",[],[]) (RowHeadColumns 0)
-  []
-  [Row ("",[],[])
- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-  [Plain [Str "First",Space,Str "option"]]
- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-  [Plain [Str "242"]]
- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-  [Plain [Str "45"]]]
-,Row ("",[],[])
- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-  [Plain [Str "Second",Space,Str "option"]]
- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-  [Plain [Str "99"]]
- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-  [Plain [Str "18"]]]])]
- (TableFoot ("",[],[])
- [])
-,Header 2 ("section", [], []) []
-,Table ("",[],[])
- (Caption Nothing [Para [Str "Table", Space, Str "2"]])
- [(AlignDefault,ColWidth 0.3332963620230701)
- ,(AlignDefault,ColWidth 0.3332963620230701)
- ,(AlignDefault,ColWidth 0.3334072759538598)]
- (TableHead ("",[],[])
- [Row ("",[],[])
-  [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-   [Plain [Str "One"]]
-  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-   [Plain [Str "Two"]]
-  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-   [Plain [Str "Three"]]]])
- [(TableBody ("",[],[]) (RowHeadColumns 0)
-  []
-  [])]
- (TableFoot ("",[],[])
- [])
-,Para [Str "See",Space,Str "Table",Space,Str "2."]]
+[ Para
+    [ Str "See" , Space , Str "Table" , Space , Str "1." ]
+, Table
+    ( "" , [] , [] )
+    (Caption Nothing [ Para [ Str "Table" , Space , Str "1" ] ])
+    [ ( AlignDefault , ColWidth 0.7605739372523824 )
+    , ( AlignDefault , ColWidth 0.11971303137380876 )
+    , ( AlignDefault , ColWidth 0.11971303137380876 )
+    ]
+    (TableHead
+       ( "" , [] , [] )
+       [ Row
+           ( "" , [] , [] )
+           [ Cell
+               ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "Count" ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "%" ] ]
+           ]
+       ])
+    [ TableBody
+        ( "" , [] , [] )
+        (RowHeadColumns 0)
+        []
+        [ Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "First" , Space , Str "option" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "242" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "45" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "Second" , Space , Str "option" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "99" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "18" ] ]
+            ]
+        ]
+    ]
+    (TableFoot ( "" , [] , [] ) [])
+, Header 2 ( "section" , [] , [] ) []
+, Table
+    ( "" , [] , [] )
+    (Caption Nothing [ Para [ Str "Table" , Space , Str "2" ] ])
+    [ ( AlignDefault , ColWidth 0.33329636202307006 )
+    , ( AlignDefault , ColWidth 0.33329636202307006 )
+    , ( AlignDefault , ColWidth 0.33340727595385977 )
+    ]
+    (TableHead
+       ( "" , [] , [] )
+       [ Row
+           ( "" , [] , [] )
+           [ Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "One" ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "Two" ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "Three" ] ]
+           ]
+       ])
+    [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]
+    (TableFoot ( "" , [] , [] ) [])
+, Para
+    [ Str "See" , Space , Str "Table" , Space , Str "2." ]
+]
diff --git a/test/docx/table_header_rowspan.native b/test/docx/table_header_rowspan.native
--- a/test/docx/table_header_rowspan.native
+++ b/test/docx/table_header_rowspan.native
@@ -1,189 +1,542 @@
-[Table ("",[],[]) (Caption Nothing
- [])
- [(AlignLeft,ColWidth 0.30701754385964913)
- ,(AlignDefault,ColWidth 0.1364522417153996)
- ,(AlignDefault,ColWidth 0.10009746588693957)
- ,(AlignDefault,ColWidth 9.707602339181287e-2)
- ,(AlignDefault,ColWidth 7.719298245614035e-2)
- ,(AlignDefault,ColWidth 7.085769980506823e-2)
- ,(AlignDefault,ColWidth 7.09551656920078e-2)
- ,(AlignDefault,ColWidth 0.14035087719298245)]
- (TableHead ("",[],[])
-[Row ("",[],[])
- [Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1)
-  [Plain [Str "A"]]
- ,Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1)
-  [Plain [Strong [Str "B"]]]
- ,Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1)
-  [Plain [Strong [Str "C"]]]
- ,Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1)
-  [Plain [Strong [Str "D"]]]
- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 3)
-  [Plain [Str "E"]]
- ,Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1)
-  [Plain [Str "F"]]]
-,Row ("",[],[])
- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-  [Plain [Strong [Str "G"]]]
- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-  [Plain [Strong [Str "H"]]]
- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-  [Plain [Strong [Str "I"]]]]])
- [(TableBody ("",[],[]) (RowHeadColumns 0)
-  []
-  [Row ("",[],[])
-   [Cell ("",[],[]) AlignLeft (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"]]]
-  ,Row ("",[],[])
-   [Cell ("",[],[]) AlignLeft (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"]]]
-  ,Row ("",[],[])
-   [Cell ("",[],[]) AlignLeft (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"]]]
-  ,Row ("",[],[])
-   [Cell ("",[],[]) AlignLeft (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"]]]
-  ,Row ("",[],[])
-   [Cell ("",[],[]) AlignLeft (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"]]]
-  ,Row ("",[],[])
-   [Cell ("",[],[]) AlignLeft (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"]]]
-  ,Row ("",[],[])
-   [Cell ("",[],[]) AlignLeft (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"]]]
-  ,Row ("",[],[])
-   [Cell ("",[],[]) AlignLeft (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"]]]
-  ,Row ("",[],[])
-   [Cell ("",[],[]) AlignLeft (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"]]]
-  ])]
- (TableFoot ("",[],[])
- [])]
+[ Table
+    ( "" , [] , [] )
+    (Caption Nothing [])
+    [ ( AlignLeft , ColWidth 0.30701754385964913 )
+    , ( AlignDefault , ColWidth 0.13645224171539963 )
+    , ( AlignDefault , ColWidth 0.10009746588693959 )
+    , ( AlignDefault , ColWidth 9.707602339181289e-2 )
+    , ( AlignDefault , ColWidth 7.719298245614035e-2 )
+    , ( AlignDefault , ColWidth 7.085769980506823e-2 )
+    , ( AlignDefault , ColWidth 7.09551656920078e-2 )
+    , ( AlignDefault , ColWidth 0.14035087719298248 )
+    ]
+    (TableHead
+       ( "" , [] , [] )
+       [ Row
+           ( "" , [] , [] )
+           [ Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 2)
+               (ColSpan 1)
+               [ Plain [ Str "A" ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 2)
+               (ColSpan 1)
+               [ Plain [ Strong [ Str "B" ] ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 2)
+               (ColSpan 1)
+               [ Plain [ Strong [ Str "C" ] ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 2)
+               (ColSpan 1)
+               [ Plain [ Strong [ Str "D" ] ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 3)
+               [ Plain [ Str "E" ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 2)
+               (ColSpan 1)
+               [ Plain [ Str "F" ] ]
+           ]
+       , Row
+           ( "" , [] , [] )
+           [ Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Strong [ Str "G" ] ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Strong [ Str "H" ] ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Strong [ Str "I" ] ] ]
+           ]
+       ])
+    [ TableBody
+        ( "" , [] , [] )
+        (RowHeadColumns 0)
+        []
+        [ Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignLeft
+                (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" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignLeft
+                (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" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignLeft
+                (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" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignLeft
+                (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" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignLeft
+                (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" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignLeft
+                (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" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignLeft
+                (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" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignLeft
+                (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" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignLeft
+                (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" ] ]
+            ]
+        ]
+    ]
+    (TableFoot ( "" , [] , [] ) [])
+]
diff --git a/test/docx/table_one_header_row.native b/test/docx/table_one_header_row.native
--- a/test/docx/table_one_header_row.native
+++ b/test/docx/table_one_header_row.native
@@ -1,18 +1,34 @@
-[Table ("",[],[]) (Caption Nothing
- [])
- [(AlignDefault,ColWidth 0.33302433371958284)
- ,(AlignDefault,ColWidth 0.3332560834298957)
- ,(AlignDefault,ColWidth 0.33371958285052145)]
- (TableHead ("",[],[])
- [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"]]]])
- [(TableBody ("",[],[]) (RowHeadColumns 0)
-  []
-  [])]
- (TableFoot ("",[],[])
- [])]
+[ Table
+    ( "" , [] , [] )
+    (Caption Nothing [])
+    [ ( AlignDefault , ColWidth 0.3330243337195829 )
+    , ( AlignDefault , ColWidth 0.33325608342989577 )
+    , ( AlignDefault , ColWidth 0.33371958285052145 )
+    ]
+    (TableHead
+       ( "" , [] , [] )
+       [ 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" ] ]
+           ]
+       ])
+    [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]
+    (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,18 +1,37 @@
-[Table ("",[],[]) (Caption Nothing
- [])
- [(AlignDefault,ColWidth 0.3333333333333333)
- ,(AlignDefault,ColWidth 0.3333333333333333)
- ,(AlignDefault,ColWidth 0.3333333333333333)]
- (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 ("",[],[])
- [])]
+[ Table
+    ( "" , [] , [] )
+    (Caption Nothing [])
+    [ ( AlignDefault , ColWidth 0.33333333333333337 )
+    , ( AlignDefault , ColWidth 0.33333333333333337 )
+    , ( AlignDefault , ColWidth 0.33333333333333337 )
+    ]
+    (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,40 +1,78 @@
-[Table ("",[],[]) (Caption Nothing
- [])
- [(AlignDefault,ColWidth 2.0096205237840725e-2)
- ,(AlignDefault,ColWidth 1.9882415820416888e-2)
- ,(AlignDefault,ColWidth 0.22202030999465527)
- ,(AlignDefault,ColWidth 0.4761090326028862)
- ,(AlignDefault,ColWidth 1.0689470871191876e-4)
- ,(AlignDefault,ColWidth 0.26178514163548905)]
- (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 2)
-   [Plain [Str "h4"]]
-  ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-   [Plain [Str "h5"]]]])
- [(TableBody ("",[],[]) (RowHeadColumns 0)
-  []
-  [Row ("",[],[])
-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 3)
-    [Plain [Str "c11"]]
-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-    []
-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 2)
-    []]
-  ,Row ("",[],[])
-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-    []
-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 2)
-    [Plain [Str "c22"]]
-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
-    [Plain [Str "c23"]]
-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 2)
-    []]])]
- (TableFoot ("",[],[])
- [])]
+[ Table
+    ( "" , [] , [] )
+    (Caption Nothing [])
+    [ ( AlignDefault , ColWidth 1.9673503557974047e-2 )
+    , ( AlignDefault , ColWidth 1.946421096693177e-2 )
+    , ( AlignDefault , ColWidth 0.21735035579740478 )
+    , ( AlignDefault , ColWidth 0.4660946002511511 )
+    , ( AlignDefault , ColWidth 1.0464629552113855e-4 )
+    , ( AlignDefault , ColWidth 0.25627877773126834 )
+    ]
+    (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 2)
+               [ Plain [ Str "h4" ] ]
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 1)
+               [ Plain [ Str "h5" ] ]
+           ]
+       ])
+    [ TableBody
+        ( "" , [] , [] )
+        (RowHeadColumns 0)
+        []
+        [ Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 3)
+                [ Plain [ Str "c11" ] ]
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 2) []
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 2)
+                [ Plain [ Str "c22" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "c23" ] ]
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 2) []
+            ]
+        ]
+    ]
+    (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,25 +1,72 @@
-[Table ("",[],[]) (Caption Nothing
- [])
- [(AlignDefault,ColWidth 0.5)
- ,(AlignDefault,ColWidth 0.5)]
- (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 ("",[],[])
- [])]
+[ Table
+    ( "" , [] , [] )
+    (Caption Nothing [])
+    [ ( AlignDefault , ColWidth 0.5 )
+    , ( AlignDefault , ColWidth 0.5 )
+    ]
+    (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,92 +1,238 @@
-[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 ("",[],[]) (Caption Nothing
- [])
- [(AlignDefault,ColWidth 0.25)
- ,(AlignDefault,ColWidth 0.25)
- ,(AlignDefault,ColWidth 0.25)
- ,(AlignDefault,ColWidth 0.25)]
- (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,ColWidth 0.5)
- ,(AlignDefault,ColWidth 0.5)]
- (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,ColWidth 0.5)
- ,(AlignDefault,ColWidth 0.5)]
- (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 ("",[],[])
- [])]
+[ 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
+    ( "" , [] , [] )
+    (Caption Nothing [])
+    [ ( AlignDefault , ColWidth 0.25 )
+    , ( AlignDefault , ColWidth 0.25 )
+    , ( AlignDefault , ColWidth 0.25 )
+    , ( AlignDefault , ColWidth 0.25 )
+    ]
+    (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 , ColWidth 0.5 )
+    , ( AlignDefault , ColWidth 0.5 )
+    ]
+    (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 , ColWidth 0.5 )
+    , ( AlignDefault , ColWidth 0.5 )
+    ]
+    (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/pptx/single-column/image/input.native b/test/pptx/single-column/image/input.native
new file mode 100644
--- /dev/null
+++ b/test/pptx/single-column/image/input.native
@@ -0,0 +1,22 @@
+[ Header
+    1
+    ( "single-column" , [] , [] )
+    [ Str "Single" , Space , Str "column" ]
+, Div
+    ( "" , [ "columns" ] , [] )
+    [ Div
+        ( "" , [ "column" ] , [] )
+        [ Figure
+            ( "" , [] , [] )
+            (Caption
+               Nothing [ Plain [ Str "an" , Space , Str "image" ] ])
+            [ Plain
+                [ Image
+                    ( "" , [] , [] )
+                    [ Str "an" , Space , Str "image" ]
+                    ( "lalune.jpg" , "" )
+                ]
+            ]
+        ]
+    ]
+]
diff --git a/test/pptx/single-column/image/output.pptx b/test/pptx/single-column/image/output.pptx
new file mode 100644
Binary files /dev/null and b/test/pptx/single-column/image/output.pptx differ
diff --git a/test/pptx/single-column/image/templated.pptx b/test/pptx/single-column/image/templated.pptx
new file mode 100644
Binary files /dev/null and b/test/pptx/single-column/image/templated.pptx differ
diff --git a/test/pptx/single-column/text/input.native b/test/pptx/single-column/text/input.native
new file mode 100644
--- /dev/null
+++ b/test/pptx/single-column/text/input.native
@@ -0,0 +1,13 @@
+[ Header
+    1
+    ( "single-column" , [] , [] )
+    [ Str "Single" , Space , Str "column" ]
+, Div
+    ( "" , [ "columns" ] , [] )
+    [ Div
+        ( "" , [ "column" ] , [] )
+        [ Para [ Str "One" , Space , Str "paragraph." ]
+        , Para [ Str "Another" , Space , Str "paragraph." ]
+        ]
+    ]
+]
diff --git a/test/pptx/single-column/text/output.pptx b/test/pptx/single-column/text/output.pptx
new file mode 100644
Binary files /dev/null and b/test/pptx/single-column/text/output.pptx differ
diff --git a/test/pptx/single-column/text/templated.pptx b/test/pptx/single-column/text/templated.pptx
new file mode 100644
Binary files /dev/null and b/test/pptx/single-column/text/templated.pptx differ
diff --git a/test/tables.latex b/test/tables.latex
--- a/test/tables.latex
+++ b/test/tables.latex
@@ -19,6 +19,7 @@
 
 Simple table without caption:
 
+{\def\LTcaptype{} % do not increment counter
 \begin{longtable}[]{@{}rlcl@{}}
 \toprule\noalign{}
 Right & Left & Center & Default \\
@@ -30,6 +31,7 @@
 123 & 123 & 123 & 123 \\
 1 & 1 & 1 & 1 \\
 \end{longtable}
+}
 
 Simple table indented two spaces:
 
@@ -90,6 +92,7 @@
 
 Multiline table without caption:
 
+{\def\LTcaptype{} % do not increment counter
 \begin{longtable}[]{@{}
   >{\centering\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1500}}
   >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1375}}
@@ -112,9 +115,11 @@
 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. \\
 \end{longtable}
+}
 
 Table without column headers:
 
+{\def\LTcaptype{} % do not increment counter
 \begin{longtable}[]{@{}rlcr@{}}
 \toprule\noalign{}
 \endhead
@@ -124,9 +129,11 @@
 123 & 123 & 123 & 123 \\
 1 & 1 & 1 & 1 \\
 \end{longtable}
+}
 
 Multiline table without column headers:
 
+{\def\LTcaptype{} % do not increment counter
 \begin{longtable}[]{@{}
   >{\centering\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1500}}
   >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1375}}
@@ -139,3 +146,4 @@
 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. \\
 \end{longtable}
+}
diff --git a/test/tables.vimdoc b/test/tables.vimdoc
new file mode 100644
--- /dev/null
+++ b/test/tables.vimdoc
@@ -0,0 +1,65 @@
+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.
+
+Simple table without caption:
+
+      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.
+
+Multiline table with caption:
+
+     Centered  Left           Right Default aligned
+      Header   Aligned      Aligned  ~
+
+      First    row             12.0 Example of a row that
+                                    spans multiple lines.
+
+      Second   row              5.0 Here's another one.
+                                    Note the blank line
+                                    between rows.
+
+    Here's the caption. It may span multiple lines.
+
+Multiline table without caption:
+
+     Centered  Left           Right Default aligned
+      Header   Aligned      Aligned  ~
+
+      First    row             12.0 Example of a row that
+                                    spans multiple lines.
+
+      Second   row              5.0 Here's another one.
+                                    Note the blank line
+                                    between rows.
+
+Table without column headers:
+
+       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.
diff --git a/test/vimdoc/definition-lists.markdown b/test/vimdoc/definition-lists.markdown
new file mode 100644
--- /dev/null
+++ b/test/vimdoc/definition-lists.markdown
@@ -0,0 +1,70 @@
+---
+vimdoc-prefix: pandoc
+abstract: "A short description"
+filename: "definition-lists.txt"
+author: Author
+title: Title
+---
+
+## Basic
+
+Term 1
+:   Definition I
+
+Term 2
+:   Definition II
+
+Term 3
+:   Definition III
+
+## Code
+
+<!-- Source: <https://github.com/ggandor/leap.nvim/blob/c4a215acef90749851d85ddba08bc282867b50eb/doc/leap.txt#L283-L294> -->
+
+`leap.opts.keys.next_target`
+: Jump to the next available target (use the previous search pattern if no input
+  has been given). `:h leap-repeat`
+
+`leap.opts.keys.prev_target`
+: Jump to the previous target (revert `next_target`).
+
+`leap.opts.keys.next_group`
+: Shift to the next group of labeled targets.
+
+`leap.opts.keys.prev_group`
+: Shift to the previous group of labeled targets (revert `next_group`).
+
+## Span
+
+[Important concept]{#important-concept}
+: Definition
+
+[I am too long to fit on the same line as a reference, so reference is put above me!]{#i-am-too-long}
+: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
+  tempor incididunt ut labore et dolore magna aliqua.
+
+## Commands
+
+In markdown vim commands are represented as inline code starting with colon (ie.
+`:MyCommand`), but writer strips the backticks
+
+`:FnlCompileBuffer`{#:FnlCompileBuffer}
+
+:   Compiles current active fennel buffer
+
+`:FnlCompile[!]`{#:FnlCompile}
+
+:   Diff compiles all indexed fennel files
+    If bang! is present then forcefully compiles all `source` files
+
+`:[range]Fnl {expr}`{#:Fnl}
+
+:    Evaluates {expr} or range
+
+     ```
+     :'<,'>Fnl
+
+     :Fnl (print "Hello World")
+
+     :Fnl (values some_var)
+     ```
diff --git a/test/vimdoc/definition-lists.vimdoc b/test/vimdoc/definition-lists.vimdoc
new file mode 100644
--- /dev/null
+++ b/test/vimdoc/definition-lists.vimdoc
@@ -0,0 +1,71 @@
+*definition-lists.txt*	A short description
+
+                               Title by Author
+
+
+                                       Type |gO| to see the table of contents.
+
+Basic ........................................................... |pandoc-basic|
+Code ............................................................. |pandoc-code|
+Span ............................................................. |pandoc-span|
+Commands ..................................................... |pandoc-commands|
+
+------------------------------------------------------------------------------
+Basic                                                             *pandoc-basic*
+
+Term 1
+    Definition I
+Term 2
+    Definition II
+Term 3
+    Definition III
+
+------------------------------------------------------------------------------
+Code                                                               *pandoc-code*
+
+`leap.opts.keys.next_target`
+    Jump to the next available target (use the previous search pattern if no
+    input has been given). |leap-repeat|
+`leap.opts.keys.prev_target`
+    Jump to the previous target (revert `next_target`).
+`leap.opts.keys.next_group`
+    Shift to the next group of labeled targets.
+`leap.opts.keys.prev_group`
+    Shift to the previous group of labeled targets (revert `next_group`).
+
+------------------------------------------------------------------------------
+Span                                                               *pandoc-span*
+
+Important concept                                     *pandoc-important-concept*
+    Definition
+                                                          *pandoc-i-am-too-long*
+I am too long to fit on the same line as a reference, so reference is put
+above me!
+    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
+    tempor incididunt ut labore et dolore magna aliqua.
+
+------------------------------------------------------------------------------
+Commands                                                       *pandoc-commands*
+
+In markdown vim commands are represented as inline code starting with colon
+(ie. `:MyCommand`), but writer strips the backticks
+
+:FnlCompileBuffer                                            *:FnlCompileBuffer*
+    Compiles current active fennel buffer
+
+:FnlCompile[!]                                                     *:FnlCompile*
+    Diff compiles all indexed fennel files If bang! is present then forcefully
+    compiles all `source` files
+
+:[range]Fnl {expr}                                                        *:Fnl*
+    Evaluates {expr} or range
+
+    >
+        :'<,'>Fnl
+
+        :Fnl (print "Hello World")
+
+        :Fnl (values some_var)
+<
+
+ vim:tw=78:sw=4:ts=4:ft=help:norl:et:
diff --git a/test/vimdoc/headers-numbered.vimdoc b/test/vimdoc/headers-numbered.vimdoc
new file mode 100644
--- /dev/null
+++ b/test/vimdoc/headers-numbered.vimdoc
@@ -0,0 +1,108 @@
+                                       Type |gO| to see the table of contents.
+
+1. unremarkable header 1 ............................... |unremarkable-header-1|
+  1.1 unremarkable header 2 ............................ |unremarkable-header-2|
+      1.1.1 unremarkable header 3 ...................... |unremarkable-header-3|
+      1.1.2 unremarkable header 3 .................... |unremarkable-header-3-1|
+  unremarkable header 2 .............................. |unremarkable-header-2-1|
+    unremarkable header 3 ............................ |unremarkable-header-3-2|
+    unremarkable header 3 ............................ |unremarkable-header-3-3|
+2. bold italic underline strikethrough ............................... |short11|
+  2.1 superscript2 subscript3 ........................................ |short21|
+      2.1.1 smallcaps code inline math display math .................. |short31|
+      2.1.2 link image ............................................... |short32|
+3. Long header 1 long header 1 long header 1 long header 1 long heade... |long1|
+  3.1 Long header 2 long header 2 long header 2 long header 2 long h... |long21|
+      3.1.1 Long header 3 long header 3 long header 3 long header 3.... |long31|
+      3.1.2 Long header 3 long header 3 long header 3 long header 3.... |long32|
+  3.2 Long header 2 long header 2 long header 2 long header 2 long h... |long22|
+      3.2.1 Long header 3 long header 3 long header 3 long header 3.... |long33|
+      3.2.2 Long header 3 long header 3 long header 3 long header 3.... |long34|
+4. ... |long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1|
+  4.1 ... |long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2|
+      4.1.1 ... |long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3|
+      4.1.2 ... |long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-1|
+  4.2 ... |long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-1|
+      4.2.1 ... |long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-2|
+      4.2.2 ... |long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-3|
+
+
+Headers with a short title and implicit ref. Last 3 headers are unnumbered.
+
+==============================================================================
+unremarkable header 1                                    *unremarkable-header-1*
+
+------------------------------------------------------------------------------
+unremarkable header 2                                    *unremarkable-header-2*
+
+UNREMARKABLE HEADER 3                                    *unremarkable-header-3*
+
+UNREMARKABLE HEADER 3                                  *unremarkable-header-3-1*
+
+------------------------------------------------------------------------------
+unremarkable header 2                                  *unremarkable-header-2-1*
+
+UNREMARKABLE HEADER 3                                  *unremarkable-header-3-2*
+
+UNREMARKABLE HEADER 3                                  *unremarkable-header-3-3*
+
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+Headers with various inline elements
+
+==============================================================================
+bold italic underline strikethrough                                    *short11*
+
+------------------------------------------------------------------------------
+superscript2 subscript3                                                *short21*
+
+SMALLCAPS `code` `$inline math$` `$display math$`                      *short31*
+
+LINK example.com                                                       *short32*
+
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+Headers with a long name and explicit short ref
+
+==============================================================================
+Long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 *long1*
+
+------------------------------------------------------------------------------
+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long21*
+
+LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long31*
+
+LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long32*
+
+------------------------------------------------------------------------------
+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long22*
+
+LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long33*
+
+LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long34*
+
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+Headers with a long name and implicit ref.
+
+Since implicit ref is very lengthy, there is no way to fit it. Therefore title
+is not rendered and the references exceed the columns (textwidth) limit
+
+==============================================================================
+Long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 *long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1*
+
+------------------------------------------------------------------------------
+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2*
+
+LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3*
+
+LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-1*
+
+------------------------------------------------------------------------------
+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-1*
+
+LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-2*
+
+LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-3*
+
+ vim:tw=78:sw=4:ts=4:ft=help:norl:et:
diff --git a/test/vimdoc/headers.markdown b/test/vimdoc/headers.markdown
new file mode 100644
--- /dev/null
+++ b/test/vimdoc/headers.markdown
@@ -0,0 +1,45 @@
+Headers with a short title and implicit ref. Last 3 headers are unnumbered.
+
+# unremarkable header 1
+## unremarkable header 2
+### unremarkable header 3
+### unremarkable header 3
+## unremarkable header 2 {.unnumbered}
+### unremarkable header 3 {.unnumbered}
+### unremarkable header 3 {.unnumbered}
+
+---
+
+Headers with various inline elements
+
+# **bold** *italic* [underline]{.underline} ~strikethrough~ {#short11}
+## superscript^2^ subscript~3~ {#short21}
+### [smallcaps]{.smallcaps} `code` $inline math$ $$display math$$ {#short31}
+### [link](example.com) ![image](https://duckduckgo.com/favicon.ico) {#short32}
+
+---
+
+Headers with a long name and explicit short ref
+
+# Long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 {#long1}
+## Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 {#long21}
+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 {#long31}
+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 {#long32}
+## Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 {#long22}
+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 {#long33}
+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 {#long34}
+
+---
+
+Headers with a long name and implicit ref.
+
+Since implicit ref is very lengthy, there is no way to fit it. Therefore title
+is not rendered and the references exceed the columns (textwidth) limit
+
+# Long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 long header 1
+## Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2
+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3
+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3
+## Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2
+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3
+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3
diff --git a/test/vimdoc/headers.vimdoc b/test/vimdoc/headers.vimdoc
new file mode 100644
--- /dev/null
+++ b/test/vimdoc/headers.vimdoc
@@ -0,0 +1,94 @@
+                                       Type |gO| to see the table of contents.
+
+unremarkable header 1 .................................. |unremarkable-header-1|
+  unremarkable header 2 ................................ |unremarkable-header-2|
+  unremarkable header 2 .............................. |unremarkable-header-2-1|
+bold italic underline strikethrough .................................. |short11|
+  superscript2 subscript3 ............................................ |short21|
+Long header 1 long header 1 long header 1 long header 1 long header 1... |long1|
+  Long header 2 long header 2 long header 2 long header 2 long heade... |long21|
+  Long header 2 long header 2 long header 2 long header 2 long heade... |long22|
+... |long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1|
+  ... |long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2|
+  ... |long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-1|
+
+
+Headers with a short title and implicit ref. Last 3 headers are unnumbered.
+
+==============================================================================
+unremarkable header 1                                    *unremarkable-header-1*
+
+------------------------------------------------------------------------------
+unremarkable header 2                                    *unremarkable-header-2*
+
+UNREMARKABLE HEADER 3                                    *unremarkable-header-3*
+
+UNREMARKABLE HEADER 3                                  *unremarkable-header-3-1*
+
+------------------------------------------------------------------------------
+unremarkable header 2                                  *unremarkable-header-2-1*
+
+UNREMARKABLE HEADER 3                                  *unremarkable-header-3-2*
+
+UNREMARKABLE HEADER 3                                  *unremarkable-header-3-3*
+
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+Headers with various inline elements
+
+==============================================================================
+bold italic underline strikethrough                                    *short11*
+
+------------------------------------------------------------------------------
+superscript2 subscript3                                                *short21*
+
+SMALLCAPS `code` `$inline math$` `$display math$`                      *short31*
+
+LINK example.com                                                       *short32*
+
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+Headers with a long name and explicit short ref
+
+==============================================================================
+Long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 *long1*
+
+------------------------------------------------------------------------------
+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long21*
+
+LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long31*
+
+LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long32*
+
+------------------------------------------------------------------------------
+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long22*
+
+LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long33*
+
+LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long34*
+
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+Headers with a long name and implicit ref.
+
+Since implicit ref is very lengthy, there is no way to fit it. Therefore title
+is not rendered and the references exceed the columns (textwidth) limit
+
+==============================================================================
+Long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 *long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1*
+
+------------------------------------------------------------------------------
+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2*
+
+LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3*
+
+LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-1*
+
+------------------------------------------------------------------------------
+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-1*
+
+LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-2*
+
+LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-3*
+
+ vim:tw=78:sw=4:ts=4:ft=help:norl:et:
diff --git a/test/vimdoc/vim-online-doc.markdown b/test/vimdoc/vim-online-doc.markdown
new file mode 100644
--- /dev/null
+++ b/test/vimdoc/vim-online-doc.markdown
@@ -0,0 +1,42 @@
+# Online vim documentation
+
+While vim documentation can be accessed with `:help`, it may be beneficial to
+link to the websites inside readme/markdown docs. Two most common websites are:
+
+- <https://vimhelp.org/> and
+- <https://neovim.io/doc/user>
+
+Also it is not uncommon to reference documentation as `:h <topic>`
+
+## Links to vimhelp.org {#vimhelp-links}
+
+For introduction to writing help files see
+<https://vimhelp.org/helphelp.txt.html#help-writing>
+
+Named link: [vimhelp link](https://vimhelp.org/helphelp.txt.html#help-writing)
+
+## Links to neo.vimhelp.org {#neo-vimhelp-links}
+
+For introduction to writing help files see
+<https://neo.vimhelp.org/helphelp.txt.html#help-writing>
+
+Named link: [vimhelp link](https://neo.vimhelp.org/helphelp.txt.html#help-writing)
+
+## Links to neovim.io {#neovim-io-links}
+
+For introduction to writing help files see
+<https://neovim.io/doc/user/helphelp.html#help-writing>
+
+Named link: [neovim.io link](https://neovim.io/doc/user/helphelp.html#help-writing)
+
+You can also reference whole files with topic omitted:
+<https://neovim.io/doc/user/vim_diff.html>
+
+## :h-style documentation {#colon-h-docs}
+
+For introduction to writing help files see
+`:h help-writing`
+
+Long name for `:help` is also supported: `:help help-writing`
+
+This is malformed: `:help help-writing `, but this is not: `:help  help-writing`
diff --git a/test/vimdoc/vim-online-doc.vimdoc b/test/vimdoc/vim-online-doc.vimdoc
new file mode 100644
--- /dev/null
+++ b/test/vimdoc/vim-online-doc.vimdoc
@@ -0,0 +1,53 @@
+                                       Type |gO| to see the table of contents.
+
+Online vim documentation ............................ |online-vim-documentation|
+  Links to vimhelp.org ......................................... |vimhelp-links|
+  Links to neo.vimhelp.org ................................. |neo-vimhelp-links|
+  Links to neovim.io ......................................... |neovim-io-links|
+  :h-style documentation ........................................ |colon-h-docs|
+
+==============================================================================
+Online vim documentation                              *online-vim-documentation*
+
+While vim documentation can be accessed with `:help`, it may be beneficial to
+link to the websites inside readme/markdown docs. Two most common websites
+are:
+
+- https://vimhelp.org/ and
+- https://neovim.io/doc/user
+
+Also it is not uncommon to reference documentation as |<topic>|
+
+------------------------------------------------------------------------------
+Links to vimhelp.org                                             *vimhelp-links*
+
+For introduction to writing help files see |help-writing|
+
+Named link: vimhelp link |help-writing|
+
+------------------------------------------------------------------------------
+Links to neo.vimhelp.org                                     *neo-vimhelp-links*
+
+For introduction to writing help files see |help-writing|
+
+Named link: vimhelp link |help-writing|
+
+------------------------------------------------------------------------------
+Links to neovim.io                                             *neovim-io-links*
+
+For introduction to writing help files see |help-writing|
+
+Named link: neovim.io link |help-writing|
+
+You can also reference whole files with topic omitted: |vim_diff.txt|
+
+------------------------------------------------------------------------------
+:h-style documentation                                            *colon-h-docs*
+
+For introduction to writing help files see |help-writing|
+
+Long name for `:help` is also supported: |help-writing|
+
+This is malformed: |help-writing|, but this is not: |help-writing|
+
+ vim:tw=78:sw=4:ts=4:ft=help:norl:et:
diff --git a/test/writer.vimdoc b/test/writer.vimdoc
new file mode 100644
--- /dev/null
+++ b/test/writer.vimdoc
@@ -0,0 +1,669 @@
+                Pandoc Test Suite by John MacFarlane, Anonymous
+
+
+                                         Type |gO| to see the table of contents.
+
+
+This is a set of tests for pandoc. Most of them are adapted from John Gruber's
+markdown test suite.
+
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+================================================================================
+Headers                                                                  *headers*
+
+--------------------------------------------------------------------------------
+Level 2 with an embedded link /url                 *level-2-with-an-embedded-link*
+
+LEVEL 3 WITH EMPHASIS                                      *level-3-with-emphasis*
+
+Level 4                                                                  *level-4*
+
+Level 5                                                                  *level-5*
+
+================================================================================
+Level 1                                                                  *level-1*
+
+--------------------------------------------------------------------------------
+Level 2 with emphasis                                      *level-2-with-emphasis*
+
+LEVEL 3                                                                  *level-3*
+
+with no blank line
+
+--------------------------------------------------------------------------------
+Level 2                                                                  *level-2*
+
+with no blank line
+
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+================================================================================
+Paragraphs                                                            *paragraphs*
+
+Here's a regular paragraph.
+
+In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item.
+Because a hard-wrapped line in the middle of a paragraph looked like a list
+item.
+
+Here's one with a bullet. * criminey.
+
+There should be a hard line break
+here.
+
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+================================================================================
+Block Quotes                                                        *block-quotes*
+
+E-mail style:
+
+  This is a block quote. It is pretty short.
+
+  Code in a block quote:
+
+  >
+      sub status {
+          print "working";
+      }
+<
+  A list:
+
+  1. item one
+  2. item two
+
+  Nested block quotes:
+
+    nested
+
+    nested
+
+This should not be a block quote: 2 > 1.
+
+And a following paragraph.
+
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+================================================================================
+Code Blocks                                                          *code-blocks*
+
+Code:
+
+>
+    ---- (should be four hyphens)
+
+    sub status {
+        print "working";
+    }
+
+    this code block is indented by one tab
+<
+And:
+
+>
+        this code block is indented by two tabs
+
+    These should not be escaped:  \$ \\ \> \[ \{
+<
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+================================================================================
+Lists                                                                      *lists*
+
+--------------------------------------------------------------------------------
+Unordered                                                              *unordered*
+
+Asterisks tight:
+
+- asterisk 1
+- asterisk 2
+- asterisk 3
+
+Asterisks loose:
+
+- asterisk 1
+
+- asterisk 2
+
+- asterisk 3
+
+Pluses tight:
+
+- Plus 1
+- Plus 2
+- Plus 3
+
+Pluses loose:
+
+- Plus 1
+
+- Plus 2
+
+- Plus 3
+
+Minuses tight:
+
+- Minus 1
+- Minus 2
+- Minus 3
+
+Minuses loose:
+
+- Minus 1
+
+- Minus 2
+
+- Minus 3
+
+--------------------------------------------------------------------------------
+Ordered                                                                  *ordered*
+
+Tight:
+
+1. First
+2. Second
+3. Third
+
+and:
+
+1. One
+2. Two
+3. Three
+
+Loose using tabs:
+
+1. First
+
+2. Second
+
+3. Third
+
+and using spaces:
+
+1. One
+
+2. Two
+
+3. Three
+
+Multiple paragraphs:
+
+1. Item 1, graf one.
+
+   Item 1. graf two. The quick brown fox jumped over the lazy dog's back.
+
+2. Item 2.
+
+3. Item 3.
+
+--------------------------------------------------------------------------------
+Nested                                                                    *nested*
+
+- Tab
+  - Tab
+    - Tab
+
+Here's another:
+
+1. First
+2. Second:
+   - Fee
+   - Fie
+   - Foe
+3. Third
+
+Same thing but with paragraphs:
+
+1. First
+
+2. Second:
+
+   - Fee
+   - Fie
+   - Foe
+
+3. Third
+
+--------------------------------------------------------------------------------
+Tabs and spaces                                                  *tabs-and-spaces*
+
+- this is a list item indented with tabs
+
+- this is a list item indented with spaces
+
+  - this is an example list item indented with tabs
+
+  - this is an example list item indented with spaces
+
+--------------------------------------------------------------------------------
+Fancy list markers                                            *fancy-list-markers*
+
+(2) begins with 2
+
+(3) and now 3
+
+    with a continuation
+
+    iv. sublist with roman numerals, starting with 4
+    v. more items
+       (A) a subsublist
+       (B) a subsublist
+
+Nesting:
+
+A. Upper Alpha
+   I. Upper Roman.
+      (6) Decimal start with 6
+          c) Lower alpha with paren
+
+Autonumbering:
+
+1. Autonumber.
+2. More.
+   1. Nested.
+
+Should not be a list item:
+
+M.A. 2007
+
+B. Williams
+
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+================================================================================
+Definition Lists                                                *definition-lists*
+
+Tight using spaces:
+
+apple
+    red fruit
+orange
+    orange fruit
+banana
+    yellow fruit
+
+Tight using tabs:
+
+apple
+    red fruit
+orange
+    orange fruit
+banana
+    yellow fruit
+
+Loose:
+
+apple
+    red fruit
+
+orange
+    orange fruit
+
+banana
+    yellow fruit
+
+Multiple blocks with italics:
+
+apple
+    red fruit
+
+    contains seeds, crisp, pleasant to taste
+
+orange
+    orange fruit
+
+    >
+        { orange code block }
+<
+      orange block quote
+
+Multiple definitions, tight:
+
+apple
+    red fruit
+    computer
+orange
+    orange fruit
+    bank
+
+Multiple definitions, loose:
+
+apple
+    red fruit
+
+    computer
+
+orange
+    orange fruit
+
+    bank
+
+Blank line after term, indented marker, alternate markers:
+
+apple
+    red fruit
+
+    computer
+
+orange
+    orange fruit
+
+    1. sublist
+    2. sublist
+
+================================================================================
+HTML Blocks                                                          *html-blocks*
+
+Simple block on one line:
+
+foo
+And nested without indentation:
+
+foo
+
+bar
+Interpreted markdown in a table:
+
+This is emphasized
+And this is strong
+Here's a simple block:
+
+foo
+
+This should be a code block, though:
+
+>
+    <div>
+        foo
+    </div>
+<
+As should this:
+
+>
+    <div>foo</div>
+<
+Now, nested:
+
+foo
+This should just be an HTML comment:
+
+Multiline:
+
+Code block:
+
+>
+    <!-- Comment -->
+<
+Just plain comment, with trailing spaces on the line:
+
+Code:
+
+>
+    <hr />
+<
+Hr's:
+
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+================================================================================
+Inline Markup                                                      *inline-markup*
+
+This is emphasized, and so is this.
+
+This is strong, and so is this.
+
+An emphasized link /url.
+
+This is strong and em.
+
+So is this word.
+
+This is strong and em.
+
+So is this word.
+
+This is code: `>`, `$`, `\`, `\$`, `<html>`.
+
+This is strikeout.
+
+Superscripts: abcd ahello ahello there.
+
+Subscripts: H2O, H23O, Hmany of themO.
+
+These should not be superscripts or subscripts, because of the unescaped spaces:
+a^b c^d, a~b c~d.
+
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+================================================================================
+Smart quotes, ellipses, dashes                      *smart-quotes-ellipses-dashes*
+
+"Hello," said the spider. "'Shelob' is my name."
+
+'A', 'B', and 'C' are letters.
+
+'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'
+
+'He said, "I want to go."' Were you alive in the 70's?
+
+Here is some quoted '`code`' and a "quoted link
+http://example.com/?foo=1&bar=2".
+
+Some dashes: one---two --- three---four --- five.
+
+Dashes between numbers: 5--7, 255--66, 1987--1999.
+
+Ellipses...and...and....
+
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+================================================================================
+LaTeX                                                                      *latex*
+
+- 
+- `$2+2=4$`
+- `$x \in y$`
+- `$\alpha \wedge \omega$`
+- `$223$`
+- `$p$`-Tree
+- Here's some display math:
+  `$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$`
+- Here's one that has a line break in it: `$\alpha + \omega \times x^2$`.
+
+These shouldn't be math:
+
+- To get the famous equation, write `$e = mc^2$`.
+- $22,000 is a lot of money. So is $34,000. (It worked if "lot" is emphasized.)
+- Shoes ($20) and socks ($5).
+- Escaped `$`: $73 this should be emphasized 23$.
+
+Here's a LaTeX table:
+
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+================================================================================
+Special Characters                                            *special-characters*
+
+Here is some unicode:
+
+- I hat: Î
+- o umlaut: ö
+- section: §
+- set membership: ∈
+- copyright: ©
+
+AT&T has an ampersand in their name.
+
+AT&T is another way to write it.
+
+This & that.
+
+4 < 5.
+
+6 > 5.
+
+Backslash: \
+
+Backtick: `
+
+Asterisk: *
+
+Underscore: _
+
+Left brace: {
+
+Right brace: }
+
+Left bracket: [
+
+Right bracket: ]
+
+Left paren: (
+
+Right paren: )
+
+Greater-than: >
+
+Hash: #
+
+Period: .
+
+Bang: !
+
+Plus: +
+
+Minus: -
+
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+================================================================================
+Links                                                                      *links*
+
+--------------------------------------------------------------------------------
+Explicit                                                                *explicit*
+
+Just a URL /url/.
+
+URL and title /url/.
+
+URL and title /url/.
+
+URL and title /url/.
+
+URL and title /url/
+
+URL and title /url/
+
+with_underscore /url/with_underscore
+
+Email link nobody@nowhere.net
+
+Empty .
+
+--------------------------------------------------------------------------------
+Reference                                                              *reference*
+
+Foo bar /url/.
+
+With embedded [brackets] /url/.
+
+b /url/ by itself should be a link.
+
+Indented once /url.
+
+Indented twice /url.
+
+Indented thrice /url.
+
+This should [not][] be a link.
+
+>
+    [not]: /url
+<
+Foo bar /url/.
+
+Foo biz /url/.
+
+--------------------------------------------------------------------------------
+With ampersands                                                  *with-ampersands*
+
+Here's a link with an ampersand in the URL http://example.com/?foo=1&bar=2.
+
+Here's a link with an amersand in the link text: AT&T http://att.com/.
+
+Here's an inline link /script?foo=1&bar=2.
+
+Here's an inline link in pointy braces /script?foo=1&bar=2.
+
+--------------------------------------------------------------------------------
+Autolinks                                                              *autolinks*
+
+With an ampersand: http://example.com/?foo=1&bar=2
+
+- In a list?
+- http://example.com/
+- It should.
+
+An e-mail address: nobody@nowhere.net
+
+  Blockquoted: http://example.com/
+
+Auto-links should not occur here: `<http://example.com/>`
+
+>
+    or here: <http://example.com/>
+<
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+================================================================================
+Images                                                                    *images*
+
+From "Voyage dans la Lune" by Georges Melies (1902):
+
+Here is a movie icon.
+
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+================================================================================
+Footnotes                                                              *footnotes*
+
+Here is a footnote reference, |footnote1| and another. |footnote2| This should
+not be a footnote reference, because it contains a space.[^my note] Here is an
+inline note. |footnote3|
+
+  Notes can go in quotes. |footnote4|
+
+1. And in list items. |footnote5|
+
+This paragraph should not be part of the note, as it is not indented.
+
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+                                                                       *footnote1*
+Here is the footnote. It can go anywhere after the footnote reference. It need
+not be placed at the end of the document.
+
+                                                                       *footnote2*
+Here's the long note. This one contains multiple blocks.
+
+Subsequent blocks are indented to show that they belong to the footnote (as with
+list items).
+
+>
+      { <code> }
+<
+If you want, you can indent every line, but you can also be lazy and just indent
+the first line of each block.
+
+                                                                       *footnote3*
+This is easier to type. Inline notes may contain links http://google.com and `]`
+verbatim characters, as well as [bracketed text].
+
+                                                                       *footnote4*
+In quote.
+
+                                                                       *footnote5*
+In list.
+
+ vim:tw=80:sw=4:ts=4:ft=help:norl:et:
diff --git a/test/writers-lang-and-dir.latex b/test/writers-lang-and-dir.latex
--- a/test/writers-lang-and-dir.latex
+++ b/test/writers-lang-and-dir.latex
@@ -43,9 +43,9 @@
   \KOMAoptions{parskip=half}}
 \makeatother
 \ifLuaTeX
-\usepackage[bidi=basic,shorthands=off,]{babel}
+\usepackage[bidi=basic,shorthands=off]{babel}
 \else
-\usepackage[bidi=default,shorthands=off,]{babel}
+\usepackage[bidi=default,shorthands=off]{babel}
 \fi
 \ifLuaTeX
   \usepackage{selnolig} % disable illegal ligatures
