diff --git a/AUTHORS.md b/AUTHORS.md
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -2,6 +2,7 @@
 
 - Aaron Wolen
 - Adelar da Silva Queiróz
+- Agriya Khetarpal
 - Agustín Martín Barbero
 - Akash Patel
 - Akos Marton
@@ -338,6 +339,7 @@
 - Pavol Otto
 - Per Christian Gaustad
 - Pete Ryland
+- Peter Briggs
 - Peter Fabinksi
 - Peter Wang
 - Philip Pesca
@@ -383,6 +385,7 @@
 - Shim Myeongseob
 - Shin Sang-jae
 - Sidarth Kapur
+- Sidney Mau
 - Sidharth Kapur
 - Simon Hengel
 - Simon Schuster
@@ -528,3 +531,4 @@
 - wiefling
 - willj-dev
 - wuffi
+- λx.x
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-02-02
+date: 2026-03-17
 ---
 
 # Synopsis
@@ -512,7 +512,7 @@
 [Jira]: https://jira.atlassian.com/secure/WikiRendererHelpAction.jspa?section=all
 [txt2tags]: https://txt2tags.org
 [EPUB]: http://idpf.org/epub
-[OPML]: http://dev.opml.org/spec2.html
+[OPML]: https://opml.org/spec2.opml
 [OpenDocument XML]: https://www.oasis-open.org/2021/06/16/opendocument-v1-3-oasis-standard-published/
 [ODT]: https://en.wikipedia.org/wiki/OpenDocument
 [Plain Old Documentation]: https://perldoc.perl.org/perlpod
@@ -544,7 +544,7 @@
 [reveal.js]: https://revealjs.com/
 [FictionBook2]: http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1
 [Jupyter notebook]: https://nbformat.readthedocs.io/en/latest/
-[InDesign ICML]: https://manualzz.com/doc/9627253/adobe-indesign-cs6-idml-cookbook
+[InDesign ICML]: https://web.archive.org/web/20211006210211/https://wwwimages.adobe.com/www.adobe.com/content/dam/acom/en/devnet/indesign/sdk/cs6/idml/idml-cookbook.pdf
 [TEI Simple]: https://github.com/TEIC/TEI-Simple
 [Muse]: https://amusewiki.org/library/manual
 [PowerPoint]: https://en.wikipedia.org/wiki/Microsoft_PowerPoint
@@ -2999,6 +2999,9 @@
 `logo`
 :   logo image for slides
 
+`logooptions`
+:   options for logo image (e.g., `width`, `height`)
+
 `navigation`
 :   controls navigation symbols (default is `empty` for no navigation
     symbols; other valid values are `frame`, `vertical`, and `horizontal`)
@@ -3016,7 +3019,7 @@
 :   image for title slide: can be a list
 
 `titlegraphicoptions`
-:   options for title slide image
+:   options for title slide image (e.g., `width`, `height`)
 
 `shorttitle`, `shortsubtitle`, `shortauthor`, `shortinstitute`, `shortdate`
 :   some beamer themes use short versions of the title, subtitle, author,
@@ -5071,6 +5074,7 @@
 (`...`) at the bottom.  The initial line `---` must not be followed by a blank
 line. A YAML metadata block may occur anywhere in the document, but if
 it is not at the beginning, it must be preceded by a blank line.
+(Note that JSON may be used as well, because JSON is a subset of YAML.)
 
 Note that, because of the way pandoc concatenates input files
 when several are provided, you may also keep the metadata in a
@@ -7167,8 +7171,10 @@
   ~ Either a string value or an object with fields `text` and
     `scheme`.  Valid values for `scheme` are `ISBN-10`,
     `GTIN-13`, `UPC`, `ISMN-10`, `DOI`, `LCCN`, `GTIN-14`,
-    `ISBN-13`, `Legal deposit number`, `URN`, `OCLC`,
-    `ISMN-13`, `ISBN-A`, `JP`, `OLCC`.
+    `ISBN-13`, `Legal deposit number`, `URN`, `OCLC number`,
+    `Co-publisher’s ISBN-13`, `ISMN-13`, `ISBN-A`, `JP e-code`,
+    `OLCC number`, `JP Magazine ID`, `UPC-12+5`, `BNF Control number`,
+    `ISSN-13`, `ARK`, `Digital file internal version number`.
 
 `title`
   ~ Either a string value, or an object with fields `file-as` and
@@ -7711,6 +7717,14 @@
 
 For docx or odt output, you don't need to enable any extensions for
 custom styles to work.
