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: July 07, 2023
+date: July 20, 2023
 ---
 
 # Synopsis
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,82 @@
 # Revision history for pandoc
 
+## pandoc 3.1.6 (2023-07-20)
+
+  * Fix new variant of the vulnerability in CVE-2023-35936.
+    Guilhem Moulin noticed that the fix to CVE-2023-35936 was incomplete.
+    An attacker could get around it by double-encoding the malicious
+    extension to create or override arbitrary files.
+
+  * `--embed-resources`: Use inline SVG instead of data uris for SVG
+    images in HTML5 (#8948). Note that SelfContained does not have
+    access to the writer name, so we check for HTML5 by determining
+    whether the document starts with `<DOCTYPE! html>`. This means
+    that inline SVG won't be used when generating document fragments.
+
+  * Fix regression on short boolean arguments (#8956).
+    In 3.1.5 boolean arguments were allowed an optional argument
+    (`true|false`).  This created a regression for uses of fused
+    short arguments, e.g. `-somyfile.html`, which was equivalent
+    to `-s -omyfile.html`, but now raised an error because
+    pandoc attempted to parse `o` as a boolean `true` or `false`.
+    This change allows the fused short arguments to be used again.
+    Note that `-strue` will be interpreted as `-s` with an
+    argument `true`, not as `-s -t -rue`.  It is best to
+    use long option names with the optional boolean values,
+    to avoid confusion.
+
+  * Make `--epub-title-page`'s argument optional. It takes a boolean
+    argument, and now that all of our boolean flags take such an
+    argument, we can make this one optional for consistency.
+
+  * Improve errors for illegal output formats. Previously if you did
+    `pandoc -s -t bbb`, it would give you an error about the missing
+    `bbb` template instead of saying that `bbb` is not a
+    supported output format.
+
+  * Improve errors for incorrect command-line option values (#8879).
+    Always give the name of the relevant argument.
+
+  * Fix typo on error message for incorrect `--preserve-tabs` argument.
+    Thanks @fsoedjede
+
+  * Docx reader: use SVG version of image if present (#7244).
+    Previously the backup PNG was exported even if an SVG was
+    present, but the SVG should be preferred.
+
+  * Typst reader: fix regression in recognition of display math (#8949).
+    The last release caused all math to be parsed as inline math.
+
+  * JATS writer: don't use `<code>` for inline code (#8889).
+    It is intended for block-level code.
+
+  * HTML writer: don't make line blocks sensitive to `--wrap` (#8952).
+
+  * RST writer: fix figure handling (#8930, #8871).
+    This fixes a number of regressions from pandoc 2.x.
+    Properly handle caption, alt attribute in figures.
+    No longer treat a paragraph with a single image in it as a figure
+    (we have a dedicated Figure element now).
+
+  * Docx writer: Copy "mirror margins" property from reference.docx (#8946).
+
+  * Text.Pandoc.UTF8: Deprecate `decodeArg` which is now a no-op.
+    This was needed for old base versions which we no longer support.
+
+  * Use released skylighting, typst.
+
+  * Allow latest commonmark-extensions. This allows entities in wikilinks.
+
+  * Switch back to using ghc 9.2 for linux and Windows binary releases
+    (#8947, #8955). With ghc 9.4+, we were getting AVX instructions
+    in the amd64 binary, which aren't supported on older hardware.
+    For maximum compatibility we switch back to ghc 9.2, which doesn't
+    cause the problem. (As documented, ghc should not be emiting these
+    instructions, so we aren't clear on the diagnosis, but the cure
+    has been tested.)
+
+  * Change Windows release build to use cabal instead of stack.
+
 ## pandoc 3.1.5 (2023-07-07)
 
   * Allow all boolean flags to take an optional `true` or `false` value
diff --git a/man/pandoc.1 b/man/pandoc.1
--- a/man/pandoc.1
+++ b/man/pandoc.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 3.1.3
+.\" Automatically generated by Pandoc 3.1.5
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "Pandoc User\[cq]s Guide" "" "July 07, 2023" "pandoc 3.1.5" ""
+.TH "Pandoc User\[cq]s Guide" "" "July 20, 2023" "pandoc 3.1.6" ""
 .hy
 .SH NAME
 pandoc - general markup converter
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.1.5
+version:         3.1.6
 build-type:      Simple
 license:         GPL-2.0-or-later
 license-file:    COPYING.md
@@ -206,6 +206,7 @@
                  test/*.native
                  test/command/*.md
                  test/command/*.csl
+                 test/command/*.svg
                  test/command/biblio.bib
                  test/command/averroes.bib
                  test/command/A.txt
@@ -235,10 +236,6 @@
                  test/command/5700-metadata-file-1.yml
                  test/command/5700-metadata-file-2.yml
                  test/command/abbrevs
-                 test/command/SVG_logo-without-xml-declaration.svg
-                 test/command/SVG_logo.svg
-                 test/command/corrupt.svg
-                 test/command/inkscape-cube.svg
                  test/command/sub-file-chapter-1.tex
                  test/command/sub-file-chapter-2.tex
                  test/command/bar.tex
@@ -477,7 +474,7 @@
                  case-insensitive      >= 1.2      && < 1.3,
                  citeproc              >= 0.8.1    && < 0.9,
                  commonmark            >= 0.2.3    && < 0.3,
-                 commonmark-extensions >= 0.2.3.4  && < 0.3,
+                 commonmark-extensions >= 0.2.3.5  && < 0.3,
                  commonmark-pandoc     >= 0.2.1.3  && < 0.3,
                  containers            >= 0.6.0.1  && < 0.7,
                  crypton-connection    >= 0.3.1    && < 0.4,
@@ -510,8 +507,8 @@
                  random                >= 1        && < 1.3,
                  safe                  >= 0.3.18   && < 0.4,
                  scientific            >= 0.3      && < 0.4,
-                 skylighting           >= 0.13.4   && < 0.14,
-                 skylighting-core      >= 0.13.4   && < 0.14,
+                 skylighting           >= 0.13.4.1 && < 0.14,
+                 skylighting-core      >= 0.13.4.1 && < 0.14,
                  split                 >= 0.2      && < 0.3,
                  syb                   >= 0.1      && < 0.8,
                  tagsoup               >= 0.14.6   && < 0.15,
@@ -526,7 +523,7 @@
                  zip-archive           >= 0.4.3    && < 0.5,
                  zlib                  >= 0.5      && < 0.7,
                  xml                   >= 1.3.12   && < 1.4,
-                 typst                 >= 0.3      && < 0.4,
+                 typst                 >= 0.3.1    && < 0.4,
                  vector                >= 0.12     && < 0.14
 
   if !os(windows)
diff --git a/src/Text/Pandoc/App/CommandLineOptions.hs b/src/Text/Pandoc/App/CommandLineOptions.hs
--- a/src/Text/Pandoc/App/CommandLineOptions.hs
+++ b/src/Text/Pandoc/App/CommandLineOptions.hs
@@ -59,13 +59,14 @@
 import qualified Data.ByteString as BS
 import qualified Data.ByteString.Lazy as B
 import qualified Data.Map as M
+import qualified Data.Set as Set
 import qualified Data.Text as T
 import qualified Text.Pandoc.UTF8 as UTF8
 
 parseOptions :: [OptDescr (Opt -> ExceptT OptInfo IO Opt)]
              -> Opt -> IO (Either OptInfo Opt)
 parseOptions options' defaults = do
-  rawArgs <- map UTF8.decodeArg <$> liftIO getArgs
+  rawArgs <- liftIO getArgs
   prg <- liftIO getProgName
   parseOptionsFromArgs options' defaults prg rawArgs
 
@@ -74,7 +75,7 @@
   -> Opt -> String -> [String] -> IO (Either OptInfo Opt)
 parseOptionsFromArgs options' defaults prg rawArgs = do
   let (actions, args, unrecognizedOpts, errors) =
-           getOpt' Permute options' (map UTF8.decodeArg rawArgs)
+           getOpt' Permute options' (preprocessArgs rawArgs)
 
   let unknownOptionErrors =
        foldr (handleUnrecognizedOption . takeWhile (/= '=')) []
@@ -230,6 +231,45 @@
 pdfEngines :: [String]
 pdfEngines = nubOrd $ map snd engines
 
+-- For motivation see #8956.  We want to allow things like `-si` without
+-- causing the `i` to be parsed as an optional boolean argument of `-s`.
+-- This is for backwards compatibility given the addition of optional
+-- boolean arguments in #8879.
+preprocessArgs :: [String] -> [String]
+preprocessArgs [] = []
+preprocessArgs ("--":xs) = "--" : xs -- a bare '--' ends option parsing
+-- note that -strue is interpreted as -strue while
+-- -stmarkdown is interpreted as -s -tmarkdown
+preprocessArgs (('-':c:d:cs):xs)
+  | isShortBooleanOpt c
+  , case toLower <$> (d:cs) of
+      "true" -> True
+      "false" -> True
+      _ -> False
+    = ('-':c:d:cs) : preprocessArgs xs
+  | isShortBooleanOpt c
+  , isShortOpt d = splitArg (c:d:cs) ++ preprocessArgs xs
+preprocessArgs (x:xs) = x : preprocessArgs xs
+
+isShortBooleanOpt :: Char -> Bool
+isShortBooleanOpt = (`Set.member` shortBooleanOpts)
+ where
+  shortBooleanOpts =
+     Set.fromList [c | Option [c] _ (OptArg _ "true|false") _ <- options]
+
+isShortOpt :: Char -> Bool
+isShortOpt = (`Set.member` shortOpts)
+ where
+  shortOpts = Set.fromList $ concat [cs | Option cs _ _ _ <- options]
+
+splitArg :: String -> [String]
+splitArg (c:d:cs)
+  | isShortBooleanOpt c
+  , isShortOpt d
+  = ['-',c] : splitArg (d:cs)
+splitArg (c:cs) = ['-':c:cs]
+splitArg [] = []
+
 -- | A list of functions, each transforming the options data structure
 --   in response to a command-line option.
 options :: [OptDescr (Opt -> ExceptT OptInfo IO Opt)]
@@ -295,7 +335,7 @@
     , Option "" ["file-scope"]
                  (OptArg
                   (\arg opt -> do
-                        boolValue <- readBoolFromOptArg arg
+                        boolValue <- readBoolFromOptArg "--file-scope" arg
                         return opt { optFileScope = boolValue })
                   "true|false")
                  "" -- "Parse input files before combining"
@@ -303,7 +343,7 @@
     , Option "" ["sandbox"]
                  (OptArg
                   (\arg opt -> do
-                        boolValue <- readBoolFromOptArg arg
+                        boolValue <- readBoolFromOptArg "--sandbox" arg
                         return opt { optSandbox = boolValue })
                   "true|false")
                  ""
@@ -311,7 +351,7 @@
     , Option "s" ["standalone"]
                  (OptArg
                   (\arg opt -> do
-                        boolValue <- readBoolFromOptArg arg
+                        boolValue <- readBoolFromOptArg "--standalone/-s" arg
                         return opt { optStandalone = boolValue })
                   "true|false")
                  "" -- "Include needed header and footer on output"
@@ -348,7 +388,7 @@
     , Option "" ["ascii"]
                  (OptArg
                   (\arg opt -> do
-                        boolValue <- readBoolFromOptArg arg
+                        boolValue <- readBoolFromOptArg "--ascii" arg
                         return opt { optAscii = boolValue })
                   "true|false")
                  ""  -- "Prefer ASCII output"
@@ -356,7 +396,7 @@
     , Option "" ["toc", "table-of-contents"]
                 (OptArg
                  (\arg opt -> do
-                        boolValue <- readBoolFromOptArg arg
+                        boolValue <- readBoolFromOptArg "--toc/--table-of-contents" arg
                         return opt { optTableOfContents = boolValue })
                  "true|false")
                "" -- "Include table of contents"
@@ -368,7 +408,7 @@
                            Just t | t >= 1 && t <= 6 ->
                                     return opt { optTOCDepth = t }
                            _ -> optError $ PandocOptionError
-                                "TOC level must be a number 1-6")
+                                "Argument of --toc-depth must be a number 1-6")
                  "NUMBER")
                  "" -- "Number of levels to include in TOC"
 
@@ -384,7 +424,7 @@
                            Just ns -> return opt { optNumberOffset = ns,
                                                    optNumberSections = True }
                            _      -> optError $ PandocOptionError
-                                       "could not parse number-offset")
+                                       "could not parse argument of --number-offset")
                  "NUMBERS")
                  "" -- "Starting number for sections, subsections, etc."
 
@@ -401,7 +441,7 @@
                         "default" -> return opt{ optTopLevelDivision =
                                         TopLevelDefault }
                         _ -> optError $ PandocOptionError $
-                                "Top-level division must be " <>
+                                "Argument of --top-level division must be " <>
                                 "section,  chapter, part, or default" )
                    "section|chapter|part")
                  "" -- "Use top-level division type in LaTeX, ConTeXt, DocBook"
@@ -473,7 +513,7 @@
                     case safeStrRead arg of
                          Just t | t > 0 -> return opt { optDpi = t }
                          _              -> optError $ PandocOptionError
-                                        "dpi must be a number greater than 0")
+                                        "Argument of --dpi must be a number greater than 0")
                   "NUMBER")
                  "" -- "Dpi (default 96)"
 
@@ -486,7 +526,7 @@
                       "native" -> return opt { optEol = Native }
                       -- mac-syntax (cr) is not supported in ghc-base.
                       _      -> optError $ PandocOptionError
-                                "--eol must be crlf, lf, or native")
+                                "Argument of --eol must be crlf, lf, or native")
                   "crlf|lf|native")
                  "" -- "EOL (default OS-dependent)"
 
@@ -496,14 +536,14 @@
                       case safeStrRead arg of
                            Just t | t > 0 -> return opt { optColumns = t }
                            _              -> optError $ PandocOptionError
-                                   "columns must be a number greater than 0")
+                                   "Argument of --columns must be a number greater than 0")
                  "NUMBER")
                  "" -- "Length of line in characters"
 
     , Option "p" ["preserve-tabs"]
                  (OptArg
                   (\arg opt -> do
-                        boolValue <- readBoolFromOptArg arg
+                        boolValue <- readBoolFromOptArg "--preserve-tabs/-p" arg
                         return opt { optPreserveTabs = boolValue })
                   "true|false")
                  "" -- "Preserve tabs instead of converting to spaces"
@@ -514,7 +554,7 @@
                       case safeStrRead arg of
                            Just t | t > 0 -> return opt { optTabStop = t }
                            _              -> optError $ PandocOptionError
-                                  "tab-stop must be a number greater than 0")
+                                  "Argument of --tab-stop must be a number greater than 0")
                   "NUMBER")
                  "" -- "Tab stop (default 4)"
 
@@ -526,7 +566,7 @@
                         then return opt { optPdfEngine = Just arg }
                         else optError $
                               PandocOptionError $ T.pack $
-                              "pdf-engine must be one of "
+                              "Argument of --pdf-engine must be one of "
                                ++ intercalate ", " pdfEngines)
                   "PROGRAM")
                  "" -- "Name of program to use in generating PDF"
@@ -550,7 +590,7 @@
                  (OptArg
                   (\arg opt -> do
                         deprecatedOption "--self-contained" "use --embed-resources --standalone"
-                        boolValue <- readBoolFromOptArg arg
+                        boolValue <- readBoolFromOptArg "--self-contained" arg
                         return opt { optSelfContained = boolValue })
                     "true|false")
                  "" -- "Make slide shows include all the needed js and css (deprecated)"
@@ -558,7 +598,7 @@
     , Option "" ["embed-resources"] -- maybe True (\argStr -> argStr == "true") arg
                  (OptArg
                   (\arg opt -> do
-                        boolValue <- readBoolFromOptArg arg
+                        boolValue <- readBoolFromOptArg "--embed-resources" arg
                         return opt { optEmbedResources =  boolValue })
                   "true|false")
                  "" -- "Make slide shows include all the needed js and css"
@@ -575,7 +615,7 @@
     , Option "" ["no-check-certificate"]
                 (OptArg
                  (\arg opt -> do
-                        boolValue <- readBoolFromOptArg arg
+                        boolValue <- readBoolFromOptArg "--no-check-certificate" arg
                         return opt { optNoCheckCertificate = boolValue })
                  "true|false")
                 "" -- "Disable certificate validation"
@@ -622,7 +662,7 @@
                            Just t ->
                                return opt{ optShiftHeadingLevelBy = t }
                            _              -> optError $ PandocOptionError
-                                               "shift-heading-level-by takes an integer argument")
+                                               "Argument of --shift-heading-level-by must be an integer")
                   "NUMBER")
                  "" -- "Shift heading level"
 
@@ -635,7 +675,7 @@
                            Just t | t > 0 && t < 6 ->
                                return opt{ optShiftHeadingLevelBy = t - 1 }
                            _              -> optError $ PandocOptionError
-                                               "base-header-level must be 1-5")
+                                               "Argument of --base-header-level must be 1-5")
                   "NUMBER")
                  "" -- "Headers base level"
 
@@ -647,7 +687,7 @@
                             "reject" -> return RejectChanges
                             "all"    -> return AllChanges
                             _        -> optError $ PandocOptionError $ T.pack
-                               ("Unknown option for track-changes: " ++ arg)
+                               "Argument of --track-changes must be accept, reject, or all"
                      return opt { optTrackChanges = action })
                   "accept|reject|all")
                  "" -- "Accepting or reject MS Word track-changes.""
@@ -655,7 +695,7 @@
     , Option "" ["strip-comments"]
                 (OptArg
                  (\arg opt -> do
-                        boolValue <- readBoolFromOptArg arg
+                        boolValue <- readBoolFromOptArg "--strip-comments" arg
                         return opt { optStripComments = boolValue })
                  "true|false")
                "" -- "Strip HTML comments"
@@ -663,7 +703,7 @@
     , Option "" ["reference-links"]
                  (OptArg
                   (\arg opt -> do
-                        boolValue <- readBoolFromOptArg arg
+                        boolValue <- readBoolFromOptArg "--reference-links" arg
                         return opt { optReferenceLinks = boolValue })
                   "true|false")
                  "" -- "Use reference links in parsing HTML"
@@ -676,7 +716,7 @@
                             "section"  -> return EndOfSection
                             "document" -> return EndOfDocument
                             _        -> optError $ PandocOptionError $ T.pack
-                               ("Unknown option for reference-location: " ++ arg)
+                               "Argument of --reference-location must be block, section, or document"
                      return opt { optReferenceLocation = action })
                   "block|section|document")
                  "" -- "Accepting or reject MS Word track-changes.""
@@ -688,8 +728,7 @@
                         "setext" -> pure True
                         "atx" -> pure False
                         _ -> optError $ PandocOptionError $ T.pack
-                          ("Unknown markdown heading format: " ++ arg ++
-                            ". Expecting atx or setext")
+                          "Argument of --markdown-headings must be setext or atx"
                       pure opt { optSetextHeaders = headingFormat }
                     )
                   "setext|atx")
@@ -698,7 +737,7 @@
     , Option "" ["list-tables"]
                  (OptArg
                   (\arg opt -> do
-                        boolValue <- readBoolFromOptArg arg
+                        boolValue <- readBoolFromOptArg "--list-tables" arg
                         return opt { optListTables = boolValue })
                   "true|false")
                  "" -- "Use list tables for RST"
@@ -706,7 +745,7 @@
     , Option "" ["listings"]
                  (OptArg
                   (\arg opt -> do
-                        boolValue <- readBoolFromOptArg arg
+                        boolValue <- readBoolFromOptArg "--listings" arg
                         return opt { optListings = boolValue })
                   "true|false")
                  "" -- "Use listings package for LaTeX code blocks"
@@ -714,7 +753,7 @@
     , Option "i" ["incremental"]
                  (OptArg
                   (\arg opt -> do
-                        boolValue <- readBoolFromOptArg arg
+                        boolValue <- readBoolFromOptArg "--incremental/-i" arg
                         return opt { optIncremental = boolValue })
                   "true|false")
                  "" -- "Make list items display incrementally in Slidy/Slideous/S5"
@@ -726,14 +765,14 @@
                            Just t | t >= 0 && t <= 6 ->
                                     return opt { optSlideLevel = Just t }
                            _      -> optError $ PandocOptionError
-                                    "slide level must be a number between 0 and 6")
+                                    "Argument of --slide-level must be a number between 0 and 6")
                  "NUMBER")
                  "" -- "Force header level for slides"
 
     , Option "" ["section-divs"]
                  (OptArg
                   (\arg opt -> do
-                        boolValue <- readBoolFromOptArg arg
+                        boolValue <- readBoolFromOptArg "--section-divs" arg
                         return opt { optSectionDivs = boolValue })
                   "true|false")
                  "" -- "Put sections in div tags in HTML"
@@ -741,7 +780,7 @@
     , Option "" ["html-q-tags"]
                  (OptArg
                   (\arg opt -> do
-                        boolValue <- readBoolFromOptArg arg
+                        boolValue <- readBoolFromOptArg "--html-q-tags" arg
                         return opt { optHtmlQTags = boolValue })
                   "true|false")
                  "" -- "Use <q> tags for quotes in HTML"
@@ -754,7 +793,7 @@
                             "javascript" -> return JavascriptObfuscation
                             "none"       -> return NoObfuscation
                             _            -> optError $ PandocOptionError $ T.pack
-                               ("Unknown obfuscation method: " ++ arg)
+                               "Argument of --email-obfuscation must be references, javascript, or none"
                      return opt { optEmailObfuscation = method })
                   "none|javascript|references")
                  "" -- "Method for obfuscating email in HTML"
@@ -801,14 +840,10 @@
                  "" -- "Path of epub cover image"
 
     , Option "" ["epub-title-page"]
-                 (ReqArg
-                  (\arg opt ->
-                    case arg of
-                      "true" -> return opt{ optEpubTitlePage = True }
-                      "false" -> return opt{ optEpubTitlePage = False }
-                      _ -> optError $ PandocOptionError $
-                                "Argument to --epub-title-page must be " <>
-                                "true or false" )
+                 (OptArg
+                  (\arg opt -> do
+                     boolValue <- readBoolFromOptArg "--epub-title-page" arg
+                     return opt{ optEpubTitlePage = boolValue })
                  "true|false")
                  ""
 
@@ -834,7 +869,7 @@
                            Just t | t >= 1 && t <= 6 ->
                                     return opt { optSplitLevel = t }
                            _      -> optError $ PandocOptionError
-                                    "split level must be a number between 1 and 6")
+                                    "Argument of --split-level must be a number between 1 and 6")
                  "NUMBER")
                  "" -- "Header level at which to split documents in chunked HTML or EPUB"
 
@@ -854,7 +889,7 @@
                            Just t | t >= 1 && t <= 6 ->
                                     return opt { optSplitLevel = t }
                            _      -> optError $ PandocOptionError
-                                    "split level must be a number between 1 and 6")
+                                    "Argument of --epub-chapter-level must be a number between 1 and 6")
                  "NUMBER")
                  "" -- "Header level at which to split documents in chunked HTML or EPUB"
 
@@ -866,7 +901,7 @@
                       "best" -> return opt{ optIpynbOutput = IpynbOutputBest }
                       "none" -> return opt{ optIpynbOutput = IpynbOutputNone }
                       _ -> optError $ PandocOptionError
-                             "ipynb-output must be all, none, or best")
+                             "Argument of --ipynb-output must be all, none, or best")
                  "all|none|best")
                  "" -- "Starting number for sections, subsections, etc."
 
@@ -890,7 +925,7 @@
                   (\arg opt -> do
                     case lookupMeta (T.pack "csl") $ optMetadata opt of
                       Just _ -> optError $ PandocOptionError
-                                   "Only one CSL file can be specified."
+                                   "--csl option can only be used once"
                       Nothing -> return opt{ optMetadata = addMeta "csl" (normalizePath arg) $
                       optMetadata opt })
                    "FILE")
@@ -955,7 +990,7 @@
     , Option "" ["trace"]
                  (OptArg
                   (\arg opt -> do
-                        boolValue <- readBoolFromOptArg arg
+                        boolValue <- readBoolFromOptArg "--trace" arg
                         return opt { optTrace = boolValue })
                   "true|false")
                  "" -- "Turn on diagnostic tracing in readers."
@@ -963,7 +998,7 @@
     , Option "" ["dump-args"]
                  (OptArg
                   (\arg opt -> do
-                        boolValue <- readBoolFromOptArg arg
+                        boolValue <- readBoolFromOptArg "--dump-args" arg
                         return opt { optDumpArgs = boolValue })
                   "true|false")
                  "" -- "Print output filename and arguments to stdout."
@@ -971,7 +1006,7 @@
     , Option "" ["ignore-args"]
                  (OptArg
                   (\arg opt -> do
-                        boolValue <- readBoolFromOptArg arg
+                        boolValue <- readBoolFromOptArg "--ignore-args" arg
                         return opt { optIgnoreArgs = boolValue })
                   "true|false")
                  "" -- "Ignore command-line arguments."
@@ -989,7 +1024,7 @@
     , Option "" ["fail-if-warnings"]
                  (OptArg
                   (\arg opt -> do
-                        boolValue <- readBoolFromOptArg arg
+                        boolValue <- readBoolFromOptArg "--fail-if-warnings" arg
                         return opt { optFailIfWarnings = boolValue })
                   "true|false")
                  "" -- "Exit with error status if there were  warnings."
@@ -1155,12 +1190,13 @@
   | s == "FALSE" = MetaBool False
   | otherwise    = MetaString $ T.pack s
 
-readBoolFromOptArg ::  Maybe String -> ExceptT OptInfo IO Bool
-readBoolFromOptArg = maybe (return True) readBoolFromArg
+readBoolFromOptArg ::  Text -> Maybe String -> ExceptT OptInfo IO Bool
+readBoolFromOptArg opt = maybe (return True) readBoolFromArg
     where readBoolFromArg arg = case toLower <$> arg of
             "true"  -> return True
             "false" -> return False
-            _       -> optError $ PandocOptionError "value must be either true or false"
+            _       -> optError $ PandocOptionError $
+                        "Argument of " <> opt <> " must be either true or false"
 
 -- On Windows with ghc 8.6+, we need to rewrite paths
 -- beginning with \\ to \\?\UNC\. -- See #5127.
diff --git a/src/Text/Pandoc/App/OutputSettings.hs b/src/Text/Pandoc/App/OutputSettings.hs
--- a/src/Text/Pandoc/App/OutputSettings.hs
+++ b/src/Text/Pandoc/App/OutputSettings.hs
@@ -143,15 +143,17 @@
                  Just t -> (runWithDefaultPartials $ compileTemplate path t) >>=
                            templateOrThrow
       return (w, wexts, templ)
-    else do
-      tmpl <- processCustomTemplate (compileDefaultTemplate format)
+    else
       if optSandbox opts
-      then case runPure (getWriter flvrd) of
+      then do
+        tmpl <- processCustomTemplate (compileDefaultTemplate format)
+        case runPure (getWriter flvrd) of
              Right (w, wexts) -> return (makeSandboxed w, wexts, tmpl)
              Left e           -> throwError e
       else do
-           (w, wexts) <- getWriter flvrd
-           return (w, wexts, tmpl)
+        (w, wexts) <- getWriter flvrd
+        tmpl <- processCustomTemplate (compileDefaultTemplate format)
+        return (w, wexts, tmpl)
 
 
   let addSyntaxMap existingmap f = do
diff --git a/src/Text/Pandoc/Class/IO.hs b/src/Text/Pandoc/Class/IO.hs
--- a/src/Text/Pandoc/Class/IO.hs
+++ b/src/Text/Pandoc/Class/IO.hs
@@ -224,6 +224,8 @@
            -> m ()
 writeMedia dir (fp, _mt, bs) = do
   -- we normalize to get proper path separators for the platform
+  -- we unescape URI encoding, but given how insertMedia
+  -- is written, we shouldn't have any % in a canonical media name...
   let fullpath = normalise $ dir </> unEscapeString fp
   liftIOError (createDirectoryIfMissing True) (takeDirectory fullpath)
   report $ Extracting (T.pack fullpath)
diff --git a/src/Text/Pandoc/MediaBag.hs b/src/Text/Pandoc/MediaBag.hs
--- a/src/Text/Pandoc/MediaBag.hs
+++ b/src/Text/Pandoc/MediaBag.hs
@@ -90,16 +90,17 @@
                        && Windows.isRelative fp''
                        && isNothing uri
                        && not (".." `isInfixOf` fp'')
+                       && '%' `notElem` fp''
                      then fp''
-                     else showDigest (sha1 contents) <> "." <> ext
+                     else showDigest (sha1 contents) <> ext
         fallback = case takeExtension fp'' of
                         ".gz" -> getMimeTypeDef $ dropExtension fp''
                         _     -> getMimeTypeDef fp''
         mt = fromMaybe fallback mbMime
         path = maybe fp'' (unEscapeString . uriPath) uri
         ext = case takeExtension path of
-                '.':e -> e
-                _ -> maybe "" T.unpack $ extensionFromMimeType mt
+                '.':e | '%' `notElem` e -> '.':e
+                _ -> maybe "" (\x -> '.':T.unpack x) $ extensionFromMimeType mt
 
 -- | Lookup a media item in a 'MediaBag', returning mime type and contents.
 lookupMedia :: FilePath
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
@@ -915,10 +915,9 @@
   , pic_ns <- "http://schemas.openxmlformats.org/drawingml/2006/picture"
   , picElems <- findElements (QName "pic" (Just pic_ns) (Just "pic")) drawingElem
   = let (title, alt) = getTitleAndAlt ns drawingElem
-        a_ns = "http://schemas.openxmlformats.org/drawingml/2006/main"
         drawings = map (\el ->
-                        ((findElement (QName "blip" (Just a_ns) (Just "a")) el
-                          >>= findAttrByName ns "r" "embed"), el)) picElems
+                        ((findBlip el >>= findAttrByName ns "r" "embed"), el))
+                       picElems
     in mapM (\case
                 (Just s, el) -> do
                   (fp, bs) <- expandDrawingId s
@@ -1040,10 +1039,9 @@
   , pic_ns <- "http://schemas.openxmlformats.org/drawingml/2006/picture"
   , picElems <- findElements (QName "pic" (Just pic_ns) (Just "pic")) element
   = let (title, alt) = getTitleAndAlt ns element
-        a_ns = "http://schemas.openxmlformats.org/drawingml/2006/main"
         drawings = map (\el ->
-                         ((findElement (QName "blip" (Just a_ns) (Just "a")) el
-                             >>= findAttrByName ns "r" "embed"), el)) picElems
+                         ((findBlip el >>= findAttrByName ns "r" "embed"), el))
+                   picElems
     in mapM (\case
                 (Just s, el) -> do
                   (fp, bs) <- expandDrawingId s
@@ -1236,3 +1234,11 @@
 
 setFont :: Maybe Font -> ReaderEnv -> ReaderEnv
 setFont f s = s{envFont = f}
+
+findBlip :: Element -> Maybe Element
+findBlip el = do
+  blip <- findElement (QName "blip" (Just a_ns) (Just "a")) el
+  -- return svg if present:
+  filterElementName (\(QName tag _ _) -> tag == "svgBlip") el `mplus` pure blip
+ where
+  a_ns = "http://schemas.openxmlformats.org/drawingml/2006/main"
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
@@ -95,7 +95,8 @@
     Txt t -> pure $ B.text t
     Lab name -> pure $ B.spanWith (name, [], []) mempty
     Elt (Identifier tname) _ _
-      | "math." `T.isPrefixOf` tname ->
+      | "math." `T.isPrefixOf` tname
+      , tname /= "math.equation" ->
           B.math . writeTeX <$> pMathMany (Seq.singleton res)
     Elt name@(Identifier tname) pos fields ->
       case M.lookup name inlineHandlers of
diff --git a/src/Text/Pandoc/SelfContained.hs b/src/Text/Pandoc/SelfContained.hs
--- a/src/Text/Pandoc/SelfContained.hs
+++ b/src/Text/Pandoc/SelfContained.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE LambdaCase        #-}
 {-# LANGUAGE TupleSections     #-}
@@ -17,13 +18,13 @@
 module Text.Pandoc.SelfContained ( makeDataURI, makeSelfContained ) where
 import Codec.Compression.GZip as Gzip
 import Control.Applicative ((<|>))
-import Control.Monad.Trans (lift)
 import Data.ByteString (ByteString)
 import Data.ByteString.Base64 (encodeBase64)
 import qualified Data.ByteString.Char8 as B
 import qualified Data.ByteString.Lazy as L
 import qualified Data.Text as T
 import Data.Char (isAlphaNum, isAscii)
+import Data.Digest.Pure.SHA (sha1, showDigest)
 import Network.URI (escapeURIString)
 import System.FilePath (takeDirectory, takeExtension, (</>))
 import Text.HTML.TagSoup
@@ -32,12 +33,17 @@
 import Text.Pandoc.Logging
 import Text.Pandoc.Error (PandocError(..))
 import Text.Pandoc.MIME (MimeType)
-import Text.Pandoc.Shared (renderTags', trim, tshow)
+import Text.Pandoc.Shared (renderTags', trim, tshow, safeRead)
 import Text.Pandoc.URI (isURI)
 import Text.Pandoc.UTF8 (toString, toText, fromText)
 import Text.Pandoc.Parsing (ParsecT, runParserT)
 import qualified Text.Pandoc.Parsing as P
 import Control.Monad.Except (throwError, catchError)
+import Data.Either (lefts, rights)
+import Data.Maybe (isNothing)
+import qualified Data.Map as M
+import Control.Monad.State
+-- import Debug.Trace
 
 isOk :: Char -> Bool
 isOk c = isAscii c && isAlphaNum c
@@ -60,7 +66,14 @@
   x == "poster" ||
   x == "data-background-image"
 
-convertTags :: PandocMonad m => [Tag T.Text] -> m [Tag T.Text]
+data ConvertState =
+  ConvertState
+  { isHtml5 :: Bool
+  , svgMap  :: M.Map T.Text T.Text -- map from hash to id
+  } deriving (Show)
+
+convertTags :: PandocMonad m =>
+               [Tag T.Text] -> StateT ConvertState m [Tag T.Text]
 convertTags [] = return []
 convertTags (t@TagOpen{}:ts)
   | fromAttrib "data-external" t == "1" = (t:) <$> convertTags ts
@@ -132,20 +145,95 @@
   | any (isSourceAttribute tagname) as
      = do
        as' <- mapM processAttribute as
+       let attrs = rights as'
+       let svgContents = lefts as'
        rest <- convertTags ts
-       return $ TagOpen tagname as' : rest
+       case svgContents of
+         [] -> return $ TagOpen tagname attrs : rest
+         ((hash, tags) : _) -> do
+             -- drop "</img>" if present
+             let rest' = case rest of
+                           TagClose tn : xs | tn == tagname ->  xs
+                           _ -> rest
+             svgmap <- gets svgMap
+             case M.lookup hash svgmap of
+               Just svgid -> do
+                 let attrs' = if ("id", svgid) `elem` attrs
+                                 then [(k,v) | (k,v) <- attrs, k /= "id"]
+                                 else attrs
+                 return $ TagOpen "svg" attrs' :
+                          TagOpen "use" [("href", "#" <> svgid)] :
+                          TagClose "use" :
+                          TagClose "svg" :
+                          rest'
+               Nothing ->
+                  case dropWhile (not . isTagOpenName "svg") tags of
+                    TagOpen "svg" svgattrs : tags' -> do
+                      let attrs' = combineSvgAttrs svgattrs attrs
+                      let (svgId, attrs'') = -- keep original image id if present
+                            case lookup "id" as of
+                              Just id' -> (id', attrs')
+                              Nothing  ->
+                                let newid = "svg_" <> hash
+                                 in (newid, ("id", newid) :
+                                             filter (\(k,_) -> k /= "id") attrs')
+                      modify $ \st -> st{ svgMap = M.insert hash svgId (svgMap st) }
+                      return $ TagOpen "svg" attrs'' : tags' ++ rest'
+                    _ -> return $ TagOpen tagname attrs : rest
   where processAttribute (x,y) =
            if isSourceAttribute tagname (x,y)
               then do
                 res <- getData (fromAttrib "type" t) y
                 case res of
-                  AlreadyDataURI enc -> return (x, enc)
-                  Fetched (mt,bs) -> return (x, makeDataURI (mt,bs))
-                  CouldNotFetch _ -> return (x, y)
-              else return (x,y)
+                  AlreadyDataURI enc -> return $ Right (x, enc)
+                  Fetched ("image/svg+xml", bs) -> do
+                    -- we filter CR in the hash to ensure that Windows
+                    -- and non-Windows tests agree:
+                    let hash = T.pack (showDigest
+                                        (sha1 (L.fromStrict
+                                           (B.filter (/='\r') bs))))
+                    return $ Left (hash, getSvgTags (toText bs))
+                  Fetched (mt,bs) -> return $ Right (x, makeDataURI (mt,bs))
+                  CouldNotFetch _ -> return $ Right (x, y)
+              else return $ Right (x,y)
 
 convertTags (t:ts) = (t:) <$> convertTags ts
 
+-- we want to drop spaces, <?xml>, and comments before <svg>
+-- and anything after </svg>:
+getSvgTags :: T.Text -> [Tag T.Text]
+getSvgTags t =
+  case takeWhile (not . isTagCloseName "svg") .
+       dropWhile (not . isTagOpenName "svg") $ parseTags t of
+    [] -> []
+    xs -> xs ++ [TagClose "svg"]
+
+combineSvgAttrs :: [(T.Text, T.Text)] -> [(T.Text, T.Text)] -> [(T.Text, T.Text)]
+combineSvgAttrs svgAttrs imgAttrs =
+  case (mbViewBox, mbHeight, mbWidth) of
+    (Nothing, Just h, Just w) -> -- calculate viewBox
+      combinedAttrs ++ [("viewBox", T.unwords ["0", "0", tshow w, tshow h])]
+    (Just (llx,lly,urx,ury), Nothing, Nothing) -> -- calculate width, height
+      combinedAttrs ++
+        [ ("width", tshow (floor urx - floor llx :: Int))
+        , ("height", tshow (floor ury - floor lly :: Int)) ]
+    _ -> combinedAttrs
+ where
+  combinedAttrs = imgAttrs ++
+    [(k,v) | (k,v) <- svgAttrs, isNothing (lookup k imgAttrs)]
+  parseViewBox t =
+    case map (safeRead . addZero) $ T.words t of
+      [Just llx, Just lly, Just urx, Just ury] -> Just (llx, lly, urx, ury)
+      _ -> Nothing
+  addZero t =
+    if "-." `T.isPrefixOf` t
+       then "-0." <> T.drop 2 t -- safeRead fails on -.33, needs -0.33
+       else t
+  (mbViewBox :: Maybe (Double, Double, Double, Double)) =
+        lookup "viewBox" svgAttrs >>= parseViewBox
+  (mbHeight :: Maybe Int) = lookup "height" combinedAttrs >>= safeRead
+  (mbWidth :: Maybe Int) = lookup "width" combinedAttrs >>= safeRead
+
 cssURLs :: PandocMonad m
         => FilePath -> ByteString -> m ByteString
 cssURLs d orig = do
@@ -293,5 +381,10 @@
 makeSelfContained :: PandocMonad m => T.Text -> m T.Text
 makeSelfContained inp = do
   let tags = parseTags inp
-  out' <- convertTags tags
+  let html5 = case tags of
+                  (TagOpen "!DOCTYPE" [("html","")]:_) -> True
+                  _ -> False
+  let convertState = ConvertState { isHtml5 = html5,
+                                    svgMap = mempty }
+  out' <- evalStateT (convertTags tags) convertState
   return $ renderTags' out'
diff --git a/src/Text/Pandoc/Shared.hs b/src/Text/Pandoc/Shared.hs
--- a/src/Text/Pandoc/Shared.hs
+++ b/src/Text/Pandoc/Shared.hs
@@ -758,7 +758,7 @@
 renderTags' :: [Tag T.Text] -> T.Text
 renderTags' = renderTagsOptions
                renderOptions{ optMinimize = matchTags ["hr", "br", "img",
-                                                       "meta", "link", "col"]
+                                                       "meta", "link", "col", "use"]
                             , optRawTag   = matchTags ["script", "style"] }
               where matchTags tags = flip elem tags . T.toLower
 
diff --git a/src/Text/Pandoc/UTF8.hs b/src/Text/Pandoc/UTF8.hs
--- a/src/Text/Pandoc/UTF8.hs
+++ b/src/Text/Pandoc/UTF8.hs
@@ -140,5 +140,6 @@
 encodePath :: FilePath -> FilePath
 encodePath = id
 
+{-# DEPRECATED decodeArg "decodeArg is now a no-op" #-}
 decodeArg :: String -> String
 decodeArg = id
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
@@ -506,6 +506,7 @@
   -- we do, however, copy some settings over from reference
   let settingsPath = "word/settings.xml"
       settingsList = [ "zoom"
+                     , "mirrorMargins"
                      , "embedSystemFonts"
                      , "doNotTrackMoves"
                      , "defaultTabStop"
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
@@ -750,12 +750,9 @@
       case contents of
         Empty _ | not (isEnabled Ext_empty_paragraphs opts) -> return mempty
         _ -> return $ H.p contents
-blockToHtmlInner opts (LineBlock lns) =
-  if writerWrapText opts == WrapNone
-  then blockToHtml opts $ linesToPara lns
-  else do
-    htmlLines <- inlineListToHtml opts $ intercalate [LineBreak] lns
-    return $ H.div ! A.class_ "line-block" $ htmlLines
+blockToHtmlInner opts (LineBlock lns) = do
+  htmlLines <- inlineListToHtml opts $ intercalate [LineBreak] lns
+  return $ H.div ! A.class_ "line-block" $ htmlLines
 blockToHtmlInner opts (Div (ident, "section":dclasses, dkvs)
                    (Header level
                      hattr@(hident,hclasses,hkvs) ils : xs)) = do
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
@@ -419,9 +419,8 @@
   contents <- inlinesToJATS opts lst
   return $ char '“' <> contents <> char '”'
 inlineToJATS opts (Code a str) =
-  return $ inTags False tag attr $ literal (escapeStringForXML str)
-    where (lang, attr) = codeAttr opts a
-          tag          = if T.null lang then "monospace" else "code"
+  return $ inTags False "monospace" attr $ literal (escapeStringForXML str)
+    where (_lang, attr) = codeAttr opts a
 inlineToJATS _ il@(RawInline f x)
   | f == "jats" = return $ literal x
   | otherwise   = do
diff --git a/src/Text/Pandoc/Writers/RST.hs b/src/Text/Pandoc/Writers/RST.hs
--- a/src/Text/Pandoc/Writers/RST.hs
+++ b/src/Text/Pandoc/Writers/RST.hs
@@ -262,21 +262,6 @@
            nest 3 contents $$
            blankline
 blockToRST (Plain inlines) = inlineListToRST inlines
-blockToRST (Para [Image attr txt (src, _)]) = do
-  description <- inlineListToRST txt
-  dims <- imageDimsToRST attr
-  let fig = "image:: " <> literal src
-      alt | null txt = empty
-          | otherwise = ":alt: " <> description
-      capt = empty
-      (_,cls,_) = attr
-      classes = case cls of
-                   []               -> empty
-                   ["align-right"]  -> ":align: right"
-                   ["align-left"]   -> ":align: left"
-                   ["align-center"] -> ":align: center"
-                   _ -> ":class: " <> literal (T.unwords cls)
-  return $ hang 3 ".. " (fig $$ alt $$ classes $$ dims $+$ capt) $$ blankline
 blockToRST (Para inlines)
   | LineBreak `elem` inlines =
       linesToLineBlock $ splitBy (==LineBreak) inlines
@@ -394,13 +379,21 @@
   -- ensure that sublists have preceding blank line
   return $ blankline $$ vcat contents $$ blankline
 
-blockToRST (Figure (ident, classes, _) _ body) = do
+blockToRST (Figure (ident, classes, _kvs)
+             (Caption _ longCapt) body) = do
   let figure attr txt (src, tit) = do
         description <- inlineListToRST txt
+        capt <- blockListToRST longCapt
         dims <- imageDimsToRST attr
-        let fig = "figure:: " <> literal src
-            alt = ":alt: " <> if T.null tit then description else literal tit
-            capt = description
+        let fig = "figure::" <+> literal src
+            alt = if null txt
+                     then if T.null tit
+                              then empty
+                              else ":alt:" <+> literal tit
+                     else ":alt:" <+> description
+            name = if T.null ident
+                      then empty
+                      else "name:" <+> literal ident
             (_,cls,_) = attr
             align = case cls of
                       []               -> empty
@@ -408,7 +401,7 @@
                       ["align-left"]   -> ":align: left"
                       ["align-center"] -> ":align: center"
                       _ -> ":figclass: " <> literal (T.unwords cls)
-        return $ hang 3 ".. " (fig $$ alt $$ align $$ dims $+$ capt)
+        return $ hang 3 ".. " (fig $$ name $$ alt $$ align $$ dims $+$ capt)
               $$ blankline
   case body of
     [Para  [Image attr txt tgt]] -> figure attr txt tgt
diff --git a/test/Tests/MediaBag.hs b/test/Tests/MediaBag.hs
--- a/test/Tests/MediaBag.hs
+++ b/test/Tests/MediaBag.hs
@@ -20,7 +20,7 @@
         let d = B.doc $
                   B.para (B.image "../../test/lalune.jpg" "" mempty) <>
                   B.para (B.image "moon.jpg" "" mempty) <>
-                  B.para (B.image "data://image/png;base64,cHJpbnQgImhlbGxvIgo=;.lua+%2f%2e%2e%2f%2e%2e%2fa%2elua" "" mempty) <>
+                  B.para (B.image "data:image/png;base64,cHJpbnQgImhlbGxvIgo=;.lua+%2f%2e%2e%2f%2e%2e%2fa%2elua" "" mempty) <>
                   B.para (B.image "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" "" mempty)
         runIOorExplode $ do
           fillMediaBag d
@@ -35,4 +35,14 @@
           (exists3 && not exists4)
         exists5 <- doesFileExist ("foo" </> "d5fceb6532643d0d84ffe09c40c481ecdf59e15a.gif")
         assertBool "data uri with gif is not properly decoded" exists5
+        -- double-encoded version:
+        let e = B.doc $
+                  B.para (B.image "data:image/png;base64,cHJpbnQgInB3bmVkIgo=;.lua+%252f%252e%252e%252f%252e%252e%252fb%252elua" "" mempty)
+        runIOorExplode $ do
+          fillMediaBag e
+          extractMedia "bar" e
+        exists6 <- doesFileExist ("bar" </> "772ceca21a2751863ec46cb23db0e7fc35b9cff8.png")
+        exists7 <- doesFileExist "b.lua"
+        assertBool "data uri with double-encoded malicious payload gets written outside of destination dir"
+          (exists6 && not exists7)
   ]
diff --git a/test/Tests/Writers/JATS.hs b/test/Tests/Writers/JATS.hs
--- a/test/Tests/Writers/JATS.hs
+++ b/test/Tests/Writers/JATS.hs
@@ -40,7 +40,6 @@
 tests =
   [ testGroup "inline code"
     [ "basic" =: code "@&" =?> "<p><monospace>@&amp;</monospace></p>"
-    , "lang" =: codeWith ("", ["c"], []) "@&" =?> "<p><code language=\"c\">@&amp;</code></p>"
     ]
   , testGroup "block code"
     [ "basic" =: codeBlock "@&" =?> "<preformat>@&amp;</preformat>"
diff --git a/test/command/4420.md b/test/command/4420.md
--- a/test/command/4420.md
+++ b/test/command/4420.md
@@ -2,8 +2,8 @@
 % pandoc -f native -t rst
 [Para [Image ("",["align-right"],[("width","100px")]) [Str "image"] ("foo.png","fig:test")]]
 ^D
-.. image:: foo.png
-   :alt: image
-   :align: right
+|image|
+
+.. |image| image:: foo.png
    :width: 100px
 ```
diff --git a/test/command/6948.md b/test/command/6948.md
--- a/test/command/6948.md
+++ b/test/command/6948.md
@@ -4,9 +4,9 @@
 % pandoc -f native -t rst
 [Para [Image ("",["align-center"],[]) [Str "https://pandoc.org/diagram.jpg"] ("https://pandoc.org/diagram.jpg","")]]
 ^D
-.. image:: https://pandoc.org/diagram.jpg
-   :alt: https://pandoc.org/diagram.jpg
-   :align: center
+|https://pandoc.org/diagram.jpg|
+
+.. |https://pandoc.org/diagram.jpg| image:: https://pandoc.org/diagram.jpg
 ```
 
 Here we just omit the center attribute as it's not valid:
diff --git a/test/command/8948.md b/test/command/8948.md
new file mode 100644
--- /dev/null
+++ b/test/command/8948.md
@@ -0,0 +1,19 @@
+```
+% pandoc --embed-resources
+![minimal](command/minimal.svg)
+![minimal](command/minimal.svg)
+^D
+<p><svg alt="minimal"><use href="#svg_7868854ffb8f30209cd098bb6207b390b001249e" /></svg> <svg id="svg_7868854ffb8f30209cd098bb6207b390b001249e" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" width="481" height="151">
+    <path d="M 0 35.5 L 6.5 22.5 L 16 37 L 23 24 L 34.8 43.7 L 42.5 30 L 50.3 47 L 59.7 27.7 L 69 47 L 85 17.7 L 98.3 39 L 113 9.7 L 127.7 42.3 L 136.3 23.7 L 147 44.3 L 158.3 20.3 L 170.3 40.3 L 177.7 25.7 L 189.7 43 L 199.7 21 L 207.7 35 L 219 11 L 233 37 L 240.3 23.7 L 251 43 L 263 18.3 L 272.7 33.3 L 283 10 L 295 32.3 L 301.3 23 L 311.7 37 L 323.7 7.7 L 339.3 39 L 346.3 25.7 L 356.3 42.3 L 369.7 15 L 376.3 25.7 L 384 9 L 393 28.3 L 400.3 19 L 411.7 38.3 L 421 21 L 434.3 43 L 445 25 L 453 36.3 L 464.3 18.3 L 476.2 40.3 L 480 33.5 L 480 215 L 0 215 L 0 35.5 Z" fill="#175720"></path>
+</svg></p>
+```
+
+```
+% pandoc --embed-resources
+![minimal](command/minimal.svg)
+![minimal](command/minimal.svg){#foo}
+^D
+<p><svg alt="minimal"><use href="#foo" /></svg> <svg id="foo" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" width="481" height="151">
+    <path d="M 0 35.5 L 6.5 22.5 L 16 37 L 23 24 L 34.8 43.7 L 42.5 30 L 50.3 47 L 59.7 27.7 L 69 47 L 85 17.7 L 98.3 39 L 113 9.7 L 127.7 42.3 L 136.3 23.7 L 147 44.3 L 158.3 20.3 L 170.3 40.3 L 177.7 25.7 L 189.7 43 L 199.7 21 L 207.7 35 L 219 11 L 233 37 L 240.3 23.7 L 251 43 L 263 18.3 L 272.7 33.3 L 283 10 L 295 32.3 L 301.3 23 L 311.7 37 L 323.7 7.7 L 339.3 39 L 346.3 25.7 L 356.3 42.3 L 369.7 15 L 376.3 25.7 L 384 9 L 393 28.3 L 400.3 19 L 411.7 38.3 L 421 21 L 434.3 43 L 445 25 L 453 36.3 L 464.3 18.3 L 476.2 40.3 L 480 33.5 L 480 215 L 0 215 L 0 35.5 Z" fill="#175720"></path>
+</svg></p>
+```
diff --git a/test/command/8956.md b/test/command/8956.md
new file mode 100644
--- /dev/null
+++ b/test/command/8956.md
@@ -0,0 +1,48 @@
+```
+% pandoc -iNtslidy
+# One
+
+- one
+- two
+^D
+<div id="one" class="slide section level1" number="1">
+<h1><span class="header-section-number">1</span> One</h1>
+<ul class="incremental">
+<li>one</li>
+<li>two</li>
+</ul>
+</div>
+```
+
+````
+% pandoc -pstnative
+```
+	after tab
+```
+^D
+Pandoc
+  Meta { unMeta = fromList [] }
+  [ CodeBlock ( "" , [] , [] ) "\tafter tab" ]
+````
+
+```
+% pandoc -sfalse
+hi
+^D
+<p>hi</p>
+```
+
+```
+% pandoc --standalone=false
+hi
+^D
+<p>hi</p>
+```
+
+```
+% pandoc --standalone=FALSE
+hi
+^D
+<p>hi</p>
+```
+
diff --git a/test/command/figures-rst.md b/test/command/figures-rst.md
--- a/test/command/figures-rst.md
+++ b/test/command/figures-rst.md
@@ -6,5 +6,8 @@
 
 ^D
 .. figure:: foo.png
+   name: fig-id
    :alt: fig:
+
+   Caption
 ```
diff --git a/test/command/minimal.svg b/test/command/minimal.svg
new file mode 100644
--- /dev/null
+++ b/test/command/minimal.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" standalone="no"?>
+
+<svg viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve">
+    <path d="M 0 35.5 L 6.5 22.5 L 16 37 L 23 24 L 34.8 43.7 L 42.5 30 L 50.3 47 L 59.7 27.7 L 69 47 L 85 17.7 L 98.3 39 L 113 9.7 L 127.7 42.3 L 136.3 23.7 L 147 44.3 L 158.3 20.3 L 170.3 40.3 L 177.7 25.7 L 189.7 43 L 199.7 21 L 207.7 35 L 219 11 L 233 37 L 240.3 23.7 L 251 43 L 263 18.3 L 272.7 33.3 L 283 10 L 295 32.3 L 301.3 23 L 311.7 37 L 323.7 7.7 L 339.3 39 L 346.3 25.7 L 356.3 42.3 L 369.7 15 L 376.3 25.7 L 384 9 L 393 28.3 L 400.3 19 L 411.7 38.3 L 421 21 L 434.3 43 L 445 25 L 453 36.3 L 464.3 18.3 L 476.2 40.3 L 480 33.5 L 480 215 L 0 215 L 0 35.5 Z" fill="#175720"/>
+</svg>
diff --git a/test/typst-reader.native b/test/typst-reader.native
--- a/test/typst-reader.native
+++ b/test/typst-reader.native
@@ -43,7 +43,7 @@
       ]
   , Para
       [ Math
-          InlineMath
+          DisplayMath
           "F_{n} = \\left\\lfloor {\\frac{1}{\\sqrt{5}}\\phi^{n}} \\right\\rceil,\\quad\\phi = \\frac{1 + \\sqrt{5}}{2}"
       ]
   , Para []
@@ -658,7 +658,7 @@
           , Str "."
           ]
       , Para
-          [ Math InlineMath "\\mathcal{ABCDEFGHIJKLMNOPQRSTUVWXYZ}" ]
+          [ Math DisplayMath "\\mathcal{ABCDEFGHIJKLMNOPQRSTUVWXYZ}" ]
       , Para
           [ Str "Getting"
           , Space
@@ -3818,7 +3818,7 @@
           ]
       , Para
           [ Math
-              InlineMath
+              DisplayMath
               "\\sum_{j = 0}^{3}j^{2}\\qquad\\int_{x = 0}^{3}x^{2}dx"
           ]
       , Para
@@ -4133,7 +4133,7 @@
                           (ColSpan 1)
                           [ Para
                               [ Math
-                                  InlineMath
+                                  DisplayMath
                                   "\\left. \\left\\lbrack \\sum_{k = 0}^{n}e^{k^{2}} \\right\\rbrack \\right."
                               ]
                           ]
@@ -4200,7 +4200,7 @@
                           (ColSpan 1)
                           [ Para
                               [ Math
-                                  InlineMath
+                                  DisplayMath
                                   "\\left\\langle i,2^{2^{i}} \\right\\rangle"
                               ]
                           ]
@@ -4277,7 +4277,7 @@
                           (ColSpan 1)
                           [ Para
                               [ Math
-                                  InlineMath
+                                  DisplayMath
                                   "\\left( \\frac{1}{n^{\\alpha}} \\right)"
                               ]
                           ]
@@ -4299,7 +4299,7 @@
                           (ColSpan 1)
                           [ Para
                               [ Math
-                                  InlineMath "(\\frac{1}{n^{\\alpha}})"
+                                  DisplayMath "(\\frac{1}{n^{\\alpha}})"
                               ]
                           ]
                       , Cell
@@ -4363,7 +4363,7 @@
                           (ColSpan 1)
                           [ Para
                               [ Math
-                                  InlineMath
+                                  DisplayMath
                                   "\\left. \\frac{df}{dx} \\right|_{x_{0}}"
                               ]
                           ]
@@ -4433,7 +4433,7 @@
                           (ColSpan 1)
                           [ Para
                               [ Math
-                                  InlineMath
+                                  DisplayMath
                                   "\\begin{pmatrix}\na & b \\\\\nc & d\n\\end{pmatrix}"
                               ]
                           ]
@@ -4579,7 +4579,7 @@
                           (ColSpan 1)
                           [ Para
                               [ Math
-                                  InlineMath
+                                  DisplayMath
                                   "f_{n} = \\begin{cases}\na & \\text{if }n = 0 \\\\\nr \\cdot f_{n - 1} & \\text{else }\n\\end{cases}"
                               ]
                           ]
@@ -4790,7 +4790,7 @@
                           (RowSpan 1)
                           (ColSpan 1)
                           [ Para
-                              [ Math InlineMath "S = k \\cdot \\lg W" ]
+                              [ Math DisplayMath "S = k \\cdot \\lg W" ]
                           ]
                       , Cell
                           ( "" , [] , [] )
@@ -4840,7 +4840,7 @@
                           (ColSpan 1)
                           [ Para
                               [ Math
-                                  InlineMath
+                                  DisplayMath
                                   "\\begin{array}{r}\n\\sin(x) = x - \\frac{x^{3}}{3!} \\\\\n + \\frac{x^{5}}{5!} - \\cdots\n\\end{array}"
                               ]
                           ]
@@ -4889,7 +4889,7 @@
                           (ColSpan 1)
                           [ Para
                               [ Math
-                                  InlineMath
+                                  DisplayMath
                                   "\\begin{aligned}\n\\nabla \\cdot \\mathbf{D} & = \\rho \\\\\n\\nabla \\cdot \\mathbf{B} & = 0\n\\end{aligned}"
                               ]
                           ]
@@ -5042,7 +5042,7 @@
                           (ColSpan 1)
                           [ Para
                               [ Math
-                                  InlineMath
+                                  DisplayMath
                                   "\\lim\\limits_{h \\rightarrow 0}\\frac{f(x + h) - f(x)}{h}"
                               ]
                           ]
@@ -5065,7 +5065,7 @@
                           (ColSpan 1)
                           [ Para
                               [ Math
-                                  InlineMath
+                                  DisplayMath
                                   "\\int x^{2}dx = x^{3}/3 + C"
                               ]
                           ]
@@ -5088,7 +5088,7 @@
                           (ColSpan 1)
                           [ Para
                               [ Math
-                                  InlineMath
+                                  DisplayMath
                                   "\\nabla = \\mathbf{i}\\frac{d}{dx} + \\mathbf{j}\\frac{d}{dy} + \\mathbf{k}\\frac{d}{dz}"
                               ]
                           ]
@@ -5304,7 +5304,7 @@
           ]
       , Para
           [ Math
-              InlineMath
+              DisplayMath
               "\\frac{1}{\\sqrt{2\\sigma^{2}\\pi}}e^{- \\frac{(x - \\mu)^{2}}{2\\sigma^{2}}}"
           ]
       , Para
diff --git a/test/writer.rst b/test/writer.rst
--- a/test/writer.rst
+++ b/test/writer.rst
@@ -784,7 +784,7 @@
 From “Voyage dans la Lune” by Georges Melies (1902):
 
 .. figure:: lalune.jpg
-   :alt: Voyage dans la Lune
+   :alt: lalune
 
    lalune
 