+
+For icml output, you can also set an `object-style` in images:
+
+    ![Image with object style](myImage.jpg){object-style="fixedSizeImage"}
+
+In InDesign you'll see that object style given to the image,
+and you'll be able to customize it, or load its definition from
+a template of yours.
 
 [pandoc filters]: https://pandoc.org/filters.html
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -88,7 +88,7 @@
 - `native` (native Haskell)
 - `odt` ([OpenDocument text
   document](https://en.wikipedia.org/wiki/OpenDocument))
-- `opml` ([OPML](http://dev.opml.org/spec2.html))
+- `opml` ([OPML](https://opml.org/spec2.opml))
 - `org` ([Emacs Org mode](https://orgmode.org))
 - `pod` (Perl’s [Plain Old
   Documentation](https://perldoc.perl.org/perlpod))
@@ -174,7 +174,7 @@
   markup](https://www.w3.org/TR/html-polyglot/))
 - `html4` ([XHTML](https://www.w3.org/TR/xhtml1/) 1.0 Transitional)
 - `icml` ([InDesign
-  ICML](https://manualzz.com/doc/9627253/adobe-indesign-cs6-idml-cookbook))
+  ICML](https://web.archive.org/web/20211006210211/https://wwwimages.adobe.com/www.adobe.com/content/dam/acom/en/devnet/indesign/sdk/cs6/idml/idml-cookbook.pdf))
 - `ipynb` ([Jupyter
   notebook](https://nbformat.readthedocs.io/en/latest/))
 - `jats_archiving` ([JATS](https://jats.nlm.nih.gov) XML, Archiving and
@@ -206,7 +206,7 @@
 - `native` (native Haskell)
 - `odt` ([OpenDocument text
   document](https://en.wikipedia.org/wiki/OpenDocument))
-- `opml` ([OPML](http://dev.opml.org/spec2.html))
+- `opml` ([OPML](https://opml.org/spec2.opml))
 - `opendocument` ([OpenDocument
   XML](https://www.oasis-open.org/2021/06/16/opendocument-v1-3-oasis-standard-published/))
 - `org` ([Emacs Org mode](https://orgmode.org))
@@ -282,8 +282,9 @@
 Guide](https://pandoc.org/MANUAL.html). It is also available
 [here](MANUAL.txt) as pandoc-flavored Markdown. The website also
 contains some [examples of the use of
-pandoc](https://pandoc.org/demos.html) and a limited [online
-demo](https://pandoc.org/try).
+pandoc](https://pandoc.org/demos.html), a limited [online
+demo](https://pandoc.org/try), and a [WebAssembly-based online
+demo](https://pandoc.org/app).
 
 ## Contributing
 
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,195 @@
 # Revision history for pandoc
 
+## pandoc 3.9.0.1 (2026-03-17)
+
+  * WASM GUI:
+
+    + Don't block everything while pandoc.wasm loads.
+    + Fix bug with Unicode filenames (#11447).
+    + Catch errors loading pandoc.
+
+  * Docx reader:
+
+    + Recognize media inside textboxes (#11053, Raymond Berger).
+    + Properly handle media stored with packaged-rooted paths
+      such as `/media` (#11518).  This can be produced by the online version of Word.
+      With this change, media stored at an absolute path will be stored
+      with its original name and not given a SHA1-based name.
+    + Preserve non-textbox content when unwrapping textboxes (#11510, #6893,
+      #11412, #5394, #9633). Treat text inside a textbox containing an image
+      as a figure caption.
+
+  * Typst reader:
+
+    + Handle bibliography command (#11460). If this is present, a
+      bibliography section is added to the document and the bibliography
+      paths are added to `bibliography` in the metadata. This sets things
+      up for using `--citeproc`.
+
+  * Textile reader:
+
+    + Handle block content in cells (#11455).
+
+  * Docx reader:
+
+    + Support `w:gridBefore` table row property (#11464, Jan Tojnar).
+
+  * LaTeX reader:
+
+    + Support `\footnotemark` and `\footnotetext` (#11450).
+      These commands allow separating the footnote mark from its content, useful
+      in tables, minipages, and other contexts where \footnote cannot be used
+      directly.
+    + Support supertabular environment (#11523, bodigrim).
+
+  * ODT Reader:
+
+    + Fix relative linked images (#11369, Tuong Nguyen Manh).
+    + Recognize `Preformatted_20_Text` style Jan Tojnar
+      This is used by LibreOffice, and we will switch to that as well.
+    + Add block smushing logic (Jan Tojnar).
+    + Support Preformatted Text style (#4841, Jan Tojnar).
+
+  * Markdown reader:
+
+    + Fix bug with `lists_without_preceding_blankline` (#11534).
+
+  * Typst writer:
+
+    + Don't add a carriage return after `\` for hard break (#11446).
+      They are not necessary.  Note that they can still be included
+      if you use `--wrap=preserve` and add a newline in your source document.
+    + Improve handling of data: URIs in images. Instead of using an
+      SVG with a link containing the data URI (the solution of #10460),
+      we can now simply produce a `bytes` object with the requisite bytes.
+      Typst figures out the format automatically.
+    + Fix escaping of quotes (#11463).
+    + Include alt attributes on images (mcanouil).
+    + Properly escape `.` after bracketed argument (#11511).
+
+  * Docx writer:
+
+    + Don't depend on `extractTarget` from Docx reader.
+    + Fix section breaks with `--top-level-division` (#11482, #10578).
+
+  * EPUB writer:
+
+    + Add cover metadata for EPUB3 (#11479). This allows
+      file managers to show cover thumbnails for EPUB3 files as well.
+    + Update allowed values for EPUB3 metadata `identifier.scheme` (#11481,
+      Pascal Wagler).
+
+  * ODT writer:
+
+    + Rename inline source class to match LibreOffice (#3390, Jan Tojnar).
+      Rename the text style we use to represent `Code` inlines from
+      `Source_20_Text` to `Source_Text`. This is the same name LibreOffice
+      Writer uses so it will be recognized by the Character Styles section
+      of the Styles menu.
+    + Remove font size from inline source class (Jan Tojnar). This matches
+      what LibreOffice Writer is doing. Also fixes literals inside
+      headings being too small.
+    + Modernize `Preformatted Text` & `Source Text` styles (Jan Tojnar).
+      Presumably, `font-family-generic` and `font-pitch` will allow to find a
+      replacement on systems that do not have `Courier New`.
+
+  * Markdown writer:
+
+    + Fix rendering of alerts (#11479). We only properly handled the case
+      where the alert started with a paragraph, but it can start with a list
+      or other block type.
+    + Escape literal `&` that would trigger entity (#11490).
+
+  * HTML writer:
+
+    + For revealjs, default `scrollProgress` to `auto` (Christophe Dervieux).
+
+  * PPTX writer:
+
+    + Register content type for embedded fonts (#11492).
+
+  * MediaWiki writer:
+
+    + Use appropriate syntax for external images (#11494).
+      Note that they will only be rendered as images if an option
+      `$wgAllowExternalImages` is enabled in the MediaWiki instance.
+
+  * ICML writer:
+
+    + Support for image object styles (#11498, massifrg).
+      This change allows users to style images in InDesign bysetting the
+      `object-style` attribute in a pandoc Image, which is mapped to the
+      AppliedObjectStyle attribute in the Rectangle element around an Image
+      element in the resulting ICML.
+
+  * JATS writer:
+
+    + Improve representation of Divs (Albert Krewinkel).  The writer now
+      checks if the element used to represent (non-special) Divs has any
+      `<boxed-text>` specific attributes. If it does, the writer keeps
+      wrapping the Div contents in a `<boxed-text>`, as it did before.
+      Otherwise, the writer falls back to the more appropriate `<p>` element
+      or simply unwraps the Div if the wrapping element wouldn't have any
+      attributes. The new behavior gives better semantic results in most cases,
+      as `<boxed-text>` should be used for text that "is outside the flow of the
+      narrative text", which doesn't apply to most divs.
+      "Special" divs, like those used to mark sections, are not
+      affected by this change.
+
+  * Text.Pandoc.Writers.GridTable:
+
+    + Normalize tables (#8102). Previously, if an invalid table was passed to
+      `toTable`, an array index error could be raised. Normalizing the table
+      forces it into a shape that won't allow this error.
+
+  * Lua subsystem (Albert Krewinkel):
+
+    + Add new function `pandoc.types.Sources` (#11441).
+
+  * LaTeX template: properly handle keywords with commas.
+    These need to be put in an `\xmpquote{..}` command. Closes #11528.
+
+  * HTML styles template:  avoid duplicate code selector.
+    Consolidate two clauses. Closes #11484.
+
+  * Revealjs template: fix type rendering of scroll-view options
+    (Christophe Dervieux, #11486).
+
+  * Typst template:
+
+    + Use both place and block for title (Gordon Woodhull).
+      Otherwise the title will be confined to the left column
+    + Put title block in a conditional (#11529). This avoids an
+      empty block for documents that lack metadata information.
+      The empty block causes problems if `#set page` is used, as
+      it will cause a page break.
+
+  * Beamer template: add `logooption` variable (#11452, Sidney Mau).
+
+  * Text.Pandoc.ImageSize:
+
+    + Correctly handle percentage width, height on SVG (#11530).
+      Previously we were getting image size of 0 when a percentage
+      was specified for width or height on SVG.  With this change,
+      we simply ignore these percentages (becaues ImageSize doesn't
+      know the size of the containing element).
+
+  * Re-add `-threaded` to compile options in pandoc-cli.
+
+  * Use released djot, asciidoc, texmath, typst.
+
+  * Allow crypton 1.1, tls 2.2, http-client-tls 0.4.
+
+  * Require auto-update >= 0.2.6 to fix server on macOS (#11488).
+
+  * pandoc-cli.cabal: bump base min bound to 4.18 (same as pandoc).
+
+  * MANUAL.txt:
+
+    + Note that JSON may be used in YAML metadata blocks (#11525).
+    + Update link for ICML in manual.
+    + Fix outdated OPML spec URL in MANUAL.txt (#11504, Peter Briggs).
+
 ## pandoc 3.9 (2026-02-03)
 
   * Add support for compiling pandoc to WASM. (To build, `make
@@ -3187,7 +3377,7 @@
 
   * New module Text.Pandoc.Transforms [API change] (Albert Krewinkel).
     This module exports the following functions which were formerly
-    exported from Tetx.Pnadoc.Shared: `headerShift`,
+    exported from Text.Pandoc.Shared: `headerShift`,
     `filterIpynbOutput`, `eastAsianLineBreakFilter`, as well as some
     functions that were previously not exported.
 
diff --git a/data/odt/styles.xml b/data/odt/styles.xml
--- a/data/odt/styles.xml
+++ b/data/odt/styles.xml
@@ -250,18 +250,35 @@
       <style:paragraph-properties fo:margin-top="0in"
       fo:margin-bottom="0in" style:contextual-spacing="false" />
       <style:text-properties style:font-name="Courier New"
-      fo:font-size="10pt" style:font-name-asian="Courier New"
+      fo:font-family="&apos;Courier New&apos;"
+      style:font-family-generic="modern"
+      style:font-pitch="fixed"
+      fo:font-size="10pt"
+      style:font-name-asian="Courier New"
+      style:font-family-asian="&apos;Courier New&apos;"
+      style:font-family-generic-asian="modern"
+      style:font-pitch-asian="fixed"
       style:font-size-asian="10pt"
       style:font-name-complex="Courier New"
+      style:font-family-complex="&apos;Courier New&apos;"
+      style:font-family-generic-complex="modern"
+      style:font-pitch-complex="fixed"
       style:font-size-complex="10pt"
       fo:language="zxx" />
     </style:style>
-    <style:style style:name="Source_Text" style:family="text">
+    <style:style style:name="Source_20_Text" style:display-name="Source Text" style:family="text">
       <style:text-properties style:font-name="Courier New"
-      fo:font-size="10pt" style:font-name-asian="Courier New"
-      style:font-size-asian="10pt"
+      fo:font-family="&apos;Courier New&apos;"
+      style:font-family-generic="modern"
+      style:font-pitch="fixed"
+      style:font-name-asian="Courier New"
+      style:font-family-asian="&apos;Courier New&apos;"
+      style:font-family-generic-asian="modern"
+      style:font-pitch-asian="fixed"
       style:font-name-complex="Courier New"
-      style:font-size-complex="10pt"
+      style:font-family-complex="&apos;Courier New&apos;"
+      style:font-family-generic-complex="modern"
+      style:font-pitch-complex="fixed"
       fo:language="zxx" />
     </style:style>
     <style:style style:name="Highlighted" style:family="text">
diff --git a/data/templates/default.beamer b/data/templates/default.beamer
--- a/data/templates/default.beamer
+++ b/data/templates/default.beamer
@@ -125,7 +125,7 @@
 $endfor$}
 $endif$
 $if(logo)$
-\logo{\includegraphics{$logo$}}
+\logo{\includegraphics$if(logooptions)$[$for(logooptions)$$logooptions$$sep$, $endfor$]$endif${$logo$}}
 $endif$
 
 \begin{document}
diff --git a/data/templates/default.icml b/data/templates/default.icml
--- a/data/templates/default.icml
+++ b/data/templates/default.icml
@@ -28,6 +28,11 @@
     <RootCellStyleGroup Self="pandoc_cell_styles">
       <CellStyle Self="CellStyle/Cell" AppliedParagraphStyle="ParagraphStyle/$$ID/[No paragraph style]" Name="Cell" />
     </RootCellStyleGroup>
+$if(objectStyles)$
+    <RootObjectStyleGroup Self="pandoc_object_styles">
+      $objectStyles$
+    </RootObjectStyleGroup>
+$endif$
   <Story Self="pandoc_story"
       TrackChanges="false"
       StoryTitle="$if(title-prefix)$$title-prefix$ – $endif$$pagetitle$"
diff --git a/data/templates/default.revealjs b/data/templates/default.revealjs
--- a/data/templates/default.revealjs
+++ b/data/templates/default.revealjs
@@ -243,13 +243,23 @@
         // Enable scroll view
         view: '$view/nowrap$',
         // see https://revealjs.com/scroll-view/#scrollbar
+$if(scrollProgressAuto)$
+        scrollProgress: 'auto',
+$elseif(scrollProgress)$
         scrollProgress: $scrollProgress$,
+$else$
+        scrollProgress: false,
+$endif$
         // see https://revealjs.com/scroll-view/#url-activation
-        scrollActivationWidth: '$scrollActivationWidth$',
+        scrollActivationWidth: $scrollActivationWidth$,
         // see https://revealjs.com/scroll-view/#scroll-snapping
-        scrollSnap: '$scrollSnap$',
+$if(scrollSnap)$
+        scrollSnap: '$scrollSnap/nowrap$',
+$else$
+        scrollSnap: false,
+$endif$
         // Experimental. see https://revealjs.com/scroll-view/#scroll-snapping
-        scrollLayout: '$scrollLayout$',
+        scrollLayout: '$scrollLayout/nowrap$',
 $endif$
 $if(parallaxBackgroundImage)$
 
diff --git a/data/templates/hypersetup.latex b/data/templates/hypersetup.latex
--- a/data/templates/hypersetup.latex
+++ b/data/templates/hypersetup.latex
@@ -12,7 +12,7 @@
   pdfsubject={$subject$},
 $endif$
 $if(keywords)$
-  pdfkeywords={$for(keywords)$$keywords$$sep$, $endfor$},
+  pdfkeywords={$for(keywords)$\xmpquote{$keywords$}$sep$, $endfor$},
 $endif$
 $if(colorlinks)$
   colorlinks=true,
diff --git a/data/templates/styles.html b/data/templates/styles.html
--- a/data/templates/styles.html
+++ b/data/templates/styles.html
@@ -106,6 +106,7 @@
 }
 $endif$
 code {
+  white-space: pre-wrap;
   font-family: $if(monofont)$$monofont$$else$Menlo, Monaco, Consolas, 'Lucida Console', monospace$endif$;
 $if(monobackgroundcolor)$
   background-color: $monobackgroundcolor$;
@@ -183,7 +184,6 @@
   text-decoration: none;
 }
 $endif$
-code{white-space: pre-wrap;}
 span.smallcaps{font-variant: small-caps;}
 div.columns{display: flex; gap: min(4vw, 1.5em);}
 div.column{flex: auto; overflow-x: auto;}
diff --git a/data/templates/template.typst b/data/templates/template.typst
--- a/data/templates/template.typst
+++ b/data/templates/template.typst
@@ -73,7 +73,10 @@
     }
   }
 
-  block(below: 1em, width: 100%)[
+#let has-title-block = title != none or (authors != none and authors != ()) or
+                       date != none or abstract != none
+#if has-title-block {
+  place(top, float: true, scope: "parent", clearance: 4mm, block(below: 1em, width: 100%)[
     #if title != none {
       align(center, block[
           #text(weight: "bold", size: 1.5em, hyphenate: false)[#title #if thanks != none {
@@ -113,7 +116,7 @@
         #text(weight: "semibold")[#abstract-title] #h(1em) #abstract
       ]
     }
-  ]
-
+  ])
+}
   doc
 }
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.9
+version:         3.9.0.1
 build-type:      Simple
 license:         GPL-2.0-or-later
 license-file:    COPYING.md
@@ -207,12 +207,13 @@
                  citeproc/biblatex-localization/*.lbx.strings
                  -- documentation
                  MANUAL.txt, COPYRIGHT
-extra-doc-files:
-                 changelog.md
+extra-doc-files: changelog.md,
+                 AUTHORS.md,
+                 INSTALL.md,
+                 README.md,
+                 CONTRIBUTING.md,
+                 BUGS
 extra-source-files:
-                 -- documentation
-                 INSTALL.md, AUTHORS.md, README.md,
-                 CONTRIBUTING.md, BUGS,
                  -- tests
                  test/bodybg.gif
                  test/*.native
@@ -276,6 +277,8 @@
                  test/command/6466-whole.hs
                  test/command/7861.yaml
                  test/command/7861/metadata/placeholder
+                 test/command/11486/scroll.revealjs
+                 test/command/11498.png
                  test/asciidoc-reader.adoc
                  test/asciidoc-reader.native
                  test/asciidoc-reader-include.rb
@@ -523,7 +526,7 @@
                  commonmark-extensions >= 0.2.6    && < 0.3,
                  commonmark-pandoc     >= 0.2.3    && < 0.3,
                  containers            >= 0.6.0.1  && < 0.9,
-                 crypton               >= 0.30     && < 1.1,
+                 crypton               >= 0.30     && < 1.2,
                  data-default          >= 0.4      && < 0.9,
                  deepseq               >= 1.3      && < 1.6,
                  directory             >= 1.2.3    && < 1.4,
@@ -555,7 +558,7 @@
                  syb                   >= 0.1      && < 0.8,
                  tagsoup               >= 0.14.6   && < 0.15,
                  temporary             >= 1.1      && < 1.4,
-                 texmath               >= 0.13.1   && < 0.14,
+                 texmath               >= 0.13.1.1 && < 0.14,
                  text                  >= 1.1.1.0  && < 2.2,
                  text-conversions      >= 0.3      && < 0.4,
                  time                  >= 1.5      && < 1.16,
@@ -567,10 +570,10 @@
                  zip-archive           >= 0.4.3.1  && < 0.5,
                  zlib                  >= 0.5      && < 0.8,
                  xml                   >= 1.3.12   && < 1.4,
-                 typst                 >= 0.9      && < 0.10,
+                 typst                 >= 0.9.0.1  && < 0.10,
                  vector                >= 0.12     && < 0.14,
-                 djot                  >= 0.1.3    && < 0.2,
-                 asciidoc              >= 0.1.0.1  && < 0.2
+                 djot                  >= 0.1.4    && < 0.2,
+                 asciidoc              >= 0.1.0.2  && < 0.2
 
   if !os(windows)
     build-depends:  unix >= 2.4 && < 2.9
@@ -581,11 +584,11 @@
      cpp-options:   -DPANDOC_HTTP_SUPPORT
      build-depends:
                  crypton-connection    >= 0.3.1    && < 0.5,
-                 crypton-x509-system   >= 1.6.7    && < 1.9,
+                 crypton-x509-system   >= 1.6.7    && < 1.10,
                  http-client           >= 0.4.30   && < 0.8,
-                 http-client-tls       >= 0.2.4    && < 0.4,
+                 http-client-tls       >= 0.2.4    && < 0.5,
                  network               >= 2.6      && < 3.3,
-                 tls                   >= 2.0.1    && < 2.2
+                 tls                   >= 2.0.1    && < 2.4
   hs-source-dirs:  src
 
   exposed-modules: Text.Pandoc,
diff --git a/src/Text/Pandoc/ImageSize.hs b/src/Text/Pandoc/ImageSize.hs
--- a/src/Text/Pandoc/ImageSize.hs
+++ b/src/Text/Pandoc/ImageSize.hs
@@ -374,7 +374,9 @@
   let dpi = fromIntegral $ writerDpi opts
   let dirToInt dir = do
         dim <- findAttrBy (== QName dir Nothing Nothing) doc >>= lengthToDim
-        return $ inPixel opts dim
+        case dim of
+           Percent _ -> mzero
+           _ -> pure $ inPixel opts dim
   w <- dirToInt "width" <|> (fst <$> viewboxSize)
   h <- dirToInt "height" <|> (snd <$> viewboxSize)
   return ImageSize {
diff --git a/src/Text/Pandoc/Readers/Docx/Combine.hs b/src/Text/Pandoc/Readers/Docx/Combine.hs
--- a/src/Text/Pandoc/Readers/Docx/Combine.hs
+++ b/src/Text/Pandoc/Readers/Docx/Combine.hs
@@ -52,7 +52,8 @@
 
 -}
 
-module Text.Pandoc.Readers.Docx.Combine ( smushInlines
+module Text.Pandoc.Readers.Docx.Combine ( combineBlocks
+                                        , smushInlines
                                         , smushBlocks
                                         )
        where
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
@@ -160,21 +160,54 @@
   | isElem ns "w" "smartTag" element
   = concatMap (unwrapElement ns) (elChildren element)
   | isElem ns "w" "p" element
-  , textboxes@(_:_) <- findChildrenByName ns "w" "r" element >>=
-                       findChildrenByName ns "mc" "AlternateContent" >>=
-                       findChildrenByName ns "mc" "Fallback" >>=
-                       findChildrenByName ns "w" "pict" >>=
-                       (\e -> findChildrenByName ns "v" "shape" e <>
-                              findChildrenByName ns "v" "rect" e) >>=
-                       findChildrenByName ns "v" "textbox" >>=
-                       findChildrenByName ns "w" "txbxContent"
-  = concatMap (unwrapElement ns) (concatMap elChildren textboxes) -- handle #9214
+  , _:_ <- findChildrenByName ns "w" "r" element >>= findTextboxes
+  = let result = splitP (elContent element) [] -- handle #9214, #11053
+    in [element{ elName = QName "textbox-image" Nothing Nothing
+              , elContent = map Elem result }]
   | isElem ns "w" "r" element
   , Just fallback <- findChildByName ns "mc" "AlternateContent" element >>=
                      findChildByName ns "mc" "Fallback"
   = [element{ elContent = concatMap (unwrapContent ns) (elContent fallback) }]
   | otherwise
   = [element{ elContent = concatMap (unwrapContent ns) (elContent element) }]
+  where
+    -- Split a w:p's children around textbox-bearing runs, preserving order.
+    -- Non-textbox content is grouped into a copy of the original w:p;
+    -- textbox content is unwrapped into sibling elements in place.
+    splitP [] acc = [wrapP acc | hasContent acc]
+    splitP (c:cs) acc
+      | Elem el <- c
+      , isElem ns "w" "r" el
+      , tbs@(_:_) <- findTextboxes el
+      = [wrapP acc | hasContent acc]
+        ++ concatMap (unwrapElement ns) (concatMap elChildren tbs)
+        ++ splitP cs []
+      | otherwise
+      = splitP cs (acc ++ [c])
+    wrapP cs = element{ elContent = concatMap (unwrapContent ns) cs }
+    hasContent = any (\case Elem el -> isElem ns "w" "r" el
+                                                  && any (isContentElem . elName)
+                                                         (elChildren el)
+                            _ -> False)
+    isContentElem n = qName n `elem`
+      ["t", "drawing", "pict", "br", "tab", "sym", "fldChar", "instrText"]
+    -- Search textbox content in the run's effective children.
+    -- If AlternateContent is present, use only the fallback branch,
+    -- matching the w:r unwrapping logic and avoiding duplicate textbox
+    -- extraction when both direct and fallback encodings are present.
+    findRunFallback run =
+      findChildByName ns "mc" "AlternateContent" run >>=
+      findChildByName ns "mc" "Fallback"
+    findTextboxes run =
+      findTextboxContent =<<
+      case findRunFallback run of
+        Just fallback -> findChildrenByName ns "w" "pict" fallback
+        Nothing -> findChildrenByName ns "w" "pict" run
+    findTextboxContent pict =
+      (findChildrenByName ns "v" "shape" pict <>
+       findChildrenByName ns "v" "rect" pict) >>=
+      findChildrenByName ns "v" "textbox" >>=
+      findChildrenByName ns "w" "txbxContent"
 
 unwrapContent :: NameSpaces -> Content -> [Content]
 unwrapContent ns (Elem element) = map Elem $ unwrapElement ns element
@@ -292,6 +325,9 @@
 data Cell = Cell Align GridSpan VMerge [BodyPart]
             deriving Show
 
+emptyCell :: Cell
+emptyCell = Cell AlignDefault 1 Restart []
+
 type GridSpan = Integer
 
 data VMerge = Continue
@@ -461,9 +497,17 @@
   return $ Document namespaces body
 
 elemToBody :: NameSpaces -> Element -> D Body
-elemToBody ns element | isElem ns "w" "body" element =
-  Body . addCaptioned <$> mapD (elemToBodyPart ns) (elChildren element)
-elemToBody _ _ = throwError WrongElem
+elemToBody ns element
+  | isElem ns "w" "body" element =
+      Body . addCaptioned <$> concatMapM (elemToBodyParts ns) (elChildren element)
+  | otherwise = throwError WrongElem
+  where
+    elemToBodyParts ns' el
+      | qName (elName el) == "textbox-image"
+      = addSplitGroupCaptioned . splitMixedParagraphs
+          <$> mapD (elemToBodyPart ns') (elChildren el)
+      | otherwise
+      = ((:[]) <$> elemToBodyPart ns' el) `catchError` (\_ -> return [])
 
 archiveToStyles :: Archive -> (CharStyleMap, ParStyleMap)
 archiveToStyles = archiveToStyles' getStyleId getStyleId
@@ -526,22 +570,18 @@
   then Just InDocument
   else Nothing
 
-relElemToRelationship :: FilePath -> DocumentLocation -> Element
+relElemToRelationship :: DocumentLocation -> Element
                       -> Maybe Relationship
-relElemToRelationship fp relType element | qName (elName element) == "Relationship" =
+relElemToRelationship relType element | qName (elName element) == "Relationship" =
   do
     relId <- findAttr (QName "Id" Nothing Nothing) element
     target <- findAttr (QName "Target" Nothing Nothing) element
-    -- target may be relative (media/image1.jpeg) or absolute
-    -- (/word/media/image1.jpeg); we need to relativize it (see #7374)
-    let frontOfFp = T.pack $ takeWhile (/= '_') fp
-    let target' = fromMaybe target $
-           T.stripPrefix frontOfFp $ T.dropWhile (== '/') target
-    return $ Relationship relType relId target'
-relElemToRelationship _ _ _ = Nothing
+    -- target may be relative (media/image1.jpeg) or absolute (/word/media/image1.jpg)
+    return $ Relationship relType relId target
+relElemToRelationship _ _ = Nothing
 
 extractTarget :: Element -> Maybe Target
-extractTarget element = do (Relationship _ _ target) <- relElemToRelationship "word/" InDocument element
+extractTarget element = do (Relationship _ _ target) <- relElemToRelationship InDocument element
                            return target
 
 filePathToRelationships :: Archive -> FilePath -> FilePath ->  [Relationship]
@@ -549,7 +589,7 @@
   | Just relType <- filePathToRelType fp docXmlPath
   , Just entry <- findEntryByPath fp ar
   , Just relElems <- parseXMLFromEntry entry =
-  mapMaybe (relElemToRelationship fp relType) $ elChildren relElems
+  mapMaybe (relElemToRelationship relType) $ elChildren relElems
 filePathToRelationships _ _ _ = []
 
 archiveToRelationships :: Archive -> FilePath -> [Relationship]
@@ -716,12 +756,18 @@
 elemToRow :: NameSpaces -> Element -> D Row
 elemToRow ns element | isElem ns "w" "tr" element =
   do
+    let properties = findChildByName ns "w" "trPr" element
+    let gridBefore = properties
+                     >>= findChildByName ns "w" "gridBefore"
+                     >>= findAttrByName ns "w" "val"
+                     >>= stringToInteger
     let cellElems = findChildrenByName ns "w" "tc" element
+    let beforeCells = genericReplicate (fromMaybe 0 gridBefore) emptyCell
     cells <- mapD (elemToCell ns) cellElems
     let hasTblHeader = maybe NoTblHeader (const HasTblHeader)
-          (findChildByName ns "w" "trPr" element
+          (properties
            >>= findChildByName ns "w" "tblHeader")
-    return $ Row hasTblHeader cells
+    return $ Row hasTblHeader (beforeCells ++ cells)
 elemToRow _ _ = throwError WrongElem
 
 elemToCell :: NameSpaces -> Element -> D Cell
@@ -787,6 +833,28 @@
     = Captioned parstyle parparts x : addCaptioned xs
 addCaptioned (x:xs) = x : addCaptioned xs
 
+-- Split paragraphs that contain both a Drawing and text into two body parts,
+-- so that the captioning logic can combine them.
+splitMixedParagraphs :: [BodyPart] -> [BodyPart]
+splitMixedParagraphs [] = []
+splitMixedParagraphs (Paragraph ps parts : rest)
+  | (drawings@(_:_), texts@(_:_)) <- partition isDrawingPart parts
+  = Paragraph ps drawings : Paragraph ps texts : splitMixedParagraphs rest
+  where isDrawingPart Drawing{} = True
+        isDrawingPart _         = False
+splitMixedParagraphs (x:xs) = x : splitMixedParagraphs xs
+
+-- For textbox-image groups: combine image + any adjacent text into Captioned
+addSplitGroupCaptioned :: [BodyPart] -> [BodyPart]
+addSplitGroupCaptioned [] = []
+addSplitGroupCaptioned (Paragraph parstyle parparts : x : xs)
+  | isCaptionable x
+  = Captioned parstyle parparts x : addSplitGroupCaptioned xs
+addSplitGroupCaptioned (x : Paragraph parstyle parparts : xs)
+  | isCaptionable x
+  = Captioned parstyle parparts x : addSplitGroupCaptioned xs
+addSplitGroupCaptioned (x:xs) = x : addSplitGroupCaptioned xs
+
 isCaptionable :: BodyPart -> Bool
 isCaptionable (Paragraph _ [Drawing{}]) = True
 isCaptionable (Tbl{}) = True
@@ -914,11 +982,23 @@
   case target of
     Just filepath -> do
       media <- asks envMedia
-      let filepath' = case filepath of
-                        ('/':rest) -> rest
-                        _ -> "word/" ++ filepath
+      -- the mediaName is the name we store it under in the mediabag.
+      -- This is derived from the path, which might be absolute, e.g. /media/foo.jpg,
+      -- or relative, media/foo.jpg (interpreted as /word/media/foo.jpg).
+      -- The mediaName will strip off any leading `/` or `word/`.
+      -- We assume here that the media will not be stored *both* in
+      -- /media and in /word/media, which would lead to a name conflict
+      -- given the scheme here for generating a mediaName.
+      let (filepath', mediaName) =
+            case filepath of
+               ('/':rest)  -- absolute path e.g. /media/foo.jpg
+                  -> (rest, case stripPrefix "word/" rest of
+                              Just rest' -> rest'
+                              Nothing -> rest)
+               _  -- rel path to word, e.g. media/foo.jpg
+                 -> ("word/" ++ filepath, filepath)
       case lookup filepath' media of
-        Just bs -> return (filepath, bs)
+        Just bs -> return (mediaName, bs)
         Nothing -> throwError DocxError
     Nothing -> throwError DocxError
 
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
@@ -110,6 +110,7 @@
        (if bottomLevel < 1
            then walk (adjustHeaders (1 - bottomLevel))
            else id) $
+       walk (resolveFootnoteMarks (sFootnoteTexts st)) $
        walk (resolveRefs (sLabels st)) doc'
   return $ Pandoc meta bs'
 
@@ -124,7 +125,19 @@
         _ -> x
 resolveRefs _ x = x
 
+-- | Resolve footnote marks (\footnotemark) to actual notes using
+-- the footnote texts collected from \footnotetext commands.
+resolveFootnoteMarks :: M.Map Int Blocks -> Inline -> Inline
+resolveFootnoteMarks fnTexts (Span (_, classes, kvs) _)
+  | "footnote-mark" `elem` classes
+  , Just numText <- lookup "note-num" kvs
+  , [(n, "")] <- reads (T.unpack numText)
+  = case M.lookup n fnTexts of
+      Just contents -> Note (toList contents)
+      Nothing       -> Str ""  -- No matching footnotetext found
+resolveFootnoteMarks _ x = x
 
+
 -- testParser :: LP PandocIO a -> Text -> IO a
 -- testParser p t = do
 --   res <- runIOorExplode (runParserT p defaultLaTeXState{
@@ -407,6 +420,8 @@
     , ("lowercase", makeLowercase <$> tok)
     , ("thanks", skipopts >> note <$> grouped block)
     , ("footnote", skipopts >> footnote)
+    , ("footnotemark", footnotemark)
+    , ("footnotetext", footnotetext)
     , ("newline", pure B.linebreak)
     , ("passthrough", fixPassthroughEscapes <$> tok)
     -- \passthrough macro used by latex writer
@@ -476,6 +491,39 @@
   updateState $ \st -> st{ sLastNoteNum = sLastNoteNum st + 1 }
   contents <- grouped block >>= walkM resolveNoteLabel
   return $ note contents
+
+-- | Parse \footnotemark[n]. If n is not given, increment the counter.
+-- Returns a span marker that will be resolved to a Note later.
+footnotemark :: PandocMonad m => LP m Inlines
+footnotemark = do
+  mbNum <- optionalFootnoteNum
+  noteNum <- case mbNum of
+    Just n  -> return n
+    Nothing -> do
+      updateState $ \st -> st{ sLastNoteNum = sLastNoteNum st + 1 }
+      sLastNoteNum <$> getState
+  return $ B.spanWith ("", ["footnote-mark"], [("note-num", tshow noteNum)]) mempty
+
+-- | Parse \footnotetext[n]{text}. If n is not given, use current counter.
+-- Stores the text in state to be resolved later.
+footnotetext :: PandocMonad m => LP m Inlines
+footnotetext = do
+  mbNum <- optionalFootnoteNum
+  noteNum <- case mbNum of
+    Just n  -> return n
+    Nothing -> sLastNoteNum <$> getState
+  contents <- grouped block >>= walkM resolveNoteLabel
+  updateState $ \st -> st{
+    sFootnoteTexts = M.insert noteNum contents (sFootnoteTexts st) }
+  return mempty
+
+-- | Parse optional footnote number argument [n]
+optionalFootnoteNum :: PandocMonad m => LP m (Maybe Int)
+optionalFootnoteNum = option Nothing $ do
+  t <- bracketedToks
+  case reads (T.unpack $ untokenize t) of
+    [(n, "")] -> return $ Just n
+    _         -> return Nothing
 
 resolveNoteLabel :: PandocMonad m => Inline -> LP m Inline
 resolveNoteLabel (Span (_,cls,kvs) _)
diff --git a/src/Text/Pandoc/Readers/LaTeX/Parsing.hs b/src/Text/Pandoc/Readers/LaTeX/Parsing.hs
--- a/src/Text/Pandoc/Readers/LaTeX/Parsing.hs
+++ b/src/Text/Pandoc/Readers/LaTeX/Parsing.hs
@@ -165,6 +165,7 @@
                             , sLastFigureNum :: DottedNum
                             , sLastTableNum  :: DottedNum
                             , sLastNoteNum   :: Int
+                            , sFootnoteTexts :: M.Map Int Blocks
                             , sTheoremMap    :: M.Map Text TheoremSpec
                             , sLastTheoremStyle :: TheoremStyle
                             , sLastLabel     :: Maybe Text
@@ -195,6 +196,7 @@
                               , sLastFigureNum = DottedNum []
                               , sLastTableNum  = DottedNum []
                               , sLastNoteNum   = 0
+                              , sFootnoteTexts = M.empty
                               , sTheoremMap    = M.empty
                               , sLastTheoremStyle = PlainStyle
                               , sLastLabel     = Nothing
diff --git a/src/Text/Pandoc/Readers/LaTeX/Table.hs b/src/Text/Pandoc/Readers/LaTeX/Table.hs
--- a/src/Text/Pandoc/Readers/LaTeX/Table.hs
+++ b/src/Text/Pandoc/Readers/LaTeX/Table.hs
@@ -35,6 +35,8 @@
   , ("tabular*", env "tabular*" $ simpTable block inline "tabular*" True)
   , ("tabularx", env "tabularx" $ simpTable block inline "tabularx" True)
   , ("tabular", env "tabular"  $ simpTable block inline "tabular" False)
+  , ("supertabular", env "supertabular" $ simpTable block inline "supertabular" False)
+  , ("supertabular*", env "supertabular*" $ simpTable block inline "supertabular*" False)
   ]
  where
    blocks = mconcat <$> many block
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
@@ -1073,8 +1073,7 @@
                    <* lookAhead header)
               <|> (guardEnabled Ext_lists_without_preceding_blankline
                     -- Avoid creating a paragraph in a nested list.
-                    <* notFollowedBy' inList
-                    <* lookAhead listStart)
+                    <* notFollowedBy' (inList <* listStart))
               <|> do guardEnabled Ext_native_divs
                      inHtmlBlock <- stateInHtmlBlock <$> getState
                      case inHtmlBlock of
diff --git a/src/Text/Pandoc/Readers/ODT/ContentReader.hs b/src/Text/Pandoc/Readers/ODT/ContentReader.hs
--- a/src/Text/Pandoc/Readers/ODT/ContentReader.hs
+++ b/src/Text/Pandoc/Readers/ODT/ContentReader.hs
@@ -46,6 +46,8 @@
 import Text.Pandoc.Extensions (extensionsFromList, Extension(..))
 import qualified Text.Pandoc.UTF8 as UTF8
 
+import Text.Pandoc.Readers.Docx.Combine (combineBlocks)
+
 import Text.Pandoc.Readers.ODT.Base
 import Text.Pandoc.Readers.ODT.Namespaces
 import Text.Pandoc.Readers.ODT.StyleReader
@@ -205,11 +207,11 @@
            >>^ fst
 
 --
-getCurrentListLevel :: ODTReaderSafe _x ListLevel
+getCurrentListLevel :: ODTReaderSafe a ListLevel
 getCurrentListLevel = getExtraState >>^ currentListLevel
 
 --
-getListContinuationStartCounters :: ODTReaderSafe _x (M.Map ListLevel Int)
+getListContinuationStartCounters :: ODTReaderSafe a (M.Map ListLevel Int)
 getListContinuationStartCounters = getExtraState >>^ listContinuationStartCounters
 
 
@@ -278,7 +280,7 @@
 --------------------------------------------------------------------------------
 
 --
-readStyleByName :: ODTReader _x (StyleName, Style)
+readStyleByName :: ODTReader a (StyleName, Style)
 readStyleByName =
   findAttr NsText "style-name" >>? keepingTheValue getStyleByName >>^ liftE
   where
@@ -327,6 +329,7 @@
   where
     isCodeStyle :: StyleName -> Bool
     isCodeStyle "Source_Text" = True
+    isCodeStyle "Source_20_Text" = True
     isCodeStyle _             = False
 
     inlineCode :: Inlines -> Inlines
@@ -415,7 +418,7 @@
      = False
 
 --
-constructPara :: ODTReaderSafe Blocks Blocks -> ODTReaderSafe Blocks Blocks
+constructPara :: ODTReaderSafe a Blocks -> ODTReaderSafe a Blocks
 constructPara reader = proc blocks -> do
   fStyle <- readStyleByName -< blocks
   case fStyle of
@@ -546,6 +549,14 @@
 firstMatch :: a -> FirstMatch a
 firstMatch = FirstMatch . Alt . Just
 
+newtype CombiningBlocks = CombiningBlocks { unCombiningBlocks :: Blocks }
+
+instance Semigroup CombiningBlocks where
+  CombiningBlocks l <> CombiningBlocks r = CombiningBlocks (combineBlocks l r)
+
+instance Monoid CombiningBlocks where
+  mempty = CombiningBlocks mempty
+
 --
 matchingElement :: (Monoid e)
                 => Namespace -> ElementName
@@ -559,14 +570,20 @@
 --
 matchChildContent'   :: (Monoid result)
                      => [ElementMatcher result]
-                     ->  ODTReaderSafe _x result
+                     ->  ODTReaderSafe a result
 matchChildContent' ls = returnV mempty >>> matchContent' ls
 
 --
+matchSmushedChildBlocks' :: [ElementMatcher CombiningBlocks] ->  ODTReaderSafe a Blocks
+matchSmushedChildBlocks' ls = liftA unCombiningBlocks
+                              $ returnV mempty
+                                >>> matchContent' ls
+
+--
 matchChildContent    :: (Monoid result)
                      => [ElementMatcher result]
                      ->  ODTReaderSafe  (result, XML.Content) result
-                     ->  ODTReaderSafe _x result
+                     ->  ODTReaderSafe a result
 matchChildContent ls fallback = returnV mempty >>> matchContent ls fallback
 
 --------------------------------------------
@@ -634,34 +651,46 @@
                                         ] read_plain_text
 
 --
-read_paragraph   :: BlockMatcher
-read_paragraph    = matchingElement NsText "p"
-                    $ constructPara
-                    $ liftA para
-                    $ withNewStyle
-                    $ matchChildContent [ read_span
-                                        , read_spaces
-                                        , read_line_break
-                                        , read_tab
-                                        , read_link
-                                        , read_note
-                                        , read_citation
-                                        , read_bookmark
-                                        , read_bookmark_start
-                                        , read_reference_start
-                                        , read_bookmark_ref
-                                        , read_reference_ref
-                                        , read_frame
-                                        , read_text_seq
-                                        ] read_plain_text
+read_paragraph   :: ElementMatcher CombiningBlocks
+read_paragraph    = matchingElement NsText "p" $
+                      liftA CombiningBlocks $ proc blocks -> do
+                        fStyle <- readStyleByName -< blocks
+                        case fStyle of
+                          Right style | isPreformattedStyle style -> do
+                            liftA (codeBlock . stringify) $ matchParagraphContent -< blocks
+                          _ ->
+                            constructPara $ liftA para $ withNewStyle matchParagraphContent -< blocks
+                        where
+                          isPreformattedStyle :: (StyleName, Style) -> Bool
+                          isPreformattedStyle ("Preformatted_20_Text", _) = True
+                          isPreformattedStyle (_, Style { styleParentName = Just "Preformatted_20_Text" }) = True
+                          isPreformattedStyle _ = False
 
 
+matchParagraphContent :: ODTReaderSafe a Inlines
+matchParagraphContent = matchChildContent [ read_span
+                                          , read_spaces
+                                          , read_line_break
+                                          , read_tab
+                                          , read_link
+                                          , read_note
+                                          , read_citation
+                                          , read_bookmark
+                                          , read_bookmark_start
+                                          , read_reference_start
+                                          , read_bookmark_ref
+                                          , read_reference_ref
+                                          , read_frame
+                                          , read_text_seq
+                                          ] read_plain_text
+
+
 ----------------------
 -- Headers
 ----------------------
 
 --
-read_header      :: BlockMatcher
+read_header      :: ElementMatcher CombiningBlocks
 read_header       = matchingElement NsText "h"
                     $  proc blocks -> do
   level    <- ( readAttrWithDefault NsText "outline-level" 1
@@ -683,15 +712,16 @@
               ) -< blocks
   anchor   <- getHeaderAnchor -< children
   let idAttr = (anchor, [], []) -- no classes, no key-value pairs
-  arr (uncurry3 headerWith) -< (idAttr, level, children)
+  arr (CombiningBlocks . uncurry3 headerWith) -< (idAttr, level, children)
 
 ----------------------
 -- Lists
 ----------------------
 
 --
-read_list        :: BlockMatcher
+read_list        :: ElementMatcher CombiningBlocks
 read_list         = matchingElement NsText "list"
+                    $ liftA CombiningBlocks
                     $ constructList
                     $ matchChildContent' [ read_list_item
                                          , read_list_header
@@ -706,26 +736,26 @@
 read_list_element               :: ElementName -> ElementMatcher [Blocks]
 read_list_element listElement   = matchingElement NsText listElement
                                   $ liftA (compactify.(:[]))
-                                    ( matchChildContent' [ read_paragraph
-                                                         , read_header
-                                                         , read_list
-                                                         , read_section
-                                                         ]
+                                    ( matchSmushedChildBlocks' [ read_paragraph
+                                                               , read_header
+                                                               , read_list
+                                                               , read_section
+                                                               ]
                                     )
 
 ----------------------
 -- Sections
 ----------------------
 
-read_section :: ElementMatcher Blocks
+read_section :: ElementMatcher CombiningBlocks
 read_section = matchingElement NsText "section"
-                 $ liftA (divWith nullAttr)
-                 $ matchChildContent' [ read_paragraph
-                                      , read_header
-                                      , read_list
-                                      , read_table
-                                      , read_section
-                                      ]
+                 $ liftA (CombiningBlocks . divWith nullAttr)
+                 $ matchSmushedChildBlocks' [ read_paragraph
+                                            , read_header
+                                            , read_list
+                                            , read_table
+                                            , read_section
+                                            ]
 
 
 ----------------------
@@ -768,7 +798,7 @@
 
 read_note_body   :: BlockMatcher
 read_note_body    = matchingElement NsText "note-body"
-                    $ matchChildContent' [ read_paragraph ]
+                    $ matchSmushedChildBlocks' [ read_paragraph ]
 
 -------------------------
 -- Citations
@@ -792,9 +822,9 @@
 ----------------------
 
 --
-read_table        :: BlockMatcher
+read_table        :: ElementMatcher CombiningBlocks
 read_table         = matchingElement NsTable "table"
-                     $ liftA table'
+                     $ liftA (CombiningBlocks . table')
                      $ (matchChildContent' [read_table_header]) &&&
                        (matchChildContent' [read_table_row])
 
@@ -829,9 +859,9 @@
                      $ liftA3 cell'
                        (readAttrWithDefault NsTable "number-rows-spanned" 1 >>^ RowSpan)
                        (readAttrWithDefault NsTable "number-columns-spanned" 1 >>^ ColSpan)
-                     $ matchChildContent' [ read_paragraph
-                                          , read_list
-                                          ]
+                     $ matchSmushedChildBlocks' [ read_paragraph
+                                                , read_list
+                                                ]
   where
     cell' rowSpan colSpan blocks = map (cell AlignDefault rowSpan colSpan) $ compactify [blocks]
 
@@ -862,14 +892,15 @@
       ""   -> returnV mempty -< ()
       src' -> do
         let exts = extensionsFromList [Ext_auto_identifiers]
-        resource   <- lookupResource                          -< T.unpack src'
+            src'' = fixRelativeLink src'
+        resource   <- lookupResource                          -< T.unpack src''
         _          <- updateMediaWithResource                 -< resource
         w          <- findAttrText' NsSVG "width"             -< ()
         h          <- findAttrText' NsSVG "height"            -< ()
         titleNodes <- matchChildContent' [ read_frame_title ] -< ()
         alt        <- matchChildContent [] read_plain_text    -< ()
         arr (firstMatch . uncurry4 imageWith)                 -<
-          (image_attributes w h, src', inlineListToIdentifier exts (toList titleNodes), alt)
+          (image_attributes w h, src'', inlineListToIdentifier exts (toList titleNodes), alt)
 
 read_frame_title :: InlineMatcher
 read_frame_title = matchingElement NsSVG "title" (matchChildContent [] read_plain_text)
@@ -898,7 +929,7 @@
 
 read_frame_text_box :: ODTReaderSafe XML.Element (FirstMatch Inlines)
 read_frame_text_box = proc box -> do
-    paragraphs <- executeIn (matchChildContent' [ read_paragraph ]) -< box
+    paragraphs <- executeIn (matchSmushedChildBlocks' [ read_paragraph ]) -< box
     arr read_img_with_caption -< toList paragraphs
 
 read_img_with_caption :: [Block] -> FirstMatch Inlines
@@ -919,7 +950,7 @@
 _ANCHOR_PREFIX_ = "anchor"
 
 --
-readAnchorAttr :: ODTReader _x Anchor
+readAnchorAttr :: ODTReader a Anchor
 readAnchorAttr = findAttrText NsText "name"
 
 -- | Beware: may fail
@@ -960,7 +991,7 @@
                      $ maybeAddAnchorFrom readAnchorAttr
 
 -- | Beware: may fail
-findAnchorRef :: ODTReader _x Anchor
+findAnchorRef :: ODTReader a Anchor
 findAnchorRef = (      findAttrText NsText "ref-name"
                   >>?^ (_ANCHOR_PREFIX_,)
                 ) >>?! getPrettyAnchor
@@ -995,13 +1026,13 @@
 -- Entry point
 ----------------------
 
-read_text :: ODTReaderSafe _x Pandoc
-read_text = matchChildContent' [ read_header
-                               , read_paragraph
-                               , read_list
-                               , read_section
-                               , read_table
-                               ]
+read_text :: ODTReaderSafe a Pandoc
+read_text = matchSmushedChildBlocks' [ read_header
+                                     , read_paragraph
+                                     , read_list
+                                     , read_section
+                                     , read_table
+                                     ]
             >>^ doc
 
 post_process :: Pandoc -> Pandoc
@@ -1013,7 +1044,7 @@
   = Table attr (Caption Nothing blks) specs th tb tf : post_process' xs
 post_process' bs = bs
 
-read_body :: ODTReader _x (Pandoc, MediaBag)
+read_body :: ODTReader a (Pandoc, MediaBag)
 read_body = executeInSub NsOffice "body"
           $ executeInSub NsOffice "text"
           $ liftAsSuccess
diff --git a/src/Text/Pandoc/Readers/ODT/StyleReader.hs b/src/Text/Pandoc/Readers/ODT/StyleReader.hs
--- a/src/Text/Pandoc/Readers/ODT/StyleReader.hs
+++ b/src/Text/Pandoc/Readers/ODT/StyleReader.hs
@@ -114,7 +114,7 @@
 -- the fonts:
 
 -- | A reader for font pitches
-fontPitchReader :: XMLReader _s _x FontPitches
+fontPitchReader :: XMLReader s a FontPitches
 fontPitchReader = executeInSub NsOffice "font-face-decls" (
                           withEveryL NsStyle "font-face" (liftAsSuccess (
                               findAttr' NsStyle "name"
@@ -129,7 +129,7 @@
 
 -- | A wrapper around the font pitch reader that lifts the result into the
 -- state.
-readFontPitches :: StyleReader x x
+readFontPitches :: StyleReader a a
 readFontPitches = producingExtraState () () fontPitchReader
 
 
@@ -141,7 +141,7 @@
 --   and use the pitch from there.
 -- * Return the result in a Maybe
 --
-findPitch :: XMLReaderSafe FontPitches _x (Maybe FontPitch)
+findPitch :: XMLReaderSafe FontPitches a (Maybe FontPitch)
 findPitch =     ( lookupAttr NsStyle "font-pitch"
                   `ifFailedDo`     findAttr NsStyle "font-name"
                                >>? (     keepingTheValue getExtraState
@@ -416,7 +416,7 @@
 --------------------------------------------------------------------------------
 
 --
-readAllStyles :: StyleReader _x Styles
+readAllStyles :: StyleReader a Styles
 readAllStyles = (      readFontPitches
                   >>?! (     readAutomaticStyles
                          &&& readStyles ))
@@ -424,7 +424,7 @@
  -- all top elements are always on the same hierarchy level
 
 --
-readStyles :: StyleReader _x Styles
+readStyles :: StyleReader a Styles
 readStyles = executeInSub NsOffice "styles" $ liftAsSuccess
   $ liftA3 Styles
     ( tryAll NsStyle "style"         readStyle        >>^ M.fromList )
@@ -432,7 +432,7 @@
     ( tryAll NsStyle "default-style" readDefaultStyle >>^ M.fromList )
 
 --
-readAutomaticStyles :: StyleReader _x Styles
+readAutomaticStyles :: StyleReader a Styles
 readAutomaticStyles = executeInSub NsOffice "automatic-styles" $ liftAsSuccess
   $ liftA3 Styles
     ( tryAll NsStyle "style"         readStyle        >>^ M.fromList )
@@ -440,12 +440,12 @@
     ( returnV M.empty                                                )
 
 --
-readDefaultStyle :: StyleReader _x (StyleFamily, StyleProperties)
+readDefaultStyle :: StyleReader a (StyleFamily, StyleProperties)
 readDefaultStyle =      lookupAttr NsStyle "family"
                    >>?! keepingTheValue readStyleProperties
 
 --
-readStyle :: StyleReader _x (StyleName,Style)
+readStyle :: StyleReader a (StyleName,Style)
 readStyle =      findAttr NsStyle "name"
             >>?! keepingTheValue
                    ( liftA4 Style
@@ -456,13 +456,13 @@
                    )
 
 --
-readStyleProperties :: StyleReaderSafe _x StyleProperties
+readStyleProperties :: StyleReaderSafe a StyleProperties
 readStyleProperties = liftA2 SProps
                        ( readTextProperties >>> choiceToMaybe )
                        ( readParaProperties >>> choiceToMaybe )
 
 --
-readTextProperties :: StyleReader _x TextProperties
+readTextProperties :: StyleReader a TextProperties
 readTextProperties =
   executeInSub NsStyle "text-properties" $ liftAsSuccess
     ( liftA6 PropT
@@ -477,15 +477,15 @@
         isFontBold = ("normal",False):("bold",True)
                     :map ((,True) . tshow) ([100,200..900]::[Int])
 
-readUnderlineMode     :: StyleReaderSafe _x (Maybe UnderlineMode)
+readUnderlineMode     :: StyleReaderSafe a (Maybe UnderlineMode)
 readUnderlineMode     = readLineMode "text-underline-mode"
                                      "text-underline-style"
 
-readStrikeThroughMode :: StyleReaderSafe _x (Maybe UnderlineMode)
+readStrikeThroughMode :: StyleReaderSafe a (Maybe UnderlineMode)
 readStrikeThroughMode = readLineMode "text-line-through-mode"
                                      "text-line-through-style"
 
-readLineMode :: Text -> Text -> StyleReaderSafe _x (Maybe UnderlineMode)
+readLineMode :: Text -> Text -> StyleReaderSafe a (Maybe UnderlineMode)
 readLineMode modeAttr styleAttr = proc x -> do
   isUL <- searchAttr  NsStyle styleAttr False isLinePresent -< x
   mode <- lookupAttr' NsStyle  modeAttr                     -< x
@@ -501,7 +501,7 @@
                     ]
 
 --
-readParaProperties :: StyleReader _x ParaProperties
+readParaProperties :: StyleReader a ParaProperties
 readParaProperties =
    executeInSub NsStyle "paragraph-properties" $ liftAsSuccess
      ( liftA3 PropP
@@ -527,7 +527,7 @@
 ----
 
 --
-readListStyle :: StyleReader _x (StyleName, ListStyle)
+readListStyle :: StyleReader a (StyleName, ListStyle)
 readListStyle =
        findAttr NsStyle "name"
   >>?! keepingTheValue
@@ -540,13 +540,13 @@
 --
 readListLevelStyles :: Namespace -> ElementName
                     -> ListLevelType
-                    -> StyleReaderSafe _x (SM.SetMap Int ListLevelStyle)
+                    -> StyleReaderSafe a (SM.SetMap Int ListLevelStyle)
 readListLevelStyles namespace elementName levelType =
   tryAll namespace elementName (readListLevelStyle levelType)
     >>^ SM.fromList
 
 --
-readListLevelStyle :: ListLevelType -> StyleReader _x (Int, ListLevelStyle)
+readListLevelStyle :: ListLevelType -> StyleReader a (Int, ListLevelStyle)
 readListLevelStyle levelType =      readAttr NsText "level"
                                >>?! keepingTheValue
                                     ( liftA5 toListLevelStyle
diff --git a/src/Text/Pandoc/Readers/Textile.hs b/src/Text/Pandoc/Readers/Textile.hs
--- a/src/Text/Pandoc/Readers/Textile.hs
+++ b/src/Text/Pandoc/Readers/Textile.hs
@@ -413,8 +413,12 @@
   notFollowedBy blankline
   raw <- trim . T.pack <$>
          many (noneOf "|\n" <|> try (char '\n' <* notFollowedBy blankline))
-  content <- mconcat <$> parseFromString' (many inline) raw
-  return ((isHeader, alignment), B.plain content)
+  content <- parseFromString' parseBlocks (raw <> "\n\n")
+  -- Convert lone Para to Plain for backward compatibility
+  let content' = case B.toList content of
+                   [Para ils] -> B.plain (B.fromList ils)
+                   _          -> content
+  return ((isHeader, alignment), content')
 
 -- | A table row is made of many table cells
 tableRow :: PandocMonad m => TextileParser m [((Bool, Alignment), Blocks)]
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
@@ -29,9 +29,11 @@
 import Text.Pandoc.Definition
 import Typst ( parseTypst, evaluateTypst )
 import Text.Pandoc.Error (PandocError(..))
+import Text.Pandoc.Translations (Term(References), translateTerm)
 import Text.Pandoc.Shared (tshow, blocksToInlines)
 import Control.Monad.Except (throwError)
 import Control.Monad (MonadPlus (mplus), void, guard, foldM)
+import Control.Monad.Trans (lift)
 import qualified Data.Foldable as F
 import qualified Data.Map as M
 import Data.Maybe (catMaybes, fromMaybe, isJust)
@@ -401,6 +403,25 @@
   ,("pad", \_ _ fields ->  -- ignore paddingy
       getField "body" fields >>= pWithContents pBlocks)
   ,("pagebreak", \_ _ _ -> pure $ B.divWith ("", ["page-break"], [("wrapper", "1")]) B.horizontalRule)
+  ,("bibliography", \_ _ fields -> do
+      let getSources v = case v of
+                      VString t -> MetaString t
+                      VArray xs -> MetaList $ map getSources $ V.toList xs
+                      _ -> MetaBool True -- should not occur
+      let mbSources = getSources <$> M.lookup "sources" fields
+
+      let updateBibliography x = updateState $ \s ->
+             s{ sMeta = B.setMeta "bibliography" x (sMeta s) }
+      maybe (pure ()) updateBibliography mbSources
+
+      let title' = M.lookup "title" fields
+      mbTitle <- case title' of
+                   Just VNone -> pure Nothing
+                   Just (VContent cs) -> Just <$> pWithContents pInlines cs
+                   Just (VString t) -> pure $ Just $ B.text t
+                   _ -> Just . B.text <$> lift (translateTerm References)
+      let hdr = maybe mempty (B.header 1) mbTitle
+      pure $ hdr <> B.divWith ("refs", [], []) mempty)
   ]
 
 inlineHandlers :: PandocMonad m =>
diff --git a/src/Text/Pandoc/Writers/Docx.hs b/src/Text/Pandoc/Writers/Docx.hs
--- a/src/Text/Pandoc/Writers/Docx.hs
+++ b/src/Text/Pandoc/Writers/Docx.hs
@@ -52,7 +52,6 @@
 import Text.Pandoc.Highlighting (defaultStyle)
 import Text.Pandoc.MIME (MimeType, getMimeTypeDef)
 import Text.Pandoc.Options
-import Text.Pandoc.Readers.Docx.Parse (extractTarget)
 import Text.Pandoc.Writers.Docx.StyleMap
 import Text.Pandoc.Writers.Docx.Types
 import Text.Pandoc.Writers.Docx.OpenXML (writeOpenXML, maxListLevel)
@@ -638,6 +637,8 @@
                           fromMaybe "application/octet-stream" mbMimeType)
       mkMediaOverride imgpath =
           mkOverrideNode ("/" <> imgpath, getMimeTypeDef imgpath)
+      unrelativize ('/':xs) = '/':xs
+      unrelativize xs = "/word/" ++ xs
       overrides = map mkOverrideNode (
                   [("/word/webSettings.xml",
                     "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml")
@@ -664,9 +665,9 @@
                   ,("/word/footnotes.xml",
                     "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml")
                   ] ++
-                  map (\x -> (maybe "" (T.unpack . ("/word/" <>)) (extractTarget x),
+                  map (\x -> (maybe "" (unrelativize . T.unpack) (extractTarget x),
                        "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml")) headers ++
-                  map (\x -> (maybe "" (T.unpack . ("/word/" <>)) (extractTarget x),
+                  map (\x -> (maybe "" (unrelativize . T.unpack) (extractTarget x),
                        "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml")) footers) ++
                     map mkImageOverride imgs ++
                     [ mkMediaOverride (eRelativePath e)
@@ -829,7 +830,9 @@
   let fontEntries = [entry | entry <- zEntries refArchive
                            , "word/fonts/" `isPrefixOf` (eRelativePath entry)]
   webSettingsEntry <- entryFromArchive refArchive "word/webSettings.xml"
-  headerFooterEntries <- mapM (entryFromArchive refArchive . ("word/" ++)) $
+  let unrelativize ('/':xs) = xs
+      unrelativize xs = "word/" ++ xs
+  headerFooterEntries <- mapM (entryFromArchive refArchive . unrelativize) $
                          mapMaybe (fmap T.unpack . extractTarget)
                          (headers ++ footers)
   let miscRelEntries = [ e | e <- zEntries refArchive
@@ -842,3 +845,6 @@
   return $ docPropsAppEntry : themeEntry : fontTableEntry : webSettingsEntry
          : fontTableRelsEntries ++ fontEntries ++ headerFooterEntries
          ++ miscRelEntries ++ otherMediaEntries
+
+extractTarget :: Element -> Maybe Text
+extractTarget = findAttr (QName "Target" Nothing Nothing)
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
@@ -20,7 +20,7 @@
 -}
 module Text.Pandoc.Writers.Docx.OpenXML ( writeOpenXML, maxListLevel ) where
 
-import Control.Monad ((>=>), when, unless)
+import Control.Monad (when, unless)
 import Control.Applicative ((<|>))
 import Control.Monad.Except (catchError)
 import Crypto.Hash (hashWith, SHA1(SHA1))
@@ -329,14 +329,6 @@
 blocksToOpenXML opts =
   fmap concat . mapM (blockToOpenXML opts)
   . separateTables . filter (not . isForeignRawBlock)
-  >=>
-  \case
-    a@(x:xs) -> do
-      sep <- sectionSeparator
-      if Just x == sep
-        then pure xs
-        else pure a
-    [] -> pure []
 
 isForeignRawBlock :: Block -> Bool
 isForeignRawBlock (RawBlock format _) = format /= "openxml"
@@ -414,9 +406,19 @@
                 Nothing -> return []
            else return []
   contents <- (number ++) <$> inlinesToOpenXML opts lst
-  addSectionBreak <- sectionSeparator >>= \case
-    Just sep | isSection -> pure (sep:)
-    _  -> pure id
+  -- Add section break before section-level headers, but not for the first one
+  -- to avoid a blank first page (#10578, #11482).
+  addSectionBreak <- if isSection
+    then do
+      isFirst <- gets stFirstSectionHeader
+      if isFirst
+        then do
+          modify $ \s -> s { stFirstSectionHeader = False }
+          pure id
+        else sectionSeparator >>= \case
+          Just sep -> pure (sep:)
+          Nothing  -> pure id
+    else pure id
   addSectionBreak <$>
     if T.null ident
        then return [Elem $ mknode "w:p" [] (map Elem paraProps ++ contents)]
diff --git a/src/Text/Pandoc/Writers/Docx/Types.hs b/src/Text/Pandoc/Writers/Docx/Types.hs
--- a/src/Text/Pandoc/Writers/Docx/Types.hs
+++ b/src/Text/Pandoc/Writers/Docx/Types.hs
@@ -121,6 +121,7 @@
        , stDelId          :: Int
        , stStyleMaps      :: StyleMaps
        , stFirstPara      :: Bool
+       , stFirstSectionHeader :: Bool  -- ^ True until first section header is processed
        , stNumIdUsed      :: Bool  -- ^ True if the current numId (envListNumId) has been used.
                                    --   Should only be used once, for the first paragraph.
        , stInTable        :: Bool
@@ -146,6 +147,7 @@
       , stDelId          = 1
       , stStyleMaps      = StyleMaps M.empty M.empty
       , stFirstPara      = False
+      , stFirstSectionHeader = True
       , stNumIdUsed      = False
       , stInTable        = False
       , stInList         = False
diff --git a/src/Text/Pandoc/Writers/EPUB.hs b/src/Text/Pandoc/Writers/EPUB.hs
--- a/src/Text/Pandoc/Writers/EPUB.hs
+++ b/src/Text/Pandoc/Writers/EPUB.hs
@@ -1048,10 +1048,9 @@
         coverageNodes = maybe [] (dcTag' "coverage") $ epubCoverage md
         rightsNodes = maybe [] (dcTag' "rights") $ epubRights md
         coverImageNodes = maybe []
-            (\img -> [unode "meta" !  [(metaprop,"cover"),
-                                       ("content",toId img)] $ ()
-                        | version == EPUB2])
-            $ mbCoverImage
+            (\img -> [unode "meta" !  [("name","cover"),
+                                       ("content",toId img)] $ ()])
+            mbCoverImage
         modifiedNodes = [ unode "meta" ! [(metaprop, "dcterms:modified")] $
                showDateTimeISO8601 currentTime | version == EPUB3 ]
         belongsToCollectionNodes =
@@ -1141,11 +1140,18 @@
         schemeToOnix "ISBN-13"              = "15"
         schemeToOnix "Legal deposit number" = "17"
         schemeToOnix "URN"                  = "22"
-        schemeToOnix "OCLC"                 = "23"
+        schemeToOnix "OCLC number"          = "23"
+        schemeToOnix "Co-publisher’s ISBN-13" = "24"
         schemeToOnix "ISMN-13"              = "25"
         schemeToOnix "ISBN-A"               = "26"
-        schemeToOnix "JP"                   = "27"
-        schemeToOnix "OLCC"                 = "28"
+        schemeToOnix "JP e-code"            = "27"
+        schemeToOnix "OLCC number"          = "28"
+        schemeToOnix "JP Magazine ID"       = "29"
+        schemeToOnix "UPC-12+5"             = "30"
+        schemeToOnix "BNF Control number"   = "31"
+        schemeToOnix "ISSN-13"              = "34"
+        schemeToOnix "ARK"                  = "35"
+        schemeToOnix "Digital file internal version number" = "36"
         schemeToOnix _                      = "01"
 
 showDateTimeISO8601 :: UTCTime -> Text
diff --git a/src/Text/Pandoc/Writers/GridTable.hs b/src/Text/Pandoc/Writers/GridTable.hs
--- a/src/Text/Pandoc/Writers/GridTable.hs
+++ b/src/Text/Pandoc/Writers/GridTable.hs
@@ -82,10 +82,15 @@
   -> [B.TableBody]
   -> B.TableFoot
   -> Table
-toTable attr caption colSpecs  thead tbodies tfoot =
+toTable attr caption colSpecs thead' tbodies' tfoot' =
   Table attr caption colSpecs' rowHeads thGrid tbGrids tfGrid
   where
-    colSpecs' = listArray (ColIndex 1, ColIndex $ length colSpecs) colSpecs
+    -- normalize in case it's invalid shape:
+    thead = B.normalizeTableHead numcols thead'
+    tbodies = map (B.normalizeTableBody numcols) tbodies'
+    tfoot = B.normalizeTableFoot numcols tfoot'
+    numcols = length colSpecs
+    colSpecs' = listArray (ColIndex 1, ColIndex numcols) colSpecs
     rowHeads = case listToMaybe tbodies of
       Nothing -> RowHeadColumns 0
       Just (TableBody _attr rowHeadCols _headerRows _rows) -> rowHeadCols
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
@@ -49,7 +49,7 @@
 import Numeric (showHex)
 import Text.DocLayout (render, literal, Doc)
 import Text.Blaze.Internal (MarkupM (Empty), customLeaf, customParent)
-import Text.DocTemplates (FromContext (lookupContext), Context (..))
+import Text.DocTemplates (FromContext (lookupContext), Context (..), Val(..))
 import qualified Text.DocTemplates.Internal as DT
 import Text.Blaze.Html hiding (contents)
 import Text.Pandoc.Definition
@@ -434,7 +434,11 @@
                          defField "backgroundTransition" ("fade" :: Doc Text) .
                          defField "viewDistance" ("3" :: Doc Text) .
                          defField "mobileViewDistance" ("2" :: Doc Text) .
-                         defField "scrollProgress" True .
+                         (case (lookupContext "scrollProgress" metadata
+                                   :: Maybe (Val Text)) of
+                            Just (BoolVal False) -> id
+                            Just (BoolVal True) -> defField "scrollProgress" True
+                            _  -> defField "scrollProgressAuto" True) .
                          defField "scrollActivationWidth" ("0" :: Doc Text) .
                          defField "scrollSnap" ("mandatory" :: Doc Text) .
                          defField "scrollLayout" ("full" :: Doc Text) .
diff --git a/src/Text/Pandoc/Writers/ICML.hs b/src/Text/Pandoc/Writers/ICML.hs
--- a/src/Text/Pandoc/Writers/ICML.hs
+++ b/src/Text/Pandoc/Writers/ICML.hs
@@ -44,6 +44,7 @@
 data WriterState = WriterState{
     blockStyles  :: Set.Set Text
   , inlineStyles :: Set.Set Text
+  , objectStyles :: Set.Set Text
   , links        :: Hyperlink
   , listDepth    :: Int
   , maxListDepth :: Int
@@ -55,6 +56,7 @@
 defaultWriterState = WriterState{
     blockStyles  = Set.empty
   , inlineStyles = Set.empty
+  , objectStyles = Set.empty
   , links        = []
   , listDepth    = 1
   , maxListDepth = 0
@@ -147,9 +149,10 @@
              meta
   (main, st) <- runStateT (blocksToICML opts [] blocks) defaultWriterState
   let context = defField "body" main
-              $ defField "charStyles" (charStylesToDoc st)
-              $ defField "parStyles"  (parStylesToDoc st)
-              $ defField "hyperlinks" (hyperlinksToDoc $ links st) metadata
+              $ defField "charStyles"   (charStylesToDoc st)
+              $ defField "parStyles"    (parStylesToDoc st)
+              $ defField "objectStyles" (objectStylesToDoc st)
+              $ defField "hyperlinks"   (hyperlinksToDoc $ links st) metadata
   return $ render colwidth $
     (if writerPreferAscii opts then fmap toEntities else id) $
     case writerTemplate opts of
@@ -272,6 +275,16 @@
                          else empty
       in  inTags True "CharacterStyle" ([("Self", "CharacterStyle/"<>s), ("Name", s)] ++ attrs') props
 
+-- | Convert a WriterState with its object styles to the ICML listing of Object Styles.
+objectStylesToDoc :: WriterState -> Doc Text
+objectStylesToDoc st = vcat $ map makeStyle $ Set.toAscList $ objectStyles st
+  where
+    makeStyle s =
+      let attrs = []
+          props = inTags True "Properties" [] $
+                    inTags False "BasedOn" [("type", "string")] (text "$ID/None")
+      in  inTags True "ObjectStyle" ([("Self", "ObjectStyle/"<>s), ("Name", s)] ++ attrs) props
+
 -- | Escape colon characters as %3a
 escapeColons :: Text -> Text
 escapeColons txt = Text.replace ":" "%3a" txt
@@ -601,6 +614,10 @@
       attrs = [("AppliedCharacterStyle", stl)]
   in  (stlStr, attrs)
 
+-- | Key for specifying user-defined object (image) styles
+objectStyleKey :: Text
+objectStyleKey = "object-style"
+
 -- | Assemble an ICML Image.
 imageICML :: PandocMonad m => WriterOptions -> Style -> Attr -> Target -> WS m (Doc Text)
 imageICML opts style attr (src, _) = do
@@ -647,19 +664,31 @@
                 then mempty
                 else  selfClosingTag "Link" [("Self", "ueb"),
                                              ("LinkResourceURI", src')]
-      image  = inTags True "Image"
-                   [("Self","ue6"), ("ItemTransform", scale<>" -"<>hw<>" -"<>hh)]
-                 $ vcat [
-                     inTags True "Properties" [] $ vcat [
-                         inTags True "Profile" [("type","string")] $ text "$ID/Embedded"
-                       , selfClosingTag "GraphicBounds" [("Left","0"), ("Top","0")
-                         , ("Right",  showFl $ ow*ow / imgWidth)
-                         , ("Bottom", showFl $ oh*oh / imgHeight)]
-                       , contents
-                       ]
-                   , link
-                   ]
-      doc    = inTags True "CharacterStyleRange" attrs
-                 $ inTags True "Rectangle" [("Self","uec"), ("StrokeWeight", "0"),
-                     ("ItemTransform", scale<>" "<>hw<>" -"<>hh)] (props $$ image)
-  state $ \st -> (doc, st{ inlineStyles = Set.insert stlStr $ inlineStyles st } )
+      (_,_,kvs) = attr
+      applyObjectStyle = lookup objectStyleKey kvs
+      image = inTags True "Image"
+            [("Self","ue6"), ("ItemTransform", scale <> " -" <> hw <> " -" <> hh)]
+            $ vcat [
+                inTags True "Properties" [] $ vcat [
+                    inTags True "Profile" [("type","string")] $ text "$ID/Embedded",
+                    selfClosingTag "GraphicBounds" [("Left","0"), ("Top","0"),
+                    ("Right", showFl $ ow * ow / imgWidth),
+                    ("Bottom", showFl $ oh * oh / imgHeight)],
+                    contents
+                ],
+                link
+            ]
+      doc   = inTags True "CharacterStyleRange" attrs
+          $ inTags True "Rectangle"
+              ([("Self","uec"),
+                ("StrokeWeight", "0"),
+                ("ItemTransform", scale <> " " <> hw <> " -" <> hh)] ++
+                maybe [] (\aos -> [("AppliedObjectStyle", "ObjectStyle/" <> aos)]) applyObjectStyle
+              )
+              (props $$ image)
+  state $ \st -> (doc, st{
+      inlineStyles = Set.insert stlStr $ inlineStyles st,
+      objectStyles = case applyObjectStyle of
+          Just styleName -> Set.insert styleName $ objectStyles st
+          Nothing        -> objectStyles st
+    })
diff --git a/src/Text/Pandoc/Writers/JATS.hs b/src/Text/Pandoc/Writers/JATS.hs
--- a/src/Text/Pandoc/Writers/JATS.hs
+++ b/src/Text/Pandoc/Writers/JATS.hs
@@ -360,11 +360,21 @@
   return $ inTags True cls attr contents
 blockToJATS opts (Div (ident,_,kvs) bs) = do
   contents <- blocksToJATS opts bs
-  let attr = [("id", escapeNCName ident) | not (T.null ident)] ++
-             [("xml:lang",l) | ("lang",l) <- kvs] ++
-             [(k,v) | (k,v) <- kvs, k `elem` ["specific-use",
-                 "content-type", "orientation", "position"]]
-  return $ inTags True "boxed-text" attr contents
+  -- Attributes that are allowed on both @<p>@ and @<boxed-text>@ elements
+  let generic_attr = [("id", escapeNCName ident) | not (T.null ident)] ++
+                     [("xml:lang",l) | ("lang",l) <- kvs] ++
+                     [(k,v) | (k,v) <- kvs, k `elem` ["specific-use",
+                                                      "content-type"]]
+  let boxed_attr = [(k,v) | (k,v) <- kvs, k `elem` ["orientation", "position"]]
+  let attr = generic_attr <> boxed_attr
+  return $
+    if null attr
+    then contents
+    else -- The contents must be wrapped in an appropriate element.
+      let element = if null boxed_attr
+                    then "p"
+                    else "boxed-text"
+      in inTags True element (generic_attr <> boxed_attr) contents
 blockToJATS opts (Header _ _ title) = do
   title' <- inlinesToJATS opts (map fixLineBreak title)
   return $ inTagsSimple "title" title'
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
@@ -376,15 +376,10 @@
   | isEnabled Ext_alerts opts
   , (cls:_) <- classes
   , cls `elem` ["note", "tip", "warning", "caution", "important"]
-  , (Div ("", ["title"], []) _ : Para ils : bs') <- bs
-   = blockToMarkdown' opts $ BlockQuote $
-       (Para (RawInline (Format "markdown") (case cls of
-         "note" -> "[!NOTE]\n"
-         "tip" -> "[!TIP]\n"
-         "warning" -> "[!WARNING]\n"
-         "caution" -> "[!CAUTION]\n"
-         "important" -> "[!IMPORTANT]\n"
-         _ -> "[!NOTE]\n") : ils)) : bs'
+  , (Div ("", ["title"], []) _ : bs') <- bs = do
+    contents <- blockListToMarkdown opts bs'
+    let alertLabel = literal $ "[!" <> T.toUpper cls <> "]"
+    pure $ text "> " <> alertLabel $$ prefixed "> " contents $$ blankline
   | otherwise = do
     contents <- blockListToMarkdown opts bs
     variant <- asks envVariant
diff --git a/src/Text/Pandoc/Writers/Markdown/Inline.hs b/src/Text/Pandoc/Writers/Markdown/Inline.hs
--- a/src/Text/Pandoc/Writers/Markdown/Inline.hs
+++ b/src/Text/Pandoc/Writers/Markdown/Inline.hs
@@ -89,6 +89,9 @@
     | isEnabled Ext_mark opts = '\\':'=':go ('=':cs)
   go ('~':'~':cs)
     | isEnabled Ext_strikeout opts = '\\':'~':go ('~':cs)
+  go ('&':cs)
+    | Right _ <- parse characterReference "" ('&':cs)
+    = '\\':'&': go cs
   go (c:cs) =
     case c of
        '[' -> '\\':c:go cs
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
@@ -106,16 +106,22 @@
                     then ""
                     else "alt=" <> capt'
                else "alt=" <> tit
-  return $ literal ("[[" <>
-            T.intercalate "|"
-            (filter (not . T.null) ["File:" <> src
-                                 , "thumb"
-                                 , "none"
-                                 , img
-                                 , opt
-                                 , capt'
-                                 ]) <>
-            "]]") <> cr
+  let separator = "<nowiki></nowiki>"
+  -- External images (URIs) cannot use [[File:...]] syntax;
+  -- they must be rendered as bare URLs. MediaWiki will auto-embed
+  -- them when $wgAllowExternalImages is enabled.
+  return $ if isURI src
+           then literal (separator <> src <> separator) <> cr
+           else literal ("[[" <>
+                  T.intercalate "|"
+                  (filter (not . T.null) ["File:" <> src
+                                       , "thumb"
+                                       , "none"
+                                       , img
+                                       , opt
+                                       , capt'
+                                       ]) <>
+                  "]]") <> cr
 
 blockToMediaWiki (Para inlines) = do
   tags <- asks useTags
@@ -496,21 +502,28 @@
        where src' = fromMaybe src $ T.stripPrefix "/" src
 
 inlineToMediaWiki (Image attr alt (source, tit)) = do
-  img  <- imageToMediaWiki attr
-  alt' <- inlineListToMediaWiki alt
-  let altText = render Nothing alt'
-  let txt = if T.null altText
-               then if T.null tit
-                       then ""
-                       else tit
-               else altText
-  return $ literal $ "[[" <>
-           T.intercalate "|"
-           (filter (not . T.null)
-            [ "File:" <> source
-            , img
-            , txt
-            ]) <> "]]"
+  let separator = "<nowiki></nowiki>"
+  -- External images (URIs) cannot use [[File:...]] syntax;
+  -- they must be rendered as bare URLs. MediaWiki will auto-embed
+  -- them when $wgAllowExternalImages is enabled.
+  if isURI source
+     then return $ literal $ separator <> source <> separator
+     else do
+       img  <- imageToMediaWiki attr
+       alt' <- inlineListToMediaWiki alt
+       let altText = render Nothing alt'
+       let txt = if T.null altText
+                    then if T.null tit
+                            then ""
+                            else tit
+                    else altText
+       return $ literal $ "[[" <>
+                T.intercalate "|"
+                (filter (not . T.null)
+                 [ "File:" <> source
+                 , img
+                 , txt
+                 ]) <> "]]"
 
 inlineToMediaWiki (Note contents) = do
   contents' <- blockListToMediaWiki contents
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
@@ -671,7 +671,7 @@
     where
       unhighlighted s = inlinedCode $ preformatted s
       inlinedCode s = return $ inTags False "text:span"
-                                 [("text:style-name", "Source_Text")] s
+                                 [("text:style-name", "Source_20_Text")] s
       mkImg (_, _, kvs) s _ = do
                id' <- gets stImageId
                modify (\st -> st{ stImageId = id' + 1 })
diff --git a/src/Text/Pandoc/Writers/Powerpoint/Output.hs b/src/Text/Pandoc/Writers/Powerpoint/Output.hs
--- a/src/Text/Pandoc/Writers/Powerpoint/Output.hs
+++ b/src/Text/Pandoc/Writers/Powerpoint/Output.hs
@@ -2689,12 +2689,16 @@
   mediaInfos <- mconcat . M.elems <$> gets stMediaIds
   filePaths <- patternsToFilePaths $ inheritedPatterns p
   let mediaFps = filter (match (compile "ppt/media/image*")) filePaths
+      fontFps = filter (match (compile "ppt/fonts/*")) filePaths
   let defaults = [ DefaultContentType "xml" "application/xml"
                  , DefaultContentType "rels" "application/vnd.openxmlformats-package.relationships+xml"
                  ]
       mediaDefaults = nub $
                       mapMaybe mediaContentType mediaInfos <>
                       mapMaybe mediaFileContentType mediaFps
+      fontDefaults = [ DefaultContentType "fntdata" "application/x-fontdata"
+                     | any (\fp -> takeExtension fp == ".fntdata") fontFps
+                     ]
 
       inheritedOverrides = mapMaybe pathToOverride filePaths
       createdOverrides = mapMaybe pathToOverride [ "docProps/core.xml"
@@ -2708,7 +2712,7 @@
                        relativePaths
   speakerNotesOverrides <- mapMaybe pathToOverride <$> getSpeakerNotesFilePaths
   return $ ContentTypes
-    (defaults <> mediaDefaults)
+    (defaults <> mediaDefaults <> fontDefaults)
     (inheritedOverrides <> createdOverrides <> slideOverrides <> speakerNotesOverrides)
 
 presML :: T.Text
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,7 +18,7 @@
     writeTypst
   ) where
 import Text.Pandoc.Definition
-import Text.Pandoc.Class ( PandocMonad, report )
+import Text.Pandoc.Class ( PandocMonad, report, runPure, fetchItem )
 import Text.Pandoc.ImageSize ( dimension, Dimension(Pixel), Direction(..),
                                showInInch )
 import Text.Pandoc.Options ( WriterOptions(..), WrapOption(..), isEnabled,
@@ -33,10 +33,11 @@
 import Text.Pandoc.Writers.Shared ( lookupMetaInlines, lookupMetaString,
                                     metaToContext, defField, resetField,
                                     setupTranslations )
-import Text.Pandoc.Shared (isTightList, orderedListMarkers, tshow)
+import Text.Pandoc.Shared (isTightList, orderedListMarkers, tshow, stringify)
 import Text.Pandoc.Highlighting (highlight, formatTypstBlock, formatTypstInline,
                                  styleToTypst)
 import Text.Pandoc.Translations (Term(Abstract), translateTerm)
+import Text.Pandoc.Error (PandocError(PandocSomeError))
 import Text.Pandoc.Walk (query)
 import Text.Pandoc.Writers.Math (convertMath)
 import qualified Text.TeXMath as TM
@@ -44,11 +45,13 @@
 import Text.DocTemplates (renderTemplate)
 import Text.Pandoc.Extensions (Extension(..))
 import Text.Pandoc.Logging (LogMessage(..))
+import qualified Text.Pandoc.UTF8 as UTF8
 import Text.Collate.Lang (Lang(..), parseLang)
 import Text.Printf (printf)
 import Data.Char (isDigit)
 import Data.Maybe (fromMaybe)
 import Unicode.Char (isXIDContinue)
+import qualified Data.ByteString as B
 
 -- | Convert Pandoc to Typst.
 writeTypst :: PandocMonad m => WriterOptions -> Pandoc -> m Text
@@ -363,12 +366,13 @@
     Figure (ident,_,_) (Caption _mbshort capt) blocks -> do
       caption <- blocksToTypst capt
       opts <-  gets stOptions
+      let toImage (Image attr inlines (src, _)) =
+            Just $ mkImage opts False src attr (getAlt attr inlines)
+          toImage _ = Nothing
       contents <- case blocks of
                      -- don't need #box around block-level image
-                     [Para [Image attr _ (src, _)]]
-                       -> pure $ mkImage opts False src attr
-                     [Plain [Image attr _ (src, _)]]
-                       -> pure $ mkImage opts False src attr
+                     [Para [img]] | Just i <- toImage img -> pure i
+                     [Plain [img]] | Just i <- toImage img -> pure i
                      _ -> brackets <$> blocksToTypst blocks
       let lab = toLabel FreestandingLabel ident
       return $ "#figure(" <> nest 2 ((contents <> ",")
@@ -443,7 +447,7 @@
         WrapPreserve -> return cr
         WrapAuto     -> return space
         WrapNone     -> return space
-    LineBreak -> return (space <> "\\" <> cr)
+    LineBreak -> return (space <> "\\" <> space)
     Math mathType str -> do
       res <- convertMath TM.writeTypst mathType str
       case res of
@@ -529,16 +533,16 @@
                     (if inlines == [Str src]
                           then mempty
                           else nowrap $ brackets contents)
-    Image attr _inlines (src,_tit) -> do
+    Image attr inlines (src,_tit) -> do
       opts <-  gets stOptions
-      pure $ mkImage opts True src attr
+      pure $ mkImage opts True src attr (getAlt attr inlines)
     Note blocks -> do
       contents <- blocksToTypst blocks
       return $ "#footnote" <> brackets (chomp contents)
 
 -- see #9104; need box or image is treated as block-level
-mkImage :: WriterOptions -> Bool -> Text -> Attr -> Doc Text
-mkImage opts useBox src attr
+mkImage :: WriterOptions -> Bool -> Text -> Attr -> Maybe Text -> Doc Text
+mkImage opts useBox src attr mbAlt
   | useBox = "#box" <> parens coreImage
   | otherwise = coreImage
  where
@@ -552,12 +556,34 @@
      (case dimension Width attr of
         Nothing -> mempty
         Just dim -> ", width: " <> showDim dim)
+  altAttr = case mbAlt of
+              Just alt -> ", alt: " <> doubleQuoted alt
+              Nothing -> mempty
   isData = "data:" `T.isPrefixOf` src'
-  dataSvg = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><image xlink:href=\"" <> src' <> "\" /></svg>"
-  coreImage
-    | isData = "image.decode" <> parens(doubleQuoted dataSvg <> dimAttrs)
-    | otherwise = "image" <> parens (doubleQuoted src' <> dimAttrs)
+  eitherImageData = if isData
+                       then runPure (fetchItem src)
+                       else Left $ PandocSomeError "not a data URI"
+  toArray = parens . hcat . intersperse "," . map (literal . tshow) . B.unpack
+  attrs = dimAttrs <> altAttr
+  coreImage = "image" <> parens
+    (case eitherImageData of
+      Right (contents, Just "image/svg+xml")
+        -> "bytes" <> parens (doubleQuoted (UTF8.toText contents)) <> attrs
+      Right (bytes, _mime) -> "bytes" <> parens (toArray bytes) <> attrs
+      Left _ -> doubleQuoted src' <> attrs)
 
+-- | Extract alt text from image attributes and inlines.
+-- Use explicit alt attribute if present; otherwise use inlines.
+-- Empty alt="" means decorative image (no alt text).
+getAlt :: Attr -> [Inline] -> Maybe Text
+getAlt (_, _, kvs) imgInlines =
+  case lookup "alt" kvs of
+    Just "" -> Nothing  -- decorative
+    Just alt -> Just alt
+    Nothing -> case imgInlines of
+                 [] -> Nothing
+                 _ -> Just (stringify imgInlines)
+
 textstyle :: PandocMonad m => Doc Text -> [Inline] -> TW m (Doc Text)
 textstyle s inlines = do
   (s <>) . brackets . fixInitialAfterBreakEscape
@@ -579,8 +605,10 @@
 escapeTypst :: Bool -> EscapeContext -> Text -> Doc Text
 escapeTypst smart context t =
   (case T.uncons t of
-    Just (c, _)
+    Just (c, rest)
       | c == ';' -> char '\\' -- see #9252
+      | c == '.'
+      , not (T.null rest) -> char '\\' -- see #11511
       | needsEscapeAtLineStart c || isOrderedListMarker t
         -> afterBreak "\\"
     _ -> mempty) <>
@@ -593,13 +621,19 @@
       | otherwise = (c, T.snoc t' c)
     escapeChar c
       | c == '\160' = "~"
+      | c == '\8216', smart = "'" -- left quote
       | c == '\8217', smart = "'" -- apostrophe
+      | c == '\8220', smart = "\"" -- left double quote
+      | c == '\8221', smart = "\"" -- right double quote
       | c == '\8212', smart = "---" -- em dash
       | c == '\8211', smart = "--" -- en dash
       | needsEscape c = "\\" <> T.singleton c
       | otherwise = T.singleton c
     needsEscape '\160' = True
+    needsEscape '\8216' = smart
     needsEscape '\8217' = smart
+    needsEscape '\8220' = smart
+    needsEscape '\8221' = smart
     needsEscape '\8212' = smart
     needsEscape '\8211' = smart
     needsEscape '\'' = smart
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
@@ -215,6 +215,18 @@
             "text in shape format"
             "docx/text_in_shape_format.docx"
             "docx/text_in_shape_format.native"
+          , testCompare
+            "image inside textbox content"
+            "docx/textbox_image.docx"
+            "docx/textbox_image.native"
+          , testCompare
+            "image inside textbox content with duplicate encoding"
+            "docx/textbox_image_duplicate_encoding.docx"
+            "docx/textbox_image_duplicate_encoding.native"
+          , testCompare
+            "image with textbox caption in same paragraph"
+            "docx/image_with_textbox_caption.docx"
+            "docx/image_with_textbox_caption.native"
           ]
         , testGroup "blocks"
           [ testCompare
@@ -318,6 +330,10 @@
             "docx/table_with_list_cell.docx"
             "docx/table_with_list_cell.native"
           , testCompare
+            "a table with gridBefore"
+            "docx/table_gridbefore.docx"
+            "docx/table_gridbefore.native"
+          , testCompare
             "a table with a header which contains rowspans greater than 1"
             "docx/table_header_rowspan.docx"
             "docx/table_header_rowspan.native"
@@ -469,6 +485,15 @@
           [ testMediaBag
             "image extraction"
             "docx/image.docx"
+          , testMediaBag
+            "image inside textbox content populates media bag"
+            "docx/textbox_image.docx"
+          , testMediaBag
+            "image inside textbox content with duplicate encoding populates media bag"
+            "docx/textbox_image_duplicate_encoding.docx"
+          , testMediaBag
+            "image with textbox caption in same paragraph populates media bag"
+            "docx/image_with_textbox_caption.docx"
           ]
         , testGroup "custom styles"
           [ testCompare
diff --git a/test/Tests/Readers/ODT.hs b/test/Tests/Readers/ODT.hs
--- a/test/Tests/Readers/ODT.hs
+++ b/test/Tests/Readers/ODT.hs
@@ -167,6 +167,7 @@
 namesOfTestsComparingToNative   = [ "blockquote"
                                   , "image"
                                   , "imageIndex"
+                                  , "imageRelative"
                                   , "imageWithCaption"
                                   , "inlinedCode"
                                   , "listContinueNumbering"
@@ -175,6 +176,8 @@
                                   , "orderedListRoman"
                                   , "orderedListSimple"
                                   , "orderedListHeader"
+                                  , "preformattedText"
+                                  , "preformattedTextParentStyle"
                                   , "referenceToChapter"
                                   , "referenceToListItem"
                                   , "referenceToText"
diff --git a/test/Tests/Writers/Docx.hs b/test/Tests/Writers/Docx.hs
--- a/test/Tests/Writers/Docx.hs
+++ b/test/Tests/Writers/Docx.hs
@@ -222,6 +222,67 @@
             "docx/document-properties-short-desc.native"
             "docx/golden/document-properties-short-desc.docx"
           ]
+        , testGroup "top-level-division"
+          -- Helper to count occurrences of a substring
+          -- Note: counts by splitting on "<w:sectPr" which marks section properties
+          [ testCase "no section break before first chapter (#10578)" $ do
+              -- With --top-level-division=chapter, there should be no section
+              -- break before the first chapter (to avoid blank first page)
+              let opts = def{ writerTopLevelDivision = TopLevelChapter }
+              bs <- runIOorExplode $ do
+                setVerbosity ERROR
+                let doc = Pandoc mempty
+                          [ Header 1 ("ch1", [], []) [Str "Chapter", Space, Str "1"]
+                          , Para [Str "First", Space, Str "chapter."]
+                          ]
+                writeDocx opts doc
+              let archive = toArchive bs
+              entry <- case findEntryByPath "word/document.xml" archive of
+                Nothing -> assertFailure "Missing word/document.xml in output docx"
+                Just e -> return e
+              let docXml = show (fromEntry entry)
+              -- Count occurrences of "<w:sectPr" (opening tag for section properties)
+              let countOccurrences needle haystack =
+                    length (filter (needle `isPrefixOf`) (tails haystack))
+                    where tails [] = []; tails s@(_:xs) = s : tails xs
+              let sectPrCount = countOccurrences "<w:sectPr" docXml
+              -- Should have exactly 1 sectPr (the final document section),
+              -- not 2 (which would mean one before the chapter heading)
+              assertBool ("Expected 1 sectPr (final section only), found " ++ show sectPrCount)
+                (sectPrCount == 1)
+          , testCase "section breaks between chapters (#11482)" $ do
+              -- With --top-level-division=chapter, there should be section
+              -- breaks between chapters (but not before the first one)
+              let opts = def{ writerTopLevelDivision = TopLevelChapter }
+              bs <- runIOorExplode $ do
+                setVerbosity ERROR
+                let doc = Pandoc mempty
+                          [ Header 1 ("ch1", [], []) [Str "Chapter", Space, Str "1"]
+                          , Para [Str "First", Space, Str "chapter."]
+                          , Header 1 ("ch2", [], []) [Str "Chapter", Space, Str "2"]
+                          , Para [Str "Second", Space, Str "chapter."]
+                          , Header 1 ("ch3", [], []) [Str "Chapter", Space, Str "3"]
+                          , Para [Str "Third", Space, Str "chapter."]
+                          ]
+                writeDocx opts doc
+              let archive = toArchive bs
+              entry <- case findEntryByPath "word/document.xml" archive of
+                Nothing -> assertFailure "Missing word/document.xml in output docx"
+                Just e -> return e
+              let docXml = show (fromEntry entry)
+              -- Count occurrences of "<w:sectPr" (opening tag for section properties)
+              let countOccurrences needle haystack =
+                    length (filter (needle `isPrefixOf`) (tails haystack))
+                    where tails [] = []; tails s@(_:xs) = s : tails xs
+              let sectPrCount = countOccurrences "<w:sectPr" docXml
+              -- Should have 3 sectPr elements:
+              -- - 1 before chapter 2
+              -- - 1 before chapter 3
+              -- - 1 final document section
+              -- (No section break before chapter 1)
+              assertBool ("Expected 3 sectPr elements, found " ++ show sectPrCount)
+                (sectPrCount == 3)
+          ]
         , testGroup "reference docx"
           [ testCase "no media directory override in content types" $ do
               let opts = def{ writerReferenceDoc = Just "docx/inline_images.docx" }
diff --git a/test/command/11450.md b/test/command/11450.md
new file mode 100644
--- /dev/null
+++ b/test/command/11450.md
@@ -0,0 +1,62 @@
+Test for \footnotemark and \footnotetext (issue #11450)
+
+```
+% pandoc -f latex -t native
+Text\footnotemark{}.
+\footnotetext{The footnote content.}
+^D
+[ Para
+    [ Str "Text"
+    , Note
+        [ Para
+            [ Str "The"
+            , Space
+            , Str "footnote"
+            , Space
+            , Str "content."
+            ]
+        ]
+    , Str "."
+    ]
+]
+```
+
+With explicit footnote numbers:
+
+```
+% pandoc -f latex -t native
+First\footnotemark[1] and second\footnotemark[2].
+\footnotetext[1]{First note.}
+\footnotetext[2]{Second note.}
+^D
+[ Para
+    [ Str "First"
+    , Note [ Para [ Str "First" , Space , Str "note." ] ]
+    , Space
+    , Str "and"
+    , Space
+    , Str "second"
+    , Note [ Para [ Str "Second" , Space , Str "note." ] ]
+    , Str "."
+    ]
+]
+```
+
+Mixed with regular footnotes:
+
+```
+% pandoc -f latex -t native
+Text\footnotemark[1] and more\footnote{Regular footnote.}
+\footnotetext[1]{Marked footnote.}
+^D
+[ Para
+    [ Str "Text"
+    , Note [ Para [ Str "Marked" , Space , Str "footnote." ] ]
+    , Space
+    , Str "and"
+    , Space
+    , Str "more"
+    , Note [ Para [ Str "Regular" , Space , Str "footnote." ] ]
+    ]
+]
+```
diff --git a/test/command/11455.md b/test/command/11455.md
new file mode 100644
--- /dev/null
+++ b/test/command/11455.md
@@ -0,0 +1,26 @@
+```
+% pandoc -f textile -t html
+| foo | bar |
+| table
+* item 1
+* item 2
+* item 3 | xxx |
+^D
+<table>
+<tbody>
+<tr>
+<td>foo</td>
+<td>bar</td>
+</tr>
+<tr>
+<td><p>table</p>
+<ul>
+<li>item 1</li>
+<li>item 2</li>
+<li>item 3</li>
+</ul></td>
+<td>xxx</td>
+</tr>
+</tbody>
+</table>
+```
diff --git a/test/command/11463.md b/test/command/11463.md
new file mode 100644
--- /dev/null
+++ b/test/command/11463.md
@@ -0,0 +1,13 @@
+```
+% pandoc -t typst
+'hi' and \'
+^D
+'hi' and \'
+```
+
+```
+% pandoc -f markdown -t typst | pandoc -f typst -t markdown
+"hi" \" 'hi' and \'
+^D
+"hi" \" 'hi' and \'
+```
diff --git a/test/command/11479.md b/test/command/11479.md
new file mode 100644
--- /dev/null
+++ b/test/command/11479.md
@@ -0,0 +1,31 @@
+```
+% pandoc -f docbook -t gfm
+<important>
+<itemizedlist>
+<listitem>
+<simpara>Test.</simpara>
+</listitem>
+<listitem>
+<simpara>Test 2.</simpara>
+</listitem>
+</itemizedlist>
+</important>
+^D
+> [!IMPORTANT]
+> - Test.
+>
+> - Test 2.
+```
+
+```
+% pandoc -f gfm -t gfm
+> [!IMPORTANT]
+> - Test.
+>
+> - Test 2.
+^D
+> [!IMPORTANT]
+> - Test.
+>
+> - Test 2.
+```
diff --git a/test/command/11486.md b/test/command/11486.md
new file mode 100644
--- /dev/null
+++ b/test/command/11486.md
@@ -0,0 +1,82 @@
+```
+% pandoc -t revealjs --template=command/11486/scroll.revealjs
+---
+view: scroll
+---
+^D
+        scrollActivationWidth: 0,
+        scrollSnap: 'mandatory',
+        scrollProgress: 'auto',
+```
+
+```
+% pandoc -t revealjs --template=command/11486/scroll.revealjs
+---
+view: scroll
+scrollSnap: false
+---
+^D
+        scrollActivationWidth: 0,
+        scrollSnap: false,
+        scrollProgress: 'auto',
+```
+
+```
+% pandoc -t revealjs --template=command/11486/scroll.revealjs
+---
+view: scroll
+scrollSnap: proximity
+---
+^D
+        scrollActivationWidth: 0,
+        scrollSnap: 'proximity',
+        scrollProgress: 'auto',
+```
+
+```
+% pandoc -t revealjs --template=command/11486/scroll.revealjs
+---
+view: scroll
+scrollActivationWidth: 500
+---
+^D
+        scrollActivationWidth: 500,
+        scrollSnap: 'mandatory',
+        scrollProgress: 'auto',
+```
+
+```
+% pandoc -t revealjs --template=command/11486/scroll.revealjs
+---
+view: scroll
+scrollProgress: true
+---
+^D
+        scrollActivationWidth: 0,
+        scrollSnap: 'mandatory',
+        scrollProgress: true,
+```
+
+```
+% pandoc -t revealjs --template=command/11486/scroll.revealjs
+---
+view: scroll
+scrollProgress: false
+---
+^D
+        scrollActivationWidth: 0,
+        scrollSnap: 'mandatory',
+        scrollProgress: false,
+```
+
+```
+% pandoc -t revealjs --template=command/11486/scroll.revealjs
+---
+view: scroll
+scrollProgress: auto
+---
+^D
+        scrollActivationWidth: 0,
+        scrollSnap: 'mandatory',
+        scrollProgress: 'auto',
+```
diff --git a/test/command/11486/scroll.revealjs b/test/command/11486/scroll.revealjs
new file mode 100644
--- /dev/null
+++ b/test/command/11486/scroll.revealjs
@@ -0,0 +1,15 @@
+$if(view)$
+        scrollActivationWidth: $scrollActivationWidth$,
+$if(scrollSnap)$
+        scrollSnap: '$scrollSnap/nowrap$',
+$else$
+        scrollSnap: false,
+$endif$
+$if(scrollProgressAuto)$
+        scrollProgress: 'auto',
+$elseif(scrollProgress)$
+        scrollProgress: $scrollProgress$,
+$else$
+        scrollProgress: false,
+$endif$
+$endif$
diff --git a/test/command/11490.md b/test/command/11490.md
new file mode 100644
--- /dev/null
+++ b/test/command/11490.md
@@ -0,0 +1,13 @@
+```
+% pandoc -t markdown
+&lt;&amp;lt;
+^D
+\<\&lt;
+```
+
+```
+% pandoc -t markdown
+&amp;#xa0;
+^D
+\&#xa0;
+```
diff --git a/test/command/11494.md b/test/command/11494.md
new file mode 100644
--- /dev/null
+++ b/test/command/11494.md
@@ -0,0 +1,73 @@
+External images should not use [[File:...]] syntax.
+
+Inline external image:
+```
+% pandoc -f native -t mediawiki
+[Para [Image ("",[],[]) [] ("https://example.org/image.png", "")]]
+^D
+<nowiki></nowiki>https://example.org/image.png<nowiki></nowiki>
+```
+
+Inline local image (should still use [[File:]]):
+```
+% pandoc -f native -t mediawiki
+[Para [Image ("",[],[]) [] ("local.png", "")]]
+^D
+[[File:local.png]]
+```
+
+Figure with external image (from markdown):
+```
+% pandoc -f markdown -t mediawiki
+![](https://example.org/figure.png)
+^D
+<nowiki></nowiki>https://example.org/figure.png<nowiki></nowiki>
+```
+
+Local image (from markdown, no caption):
+```
+% pandoc -f markdown -t mediawiki
+![](local.png)
+^D
+[[File:local.png]]
+```
+
+Figure with caption and external image:
+```
+% pandoc -f markdown -t mediawiki
+![Caption](https://example.org/figure.png)
+^D
+<div class="figure">
+<nowiki></nowiki>https://example.org/figure.png<nowiki></nowiki>
+</div>
+```
+
+Figure with caption and local image:
+```
+% pandoc -f markdown -t mediawiki
+![Caption](local.png)
+^D
+<div class="figure">
+[[File:local.png|Caption]]
+</div>
+```
+
+SimpleFigure with external image (native format with fig: title):
+```
+% pandoc -f native -t mediawiki
+[Figure ("",[],[]) (Caption Nothing []) [Para [Image ("",[],[]) [Str "caption"] ("https://example.org/figure.png", "fig:")]]]
+^D
+<div class="figure">
+<nowiki></nowiki>https://example.org/figure.png<nowiki></nowiki>
+</div>
+```
+
+SimpleFigure with local image (native format with fig: title):
+```
+% pandoc -f native -t mediawiki
+[Figure ("",[],[]) (Caption Nothing []) [Para [Image ("",[],[]) [Str "caption"] ("local.png", "fig:")]]]
+^D
+<div class="figure">
+[[File:local.png|thumb|none|alt=caption|caption]]
+</div>
+```
diff --git a/test/command/11498.md b/test/command/11498.md
new file mode 100644
--- /dev/null
+++ b/test/command/11498.md
@@ -0,0 +1,121 @@
+```
+% pandoc -f markdown -t icml
+![](command/11498.png){object-style="myStyle"}
+^D
+<ParagraphStyleRange AppliedParagraphStyle="ParagraphStyle/Paragraph">
+  <CharacterStyleRange AppliedCharacterStyle="$ID/NormalCharacterStyle">
+    <Rectangle Self="uec" StrokeWeight="0" ItemTransform="1 0 0 1 32 -32" AppliedObjectStyle="ObjectStyle/myStyle">
+      <Properties>
+        <PathGeometry>
+          <GeometryPathType PathOpen="false">
+            <PathPointArray>
+              <PathPointType Anchor="-32 -32" LeftDirection="-32 -32" RightDirection="-32 -32" />
+              <PathPointType Anchor="-32 32" LeftDirection="-32 32" RightDirection="-32 32" />
+              <PathPointType Anchor="32 32" LeftDirection="32 32" RightDirection="32 32" />
+              <PathPointType Anchor="32 -32" LeftDirection="32 -32" RightDirection="32 -32" />
+            </PathPointArray>
+          </GeometryPathType>
+        </PathGeometry>
+      </Properties>
+      <Image Self="ue6" ItemTransform="1 0 0 1 -32 -32">
+        <Properties>
+          <Profile type="string">
+            $ID/Embedded
+          </Profile>
+          <GraphicBounds Left="0" Top="0" Right="64" Bottom="64" />
+        </Properties>
+        <Link Self="ueb" LinkResourceURI="file:command/11498.png" />
+      </Image>
+    </Rectangle>
+  </CharacterStyleRange>
+</ParagraphStyleRange>
+```
+```
+% pandoc -s -f markdown -t icml
+![](command/11498.png){object-style="myStyle"}
+^D
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<?aid style="50" type="snippet" readerVersion="6.0" featureSet="513" product="8.0(370)" ?>
+<?aid SnippetType="InCopyInterchange"?>
+<Document DOMVersion="8.0" Self="pandoc_doc">
+    <RootCharacterStyleGroup Self="pandoc_character_styles">
+      <CharacterStyle Self="$ID/NormalCharacterStyle" Name="Default" />
+      <CharacterStyle Self="CharacterStyle/" Name="">
+        <Properties>
+          <BasedOn type="object">$ID/NormalCharacterStyle</BasedOn>
+        </Properties>
+      </CharacterStyle>
+    </RootCharacterStyleGroup>
+    <RootParagraphStyleGroup Self="pandoc_paragraph_styles">
+      <ParagraphStyle Self="$ID/NormalParagraphStyle" Name="$ID/NormalParagraphStyle"
+          SpaceBefore="6" SpaceAfter="6"> <!-- paragraph spacing -->
+        <Properties>
+          <TabList type="list">
+            <ListItem type="record">
+              <Alignment type="enumeration">LeftAlign</Alignment>
+              <AlignmentCharacter type="string">.</AlignmentCharacter>
+              <Leader type="string"></Leader>
+              <Position type="unit">10</Position> <!-- first tab stop -->
+            </ListItem>
+          </TabList>
+        </Properties>
+      </ParagraphStyle>
+      <ParagraphStyle Self="ParagraphStyle/Paragraph" Name="Paragraph" LeftIndent="0">
+        <Properties>
+          <BasedOn type="object">$ID/NormalParagraphStyle</BasedOn>
+        </Properties>
+      </ParagraphStyle>
+    </RootParagraphStyleGroup>
+    <RootTableStyleGroup Self="pandoc_table_styles">
+      <TableStyle Self="TableStyle/Table" Name="Table" />
+    </RootTableStyleGroup>
+    <RootCellStyleGroup Self="pandoc_cell_styles">
+      <CellStyle Self="CellStyle/Cell" AppliedParagraphStyle="ParagraphStyle/$ID/[No paragraph style]" Name="Cell" />
+    </RootCellStyleGroup>
+    <RootObjectStyleGroup Self="pandoc_object_styles">
+      <ObjectStyle Self="ObjectStyle/myStyle" Name="myStyle">
+        <Properties>
+          <BasedOn type="string">$ID/None</BasedOn>
+        </Properties>
+      </ObjectStyle>
+    </RootObjectStyleGroup>
+  <Story Self="pandoc_story"
+      TrackChanges="false"
+      StoryTitle=""
+      AppliedTOCStyle="n"
+      AppliedNamedGrid="n" >
+    <StoryPreference OpticalMarginAlignment="true" OpticalMarginSize="12" />
+
+<!-- body needs to be non-indented, otherwise code blocks are indented too far -->
+<ParagraphStyleRange AppliedParagraphStyle="ParagraphStyle/Paragraph">
+  <CharacterStyleRange AppliedCharacterStyle="$ID/NormalCharacterStyle">
+    <Rectangle Self="uec" StrokeWeight="0" ItemTransform="1 0 0 1 32 -32" AppliedObjectStyle="ObjectStyle/myStyle">
+      <Properties>
+        <PathGeometry>
+          <GeometryPathType PathOpen="false">
+            <PathPointArray>
+              <PathPointType Anchor="-32 -32" LeftDirection="-32 -32" RightDirection="-32 -32" />
+              <PathPointType Anchor="-32 32" LeftDirection="-32 32" RightDirection="-32 32" />
+              <PathPointType Anchor="32 32" LeftDirection="32 32" RightDirection="32 32" />
+              <PathPointType Anchor="32 -32" LeftDirection="32 -32" RightDirection="32 -32" />
+            </PathPointArray>
+          </GeometryPathType>
+        </PathGeometry>
+      </Properties>
+      <Image Self="ue6" ItemTransform="1 0 0 1 -32 -32">
+        <Properties>
+          <Profile type="string">
+            $ID/Embedded
+          </Profile>
+          <GraphicBounds Left="0" Top="0" Right="64" Bottom="64" />
+        </Properties>
+        <Link Self="ueb" LinkResourceURI="file:command/11498.png" />
+      </Image>
+    </Rectangle>
+  </CharacterStyleRange>
+</ParagraphStyleRange>
+
+  </Story>
+  
+</Document>
+```
diff --git a/test/command/11498.png b/test/command/11498.png
new file mode 100644
Binary files /dev/null and b/test/command/11498.png differ
diff --git a/test/command/11511.md b/test/command/11511.md
new file mode 100644
--- /dev/null
+++ b/test/command/11511.md
@@ -0,0 +1,6 @@
+```
+% pandoc -f html -t typst
+<p><a href="http://torch.utils.data" rel="noopener noreferrer nofollow" target="_blank">torch.utils.data</a>.Dataset</p>
+^D
+#link("http://torch.utils.data")[torch.utils.data]\.Dataset
+```
diff --git a/test/command/11534.md b/test/command/11534.md
new file mode 100644
--- /dev/null
+++ b/test/command/11534.md
@@ -0,0 +1,42 @@
+```
+% pandoc -f markdown+lists_without_preceding_blankline+alerts -t native
+:::: caution
+::: title
+Caution
+:::
+
+Foo bar, wuppie fluppie!
+::::
+^D
+[ Div
+    ( "" , [ "caution" ] , [] )
+    [ Div ( "" , [ "title" ] , [] ) [ Para [ Str "Caution" ] ]
+    , Para
+        [ Str "Foo"
+        , Space
+        , Str "bar,"
+        , Space
+        , Str "wuppie"
+        , Space
+        , Str "fluppie!"
+        ]
+    ]
+]
+```
+
+```
+% pandoc -f markdown+lists_without_preceding_blankline -t native
+hello
+- a
+- b
+c
+^D
+[ Para [ Str "hello" ]
+, BulletList
+    [ [ Plain [ Str "a" ] ]
+    , [ Plain [ Str "b" , SoftBreak , Str "c" ] ]
+    ]
+]
+
+```
+
diff --git a/test/command/9236.md b/test/command/9236.md
--- a/test/command/9236.md
+++ b/test/command/9236.md
@@ -9,25 +9,26 @@
 And inline: ![minimal](command/minimal.svg){height=2in} and
 ![minimal](command/minimal.svg).
 ^D
-#figure(image("command/minimal.svg", width: 3in),
+#figure(image("command/minimal.svg", width: 3in, alt: "minimal"),
   caption: [
     minimal
   ]
 )
 
-#figure(image("command/minimal.svg", height: 2in, width: 3in),
+#figure(image("command/minimal.svg", height: 2in, width: 3in, alt: "minimal"),
   caption: [
     minimal
   ]
 )
 
-#figure(image("command/minimal.svg"),
+#figure(image("command/minimal.svg", alt: "minimal"),
   caption: [
     minimal
   ]
 )
 
-And inline: #box(image("command/minimal.svg", height: 2in)) and
-#box(image("command/minimal.svg")).
+And inline:
+#box(image("command/minimal.svg", height: 2in, alt: "minimal")) and
+#box(image("command/minimal.svg", alt: "minimal")).
 
 ```
diff --git a/test/command/typst-image-alt.md b/test/command/typst-image-alt.md
new file mode 100644
--- /dev/null
+++ b/test/command/typst-image-alt.md
@@ -0,0 +1,78 @@
+```
+% pandoc -f markdown-implicit_figures -t typst
+![Alt text from inlines](image.png)
+^D
+#box(image("image.png", alt: "Alt text from inlines"))
+```
+
+```
+% pandoc -f markdown-implicit_figures -t typst
+![](image.png){alt="Explicit alt attribute"}
+^D
+#box(image("image.png", alt: "Explicit alt attribute"))
+```
+
+```
+% pandoc -f markdown-implicit_figures -t typst
+![Inlines ignored](image.png){alt="Explicit wins"}
+^D
+#box(image("image.png", alt: "Explicit wins"))
+```
+
+```
+% pandoc -f markdown-implicit_figures -t typst
+![](image.png)
+^D
+#box(image("image.png"))
+```
+
+```
+% pandoc -f markdown-implicit_figures -t typst
+![Inlines ignored for decorative](image.png){alt=""}
+^D
+#box(image("image.png"))
+```
+
+```
+% pandoc -t typst
+![Caption text](image.png){alt="Alt text describing the image"}
+
+^D
+#figure(image("image.png", alt: "Alt text describing the image"),
+  caption: [
+    Caption text
+  ]
+)
+```
+
+```
+% pandoc -t typst
+![Caption only](image.png)
+
+^D
+#figure(image("image.png", alt: "Caption only"),
+  caption: [
+    Caption only
+  ]
+)
+```
+
+```
+% pandoc -f markdown -t typst
+![Caption](test.png){alt="A \"quoted\" phrase and C:\\path\\file"}
+^D
+#figure(image("test.png", alt: "A \"quoted\" phrase and C:\\path\\file"),
+  caption: [
+    Caption
+  ]
+)
+
+```
+
+```
+% pandoc -f html -t typst
+<img src="data:image/png;base64,iVBORw0KGgo=" alt="A small red dot">
+^D
+#box(image(bytes((137,80,78,71,13,10,26,10)), alt: "A small red dot"))
+
+```
diff --git a/test/command/typst-images.md b/test/command/typst-images.md
new file mode 100644
--- /dev/null
+++ b/test/command/typst-images.md
@@ -0,0 +1,32 @@
+```
+% pandoc -t typst
+![dot](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAACXBIWXMAAC4jAAAuIwF4pT92AAAASUlEQVQYGa3OWwoAIAgEQNf739k0EjVCfxKCHtMqiEh0jcWjOKBAkQjPe7MFdun/IbRdDNb05nvolzWzEx0DdozK96W1PzjNHxcgphkBs9CoHwAAAABJRU5ErkJggg==){width=1in}
+^D
+#figure(image(bytes((137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,10,0,0,0,10,8,6,0,0,0,141,50,207,189,0,0,0,9,112,72,89,115,0,0,46,35,0,0,46,35,1,120,165,63,118,0,0,0,73,73,68,65,84,24,25,173,206,91,10,0,32,8,4,64,215,251,223,217,52,18,53,66,127,18,130,30,211,42,136,72,116,141,197,163,56,160,64,145,8,207,123,179,5,118,233,255,33,180,93,12,214,244,230,123,232,151,53,179,19,29,3,118,140,202,247,165,181,63,56,205,31,23,32,166,25,1,179,208,168,31,0,0,0,0,73,69,78,68,174,66,96,130)), width: 1in, alt: "dot"),
+  caption: [
+    dot
+  ]
+)
+```
+
+```
+% pandoc -t typst
+![dot](dot.png){width="1in"}
+^D
+#figure(image("dot.png", width: 1in, alt: "dot"),
+  caption: [
+    dot
+  ]
+)
+```
+
+```
+% pandoc -t typst
+![chicken](data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20100%20100%22%20aria-label%3D%22Chicken%22%3E%20%3Cpath%20d%3D%22M76.5%2033.3l-8.3-6.6%204-5c-1.3-2-1.3-4.7.1-6.6%203.4-3.8%208.7-2%2010.2%202.2%204.5.7%207.5%205.4%204.4%209.4a5.7%205.7%200%2001-6.4%201.6zM73%2026.2l3%202.4%203.8-4.7c1.3%201%203.5%202%204.5.7%202.1-2.9-1.5-5.4-4.7-3.5%201.2-4.6-2.7-6.2-4.5-3.9-.7%202.2.2%203%201.7%204.2z%22%2F%3E%20%3Cpath%20d%3D%22M54%2072.3a19.1%2019.1%200%2001-19.2-17.8%2021.4%2021.4%200%20014.7-15.2c3.5-4.3%208.4-7.1%2013.7-8l3.1-.1c8.2-.9%2012.9-5.5%2013-5.6l1-1%208.2%206.5-1%201.3c-3.3%204-2.8%2011.3-2.5%2014.2a21.5%2021.5%200%2001-4.4%2017.5%2021.2%2021.2%200%2001-16.5%208.2zM70.6%2029a27%2027%200%2001-14%205.5l-3%20.2a18%2018%200%2000-11.3%206.7%2018%2018%200%2000-4%2012.8%2016%2016%200%200015.9%2014.7c5.4%200%2010.4-2.5%2014-6.9A18%2018%200%200072%2049.4c0-.8-.2-1.6-.3-2.2-.5-4-.7-10.7%202.1-15.5z%22%2F%3E%20%3Cpath%20d%3D%22M46%2087C22.6%2087%20.5%2087%20.5%2066.8c0-19%2020.4-34.6%2045.5-34.6%201.2%200%202.5%200%203.7.2%2010.1.6%209.7-.1.5%203.2a18.3%2018.3%200%2000-12%2018.6%2016%2016%200%200015.9%2014.7c5.4%200%2010.4-2.5%2014-6.9A18%2018%200%200072%2049.4c-.6-4-.4-7.4-.2-11.3a35.8%2035.8%200%200119.5%2026A11.7%2011.7%200%200187.8%2087H46zm-2.8-51.3c-22%201-39.4%2014.6-39.4%2031%200%2015.8%2016%2016.9%2042.2%2016.9h41.8c4.6%200%208.4-3.8%208.4-8.4-.4-4.8-3.2-7.7-8.1-8.4-.3-10.4-7.4-18.4-13.3-22.7.1%202%20.5%204.3.7%206.1%200%205-1.6%2010-4.8%2014A21.2%2021.2%200%200154%2072.3a19.1%2019.1%200%2001-19.3-17.8%2021.4%2021.4%200%20018.4-18.8z%22%2F%3E%20%3C%2Fsvg%3E)
+^D
+#figure(image(bytes("<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 100 100\" aria-label=\"Chicken\"> <path d=\"M76.5 33.3l-8.3-6.6 4-5c-1.3-2-1.3-4.7.1-6.6 3.4-3.8 8.7-2 10.2 2.2 4.5.7 7.5 5.4 4.4 9.4a5.7 5.7 0 01-6.4 1.6zM73 26.2l3 2.4 3.8-4.7c1.3 1 3.5 2 4.5.7 2.1-2.9-1.5-5.4-4.7-3.5 1.2-4.6-2.7-6.2-4.5-3.9-.7 2.2.2 3 1.7 4.2z\"/> <path d=\"M54 72.3a19.1 19.1 0 01-19.2-17.8 21.4 21.4 0 014.7-15.2c3.5-4.3 8.4-7.1 13.7-8l3.1-.1c8.2-.9 12.9-5.5 13-5.6l1-1 8.2 6.5-1 1.3c-3.3 4-2.8 11.3-2.5 14.2a21.5 21.5 0 01-4.4 17.5 21.2 21.2 0 01-16.5 8.2zM70.6 29a27 27 0 01-14 5.5l-3 .2a18 18 0 00-11.3 6.7 18 18 0 00-4 12.8 16 16 0 0015.9 14.7c5.4 0 10.4-2.5 14-6.9A18 18 0 0072 49.4c0-.8-.2-1.6-.3-2.2-.5-4-.7-10.7 2.1-15.5z\"/> <path d=\"M46 87C22.6 87 .5 87 .5 66.8c0-19 20.4-34.6 45.5-34.6 1.2 0 2.5 0 3.7.2 10.1.6 9.7-.1.5 3.2a18.3 18.3 0 00-12 18.6 16 16 0 0015.9 14.7c5.4 0 10.4-2.5 14-6.9A18 18 0 0072 49.4c-.6-4-.4-7.4-.2-11.3a35.8 35.8 0 0119.5 26A11.7 11.7 0 0187.8 87H46zm-2.8-51.3c-22 1-39.4 14.6-39.4 31 0 15.8 16 16.9 42.2 16.9h41.8c4.6 0 8.4-3.8 8.4-8.4-.4-4.8-3.2-7.7-8.1-8.4-.3-10.4-7.4-18.4-13.3-22.7.1 2 .5 4.3.7 6.1 0 5-1.6 10-4.8 14A21.2 21.2 0 0154 72.3a19.1 19.1 0 01-19.3-17.8 21.4 21.4 0 018.4-18.8z\"/> </svg>"), alt: "chicken"),
+  caption: [
+    chicken
+  ]
+)
+```
diff --git a/test/docx/image_with_textbox_caption.docx b/test/docx/image_with_textbox_caption.docx
new file mode 100644
Binary files /dev/null and b/test/docx/image_with_textbox_caption.docx differ
diff --git a/test/docx/image_with_textbox_caption.native b/test/docx/image_with_textbox_caption.native
new file mode 100644
--- /dev/null
+++ b/test/docx/image_with_textbox_caption.native
@@ -0,0 +1,44 @@
+[ Figure
+    ( "" , [] , [] )
+    (Caption
+       Nothing
+       [ Para
+           [ Str "1"
+           , Space
+           , Str "Daniel"
+           , Space
+           , Str "Schliebner:"
+           , Space
+           , Str "Cantor'sches"
+           , Space
+           , Str "Diagonalverfahren."
+           , Space
+           , Str "Von"
+           , Space
+           , Str "Mengen,"
+           , Space
+           , Str "Unendlichkeiten"
+           , Space
+           , Str "und"
+           , Space
+           , Str "Wahnsinn,"
+           , Space
+           , Str "Pdf:"
+           , Space
+           , Str
+               "https://www2.informatik.hu-berlin.de/~kossahl/Uni/Ma1/Cantor.pdf"
+           ]
+       ])
+    [ Plain
+        [ Image
+            ( ""
+            , []
+            , [ ( "width" , "2.3680555555555554in" )
+              , ( "height" , "0.9340277777777778in" )
+              ]
+            )
+            []
+            ( "media/image1.emf" , "" )
+        ]
+    ]
+]
diff --git a/test/docx/table_gridbefore.docx b/test/docx/table_gridbefore.docx
new file mode 100644
Binary files /dev/null and b/test/docx/table_gridbefore.docx differ
diff --git a/test/docx/table_gridbefore.native b/test/docx/table_gridbefore.native
new file mode 100644
--- /dev/null
+++ b/test/docx/table_gridbefore.native
@@ -0,0 +1,823 @@
+[ Table
+    ( "" , [] , [] )
+    (Caption Nothing [])
+    [ ( AlignDefault , ColWidth 7.883369330453563e-3 )
+    , ( AlignDefault , ColWidth 3.0669546436285097e-2 )
+    , ( AlignDefault , ColWidth 3.0669546436285097e-2 )
+    , ( AlignDefault , ColWidth 3.0669546436285097e-2 )
+    , ( AlignDefault , ColWidth 3.0669546436285097e-2 )
+    , ( AlignDefault , ColWidth 3.0669546436285097e-2 )
+    , ( AlignDefault , ColWidth 3.0669546436285097e-2 )
+    , ( AlignDefault , ColWidth 3.0669546436285097e-2 )
+    , ( AlignDefault , ColWidth 3.0669546436285097e-2 )
+    , ( AlignDefault , ColWidth 3.0669546436285097e-2 )
+    , ( AlignDefault , ColWidth 0.42861771058315334 )
+    ]
+    (TableHead
+       ( "" , [] , [] )
+       [ Row
+           ( "" , [] , [] )
+           [ Cell
+               ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+           , Cell
+               ( "" , [] , [] )
+               AlignDefault
+               (RowSpan 1)
+               (ColSpan 8)
+               [ Plain [ Str "Bits" ] ]
+           , Cell
+               ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+           , Cell
+               ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+           ]
+       ])
+    [ TableBody
+        ( "" , [] , [] )
+        (RowHeadColumns 0)
+        []
+        [ Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "8" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "7" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "6" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "5" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "4" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "3" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "2" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "1" ] ]
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "1" ] ]
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "TEXT" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "1" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "BINARY" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "1" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "1" ] ]
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "HYPERLINKS" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "1" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "FILEURL" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "1" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "1" ] ]
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "LOCATION" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "1" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "1" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "ENHANCED" , Space , Str "STATUS" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "1" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "1" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "1" ] ]
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain
+                    [ Str "Value"
+                    , Space
+                    , Str "allocated"
+                    , Space
+                    , Str "for"
+                    , Space
+                    , Str "use"
+                    , Space
+                    , Str "in"
+                    , Space
+                    , Str "interworking"
+                    , Space
+                    , Str "(NOTE)"
+                    ]
+                ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "1" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "LOCATION" , Space , Str "ALTITUDE" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "1" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "1" ] ]
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "LOCATION" , Space , Str "TIMESTAMP" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 2)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "1" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "1" ] ]
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "0" ] ]
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 1)
+                [ Plain [ Str "CODED" , Space , Str "TEXT" ] ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 10)
+                [ Plain
+                    [ Str "All"
+                    , Space
+                    , Str "other"
+                    , Space
+                    , Str "values"
+                    , Space
+                    , Str "are"
+                    , Space
+                    , Str "reserved."
+                    ]
+                ]
+            ]
+        , Row
+            ( "" , [] , [] )
+            [ Cell
+                ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []
+            , Cell
+                ( "" , [] , [] )
+                AlignDefault
+                (RowSpan 1)
+                (ColSpan 10)
+                [ Plain
+                    [ Str "NOTE:"
+                    , Space
+                    , Str "Usage"
+                    , Space
+                    , Str "of"
+                    , Space
+                    , Str "this"
+                    , Space
+                    , Str "value"
+                    , Space
+                    , Str "is"
+                    , Space
+                    , Str "described"
+                    , Space
+                    , Str "in"
+                    , Space
+                    , Str "3GPP\160TS\160\&29.582\160[48]."
+                    ]
+                ]
+            ]
+        ]
+    ]
+    (TableFoot ( "" , [] , [] ) [])
+]
diff --git a/test/docx/textbox_image.docx b/test/docx/textbox_image.docx
new file mode 100644
Binary files /dev/null and b/test/docx/textbox_image.docx differ
diff --git a/test/docx/textbox_image.native b/test/docx/textbox_image.native
new file mode 100644
--- /dev/null
+++ b/test/docx/textbox_image.native
@@ -0,0 +1,30 @@
+[ Para
+    [ Str "The"
+    , Space
+    , Str "image"
+    , Space
+    , Str "is"
+    , Space
+    , Str "below."
+    ]
+, Para
+    [ Image
+        ( ""
+        , []
+        , [ ( "width" , "4.543038057742782in" )
+          , ( "height" , "2.9166666666666665in" )
+          ]
+        )
+        []
+        ( "media/image1.png" , "" )
+    ]
+, Para
+    [ Str "The"
+    , Space
+    , Str "image"
+    , Space
+    , Str "is"
+    , Space
+    , Str "above."
+    ]
+]
diff --git a/test/docx/textbox_image_duplicate_encoding.docx b/test/docx/textbox_image_duplicate_encoding.docx
new file mode 100644
Binary files /dev/null and b/test/docx/textbox_image_duplicate_encoding.docx differ
diff --git a/test/docx/textbox_image_duplicate_encoding.native b/test/docx/textbox_image_duplicate_encoding.native
new file mode 100644
--- /dev/null
+++ b/test/docx/textbox_image_duplicate_encoding.native
@@ -0,0 +1,30 @@
+[ Para
+    [ Str "The"
+    , Space
+    , Str "image"
+    , Space
+    , Str "is"
+    , Space
+    , Str "below."
+    ]
+, Para
+    [ Image
+        ( ""
+        , []
+        , [ ( "width" , "4.543038057742782in" )
+          , ( "height" , "2.9166666666666665in" )
+          ]
+        )
+        []
+        ( "media/image1.png" , "" )
+    ]
+, Para
+    [ Str "The"
+    , Space
+    , Str "image"
+    , Space
+    , Str "is"
+    , Space
+    , Str "above."
+    ]
+]
diff --git a/test/odt/native/imageRelative.native b/test/odt/native/imageRelative.native
new file mode 100644
--- /dev/null
+++ b/test/odt/native/imageRelative.native
@@ -0,0 +1,10 @@
+[ Para
+    [ Image
+        ( ""
+        , []
+        , [ ( "width" , "5.292cm" ) , ( "height" , "5.292cm" ) ]
+        )
+        []
+        ( "../../lalune.jpg" , "" )
+    ]
+]
diff --git a/test/odt/native/preformattedText.native b/test/odt/native/preformattedText.native
new file mode 100644
--- /dev/null
+++ b/test/odt/native/preformattedText.native
@@ -0,0 +1,4 @@
+[ CodeBlock
+    ( "" , [] , [] )
+    "void main() {\n    printf(\"Hello world\");\n}"
+]
diff --git a/test/odt/native/preformattedTextParentStyle.native b/test/odt/native/preformattedTextParentStyle.native
new file mode 100644
--- /dev/null
+++ b/test/odt/native/preformattedTextParentStyle.native
@@ -0,0 +1,4 @@
+[ CodeBlock
+    ( "" , [] , [] )
+    "void main() {\n    printf(\"Hello world\");\n}"
+]
diff --git a/test/odt/native/sourceText.native b/test/odt/native/sourceText.native
new file mode 100644
--- /dev/null
+++ b/test/odt/native/sourceText.native
@@ -0,0 +1,11 @@
+[ Header
+    1
+    ( "test-foo" , [] , [] )
+    [ Span ( "anchor" , [] , [] ) []
+    , Str "Test"
+    , Space
+    , Code ( "" , [] , [] ) "foo"
+    ]
+, Para
+    [ Str "Hello" , Space , Code ( "" , [] , [] ) "world" ]
+]
diff --git a/test/odt/odt/imageRelative.odt b/test/odt/odt/imageRelative.odt
new file mode 100644
Binary files /dev/null and b/test/odt/odt/imageRelative.odt differ
diff --git a/test/odt/odt/preformattedText.odt b/test/odt/odt/preformattedText.odt
new file mode 100644
Binary files /dev/null and b/test/odt/odt/preformattedText.odt differ
diff --git a/test/odt/odt/preformattedTextParentStyle.odt b/test/odt/odt/preformattedTextParentStyle.odt
new file mode 100644
Binary files /dev/null and b/test/odt/odt/preformattedTextParentStyle.odt differ
diff --git a/test/odt/odt/sourceText.odt b/test/odt/odt/sourceText.odt
new file mode 100644
Binary files /dev/null and b/test/odt/odt/sourceText.odt differ
diff --git a/test/s5-basic.html b/test/s5-basic.html
--- a/test/s5-basic.html
+++ b/test/s5-basic.html
@@ -14,7 +14,6 @@
     /* Default styles provided by pandoc.
     ** See https://pandoc.org/MANUAL.html#variables-for-html for config info.
     */
-    code{white-space: pre-wrap;}
     span.smallcaps{font-variant: small-caps;}
     div.columns{display: flex; gap: min(4vw, 1.5em);}
     div.column{flex: auto; overflow-x: auto;}
diff --git a/test/s5-fancy.html b/test/s5-fancy.html
--- a/test/s5-fancy.html
+++ b/test/s5-fancy.html
@@ -14,7 +14,6 @@
     /* Default styles provided by pandoc.
     ** See https://pandoc.org/MANUAL.html#variables-for-html for config info.
     */
-    code{white-space: pre-wrap;}
     span.smallcaps{font-variant: small-caps;}
     div.columns{display: flex; gap: min(4vw, 1.5em);}
     div.column{flex: auto; overflow-x: auto;}
diff --git a/test/s5-inserts.html b/test/s5-inserts.html
--- a/test/s5-inserts.html
+++ b/test/s5-inserts.html
@@ -12,7 +12,6 @@
     /* Default styles provided by pandoc.
     ** See https://pandoc.org/MANUAL.html#variables-for-html for config info.
     */
-    code{white-space: pre-wrap;}
     span.smallcaps{font-variant: small-caps;}
     div.columns{display: flex; gap: min(4vw, 1.5em);}
     div.column{flex: auto; overflow-x: auto;}
diff --git a/test/tables/nordics.typst b/test/tables/nordics.typst
--- a/test/tables/nordics.typst
+++ b/test/tables/nordics.typst
@@ -3,9 +3,7 @@
     columns: (30%, 30%, 20%, 20%),
     align: (center,left,left,left,),
     table.header(table.cell(align: center)[Name], table.cell(align: center)[Capital], table.cell(align: center)[Population
-      \
-      (in 2018)], table.cell(align: center)[Area \
-      (in km#super[2])],),
+      \ (in 2018)], table.cell(align: center)[Area \ (in km#super[2])],),
     table.hline(),
     [Denmark], [Copenhagen], [5,809,502], [43,094],
     [Finland], [Helsinki], [5,537,364], [338,145],
diff --git a/test/writer.html4 b/test/writer.html4
--- a/test/writer.html4
+++ b/test/writer.html4
@@ -94,6 +94,7 @@
       color: #606060;
     }
     code {
+      white-space: pre-wrap;
       font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
       font-size: 85%;
       margin: 0;
@@ -157,7 +158,6 @@
     #TOC a:not(:hover) {
       text-decoration: none;
     }
-    code{white-space: pre-wrap;}
     span.smallcaps{font-variant: small-caps;}
     div.columns{display: flex; gap: min(4vw, 1.5em);}
     div.column{flex: auto; overflow-x: auto;}
diff --git a/test/writer.html5 b/test/writer.html5
--- a/test/writer.html5
+++ b/test/writer.html5
@@ -94,6 +94,7 @@
       color: #606060;
     }
     code {
+      white-space: pre-wrap;
       font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
       font-size: 85%;
       margin: 0;
@@ -157,7 +158,6 @@
     #TOC a:not(:hover) {
       text-decoration: none;
     }
-    code{white-space: pre-wrap;}
     span.smallcaps{font-variant: small-caps;}
     div.columns{display: flex; gap: min(4vw, 1.5em);}
     div.column{flex: auto; overflow-x: auto;}
diff --git a/test/writer.jats_archiving b/test/writer.jats_archiving
--- a/test/writer.jats_archiving
+++ b/test/writer.jats_archiving
@@ -576,27 +576,15 @@
 <sec id="html-blocks">
   <title>HTML Blocks</title>
   <p>Simple block on one line:</p>
-  <boxed-text>
-    <p>foo</p>
-  </boxed-text>
+  <p>foo</p>
   <p>And nested without indentation:</p>
-  <boxed-text>
-    <boxed-text>
-      <boxed-text>
-        <p>foo</p>
-      </boxed-text>
-    </boxed-text>
-    <boxed-text>
-      <p>bar</p>
-    </boxed-text>
-  </boxed-text>
+  <p>foo</p>
+  <p>bar</p>
   <p>Interpreted markdown in a table:</p>
   <p>This is <italic>emphasized</italic></p>
   <p>And this is <bold>strong</bold></p>
   <p>Here’s a simple block:</p>
-  <boxed-text>
-    <p>foo</p>
-  </boxed-text>
+  <p>foo</p>
   <p>This should be a code block, though:</p>
   <preformat>&lt;div&gt;
     foo
@@ -604,13 +592,7 @@
   <p>As should this:</p>
   <preformat>&lt;div&gt;foo&lt;/div&gt;</preformat>
   <p>Now, nested:</p>
-  <boxed-text>
-    <boxed-text>
-      <boxed-text>
-        <p>foo</p>
-      </boxed-text>
-    </boxed-text>
-  </boxed-text>
+  <p>foo</p>
   <p>This should just be an HTML comment:</p>
   <p>Multiline:</p>
   <p>Code block:</p>
diff --git a/test/writer.jats_articleauthoring b/test/writer.jats_articleauthoring
--- a/test/writer.jats_articleauthoring
+++ b/test/writer.jats_articleauthoring
@@ -573,27 +573,15 @@
 <sec id="html-blocks">
   <title>HTML Blocks</title>
   <p>Simple block on one line:</p>
-  <boxed-text>
-    <p>foo</p>
-  </boxed-text>
+  <p>foo</p>
   <p>And nested without indentation:</p>
-  <boxed-text>
-    <boxed-text>
-      <boxed-text>
-        <p>foo</p>
-      </boxed-text>
-    </boxed-text>
-    <boxed-text>
-      <p>bar</p>
-    </boxed-text>
-  </boxed-text>
+  <p>foo</p>
+  <p>bar</p>
   <p>Interpreted markdown in a table:</p>
   <p>This is <italic>emphasized</italic></p>
   <p>And this is <bold>strong</bold></p>
   <p>Here’s a simple block:</p>
-  <boxed-text>
-    <p>foo</p>
-  </boxed-text>
+  <p>foo</p>
   <p>This should be a code block, though:</p>
   <preformat>&lt;div&gt;
     foo
@@ -601,13 +589,7 @@
   <p>As should this:</p>
   <preformat>&lt;div&gt;foo&lt;/div&gt;</preformat>
   <p>Now, nested:</p>
-  <boxed-text>
-    <boxed-text>
-      <boxed-text>
-        <p>foo</p>
-      </boxed-text>
-    </boxed-text>
-  </boxed-text>
+  <p>foo</p>
   <p>This should just be an HTML comment:</p>
   <p>Multiline:</p>
   <p>Code block:</p>
diff --git a/test/writer.jats_publishing b/test/writer.jats_publishing
--- a/test/writer.jats_publishing
+++ b/test/writer.jats_publishing
@@ -576,27 +576,15 @@
 <sec id="html-blocks">
   <title>HTML Blocks</title>
   <p>Simple block on one line:</p>
-  <boxed-text>
-    <p>foo</p>
-  </boxed-text>
+  <p>foo</p>
   <p>And nested without indentation:</p>
-  <boxed-text>
-    <boxed-text>
-      <boxed-text>
-        <p>foo</p>
-      </boxed-text>
-    </boxed-text>
-    <boxed-text>
-      <p>bar</p>
-    </boxed-text>
-  </boxed-text>
+  <p>foo</p>
+  <p>bar</p>
   <p>Interpreted markdown in a table:</p>
   <p>This is <italic>emphasized</italic></p>
   <p>And this is <bold>strong</bold></p>
   <p>Here’s a simple block:</p>
-  <boxed-text>
-    <p>foo</p>
-  </boxed-text>
+  <p>foo</p>
   <p>This should be a code block, though:</p>
   <preformat>&lt;div&gt;
     foo
@@ -604,13 +592,7 @@
   <p>As should this:</p>
   <preformat>&lt;div&gt;foo&lt;/div&gt;</preformat>
   <p>Now, nested:</p>
-  <boxed-text>
-    <boxed-text>
-      <boxed-text>
-        <p>foo</p>
-      </boxed-text>
-    </boxed-text>
-  </boxed-text>
+  <p>foo</p>
   <p>This should just be an HTML comment:</p>
   <p>Multiline:</p>
   <p>Code block:</p>
diff --git a/test/writer.opendocument b/test/writer.opendocument
--- a/test/writer.opendocument
+++ b/test/writer.opendocument
@@ -1663,11 +1663,11 @@
 <text:p text:style-name="Text_20_body">So is
 <text:span text:style-name="T3">this</text:span> word.</text:p>
 <text:p text:style-name="Text_20_body">This is code:
-<text:span text:style-name="Source_Text">&gt;</text:span>,
-<text:span text:style-name="Source_Text">$</text:span>,
-<text:span text:style-name="Source_Text">\</text:span>,
-<text:span text:style-name="Source_Text">\$</text:span>,
-<text:span text:style-name="Source_Text">&lt;html&gt;</text:span>.</text:p>
+<text:span text:style-name="Source_20_Text">&gt;</text:span>,
+<text:span text:style-name="Source_20_Text">$</text:span>,
+<text:span text:style-name="Source_20_Text">\</text:span>,
+<text:span text:style-name="Source_20_Text">\$</text:span>,
+<text:span text:style-name="Source_20_Text">&lt;html&gt;</text:span>.</text:p>
 <text:p text:style-name="Text_20_body"><text:span text:style-name="T4">This is
 </text:span><text:span text:style-name="T5">strikeout</text:span><text:span text:style-name="T4">.</text:span></text:p>
 <text:p text:style-name="Text_20_body">Superscripts:
@@ -1692,7 +1692,7 @@
 <text:p text:style-name="Text_20_body">‘He said, “I want to go.”’ Were you alive
 in the 70’s?</text:p>
 <text:p text:style-name="Text_20_body">Here is some quoted
-‘<text:span text:style-name="Source_Text">code</text:span>’ and a
+‘<text:span text:style-name="Source_20_Text">code</text:span>’ and a
 “<text:a xlink:type="simple" xlink:href="http://example.com/?foo=1&amp;bar=2" office:name=""><text:span text:style-name="Definition">quoted
 link</text:span></text:a>”.</text:p>
 <text:p text:style-name="Text_20_body">Some dashes: one—two — three—four —
@@ -1734,7 +1734,7 @@
 <text:list text:style-name="L27">
   <text:list-item>
     <text:p text:style-name="P52">To get the famous equation, write
-    <text:span text:style-name="Source_Text">$e = mc^2$</text:span>.</text:p>
+    <text:span text:style-name="Source_20_Text">$e = mc^2$</text:span>.</text:p>
   </text:list-item>
   <text:list-item>
     <text:p text:style-name="P52">$22,000 is a
@@ -1746,7 +1746,7 @@
   </text:list-item>
   <text:list-item>
     <text:p text:style-name="P52">Escaped
-    <text:span text:style-name="Source_Text">$</text:span>: $73
+    <text:span text:style-name="Source_20_Text">$</text:span>: $73
     <text:span text:style-name="T1">this should be emphasized</text:span>
     23$.</text:p>
   </text:list-item>
@@ -1868,7 +1868,7 @@
 <text:p text:style-name="P56">Blockquoted:
 <text:a xlink:type="simple" xlink:href="http://example.com/" office:name=""><text:span text:style-name="Definition">http://example.com/</text:span></text:a></text:p>
 <text:p text:style-name="First_20_paragraph">Auto-links should not occur here:
-<text:span text:style-name="Source_Text">&lt;http://example.com/&gt;</text:span></text:p>
+<text:span text:style-name="Source_20_Text">&lt;http://example.com/&gt;</text:span></text:p>
 <text:p text:style-name="P57">or here: &lt;http://example.com/&gt;</text:p>
 <text:p text:style-name="Horizontal_20_Line" />
 <text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="images" />Images<text:bookmark-end text:name="images" /></text:h>
@@ -1898,8 +1898,9 @@
 is <text:span text:style-name="T1">easier</text:span> to type. Inline notes may
 contain
 <text:a xlink:type="simple" xlink:href="http://google.com" office:name=""><text:span text:style-name="Definition">links</text:span></text:a>
-and <text:span text:style-name="Source_Text">]</text:span> verbatim characters,
-as well as [bracketed text].</text:p></text:note-body></text:note></text:p>
+and <text:span text:style-name="Source_20_Text">]</text:span> verbatim
+characters, as well as [bracketed
+text].</text:p></text:note-body></text:note></text:p>
 <text:p text:style-name="P59">Notes can go in
 quotes.<text:note text:id="ftn3" text:note-class="footnote"><text:note-citation>4</text:note-citation><text:note-body><text:p text:style-name="Footnote">In
 quote.</text:p></text:note-body></text:note></text:p>
diff --git a/test/writer.typst b/test/writer.typst
--- a/test/writer.typst
+++ b/test/writer.typst
@@ -93,7 +93,10 @@
     }
   }
 
-  block(below: 1em, width: 100%)[
+#let has-title-block = title != none or (authors != none and authors != ()) or
+                       date != none or abstract != none
+#if has-title-block {
+  place(top, float: true, scope: "parent", clearance: 4mm, block(below: 1em, width: 100%)[
     #if title != none {
       align(center, block[
           #text(weight: "bold", size: 1.5em, hyphenate: false)[#title #if thanks != none {
@@ -133,8 +136,8 @@
         #text(weight: "semibold")[#abstract-title] #h(1em) #abstract
       ]
     }
-  ]
-
+  ])
+}
   doc
 }
 #show: doc => conf(
@@ -194,8 +197,7 @@
 
 Here's one with a bullet. \* criminey.
 
-There should be a hard line break \
-here.
+There should be a hard line break \ here.
 
 #horizontalrule
 
@@ -681,7 +683,7 @@
 - $223$
 - $p$-Tree
 - Here's some display math:
-  $ frac(d, d x) f \( x \) = lim_(h arrow.r 0) frac(f \( x + h \) - f \( x \), h) $
+  $ frac(d, d x) f\(x\)= lim_(h arrow.r 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:
@@ -833,13 +835,13 @@
 <images>
 From "Voyage dans la Lune" by Georges Melies (1902):
 
-#figure(image("lalune.jpg"),
+#figure(image("lalune.jpg", alt: "lalune"),
   caption: [
     lalune
   ]
 )
 
-Here is a movie #box(image("movie.jpg")) icon.
+Here is a movie #box(image("movie.jpg", alt: "movie")) icon.
 
 #horizontalrule
 
